2016-06-04 06:07:50 +00:00
|
|
|
from __future__ import print_function, absolute_import, unicode_literals
|
2017-02-24 01:29:56 +00:00
|
|
|
import os, sys
|
2017-02-23 23:57:24 +00:00
|
|
|
from attr import attrs, attrib
|
2017-02-24 01:29:56 +00:00
|
|
|
from zope.interface import implementer
|
2017-03-03 07:55:59 +00:00
|
|
|
from twisted.python import failure
|
2017-02-24 01:29:56 +00:00
|
|
|
from twisted.internet import defer
|
|
|
|
from ._interfaces import IWormhole
|
|
|
|
from .util import bytes_to_hexstr
|
2017-02-23 01:02:01 +00:00
|
|
|
from .timing import DebugTiming
|
2017-02-22 20:51:53 +00:00
|
|
|
from .journal import ImmediateJournal
|
2017-03-03 07:55:59 +00:00
|
|
|
from ._boss import Boss
|
2017-03-04 09:55:42 +00:00
|
|
|
from ._key import derive_key
|
2017-04-03 21:23:03 +00:00
|
|
|
from .errors import NoKeyError, WormholeClosed
|
2017-03-04 09:55:42 +00:00
|
|
|
from .util import to_bytes
|
2016-05-21 01:49:20 +00:00
|
|
|
|
2017-02-23 23:57:24 +00:00
|
|
|
# We can provide different APIs to different apps:
|
|
|
|
# * Deferreds
|
2017-05-12 20:12:36 +00:00
|
|
|
# w.get_code().addCallback(print_code)
|
|
|
|
# w.send_message(data)
|
|
|
|
# w.get_message().addCallback(got_data)
|
2017-02-23 23:57:24 +00:00
|
|
|
# w.close().addCallback(closed)
|
|
|
|
|
|
|
|
# * delegate callbacks (better for journaled environments)
|
|
|
|
# w = wormhole(delegate=app)
|
2017-05-12 20:12:36 +00:00
|
|
|
# w.send_message(data)
|
2017-02-23 23:57:24 +00:00
|
|
|
# app.wormhole_got_code(code)
|
2017-02-24 01:29:56 +00:00
|
|
|
# app.wormhole_got_verifier(verifier)
|
2017-05-12 20:12:36 +00:00
|
|
|
# app.wormhole_got_versions(versions)
|
|
|
|
# app.wormhole_got_message(data)
|
2017-02-23 23:57:24 +00:00
|
|
|
# w.close()
|
|
|
|
# app.wormhole_closed()
|
|
|
|
#
|
|
|
|
# * potential delegate options
|
|
|
|
# wormhole(delegate=app, delegate_prefix="wormhole_",
|
|
|
|
# delegate_args=(args, kwargs))
|
|
|
|
|
|
|
|
@attrs
|
2017-02-24 01:29:56 +00:00
|
|
|
@implementer(IWormhole)
|
2017-02-23 23:57:24 +00:00
|
|
|
class _DelegatedWormhole(object):
|
|
|
|
_delegate = attrib()
|
|
|
|
|
2017-03-04 09:55:42 +00:00
|
|
|
def __attrs_post_init__(self):
|
|
|
|
self._key = None
|
|
|
|
|
2017-02-23 23:57:24 +00:00
|
|
|
def _set_boss(self, boss):
|
|
|
|
self._boss = boss
|
|
|
|
|
|
|
|
# from above
|
2017-02-24 02:23:55 +00:00
|
|
|
|
|
|
|
def allocate_code(self, code_length=2):
|
|
|
|
self._boss.allocate_code(code_length)
|
2017-04-19 02:49:50 +00:00
|
|
|
def input_code(self):
|
|
|
|
return self._boss.input_code()
|
2017-02-24 02:23:55 +00:00
|
|
|
def set_code(self, code):
|
|
|
|
self._boss.set_code(code)
|
|
|
|
|
2017-04-06 19:27:06 +00:00
|
|
|
## def serialize(self):
|
|
|
|
## s = {"serialized_wormhole_version": 1,
|
|
|
|
## "boss": self._boss.serialize(),
|
|
|
|
## }
|
|
|
|
## return s
|
2017-03-03 22:19:48 +00:00
|
|
|
|
2017-05-12 20:12:36 +00:00
|
|
|
def send_message(self, plaintext):
|
2017-02-24 01:29:56 +00:00
|
|
|
self._boss.send(plaintext)
|
2017-03-04 09:55:42 +00:00
|
|
|
|
|
|
|
def derive_key(self, purpose, length):
|
|
|
|
"""Derive a new key from the established wormhole channel for some
|
|
|
|
other purpose. This is a deterministic randomized function of the
|
|
|
|
session key and the 'purpose' string (unicode/py3-string). This
|
|
|
|
cannot be called until when_verifier() has fired, nor after close()
|
|
|
|
was called.
|
|
|
|
"""
|
|
|
|
if not isinstance(purpose, type("")): raise TypeError(type(purpose))
|
|
|
|
if not self._key: raise NoKeyError()
|
|
|
|
return derive_key(self._key, to_bytes(purpose), length)
|
|
|
|
|
2017-02-23 23:57:24 +00:00
|
|
|
def close(self):
|
|
|
|
self._boss.close()
|
|
|
|
|
2017-04-19 02:49:34 +00:00
|
|
|
def debug_set_trace(self, client_name, which="B N M S O K SK R RC L C T",
|
2017-04-05 04:03:34 +00:00
|
|
|
file=sys.stderr):
|
|
|
|
self._boss._set_trace(client_name, which, file)
|
2017-03-02 03:55:13 +00:00
|
|
|
|
2017-02-23 23:57:24 +00:00
|
|
|
# from below
|
2017-05-12 20:12:36 +00:00
|
|
|
def got_welcome(self, welcome):
|
|
|
|
self._delegate.wormhole_got_welcome(welcome)
|
2017-02-23 23:57:24 +00:00
|
|
|
def got_code(self, code):
|
2017-05-12 20:12:36 +00:00
|
|
|
self._delegate.wormhole_got_code(code)
|
2017-03-04 09:55:42 +00:00
|
|
|
def got_key(self, key):
|
2017-05-12 20:12:36 +00:00
|
|
|
self._delegate.wormhole_got_unverified_key(key)
|
2017-03-04 09:55:42 +00:00
|
|
|
self._key = key # for derive_key()
|
2017-02-23 23:57:24 +00:00
|
|
|
def got_verifier(self, verifier):
|
2017-05-12 20:12:36 +00:00
|
|
|
self._delegate.wormhole_got_verifier(verifier)
|
|
|
|
def got_versions(self, versions):
|
|
|
|
self._delegate.wormhole_got_versions(versions)
|
2017-02-24 02:23:55 +00:00
|
|
|
def received(self, plaintext):
|
2017-05-12 20:12:36 +00:00
|
|
|
self._delegate.wormhole_got_message(plaintext)
|
2017-02-23 23:57:24 +00:00
|
|
|
def closed(self, result):
|
|
|
|
self._delegate.wormhole_closed(result)
|
|
|
|
|
2017-02-24 01:29:56 +00:00
|
|
|
@implementer(IWormhole)
|
2017-02-23 23:57:24 +00:00
|
|
|
class _DeferredWormhole(object):
|
2017-02-23 02:21:47 +00:00
|
|
|
def __init__(self):
|
2017-05-12 20:12:36 +00:00
|
|
|
self._welcome = None
|
|
|
|
self._welcome_observers = []
|
2017-02-23 02:21:47 +00:00
|
|
|
self._code = None
|
|
|
|
self._code_observers = []
|
2017-03-04 09:55:42 +00:00
|
|
|
self._key = None
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
self._key_observers = []
|
2017-02-23 02:21:47 +00:00
|
|
|
self._verifier = None
|
|
|
|
self._verifier_observers = []
|
2017-03-07 11:34:36 +00:00
|
|
|
self._versions = None
|
2017-03-04 10:36:19 +00:00
|
|
|
self._version_observers = []
|
2017-02-24 02:23:55 +00:00
|
|
|
self._received_data = []
|
|
|
|
self._received_observers = []
|
2017-03-07 11:09:06 +00:00
|
|
|
self._observer_result = None
|
2017-03-04 22:05:52 +00:00
|
|
|
self._closed_result = None
|
2017-02-25 02:30:00 +00:00
|
|
|
self._closed_observers = []
|
2017-02-23 02:21:47 +00:00
|
|
|
|
|
|
|
def _set_boss(self, boss):
|
|
|
|
self._boss = boss
|
|
|
|
|
|
|
|
# from above
|
2017-05-12 20:12:36 +00:00
|
|
|
def get_code(self):
|
2017-03-07 11:09:06 +00:00
|
|
|
# TODO: consider throwing error unless one of allocate/set/input_code
|
2017-04-07 02:44:27 +00:00
|
|
|
# was called first. It's legit to grab the Deferred before triggering
|
|
|
|
# the process that will cause it to fire, but forbidding that
|
|
|
|
# ordering would make it easier to cause programming errors that
|
|
|
|
# forget to trigger it entirely.
|
2017-03-07 11:09:06 +00:00
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
|
|
|
if self._code is not None:
|
2017-02-23 02:21:47 +00:00
|
|
|
return defer.succeed(self._code)
|
|
|
|
d = defer.Deferred()
|
|
|
|
self._code_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
2017-05-12 20:12:36 +00:00
|
|
|
def get_welcome(self):
|
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
|
|
|
if self._welcome is not None:
|
|
|
|
return defer.succeed(self._welcome)
|
|
|
|
d = defer.Deferred()
|
|
|
|
self._welcome_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def get_unverified_key(self):
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
|
|
|
if self._key is not None:
|
|
|
|
return defer.succeed(self._key)
|
|
|
|
d = defer.Deferred()
|
|
|
|
self._key_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
2017-05-12 20:12:36 +00:00
|
|
|
def get_verifier(self):
|
2017-03-07 11:09:06 +00:00
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
|
|
|
if self._verifier is not None:
|
2017-02-23 02:21:47 +00:00
|
|
|
return defer.succeed(self._verifier)
|
|
|
|
d = defer.Deferred()
|
|
|
|
self._verifier_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
2017-05-12 20:12:36 +00:00
|
|
|
def get_versions(self):
|
2017-03-07 11:09:06 +00:00
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
2017-03-07 11:34:36 +00:00
|
|
|
if self._versions is not None:
|
|
|
|
return defer.succeed(self._versions)
|
2017-03-04 10:36:19 +00:00
|
|
|
d = defer.Deferred()
|
|
|
|
self._version_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
2017-05-12 20:12:36 +00:00
|
|
|
def get_message(self):
|
2017-03-07 11:09:06 +00:00
|
|
|
if self._observer_result is not None:
|
|
|
|
return defer.fail(self._observer_result)
|
2017-02-24 02:23:55 +00:00
|
|
|
if self._received_data:
|
|
|
|
return defer.succeed(self._received_data.pop(0))
|
|
|
|
d = defer.Deferred()
|
|
|
|
self._received_observers.append(d)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def allocate_code(self, code_length=2):
|
|
|
|
self._boss.allocate_code(code_length)
|
2017-03-19 22:09:26 +00:00
|
|
|
def input_code(self):
|
|
|
|
return self._boss.input_code()
|
2017-02-24 02:23:55 +00:00
|
|
|
def set_code(self, code):
|
|
|
|
self._boss.set_code(code)
|
|
|
|
|
2017-03-03 22:19:48 +00:00
|
|
|
# no .serialize in Deferred-mode
|
2017-05-12 20:12:36 +00:00
|
|
|
|
|
|
|
def send_message(self, plaintext):
|
2017-02-24 01:29:56 +00:00
|
|
|
self._boss.send(plaintext)
|
2017-03-04 09:55:42 +00:00
|
|
|
|
|
|
|
def derive_key(self, purpose, length):
|
|
|
|
"""Derive a new key from the established wormhole channel for some
|
|
|
|
other purpose. This is a deterministic randomized function of the
|
|
|
|
session key and the 'purpose' string (unicode/py3-string). This
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
cannot be called until when_verified() has fired, nor after close()
|
2017-03-04 09:55:42 +00:00
|
|
|
was called.
|
|
|
|
"""
|
|
|
|
if not isinstance(purpose, type("")): raise TypeError(type(purpose))
|
|
|
|
if not self._key: raise NoKeyError()
|
|
|
|
return derive_key(self._key, to_bytes(purpose), length)
|
|
|
|
|
2017-02-23 02:21:47 +00:00
|
|
|
def close(self):
|
2017-03-03 07:55:59 +00:00
|
|
|
# fails with WormholeError unless we established a connection
|
|
|
|
# (state=="happy"). Fails with WrongPasswordError (a subclass of
|
|
|
|
# WormholeError) if state=="scary".
|
2017-03-04 22:05:52 +00:00
|
|
|
if self._closed_result:
|
|
|
|
return defer.succeed(self._closed_result) # maybe Failure
|
2017-02-25 02:30:00 +00:00
|
|
|
d = defer.Deferred()
|
|
|
|
self._closed_observers.append(d)
|
2017-03-07 11:09:06 +00:00
|
|
|
self._boss.close() # only need to close if it wasn't already
|
2017-02-25 02:30:00 +00:00
|
|
|
return d
|
2017-02-23 02:21:47 +00:00
|
|
|
|
2017-04-19 02:49:34 +00:00
|
|
|
def debug_set_trace(self, client_name, which="B N M S O K SK R RC L C T",
|
2017-04-05 04:03:34 +00:00
|
|
|
file=sys.stderr):
|
|
|
|
self._boss._set_trace(client_name, which, file)
|
2017-03-02 03:55:13 +00:00
|
|
|
|
2017-02-23 02:21:47 +00:00
|
|
|
# from below
|
2017-05-12 20:12:36 +00:00
|
|
|
def got_welcome(self, welcome):
|
|
|
|
self._welcome = welcome
|
|
|
|
for d in self._welcome_observers:
|
|
|
|
d.callback(welcome)
|
|
|
|
self._welcome_observers[:] = []
|
2017-02-23 02:21:47 +00:00
|
|
|
def got_code(self, code):
|
|
|
|
self._code = code
|
|
|
|
for d in self._code_observers:
|
|
|
|
d.callback(code)
|
|
|
|
self._code_observers[:] = []
|
2017-03-04 09:55:42 +00:00
|
|
|
def got_key(self, key):
|
|
|
|
self._key = key # for derive_key()
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
for d in self._key_observers:
|
|
|
|
d.callback(key)
|
|
|
|
self._key_observers[:] = []
|
2017-05-12 20:12:36 +00:00
|
|
|
|
2017-02-23 02:21:47 +00:00
|
|
|
def got_verifier(self, verifier):
|
|
|
|
self._verifier = verifier
|
|
|
|
for d in self._verifier_observers:
|
|
|
|
d.callback(verifier)
|
|
|
|
self._verifier_observers[:] = []
|
2017-05-12 20:12:36 +00:00
|
|
|
def got_versions(self, versions):
|
2017-03-07 11:34:36 +00:00
|
|
|
self._versions = versions
|
2017-03-04 10:36:19 +00:00
|
|
|
for d in self._version_observers:
|
2017-03-07 11:34:36 +00:00
|
|
|
d.callback(versions)
|
2017-03-04 10:36:19 +00:00
|
|
|
self._version_observers[:] = []
|
2017-02-23 02:21:47 +00:00
|
|
|
|
2017-02-24 02:23:55 +00:00
|
|
|
def received(self, plaintext):
|
|
|
|
if self._received_observers:
|
|
|
|
self._received_observers.pop(0).callback(plaintext)
|
|
|
|
return
|
|
|
|
self._received_data.append(plaintext)
|
2017-02-23 02:21:47 +00:00
|
|
|
|
|
|
|
def closed(self, result):
|
2017-05-12 20:12:36 +00:00
|
|
|
#print("closed", result, type(result), file=sys.stderr)
|
2017-03-03 07:55:59 +00:00
|
|
|
if isinstance(result, Exception):
|
2017-03-07 11:09:06 +00:00
|
|
|
self._observer_result = self._closed_result = failure.Failure(result)
|
2017-02-25 02:30:00 +00:00
|
|
|
else:
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
# pending w.key()/w.verify()/w.version()/w.read() get an error
|
2017-03-07 11:09:06 +00:00
|
|
|
self._observer_result = WormholeClosed(result)
|
2017-03-03 07:55:59 +00:00
|
|
|
# but w.close() only gets error if we're unhappy
|
2017-03-04 22:05:52 +00:00
|
|
|
self._closed_result = result
|
2017-05-12 20:12:36 +00:00
|
|
|
for d in self._welcome_observers:
|
|
|
|
d.errback(self._observer_result)
|
2017-04-23 19:30:46 +00:00
|
|
|
for d in self._code_observers:
|
|
|
|
d.errback(self._observer_result)
|
add w.when_key(), fix w.when_verified() to fire later
Previously, w.when_verified() was documented to fire only after a valid
encrypted message was received, but in fact it fired as soon as the shared
key was derived (before any encrypted messages are seen, so no actual
"verification" could occur yet).
This fixes that, and also adds a new w.when_key() API call which fires at the
earlier point. Having something which fires early is useful for the CLI
commands that want to print a pacifier message when the peer is responding
slowly. In particular it helps detect the case where 'wormhole send' has quit
early (after depositing the PAKE message on the server, but before the
receiver has started). In this case, the receiver will compute the shared
key, but then wait forever hoping for a VERSION that will never come. By
starting a timer when w.when_key() fires, and cancelling it when
w.when_verified() fires, we have a good place to tell the user that something
is taking longer than it should have.
This shifts responsibility for notifying Boss.got_verifier, out of Key and
into Receive, since Receive is what notices the first valid encrypted
message. It also shifts the Boss's ordering expectations: it now receives
B.happy() before B.got_verifier(), and consequently got_verifier ought to
arrive in the S2_happy state rather than S1_lonely.
2017-04-07 01:27:41 +00:00
|
|
|
for d in self._key_observers:
|
|
|
|
d.errback(self._observer_result)
|
2017-02-25 02:30:00 +00:00
|
|
|
for d in self._verifier_observers:
|
2017-03-07 11:09:06 +00:00
|
|
|
d.errback(self._observer_result)
|
2017-03-04 10:36:19 +00:00
|
|
|
for d in self._version_observers:
|
2017-03-07 11:09:06 +00:00
|
|
|
d.errback(self._observer_result)
|
2017-02-25 02:30:00 +00:00
|
|
|
for d in self._received_observers:
|
2017-03-07 11:09:06 +00:00
|
|
|
d.errback(self._observer_result)
|
2017-02-25 02:30:00 +00:00
|
|
|
for d in self._closed_observers:
|
2017-03-04 22:05:52 +00:00
|
|
|
d.callback(self._closed_result)
|
2017-02-23 02:21:47 +00:00
|
|
|
|
2017-03-04 11:43:42 +00:00
|
|
|
|
2017-04-06 19:09:24 +00:00
|
|
|
def create(appid, relay_url, reactor, # use keyword args for everything else
|
|
|
|
versions={},
|
2017-05-23 07:45:02 +00:00
|
|
|
delegate=None, journal=None, tor=None,
|
2017-05-12 20:12:36 +00:00
|
|
|
timing=None,
|
2017-03-04 11:43:42 +00:00
|
|
|
stderr=sys.stderr):
|
2016-05-23 01:40:44 +00:00
|
|
|
timing = timing or DebugTiming()
|
2017-02-23 02:21:47 +00:00
|
|
|
side = bytes_to_hexstr(os.urandom(5))
|
|
|
|
journal = journal or ImmediateJournal()
|
2017-02-23 23:57:24 +00:00
|
|
|
if delegate:
|
|
|
|
w = _DelegatedWormhole(delegate)
|
|
|
|
else:
|
|
|
|
w = _DeferredWormhole()
|
2017-03-07 11:34:36 +00:00
|
|
|
wormhole_versions = {} # will be used to indicate Wormhole capabilities
|
|
|
|
wormhole_versions["app_versions"] = versions # app-specific capabilities
|
|
|
|
b = Boss(w, side, relay_url, appid, wormhole_versions,
|
2017-05-23 07:45:02 +00:00
|
|
|
reactor, journal, tor, timing)
|
2017-02-23 02:21:47 +00:00
|
|
|
w._set_boss(b)
|
|
|
|
b.start()
|
2016-05-21 01:49:20 +00:00
|
|
|
return w
|
|
|
|
|
2017-04-06 19:27:06 +00:00
|
|
|
## def from_serialized(serialized, reactor, delegate,
|
2017-05-23 07:45:02 +00:00
|
|
|
## journal=None, tor=None,
|
2017-04-06 19:27:06 +00:00
|
|
|
## timing=None, stderr=sys.stderr):
|
|
|
|
## assert serialized["serialized_wormhole_version"] == 1
|
|
|
|
## timing = timing or DebugTiming()
|
|
|
|
## w = _DelegatedWormhole(delegate)
|
|
|
|
## # now unpack state machines, including the SPAKE2 in Key
|
|
|
|
## b = Boss.from_serialized(w, serialized["boss"], reactor, journal, timing)
|
|
|
|
## w._set_boss(b)
|
|
|
|
## b.start() # ??
|
|
|
|
## raise NotImplemented
|
|
|
|
## # should the new Wormhole call got_code? only if it wasn't called before.
|