test basic code allocation

This commit is contained in:
Brian Warner 2017-02-23 18:11:07 -08:00
parent ef1904bc52
commit 8a2810ba70
11 changed files with 76 additions and 13 deletions

View File

@ -54,7 +54,7 @@ digraph {
{rank=same; Other S_closed} {rank=same; Other S_closed}
Other [shape="box" style="dashed" Other [shape="box" style="dashed"
label="send -> S.send\ngot_verifier -> A.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code" label="rx_welcome -> process\nsend -> S.send\ngot_verifier -> A.got_verifier\nallocate -> C.allocate\ninput -> C.input\nset_code -> C.set_code"
] ]

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
from attr.validators import provides, instance_of from attr.validators import provides, instance_of
@ -29,7 +30,7 @@ class Boss(object):
self._M = Mailbox(self._side) self._M = Mailbox(self._side)
self._S = Send(self._side, self._timing) self._S = Send(self._side, self._timing)
self._O = Order(self._side, self._timing) self._O = Order(self._side, self._timing)
self._K = Key(self._timing) self._K = Key(self._appid, self._timing)
self._R = Receive(self._side, self._timing) self._R = Receive(self._side, self._timing)
self._RC = RendezvousConnector(self._url, self._appid, self._side, self._RC = RendezvousConnector(self._url, self._appid, self._side,
self._reactor, self._journal, self._reactor, self._journal,
@ -92,6 +93,10 @@ class Boss(object):
@m.input() @m.input()
def close(self): pass def close(self): pass
# from RendezvousConnector
@m.input()
def rx_welcome(self, welcome): pass
# from Code (provoked by input/allocate/set_code) # from Code (provoked by input/allocate/set_code)
@m.input() @m.input()
def got_code(self, code): pass def got_code(self, code): pass
@ -121,6 +126,10 @@ class Boss(object):
def closed(self): pass def closed(self): pass
@m.output()
def process_welcome(self, welcome):
pass # TODO: ignored for now
@m.output() @m.output()
def do_got_code(self, code): def do_got_code(self, code):
nameplate = code.split("-")[0] nameplate = code.split("-")[0]
@ -167,18 +176,22 @@ class Boss(object):
S0_empty.upon(close, enter=S3_closing, outputs=[close_lonely]) S0_empty.upon(close, enter=S3_closing, outputs=[close_lonely])
S0_empty.upon(send, enter=S0_empty, outputs=[S_send]) S0_empty.upon(send, enter=S0_empty, outputs=[S_send])
S0_empty.upon(rx_welcome, enter=S0_empty, outputs=[process_welcome])
S0_empty.upon(got_code, enter=S1_lonely, outputs=[do_got_code]) S0_empty.upon(got_code, enter=S1_lonely, outputs=[do_got_code])
S1_lonely.upon(rx_welcome, enter=S1_lonely, outputs=[process_welcome])
S1_lonely.upon(happy, enter=S2_happy, outputs=[]) S1_lonely.upon(happy, enter=S2_happy, outputs=[])
S1_lonely.upon(scared, enter=S3_closing, outputs=[close_scared]) S1_lonely.upon(scared, enter=S3_closing, outputs=[close_scared])
S1_lonely.upon(close, enter=S3_closing, outputs=[close_lonely]) S1_lonely.upon(close, enter=S3_closing, outputs=[close_lonely])
S1_lonely.upon(send, enter=S1_lonely, outputs=[S_send]) S1_lonely.upon(send, enter=S1_lonely, outputs=[S_send])
S1_lonely.upon(got_verifier, enter=S1_lonely, outputs=[W_got_verifier]) S1_lonely.upon(got_verifier, enter=S1_lonely, outputs=[W_got_verifier])
S2_happy.upon(rx_welcome, enter=S2_happy, outputs=[process_welcome])
S2_happy.upon(got_phase, enter=S2_happy, outputs=[W_received]) S2_happy.upon(got_phase, enter=S2_happy, outputs=[W_received])
S2_happy.upon(got_version, enter=S2_happy, outputs=[process_version]) S2_happy.upon(got_version, enter=S2_happy, outputs=[process_version])
S2_happy.upon(scared, enter=S3_closing, outputs=[close_scared]) S2_happy.upon(scared, enter=S3_closing, outputs=[close_scared])
S2_happy.upon(close, enter=S3_closing, outputs=[close_happy]) S2_happy.upon(close, enter=S3_closing, outputs=[close_happy])
S2_happy.upon(send, enter=S2_happy, outputs=[S_send]) S2_happy.upon(send, enter=S2_happy, outputs=[S_send])
S3_closing.upon(rx_welcome, enter=S3_closing, outputs=[])
S3_closing.upon(got_phase, enter=S3_closing, outputs=[]) S3_closing.upon(got_phase, enter=S3_closing, outputs=[])
S3_closing.upon(got_version, enter=S3_closing, outputs=[]) S3_closing.upon(got_version, enter=S3_closing, outputs=[])
S3_closing.upon(happy, enter=S3_closing, outputs=[]) S3_closing.upon(happy, enter=S3_closing, outputs=[])
@ -187,6 +200,7 @@ class Boss(object):
S3_closing.upon(send, enter=S3_closing, outputs=[]) S3_closing.upon(send, enter=S3_closing, outputs=[])
S3_closing.upon(closed, enter=S4_closed, outputs=[W_closed]) S3_closing.upon(closed, enter=S4_closed, outputs=[W_closed])
S4_closed.upon(rx_welcome, enter=S4_closed, outputs=[])
S4_closed.upon(got_phase, enter=S4_closed, outputs=[]) S4_closed.upon(got_phase, enter=S4_closed, outputs=[])
S4_closed.upon(got_version, enter=S4_closed, outputs=[]) S4_closed.upon(got_version, enter=S4_closed, outputs=[])
S4_closed.upon(happy, enter=S4_closed, outputs=[]) S4_closed.upon(happy, enter=S4_closed, outputs=[])

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
import os import os
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
@ -127,5 +128,14 @@ class Code(object):
outputs=[stash_nameplates]) outputs=[stash_nameplates])
S2_typing_nameplate.upon(hyphen, enter=S3_typing_code, S2_typing_nameplate.upon(hyphen, enter=S3_typing_code,
outputs=[lookup_wordlist]) outputs=[lookup_wordlist])
# TODO: need a proper pair of connected/lost states around S2
S2_typing_nameplate.upon(connected, enter=S2_typing_nameplate, outputs=[])
S2_typing_nameplate.upon(lost, enter=S2_typing_nameplate, outputs=[])
S3_typing_code.upon(tab, enter=S3_typing_code, outputs=[do_completion_code]) S3_typing_code.upon(tab, enter=S3_typing_code, outputs=[do_completion_code])
S3_typing_code.upon(RETURN, enter=S4_known, outputs=[B_got_code]) S3_typing_code.upon(RETURN, enter=S4_known, outputs=[B_got_code])
S3_typing_code.upon(connected, enter=S3_typing_code, outputs=[])
S3_typing_code.upon(lost, enter=S3_typing_code, outputs=[])
S4_known.upon(connected, enter=S4_known, outputs=[])
S4_known.upon(lost, enter=S4_known, outputs=[])

View File

@ -1,7 +1,8 @@
from __future__ import print_function, absolute_import, unicode_literals
from hashlib import sha256 from hashlib import sha256
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
from attr.validators import provides from attr.validators import provides, instance_of
from spake2 import SPAKE2_Symmetric from spake2 import SPAKE2_Symmetric
from hkdf import Hkdf from hkdf import Hkdf
from nacl.secret import SecretBox from nacl.secret import SecretBox
@ -53,6 +54,7 @@ def encrypt_data(key, plaintext):
@attrs @attrs
@implementer(_interfaces.IKey) @implementer(_interfaces.IKey)
class Key(object): class Key(object):
_appid = attrib(validator=instance_of(type(u"")))
_timing = attrib(validator=provides(_interfaces.ITiming)) _timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine() m = MethodicalMachine()

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
from attr.validators import instance_of from attr.validators import instance_of
@ -10,7 +11,7 @@ class Mailbox(object):
_side = attrib(validator=instance_of(type(u""))) _side = attrib(validator=instance_of(type(u"")))
m = MethodicalMachine() m = MethodicalMachine()
def __init__(self): def __attrs_post_init__(self):
self._mood = None self._mood = None
self._nameplate = None self._nameplate = None
self._mailbox = None self._mailbox = None
@ -129,7 +130,7 @@ class Mailbox(object):
@m.output() @m.output()
def record_nameplate_and_RC_tx_claim(self, nameplate): def record_nameplate_and_RC_tx_claim(self, nameplate):
self._nameplate = nameplate self._nameplate = nameplate
self._RX.tx_claim(self._nameplate) self._RC.tx_claim(self._nameplate)
@m.output() @m.output()
def RC_tx_claim(self): def RC_tx_claim(self):
# when invoked via M.connected(), we must use the stored nameplate # when invoked via M.connected(), we must use the stored nameplate
@ -278,5 +279,19 @@ class Mailbox(object):
ScB.upon(rx_closed, enter=SsB, outputs=[RC_stop]) ScB.upon(rx_closed, enter=SsB, outputs=[RC_stop])
ScA.upon(connected, enter=ScB, outputs=[RC_tx_close]) ScA.upon(connected, enter=ScB, outputs=[RC_tx_close])
SsB.upon(lost, enter=SsB, outputs=[])
SsB.upon(stopped, enter=Ss, outputs=[W_closed]) SsB.upon(stopped, enter=Ss, outputs=[W_closed])
SrcB.upon(rx_claimed, enter=SrcB, outputs=[])
SrcB.upon(rx_message_theirs, enter=SrcB, outputs=[])
SrcB.upon(rx_message_ours, enter=SrcB, outputs=[])
SrB.upon(rx_claimed, enter=SrB, outputs=[])
SrB.upon(rx_message_theirs, enter=SrB, outputs=[])
SrB.upon(rx_message_ours, enter=SrB, outputs=[])
ScB.upon(rx_claimed, enter=ScB, outputs=[])
ScB.upon(rx_message_theirs, enter=ScB, outputs=[])
ScB.upon(rx_message_ours, enter=ScB, outputs=[])
SsB.upon(rx_claimed, enter=SsB, outputs=[])
SsB.upon(rx_message_theirs, enter=SsB, outputs=[])
SsB.upon(rx_message_ours, enter=SsB, outputs=[])

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer from zope.interface import implementer
from automat import MethodicalMachine from automat import MethodicalMachine
from . import _interfaces from . import _interfaces
@ -5,8 +6,7 @@ from . import _interfaces
@implementer(_interfaces.INameplateLister) @implementer(_interfaces.INameplateLister)
class NameplateListing(object): class NameplateListing(object):
m = MethodicalMachine() m = MethodicalMachine()
def __init__(self):
pass
def wire(self, rendezvous_connector, code): def wire(self, rendezvous_connector, code):
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector) self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
self._C = _interfaces.ICode(code) self._C = _interfaces.ICode(code)

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
from attr.validators import provides, instance_of from attr.validators import provides, instance_of
@ -11,7 +12,7 @@ class Order(object):
_timing = attrib(validator=provides(_interfaces.ITiming)) _timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine() m = MethodicalMachine()
def __init__(self): def __attrs_post_init__(self):
self._key = None self._key = None
self._queue = [] self._queue = []
def wire(self, key, receive): def wire(self, key, receive):

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer from zope.interface import implementer
from attr import attrs, attrib from attr import attrs, attrib
from attr.validators import provides, instance_of from attr.validators import provides, instance_of
@ -12,7 +13,7 @@ class Receive(object):
_timing = attrib(validator=provides(_interfaces.ITiming)) _timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine() m = MethodicalMachine()
def __init__(self): def __attrs_post_init__(self):
self._key = None self._key = None
def wire(self, boss, key, send): def wire(self, boss, key, send):

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
import os import os
from six.moves.urllib_parse import urlparse from six.moves.urllib_parse import urlparse
from attr import attrs, attrib from attr import attrs, attrib
@ -27,7 +28,12 @@ class WSClient(websocket.WebSocketClientProtocol):
def onMessage(self, payload, isBinary): def onMessage(self, payload, isBinary):
#print("onMessage") #print("onMessage")
assert not isBinary assert not isBinary
try:
self._RC.ws_message(payload) self._RC.ws_message(payload)
except:
print("LOGGING")
log.err()
raise
def onClose(self, wasClean, code, reason): def onClose(self, wasClean, code, reason):
#print("onClose") #print("onClose")
@ -60,6 +66,7 @@ class RendezvousConnector(object):
_reactor = attrib() _reactor = attrib()
_journal = attrib(validator=provides(_interfaces.IJournal)) _journal = attrib(validator=provides(_interfaces.IJournal))
_timing = attrib(validator=provides(_interfaces.ITiming)) _timing = attrib(validator=provides(_interfaces.ITiming))
DEBUG = False
def __attrs_post_init__(self): def __attrs_post_init__(self):
self._ws = None self._ws = None

