Initial capability and event queue support
This commit is contained in:
@@ -73,11 +73,26 @@ class Agent(EventTarget):
|
||||
self.send(msg, True)
|
||||
|
||||
async def run(self):
|
||||
lastAck = 0
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(0.1)
|
||||
if self.simulator == None:
|
||||
break
|
||||
|
||||
if not "EventQueueGet" in self.simulator.capabilities:
|
||||
lastAck = 0
|
||||
continue
|
||||
|
||||
ack, events = await self.simulator.capabilities["EventQueueGet"].poll(lastAck, False)
|
||||
if ack == None:
|
||||
lastAck = 0
|
||||
continue
|
||||
|
||||
if ack == lastAck:
|
||||
continue
|
||||
|
||||
lastAck = ack
|
||||
|
||||
except asyncio.exceptions.CancelledError:
|
||||
# Attempt to gracefully logout
|
||||
|
||||
72
pymetaverse/viewer/capability.py
Normal file
72
pymetaverse/viewer/capability.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from .. import httpclient
|
||||
from .. import llsd
|
||||
|
||||
class CapabilityRegistry:
|
||||
def __init__(self):
|
||||
self.capabilities = {}
|
||||
|
||||
def register(self, name):
|
||||
def _(func):
|
||||
self.capabilities[name] = func
|
||||
return func
|
||||
return _
|
||||
|
||||
def __contains__(self, what):
|
||||
return what in self.capabilities
|
||||
|
||||
def get(self, name, url):
|
||||
try:
|
||||
return self.capabilities[name](url)
|
||||
except KeyError:
|
||||
raise ValueError("No such capability {}".format(name))
|
||||
|
||||
Capabilities = CapabilityRegistry()
|
||||
|
||||
class BaseCapability:
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
|
||||
# Please keep these in alphabetical order! :)
|
||||
|
||||
@Capabilities.register("EventQueueGet")
|
||||
class EventQueueGet(BaseCapability):
|
||||
async def poll(self, ack, done = False):
|
||||
async with httpclient.HttpClient() as session:
|
||||
async with await session.post(self.url,
|
||||
data = llsd.llsdEncode({
|
||||
"ack": ack,
|
||||
"done": done
|
||||
}),
|
||||
headers = {
|
||||
"Content-Type": "application/llsd+xml"
|
||||
},
|
||||
timeout = 60 # Timeouts on the server are 30, twice that is more than enough
|
||||
) as response:
|
||||
if response.status == 404:
|
||||
return None, []
|
||||
|
||||
elif response.status == 200:
|
||||
data = await response.read()
|
||||
result = llsd.llsdDecode(data, format="xml")
|
||||
return result["id"], result["events"]
|
||||
|
||||
else:
|
||||
return ack, []
|
||||
|
||||
@Capabilities.register("Seed")
|
||||
class Seed(BaseCapability):
|
||||
async def getCapabilities(self, caps):
|
||||
async with httpclient.HttpClient() as session:
|
||||
async with await session.post(self.url,
|
||||
data = llsd.llsdEncode(list(caps.capabilities.keys())),
|
||||
headers = {
|
||||
"Content-Type": "application/llsd+xml"
|
||||
}
|
||||
) as response:
|
||||
capList = llsd.llsdDecode(await response.read(), format="xml")
|
||||
result = {}
|
||||
for name, url in capList.items():
|
||||
if name in caps:
|
||||
result[name] = caps.get(name, url)
|
||||
|
||||
return result
|
||||
@@ -1,5 +1,7 @@
|
||||
import asyncio
|
||||
from .circuit import Circuit
|
||||
from . import messages
|
||||
from .capability import Capabilities
|
||||
from . import region
|
||||
from .. import httpclient
|
||||
from .. import llsd
|
||||
@@ -16,9 +18,16 @@ class Simulator(EventTarget):
|
||||
self.id = None
|
||||
self.circuit = None
|
||||
self.region = None
|
||||
self.caps = {}
|
||||
self.capabilities = {}
|
||||
self.messageTemplate = messages.getDefaultTemplate()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
loop.create_task(self.close())
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
def send(self, msg, reliable = False):
|
||||
self.circuit.send(msg, reliable)
|
||||
|
||||
@@ -74,8 +83,12 @@ class Simulator(EventTarget):
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
|
||||
async def fetchCapabilities(self, seed):
|
||||
pass
|
||||
async def fetchCapabilities(self, url):
|
||||
if "Seed" not in Capabilities:
|
||||
return
|
||||
|
||||
seed = Capabilities.get("Seed", url)
|
||||
self.capabilities = await seed.getCapabilities(Capabilities)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} \"{self.name}\" ({self.host[0]}:{self.host[1]})>"
|
||||
|
||||
Reference in New Issue
Block a user