Compare commits
29 Commits
Author | SHA1 | Date |
---|---|---|
Tony Garnock-Jones | 3fb8028bab | |
Tony Garnock-Jones | 3a4919b7f8 | |
Tony Garnock-Jones | 3936abe3fb | |
Tony Garnock-Jones | 599b4ed469 | |
Tony Garnock-Jones | b9e0bf0520 | |
Tony Garnock-Jones | 6e555c9fd5 | |
Emery Hemingway | 8ebde104ca | |
Tony Garnock-Jones | 05fd3ca22e | |
Tony Garnock-Jones | 7df9ce5248 | |
Tony Garnock-Jones | c0239cf322 | |
Tony Garnock-Jones | 9cc4175f24 | |
Tony Garnock-Jones | 70f42dd931 | |
Tony Garnock-Jones | ef1ebe6412 | |
Tony Garnock-Jones | d9e1be2e98 | |
Tony Garnock-Jones | 6de5e96aa1 | |
Tony Garnock-Jones | ca18ca08df | |
Tony Garnock-Jones | 40ca168eac | |
Tony Garnock-Jones | 5a73e8d4c3 | |
Tony Garnock-Jones | 710ff91a64 | |
Tony Garnock-Jones | 6e5f626ac1 | |
Tony Garnock-Jones | 92027e94a9 | |
Tony Garnock-Jones | 420868eae7 | |
Tony Garnock-Jones | 3035b43941 | |
Tony Garnock-Jones | 08e49fd14e | |
Tony Garnock-Jones | a4c0bf3e6f | |
Tony Garnock-Jones | e5b65ad0ed | |
Tony Garnock-Jones | c59e044695 | |
Tony Garnock-Jones | bf0d47f1b7 | |
Tony Garnock-Jones | 7797a3cd09 |
2
.envrc
2
.envrc
|
@ -1,6 +1,6 @@
|
|||
if ! [ -d .venv ]
|
||||
then
|
||||
python -m venv .venv
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -e '.[dev]'
|
||||
else
|
||||
|
|
3
chat.py
3
chat.py
|
@ -29,6 +29,8 @@ def main():
|
|||
|
||||
@syndicate.relay.connect(args.address, sturdy.SturdyRef.decode(syndicate.parse(args.cap)))
|
||||
def on_connected(ds):
|
||||
turn.on_stop(lambda: turn.stop(root_facet))
|
||||
|
||||
me = 'user_' + str(random.randint(10, 1000))
|
||||
|
||||
turn.publish(ds, Present(me))
|
||||
|
@ -48,4 +50,3 @@ def main():
|
|||
await f.loop.connect_read_pipe(lambda: asyncio.StreamReaderProtocol(reader), sys.stdin)
|
||||
while line := (await reader.readline()).decode('utf-8'):
|
||||
turn.external(f, lambda: turn.send(ds, Says(me, line.strip())))
|
||||
turn.external(f, lambda: turn.stop(root_facet))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "syndicate-py"
|
||||
version = "0.17.0"
|
||||
version = "0.19.1"
|
||||
description = "Syndicated Actor model and Syndicate network protocol for Python 3"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.6, <4"
|
||||
|
|
|
@ -28,36 +28,49 @@ class System:
|
|||
def __init__(self, loop = None):
|
||||
self.loop = loop or asyncio.get_event_loop()
|
||||
self.inhabitant_count = 0
|
||||
self.exit_signal = asyncio.Queue()
|
||||
|
||||
def run(self, boot_proc, debug = False, name = None, configure_logging = True):
|
||||
def run(self, boot_proc, debug = None, name = None, configure_logging = True):
|
||||
if configure_logging:
|
||||
logging.basicConfig(level = logging.DEBUG if debug else logging.INFO)
|
||||
if debug:
|
||||
self.loop.set_debug(True)
|
||||
self.queue_task(lambda: Actor(boot_proc, system = self, name = name))
|
||||
|
||||
# From Python 3.12, we may be able to use:
|
||||
# asyncio.run(self._run, debug=debug, loop_factory=lambda: self.loop)
|
||||
# but until then:
|
||||
with asyncio.Runner(debug=debug, loop_factory=lambda: self.loop) as r:
|
||||
return r.run(self._run())
|
||||
|
||||
async def _run(self):
|
||||
try:
|
||||
self.loop.run_forever()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
while asyncio.all_tasks(self.loop):
|
||||
self.loop.stop()
|
||||
self.loop.run_forever()
|
||||
self.loop.close()
|
||||
await self.exit_signal.get()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
finally:
|
||||
log.debug('System._run main loop exit')
|
||||
|
||||
def adjust_engine_inhabitant_count(self, delta):
|
||||
self.inhabitant_count = self.inhabitant_count + delta
|
||||
if self.inhabitant_count == 0:
|
||||
log.debug('Inhabitant count reached zero')
|
||||
self.loop.stop()
|
||||
self.exit_signal.put_nowait(())
|
||||
|
||||
def queue_task(self, thunk):
|
||||
async def task():
|
||||
try:
|
||||
await ensure_awaitable(thunk())
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
return self.loop.create_task(task())
|
||||
|
||||
def queue_task_threadsafe(self, thunk):
|
||||
async def task():
|
||||
try:
|
||||
await ensure_awaitable(thunk())
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
return self.loop.call_soon_threadsafe(lambda: asyncio.run_coroutine_threadsafe(task(), self.loop))
|
||||
|
||||
async def ensure_awaitable(value):
|
||||
|
@ -240,12 +253,19 @@ class Facet:
|
|||
task.cancel()
|
||||
task = None
|
||||
async def guarded_task():
|
||||
should_terminate_facet = True
|
||||
try:
|
||||
await coro_fn(self)
|
||||
if await coro_fn(self) is True:
|
||||
should_terminate_facet = False
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if should_terminate_facet:
|
||||
Turn.external(self, lambda: Turn.active.stop())
|
||||
else:
|
||||
Turn.external(self, cancel_linked_task)
|
||||
task = self.loop.create_task(guarded_task())
|
||||
self.linked_tasks.append(task)
|
||||
|
|
|
@ -4,10 +4,10 @@ from preserves import preserve
|
|||
|
||||
_dict = dict ## we're about to shadow the builtin
|
||||
|
||||
_ = P.Pattern.DDiscard(P.DDiscard())
|
||||
_ = P.Pattern.discard()
|
||||
|
||||
def bind(p):
|
||||
return P.Pattern.DBind(P.DBind(p))
|
||||
return P.Pattern.bind(p)
|
||||
|
||||
CAPTURE = bind(_)
|
||||
|
||||
|
@ -48,7 +48,7 @@ def quote(p):
|
|||
elif isinstance(p, Record):
|
||||
return _rec(p.key, *map(quote, p.fields))
|
||||
else:
|
||||
return P.Pattern.DLit(P.DLit(P.AnyAtom.decode(p)))
|
||||
return P.Pattern.lit(P.AnyAtom.decode(p))
|
||||
|
||||
def lit(v):
|
||||
if isinstance(v, list) or isinstance(v, tuple):
|
||||
|
@ -60,21 +60,41 @@ def lit(v):
|
|||
elif isinstance(v, Record):
|
||||
return _rec(v.key, *map(lit, v.fields))
|
||||
else:
|
||||
return P.Pattern.DLit(P.DLit(P.AnyAtom.decode(v)))
|
||||
return P.Pattern.lit(P.AnyAtom.decode(v))
|
||||
|
||||
def seq_entries(seq):
|
||||
entries = {}
|
||||
for i, p in enumerate(seq):
|
||||
if p.VARIANT != P.Pattern.discard.VARIANT:
|
||||
entries[i] = p
|
||||
np = len(seq)
|
||||
if np > 0 and (np - 1) not in entries:
|
||||
entries[np - 1] = P.Pattern.discard()
|
||||
return entries
|
||||
|
||||
def unlit_seq(entries):
|
||||
seq = []
|
||||
if len(entries) > 0:
|
||||
try:
|
||||
max_k = max(entries.keys())
|
||||
except TypeError:
|
||||
raise Exception('Pattern entries do not represent a gap-free sequence')
|
||||
for i in range(max_k + 1):
|
||||
seq.append(unlit(entries[i]))
|
||||
return seq
|
||||
|
||||
def unlit(p):
|
||||
if not hasattr(p, 'VARIANT'):
|
||||
p = P.Pattern.decode(p)
|
||||
if p.VARIANT == P.Pattern.DLit.VARIANT:
|
||||
return p.value.value.value
|
||||
if p.VARIANT != P.Pattern.DCompound.VARIANT:
|
||||
if p.VARIANT == P.Pattern.lit.VARIANT:
|
||||
return p.value.value
|
||||
if p.VARIANT != P.Pattern.group.VARIANT:
|
||||
raise Exception('Pattern does not represent a literal value')
|
||||
p = p.value
|
||||
if p.VARIANT == P.DCompound.rec.VARIANT:
|
||||
return Record(p.label, map(unlit, p.fields))
|
||||
if p.VARIANT == P.DCompound.arr.VARIANT:
|
||||
return list(map(unlit, p.items))
|
||||
if p.VARIANT == P.DCompound.dict.VARIANT:
|
||||
if p.type.VARIANT == P.GroupType.rec.VARIANT:
|
||||
return Record(p.type.label, unlit_seq(p.entries))
|
||||
if p.type.VARIANT == P.GroupType.arr.VARIANT:
|
||||
return list(unlit_seq(p.entries))
|
||||
if p.type.VARIANT == P.GroupType.dict.VARIANT:
|
||||
return _dict(map(lambda kv: (kv[0], unlit(kv[1])), p.entries.items()))
|
||||
raise Exception('unreachable')
|
||||
|
||||
|
@ -82,10 +102,10 @@ def rec(labelstr, *members):
|
|||
return _rec(Symbol(labelstr), *members)
|
||||
|
||||
def _rec(label, *members):
|
||||
return P.Pattern.DCompound(P.DCompound.rec(label, members))
|
||||
return P.Pattern.group(P.GroupType.rec(label), seq_entries(members))
|
||||
|
||||
def arr(*members):
|
||||
return P.Pattern.DCompound(P.DCompound.arr(members))
|
||||
return P.Pattern.group(P.GroupType.arr(), seq_entries(members))
|
||||
|
||||
def dict(*kvs):
|
||||
return P.Pattern.DCompound(P.DCompound.dict(_dict(kvs)))
|
||||
return P.Pattern.group(P.GroupType.dict(), _dict(kvs))
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
|
||||
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
|
||||
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
|
||||
ByteString„„„„„„„„³HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„´³named³handler´³embedded´³refµ„³HttpRequest„„„„„„³HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³HttpRequest„„´³named³res´³embedded´³refµ„³HttpResponse„„„„„„³HttpRequest´³rec´³lit³http-request„´³tupleµ´³named³sequenceNumber´³atom³
SignedInteger„„´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³
|
||||
QueryValue„„„„´³named³body´³refµ„³RequestBody„„„„„³HttpService´³rec´³lit³http-service„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„„„„³PathPattern´³seqof´³refµ„³PathPatternElement„„³RequestBody´³orµµ±present´³atom³
|
||||
ByteString„„µ±absent´³lit€„„„„³HttpListener´³rec´³lit³
http-listener„´³tupleµ´³named³port´³atom³
SignedInteger„„„„„³HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³
SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³
MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³embeddedType€„„µ³noise„´³schema·³version°³definitions·³Packet´³orµµ±complete´³atom³
|
||||
ByteString„„„„„„„„³HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„´³named³handler´³embedded´³refµ„³HttpRequest„„„„„„³HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³HttpRequest„„´³named³res´³embedded´³refµ„³HttpResponse„„„„„„³HttpRequest´³rec´³lit³http-request„´³tupleµ´³named³sequenceNumber´³atom³
SignedInteger„„´³named³host´³refµ„³RequestHost„„´³named³port´³atom³
SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³
|
||||
QueryValue„„„„´³named³body´³refµ„³RequestBody„„„„„³HttpService´³rec´³lit³http-service„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„„„„³PathPattern´³seqof´³refµ„³PathPatternElement„„³RequestBody´³orµµ±absent´³lit€„„µ±present´³atom³
|
||||
ByteString„„„„³RequestHost´³orµµ±absent´³lit€„„µ±present´³atom³String„„„„³HttpListener´³rec´³lit³
http-listener„´³tupleµ´³named³port´³atom³
SignedInteger„„„„„³HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³
SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³
MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³embeddedType€„„µ³noise„´³schema·³version°³definitions·³Packet´³orµµ±complete´³atom³
|
||||
ByteString„„µ±
|
||||
fragmented´³seqof´³atom³
|
||||
ByteString„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³
|
||||
ByteString„„³service´³named³service´³refµ„³ServiceSelector„„„„´³named³protocol´³refµ„³
NoiseProtocol„„´³named³
preSharedKeys´³refµ„³NoisePreSharedKeys„„„„³
NoiseProtocol´³orµµ±present´³dict·³protocol´³named³protocol´³atom³String„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³
NoiseStepType´³lit³noise„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³
|
||||
ByteString„„„„„³ Initiator´³rec´³lit³ initiator„´³tupleµ´³named³initiatorSession´³embedded´³refµ„³Packet„„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³
|
||||
ByteString„„³service´³named³service´³refµ„³ServiceSelector„„„„´³named³protocol´³refµ„³
NoiseProtocol„„´³named³
preSharedKeys´³refµ„³NoisePreSharedKeys„„„„³SessionItem´³orµµ± Initiator´³refµ„³ Initiator„„µ±Packet´³refµ„³Packet„„„„³
NoiseProtocol´³orµµ±present´³dict·³protocol´³named³protocol´³atom³String„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³
NoiseStepType´³lit³noise„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³
|
||||
ByteString„„„„„µ±invalid´³dict·³ secretKey´³named³ secretKey³any„„„„µ±absent´³dict·„„„„„³DefaultProtocol´³lit±!Noise_NK_25519_ChaChaPoly_BLAKE2s„³NoiseStepDetail´³refµ„³ServiceSelector„³ServiceSelector³any³NoiseServiceSpec´³andµ´³named³base´³refµ„³ NoiseSpec„„´³named³ secretKey´³refµ„³SecretKeyField„„„„³NoisePreSharedKeys´³orµµ±present´³dict·³
preSharedKeys´³named³
preSharedKeys´³seqof´³atom³
|
||||
ByteString„„„„„„µ±invalid´³dict·³
preSharedKeys´³named³
preSharedKeys³any„„„„µ±absent´³dict·„„„„„³NoisePathStepDetail´³refµ„³ NoiseSpec„³NoiseDescriptionDetail´³refµ„³NoiseServiceSpec„„³embeddedType€„„µ³timer„´³schema·³version°³definitions·³SetTimer´³rec´³lit³ set-timer„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„´³named³kind´³refµ„³ TimerKind„„„„„³ LaterThan´³rec´³lit³
|
||||
ByteString„„„„„„µ±invalid´³dict·³
preSharedKeys´³named³
preSharedKeys³any„„„„µ±absent´³dict·„„„„„³NoisePathStepDetail´³refµ„³ NoiseSpec„³NoiseDescriptionDetail´³refµ„³NoiseServiceSpec„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³timer„´³schema·³version°³definitions·³SetTimer´³rec´³lit³ set-timer„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„´³named³kind´³refµ„³ TimerKind„„„„„³ LaterThan´³rec´³lit³
|
||||
later-than„´³tupleµ´³named³seconds´³atom³Double„„„„„³ TimerKind´³orµµ±relative´³lit³relative„„µ±absolute´³lit³absolute„„µ±clear´³lit³clear„„„„³TimerExpired´³rec´³lit³
timer-expired„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„„„„„³embeddedType€„„µ³trace„´³schema·³version°³definitions·³Oid³any³Name´³orµµ± anonymous´³rec´³lit³ anonymous„´³tupleµ„„„„µ±named´³rec´³lit³named„´³tupleµ´³named³name³any„„„„„„„³Target´³rec´³lit³entity„´³tupleµ´³named³actor´³refµ„³ActorId„„´³named³facet´³refµ„³FacetId„„´³named³oid´³refµ„³Oid„„„„„³TaskId³any³TurnId³any³ActorId³any³FacetId³any³ TurnCause´³orµµ±turn´³rec´³lit³ caused-by„´³tupleµ´³named³id´³refµ„³TurnId„„„„„„µ±cleanup´³rec´³lit³cleanup„´³tupleµ„„„„µ±linkedTaskRelease´³rec´³lit³linked-task-release„´³tupleµ´³named³id´³refµ„³TaskId„„´³named³reason´³refµ„³LinkedTaskReleaseReason„„„„„„µ±periodicActivation´³rec´³lit³periodic-activation„´³tupleµ´³named³period´³atom³Double„„„„„„µ±delay´³rec´³lit³delay„´³tupleµ´³named³causingTurn´³refµ„³TurnId„„´³named³amount´³atom³Double„„„„„„µ±external´³rec´³lit³external„´³tupleµ´³named³description³any„„„„„„„³ TurnEvent´³orµµ±assert´³rec´³lit³assert„´³tupleµ´³named³ assertion´³refµ„³AssertionDescription„„´³named³handle´³refµ³protocol„³Handle„„„„„„µ±retract´³rec´³lit³retract„´³tupleµ´³named³handle´³refµ³protocol„³Handle„„„„„„µ±message´³rec´³lit³message„´³tupleµ´³named³body´³refµ„³AssertionDescription„„„„„„µ±sync´³rec´³lit³sync„´³tupleµ´³named³peer´³refµ„³Target„„„„„„µ± breakLink´³rec´³lit³
|
||||
break-link„´³tupleµ´³named³source´³refµ„³ActorId„„´³named³handle´³refµ³protocol„³Handle„„„„„„„„³
|
||||
ExitStatus´³orµµ±ok´³lit³ok„„µ±Error´³refµ³protocol„³Error„„„„³
|
||||
|
@ -38,7 +38,7 @@ Parameters
|
|||
Parameters„³SturdyDescriptionDetail´³dict·³key´³named³key´³atom³
|
||||
ByteString„„³oid´³named³oid³any„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³worker„´³schema·³version°³definitions·³Instance´³rec´³lit³Instance„´³tupleµ´³named³name´³atom³String„„´³named³argument³any„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³service„´³schema·³version°³definitions·³State´³orµµ±started´³lit³started„„µ±ready´³lit³ready„„µ±failed´³lit³failed„„µ±complete´³lit³complete„„µ±userDefined³any„„„³
|
||||
RunService´³rec´³lit³run-service„´³tupleµ´³named³serviceName³any„„„„³ServiceState´³rec´³lit³
service-state„´³tupleµ´³named³serviceName³any„´³named³state´³refµ„³State„„„„„³
ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³serviceName³any„„„„³ServiceDependency´³rec´³lit³
|
||||
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ServiceState„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³definitions·³Oid´³atom³
SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³
SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³embeddedType€„„µ³ dataspace„´³schema·³version°³definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³
|
||||
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ServiceState„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³definitions·³Nop´³lit€„³Oid´³atom³
SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³
SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„µ±Nop´³refµ„³Nop„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³embeddedType€„„µ³ dataspace„´³schema·³version°³definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³
|
||||
gatekeeper„´³schema·³version°³definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³description´³refµ„³Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³tuplePrefixµ´³named³
|
||||
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ResolvePath´³rec´³lit³resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³embeddedType€„„µ³dataspacePatterns„´³schema·³version°³definitions·³DLit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„³DBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³
SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
|
||||
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±DDiscard´³refµ„³DDiscard„„µ±DBind´³refµ„³DBind„„µ±DLit´³refµ„³DLit„„µ± DCompound´³refµ„³ DCompound„„„„³DDiscard´³rec´³lit³_„´³tupleµ„„„³ DCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Pattern„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Pattern„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„„„
|
||||
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ResolvePath´³rec´³lit³resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³embeddedType€„„µ³dataspacePatterns„´³schema·³version°³definitions·³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³
SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
|
||||
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±discard´³rec´³lit³_„´³tupleµ„„„„µ±bind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„„µ±group´³rec´³lit³group„´³tupleµ´³named³type´³refµ„³ GroupType„„´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ GroupType´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„„„„„µ±arr´³rec´³lit³arr„´³tupleµ„„„„µ±dict´³rec´³lit³dict„´³tupleµ„„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„„„
|
|
@ -1,15 +1,23 @@
|
|||
version 1 .
|
||||
embeddedType EntityRef.Cap .
|
||||
|
||||
# Dataspace patterns: a sublanguage of attenuation patterns.
|
||||
Pattern = DDiscard / DBind / DLit / DCompound .
|
||||
# Dataspace patterns: *almost* a sublanguage of attenuation patterns.
|
||||
#
|
||||
# One key difference is that Dataspace patterns are extensible, in that
|
||||
# they ignore fields not mentioned in group patterns.
|
||||
|
||||
DDiscard = <_>.
|
||||
DBind = <bind @pattern Pattern>.
|
||||
DLit = <lit @value AnyAtom>.
|
||||
DCompound = <rec @label any @fields [Pattern ...]>
|
||||
/ <arr @items [Pattern ...]>
|
||||
/ <dict @entries { any: Pattern ...:... }> .
|
||||
Pattern =
|
||||
/ @discard <_>
|
||||
/ <bind @pattern Pattern>
|
||||
/ <lit @value AnyAtom>
|
||||
/ <group @type GroupType @entries { any: Pattern ...:... }>
|
||||
.
|
||||
|
||||
GroupType =
|
||||
/ <rec @label any>
|
||||
/ <arr>
|
||||
/ <dict>
|
||||
.
|
||||
|
||||
AnyAtom =
|
||||
/ @bool bool
|
||||
|
|
|
@ -13,8 +13,37 @@ Step = <<rec> @stepType symbol [@detail any]> .
|
|||
# ---------------------------------------------------------------------------
|
||||
# Protocol at dataspaces *associated* with gatekeeper entities
|
||||
|
||||
# Assertion. Gatekeeper will compute an appropriate PathStep from `description` pointing at
|
||||
# `target`, and will respond with a `Bound` to `observer` (if supplied).
|
||||
# ## Handling `Resolve` requests
|
||||
#
|
||||
# When the gatekeeper entity receives a `Resolve` assertion (call it R1), it
|
||||
#
|
||||
# 1. asserts a `Resolve` (call it R2) into its associated dataspace that
|
||||
# is the same as R1 except it has a different `observer`; and
|
||||
#
|
||||
# 2. observes a `Bind` with `description` matching the `step` of R1/R2
|
||||
# according to `stepType` (e.g. treatment of SturdyStepType is not the
|
||||
# same as treatment of NoiseStepType).
|
||||
#
|
||||
# Normally, an appropriate `Bind` is expected to exist. If the gatekeeper
|
||||
# sees the `Bind` first, it takes the `target` from it and does whatever
|
||||
# `stepType` mandates before replying to R1's observer.
|
||||
#
|
||||
# However, if a `Resolved` is asserted to R2's observer before a `Bind`
|
||||
# appears, that resolution is relayed on to R1's observer directly, be it
|
||||
# positive or negative, and the gatekeeper stops waiting for a `Bind`.
|
||||
#
|
||||
# This way, entities can keep an eye out for `Resolve` requests that will
|
||||
# never complete, and answer `Rejected` to them even when no matching
|
||||
# `Bind` exists. Entities could also use `Resolve` requests to synthesize a
|
||||
# `Bind` in a "just-in-time" fashion.
|
||||
#
|
||||
# ## General treatment of `Bind` assertions
|
||||
#
|
||||
# When the gatekeeper sees a `Bind`, independently of any potential
|
||||
# `Resolve` requests, it computes an appropriate PathStep from
|
||||
# `description` pointing at `target`, and responds with a `Bound` to
|
||||
# `observer` (if supplied).
|
||||
#
|
||||
Bind = <bind @description Description @target #:any @observer BindObserver> .
|
||||
Description = <<rec> @stepType symbol [@detail any]> .
|
||||
BindObserver = @present #:Bound / @absent #f .
|
||||
|
|
|
@ -21,7 +21,7 @@ MethodPattern = @any #f / @specific @"Lowercase" symbol .
|
|||
# Assertion in driver DS
|
||||
HttpRequest = <http-request
|
||||
@sequenceNumber int
|
||||
@host string
|
||||
@host RequestHost
|
||||
@port int
|
||||
@method @"Lowercase" symbol
|
||||
@path [string ...]
|
||||
|
@ -31,14 +31,25 @@ HttpRequest = <http-request
|
|||
|
||||
Headers = {@"Lowercase" symbol: string ...:...} .
|
||||
QueryValue = @string string / <file @filename string @headers Headers @body bytes> .
|
||||
RequestBody = @present bytes / @absent #f .
|
||||
RequestBody = @absent #f / @present bytes .
|
||||
RequestHost = @absent #f / @present string .
|
||||
|
||||
# Assertion to handler entity
|
||||
HttpContext = <request @req HttpRequest @res #:HttpResponse> .
|
||||
|
||||
# HttpResponse protocol. Delivered to the `res` ref in `HttpContext`.
|
||||
#
|
||||
# (status | header)* . chunk* . done
|
||||
#
|
||||
# Done triggers completion of the response and retraction of the frame by the peer. If the
|
||||
# HttpBinding responsible for the request is withdrawn mid-way through a response (i.e. when
|
||||
# chunked transfer is used and at least one chunk has been sent) the request is abruptly
|
||||
# closed; if it is withdrawn at any other moment in the lifetime of the request, a 500 Internal
|
||||
# Server Error is send to the client.
|
||||
#
|
||||
@<TODO "trailers?">
|
||||
# Messages
|
||||
HttpResponse =
|
||||
# Messages.
|
||||
/ <status @code int @message string>
|
||||
/ <header @name symbol @value string>
|
||||
/ <chunk @chunk Chunk>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
version 1 .
|
||||
embeddedType EntityRef.Cap .
|
||||
|
||||
# https://noiseprotocol.org/
|
||||
|
||||
|
@ -42,13 +43,30 @@ DefaultProtocol = "Noise_NK_25519_ChaChaPoly_BLAKE2s" .
|
|||
# sequence is exhausted or not supplied, an all-zeros key is used each time a PSK is needed.
|
||||
NoisePreSharedKeys = @present { preSharedKeys: [bytes ...] } / @invalid { preSharedKeys: any } / @absent {} .
|
||||
|
||||
# Sessions proceed by sending Packets to the initiatorSession and responderSession according to
|
||||
# the Noise protocol definition. Each Packet represents a complete logical unit of
|
||||
# ---------------------------------------------------------------------------
|
||||
# Handshaking and running a session
|
||||
|
||||
# 1. initiator asserts <resolve <noise ServiceSelector> #:A> at Gatekeeper
|
||||
# 2. gatekeeper asserts <accepted #:B> at #:A
|
||||
# 3. initiator asserts <initiator #:C> at #:B and then sends `Packet`s to #:B
|
||||
# 4. responder sends `Packet`s to #:C
|
||||
#
|
||||
# Sessions begin with introduction of initiator (#:C) and responder (#:B) to each other, and
|
||||
# then proceed by sending `Packet`s (from #:C) to #:B and (from #:B) to #:C according to
|
||||
# the Noise protocol definition. Each `Packet` represents a complete logical unit of
|
||||
# communication; for example, a complete Turn when layering the Syndicate protocol over Noise.
|
||||
# Note well the restriction on Noise messages: no individual complete packet or packet fragment
|
||||
# may exceed 65535 bytes (N.B. not 65536!). When `fragmented`, each portion of a Packet is a
|
||||
# may exceed 65535 bytes (N.B. not 65536!). When `fragmented`, each portion of a `Packet` is a
|
||||
# complete Noise "transport message"; when `complete`, the whole thing is likewise a complete
|
||||
# "transport message".
|
||||
#
|
||||
# Retraction of the `Initiator` ends the session from the initiator-side; retraction of the
|
||||
# `<accepted ...>` assertion ends the session from the responder-side.
|
||||
|
||||
SessionItem = Initiator / Packet .
|
||||
# Assertion
|
||||
Initiator = <initiator @initiatorSession #:Packet> .
|
||||
# Message
|
||||
Packet = @complete bytes / @fragmented [bytes ...] .
|
||||
|
||||
# When layering Syndicate protocol over noise,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
version 1 .
|
||||
|
||||
Packet = Turn / Error / Extension .
|
||||
Packet = Turn / Error / Extension / Nop .
|
||||
|
||||
Extension = <<rec> @label any @fields [any ...]> .
|
||||
Nop = #f .
|
||||
|
||||
Error = <error @message string @detail any>.
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ class TunnelRelay:
|
|||
if variant == 'Turn': self._handle_turn_events(packet.value.value)
|
||||
elif variant == 'Error': self._on_error(packet.value.message, packet.value.detail)
|
||||
elif variant == 'Extension': pass
|
||||
elif variant == 'Nop': pass
|
||||
|
||||
def _on_error(self, message, detail):
|
||||
self.facet.log.error('Error from server: %r (detail: %r)', message, detail)
|
||||
|
|
Loading…
Reference in New Issue