magic-wormhole/src/wormhole/_mailbox.py

204 lines
6.3 KiB
Python
Raw Normal View History

2016-12-30 05:30:59 +00:00
from attr import attrs, attrib
from automat import MethodicalMachine
@attrs
class _Mailbox_Machine(object):
2017-02-15 20:11:17 +00:00
_connection_machine = attrib()
2016-12-30 05:30:59 +00:00
_m = attrib()
m = MethodicalMachine()
@m.state(initial=True)
def initial(self): pass
2017-02-14 07:12:57 +00:00
# all -A states: not connected
# all -B states: yes connected
# B states serialize as A, so they deserialize as unconnected
# S0: know nothing
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S0A(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S0B(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
# S1: nameplate known, not claimed
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S1A(self): pass
# S2: nameplate known, maybe claimed
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S2A(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S2B(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
# S3: nameplate claimed, mailbox known, maybe open
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S3A(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S3B(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
# S4: mailbox maybe open, nameplate maybe released
# We've definitely opened the mailbox at least once, but it must be
# re-opened with each connection, because open() is also subscribe()
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S4A(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S4B(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
# S5: mailbox maybe open, nameplate released
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S5A(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def S5B(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
# Src: waiting for release+close
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def SrcA(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def SrcB(self): pass
# Sr: closed (or never opened), waiting for release
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def SrA(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def SrB(self): pass
# Sc: released (or never claimed), waiting for close
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def ScA(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def ScB(self): pass
# Ss: closed and released, waiting for stop
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def SsB(self): pass
2016-12-30 05:30:59 +00:00
@m.state()
2017-02-14 07:12:57 +00:00
def Ss(self): pass # terminal
2016-12-30 05:30:59 +00:00
def connected(self, ws):
self._ws = ws
self.M_connected()
@m.input()
def M_start_unconnected(self): pass
@m.input()
def M_start_connected(self): pass
@m.input()
def M_set_nameplate(self): pass
@m.input()
def M_connected(self): pass
@m.input()
def M_lost(self): pass
@m.input()
def M_send(self, msg): pass
@m.input()
def M_rx_claimed(self): pass
@m.input()
def M_rx_msg_from_me(self, msg): pass
@m.input()
def M_rx_msg_from_them(self, msg): pass
@m.input()
def M_rx_released(self): pass
@m.input()
def M_rx_closed(self): pass
@m.input()
def M_stop(self): pass
@m.input()
2016-12-30 05:30:59 +00:00
def M_stopped(self): pass
@m.output()
2016-12-30 06:27:03 +00:00
def tx_claim(self):
self._c.send_command("claim", nameplate=self._nameplate)
2016-12-30 05:30:59 +00:00
@m.output()
def tx_open(self): pass
@m.output()
def queue(self, msg): pass
@m.output()
def store_mailbox(self): pass # trouble(mb)
@m.output()
def tx_add(self, msg): pass
@m.output()
def tx_add_queued(self): pass
@m.output()
def tx_release(self): pass
@m.output()
def tx_close(self): pass
@m.output()
2017-02-15 20:11:17 +00:00
def process_first_msg_from_them(self, msg):
self.tx_release()
self.process_msg_from_them(msg)
@m.output()
2016-12-30 05:30:59 +00:00
def process_msg_from_them(self, msg): pass
@m.output()
def dequeue(self, msg): pass
@m.output()
def C_stop(self): pass
2017-02-15 20:11:17 +00:00
@m.output()
def WM_stopped(self): pass
2016-12-30 05:30:59 +00:00
2017-02-14 07:12:57 +00:00
initial.upon(M_start_unconnected, enter=S0A, outputs=[])
initial.upon(M_start_connected, enter=S0B, outputs=[])
S0A.upon(M_connected, enter=S0B, outputs=[])
S0A.upon(M_set_nameplate, enter=S1A, outputs=[])
S0A.upon(M_stop, enter=SsB, outputs=[C_stop])
S0B.upon(M_lost, enter=S0A, outputs=[])
S0B.upon(M_set_nameplate, enter=S2B, outputs=[tx_claim])
S0B.upon(M_stop, enter=SsB, outputs=[C_stop])
S1A.upon(M_connected, enter=S2B, outputs=[tx_claim])
S1A.upon(M_send, enter=S1A, outputs=[queue])
2017-02-15 20:11:17 +00:00
S1A.upon(M_stop, enter=SsB, outputs=[C_stop])
2016-12-30 05:30:59 +00:00
S2A.upon(M_connected, enter=S2B, outputs=[tx_claim])
2017-02-15 20:11:17 +00:00
S2A.upon(M_stop, enter=SrA, outputs=[])
2016-12-30 05:30:59 +00:00
S2A.upon(M_send, enter=S2A, outputs=[queue])
2017-02-14 07:12:57 +00:00
S2B.upon(M_lost, enter=S2A, outputs=[])
2016-12-30 05:30:59 +00:00
S2B.upon(M_send, enter=S2B, outputs=[queue])
S2B.upon(M_stop, enter=SrB, outputs=[tx_release])
2016-12-30 05:30:59 +00:00
S2B.upon(M_rx_claimed, enter=S3B, outputs=[store_mailbox, tx_open,
tx_add_queued])
S3A.upon(M_connected, enter=S3B, outputs=[tx_open, tx_add_queued])
S3A.upon(M_send, enter=S3A, outputs=[queue])
S3A.upon(M_stop, enter=SrcA, outputs=[])
2016-12-30 05:30:59 +00:00
S3B.upon(M_lost, enter=S3A, outputs=[])
2017-02-15 20:11:17 +00:00
S3B.upon(M_rx_msg_from_them, enter=S4B,
outputs=[process_first_msg_from_them])
2016-12-30 05:30:59 +00:00
S3B.upon(M_rx_msg_from_me, enter=S3B, outputs=[dequeue])
S3B.upon(M_rx_claimed, enter=S3B, outputs=[])
S3B.upon(M_send, enter=S3B, outputs=[queue, tx_add])
S3B.upon(M_stop, enter=SrcB, outputs=[tx_release, tx_close])
2016-12-30 05:30:59 +00:00
2017-02-15 20:11:17 +00:00
S4A.upon(M_connected, enter=S4B,
outputs=[tx_open, tx_add_queued, tx_release])
2016-12-30 05:30:59 +00:00
S4A.upon(M_send, enter=S4A, outputs=[queue])
S4A.upon(M_stop, enter=SrcA, outputs=[])
2016-12-30 05:30:59 +00:00
S4B.upon(M_lost, enter=S4A, outputs=[])
S4B.upon(M_send, enter=S4B, outputs=[queue, tx_add])
S4B.upon(M_rx_msg_from_them, enter=S4B, outputs=[process_msg_from_them])
S4B.upon(M_rx_msg_from_me, enter=S4B, outputs=[dequeue])
S4B.upon(M_rx_released, enter=S5B, outputs=[])
S4B.upon(M_stop, enter=SrcB, outputs=[tx_release, tx_close])
2016-12-30 05:30:59 +00:00
S5A.upon(M_connected, enter=S5B, outputs=[tx_open, tx_add_queued])
S5A.upon(M_send, enter=S5A, outputs=[queue])
S5A.upon(M_stop, enter=ScA, outputs=[])
2016-12-30 05:30:59 +00:00
S5B.upon(M_lost, enter=S5A, outputs=[])
S5B.upon(M_send, enter=S5B, outputs=[queue, tx_add])
S5B.upon(M_rx_msg_from_them, enter=S5B, outputs=[process_msg_from_them])
S5B.upon(M_rx_msg_from_me, enter=S5B, outputs=[dequeue])
S5B.upon(M_stop, enter=ScB, outputs=[tx_close])
SrcA.upon(M_connected, enter=SrcB, outputs=[tx_release, tx_close])
SrcB.upon(M_lost, enter=SrcA, outputs=[])
SrcB.upon(M_rx_closed, enter=SrB, outputs=[])
SrcB.upon(M_rx_released, enter=ScB, outputs=[])
SrB.upon(M_lost, enter=SrA, outputs=[])
SrA.upon(M_connected, enter=SrB, outputs=[tx_release])
SrB.upon(M_rx_released, enter=SsB, outputs=[C_stop])
ScB.upon(M_lost, enter=ScA, outputs=[])
ScB.upon(M_rx_closed, enter=SsB, outputs=[C_stop])
ScA.upon(M_connected, enter=ScB, outputs=[tx_close])
2016-12-30 05:30:59 +00:00
2017-02-15 20:11:17 +00:00
SsB.upon(M_stopped, enter=Ss, outputs=[WM_stopped])
2016-12-30 05:30:59 +00:00