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}
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 attr import attrs, attrib
from attr.validators import provides, instance_of
@ -29,7 +30,7 @@ class Boss(object):
self._M = Mailbox(self._side)
self._S = Send(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._RC = RendezvousConnector(self._url, self._appid, self._side,
self._reactor, self._journal,
@ -92,6 +93,10 @@ class Boss(object):
@m.input()
def close(self): pass
# from RendezvousConnector
@m.input()
def rx_welcome(self, welcome): pass
# from Code (provoked by input/allocate/set_code)
@m.input()
def got_code(self, code): pass
@ -121,6 +126,10 @@ class Boss(object):
def closed(self): pass
@m.output()
def process_welcome(self, welcome):
pass # TODO: ignored for now
@m.output()
def do_got_code(self, code):
nameplate = code.split("-")[0]
@ -167,18 +176,22 @@ class Boss(object):
S0_empty.upon(close, enter=S3_closing, outputs=[close_lonely])
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])
S1_lonely.upon(rx_welcome, enter=S1_lonely, outputs=[process_welcome])
S1_lonely.upon(happy, enter=S2_happy, outputs=[])
S1_lonely.upon(scared, enter=S3_closing, outputs=[close_scared])
S1_lonely.upon(close, enter=S3_closing, outputs=[close_lonely])
S1_lonely.upon(send, enter=S1_lonely, outputs=[S_send])
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_version, enter=S2_happy, outputs=[process_version])
S2_happy.upon(scared, enter=S3_closing, outputs=[close_scared])
S2_happy.upon(close, enter=S3_closing, outputs=[close_happy])
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_version, 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(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_version, 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
from zope.interface import implementer
from attr import attrs, attrib
@ -127,5 +128,14 @@ class Code(object):
outputs=[stash_nameplates])
S2_typing_nameplate.upon(hyphen, enter=S3_typing_code,
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(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 zope.interface import implementer
from attr import attrs, attrib
from attr.validators import provides
from attr.validators import provides, instance_of
from spake2 import SPAKE2_Symmetric
from hkdf import Hkdf
from nacl.secret import SecretBox
@ -53,6 +54,7 @@ def encrypt_data(key, plaintext):
@attrs
@implementer(_interfaces.IKey)
class Key(object):
_appid = attrib(validator=instance_of(type(u"")))
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
from zope.interface import implementer
from attr import attrs, attrib
from attr.validators import instance_of
@ -10,7 +11,7 @@ class Mailbox(object):
_side = attrib(validator=instance_of(type(u"")))
m = MethodicalMachine()
def __init__(self):
def __attrs_post_init__(self):
self._mood = None
self._nameplate = None
self._mailbox = None
@ -129,7 +130,7 @@ class Mailbox(object):
@m.output()
def record_nameplate_and_RC_tx_claim(self, nameplate):
self._nameplate = nameplate
self._RX.tx_claim(self._nameplate)
self._RC.tx_claim(self._nameplate)
@m.output()
def RC_tx_claim(self):
# 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])
ScA.upon(connected, enter=ScB, outputs=[RC_tx_close])
SsB.upon(lost, enter=SsB, outputs=[])
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 automat import MethodicalMachine
from . import _interfaces
@ -5,8 +6,7 @@ from . import _interfaces
@implementer(_interfaces.INameplateLister)
class NameplateListing(object):
m = MethodicalMachine()
def __init__(self):
pass
def wire(self, rendezvous_connector, code):
self._RC = _interfaces.IRendezvousConnector(rendezvous_connector)
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 attr import attrs, attrib
from attr.validators import provides, instance_of
@ -11,7 +12,7 @@ class Order(object):
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()
def __init__(self):
def __attrs_post_init__(self):
self._key = None
self._queue = []
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 attr import attrs, attrib
from attr.validators import provides, instance_of
@ -12,7 +13,7 @@ class Receive(object):
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()
def __init__(self):
def __attrs_post_init__(self):
self._key = None
def wire(self, boss, key, send):

View File

@ -1,3 +1,4 @@
from __future__ import print_function, absolute_import, unicode_literals
import os
from six.moves.urllib_parse import urlparse
from attr import attrs, attrib
@ -27,7 +28,12 @@ class WSClient(websocket.WebSocketClientProtocol):
def onMessage(self, payload, isBinary):
#print("onMessage")
assert not isBinary
self._RC.ws_message(payload)
try:
self._RC.ws_message(payload)
except:
print("LOGGING")
log.err()
raise
def onClose(self, wasClean, code, reason):
#print("onClose")
@ -60,6 +66,7 @@ class RendezvousConnector(object):
_reactor = attrib()
_journal = attrib(validator=provides(_interfaces.IJournal))
_timing = attrib(validator=provides(_interfaces.ITiming))
DEBUG = False
def __attrs_post_init__(self):
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 automat import MethodicalMachine
from . import _interfaces
from ._key import derive_phase_key, encrypt_data
@attrs
@implementer(_interfaces.ISend)
class Send(object):
_side = attrib(validator=instance_of(type(u"")))
_timing = attrib(validator=provides(_interfaces.ITiming))
m = MethodicalMachine()
def __init__(self, side, timing):
self._side = side
self._timing = timing
def wire(self, mailbox):
self._M = _interfaces.IMailbox(mailbox)

View File

@ -1,6 +1,7 @@
from __future__ import print_function, unicode_literals
from twisted.trial import unittest
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from .common import ServerBase
from .. import wormhole
@ -26,3 +27,11 @@ class New(ServerBase, unittest.TestCase):
dg = Delegate()
w = wormhole.delegated_wormhole(APPID, self.relayurl, reactor, dg)
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