View File

@ -1,14 +1,18 @@
from __future__ import print_function, absolute_import, unicode_literals
from attr import attrs, attrib
from attr.validators import provides, instance_of
from zope.interface import implementer from zope.interface import implementer
from automat import MethodicalMachine from automat import MethodicalMachine
from . import _interfaces from . import _interfaces
from ._key import derive_phase_key, encrypt_data from ._key import derive_phase_key, encrypt_data
@attrs
@implementer(_interfaces.ISend) @implementer(_interfaces.ISend)
class Send(object): class Send(object):
_side = attrib(validator=instance_of(type(u"")))
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine() m = MethodicalMachine()
def __init__(self, side, timing):
self._side = side
self._timing = timing
def wire(self, mailbox): def wire(self, mailbox):
self._M = _interfaces.IMailbox(mailbox) self._M = _interfaces.IMailbox(mailbox)

View File

@ -1,6 +1,7 @@
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from .common import ServerBase from .common import ServerBase
from .. import wormhole from .. import wormhole
@ -26,3 +27,11 @@ class New(ServerBase, unittest.TestCase):
dg = Delegate() dg = Delegate()
w = wormhole.delegated_wormhole(APPID, self.relayurl, reactor, dg) w = wormhole.delegated_wormhole(APPID, self.relayurl, reactor, dg)
w.close() w.close()
@inlineCallbacks
def test_allocate(self):
w = wormhole.deferred_wormhole(APPID, self.relayurl, reactor)
code = yield w.when_code()
print("code:", code)
yield w.close()
test_allocate.timeout = 2