Initial capability and event queue support

This commit is contained in:
Kyler Eastridge
2025-06-20 10:25:58 -04:00
parent f3ed1eb2ae
commit 91f3cdbcaf
3 changed files with 103 additions and 3 deletions

View File

@@ -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

View 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

View File

@@ -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]})>"