def test_endpoints(self): eq = EventualQueue(reactor) w1 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w2 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w1.allocate_code() code = yield w1.get_code() w2.set_code(code) yield doBoth(w1.get_verifier(), w2.get_verifier()) eps1 = w1.dilate() eps2 = w2.dilate() print("w.dilate ready") f0 = ReconF(eq) yield eps2.listen.listen(f0) from twisted.python import log f1 = ReconF(eq) log.msg("connecting") p1_client = yield eps1.connect.connect(f1) log.msg("sending c->s") p1_client.transport.write(b"hello from p1\n") data = yield f0.deferreds["dataReceived"] self.assertEqual(data, b"hello from p1\n") p1_server = self.successResultOf(f0.deferreds["connectionMade"]) log.msg("sending s->c") p1_server.transport.write(b"hello p1\n") log.msg("waiting for client to receive") data = yield f1.deferreds["dataReceived"] self.assertEqual(data, b"hello p1\n") # open a second channel f0.resetDeferred("connectionMade") f0.resetDeferred("dataReceived") f1.resetDeferred("dataReceived") f2 = ReconF(eq) p2_client = yield eps1.connect.connect(f2) p2_server = yield f0.deferreds["connectionMade"] p2_server.transport.write(b"hello p2\n") data = yield f2.deferreds["dataReceived"] self.assertEqual(data, b"hello p2\n") p2_client.transport.write(b"hello from p2\n") data = yield f0.deferreds["dataReceived"] self.assertEqual(data, b"hello from p2\n") self.assertNoResult(f1.deferreds["dataReceived"]) # now close the first subchannel (p1) from the listener side p1_server.transport.loseConnection() yield f0.deferreds["connectionLost"] yield f1.deferreds["connectionLost"] f0.resetDeferred("connectionLost") # and close the second from the connector side p2_client.transport.loseConnection() yield f0.deferreds["connectionLost"] yield f2.deferreds["connectionLost"] yield w1.close() yield w2.close()
def __init__(self, key, app_id=None): self.message_def = None self.key = key if not app_id: # the following id is needed for interoperability with wormhole cli app_id = "lothar.com/wormhole/text-or-file-xfer" self.w = wormhole.create(app_id, RENDEZVOUS_RELAY, reactor)
def test_full(self): eq = EventualQueue(reactor) w1 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w2 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w1.allocate_code() code = yield w1.get_code() print("code is: {}".format(code)) w2.set_code(code) yield doBoth(w1.get_verifier(), w2.get_verifier()) print("connected") eps1_d = w1.dilate() eps2_d = w2.dilate() (eps1, eps2) = yield doBoth(eps1_d, eps2_d) (control_ep1, connect_ep1, listen_ep1) = eps1 (control_ep2, connect_ep2, listen_ep2) = eps2 print("w.dilate ready") f1 = Factory() f1.protocol = L f1.d = Deferred() f1.d.addCallback(lambda data: eq.fire_eventually(data)) d1 = control_ep1.connect(f1) f2 = Factory() f2.protocol = L f2.d = Deferred() f2.d.addCallback(lambda data: eq.fire_eventually(data)) d2 = control_ep2.connect(f2) yield d1 yield d2 print("control endpoints connected") data1 = yield f1.d data2 = yield f2.d self.assertEqual(data1, b"hello\n") self.assertEqual(data2, b"hello\n") yield w1.close() yield w2.close()
def process_wormhole(self, nickname): w = wormhole.create(APPID, MAILBOX_URL, self.reactor) w.allocate_code() code = yield w.get_code() d = w.get_message() d.addCallback(self.got_message, nickname.decode('utf-8')) d.addCallback(self.send_provisioning_response, w) return code
def go(self): if self.args.tor: with self.args.timing.add("import", which="tor_manager"): from ..tor_manager import get_tor # For now, block everything until Tor has started. Soon: launch # tor in parallel with everything else, make sure the Tor object # can lazy-provide an endpoint, and overlap the startup process # with the user handing off the wormhole code self._tor = yield get_tor(self._reactor, self.args.launch_tor, self.args.tor_control_port, timing=self.args.timing) w = create(self.args.appid or APPID, self.args.relay_url, self._reactor, tor=self._tor, timing=self.args.timing) if self.args.debug_state: w.debug_set_trace("recv", which=" ".join(self.args.debug_state), file=self.args.stdout) self._w = w # so tests can wait on events too # I wanted to do this instead: # # try: # yield self._go(w, tor) # finally: # yield w.close() # # but when _go had a UsageError, the stacktrace was always displayed # as coming from the "yield self._go" line, which wasn't very useful # for tracking it down. d = self._go(w) # if we succeed, we should close and return the w.close results # (which might be an error) @inlineCallbacks def _good(res): yield w.close() # wait for ack returnValue(res) # if we raise an error, we should close and then return the original # error (the close might give us an error, but it isn't as important # as the original one) @inlineCallbacks def _bad(f): try: yield w.close() # might be an error too except Exception: pass returnValue(f) d.addCallbacks(_good, _bad) yield d
def go(self): if self.args.tor: with self.args.timing.add("import", which="tor_manager"): from ..tor_manager import TorManager self._tor_manager = TorManager(self._reactor, self.args.launch_tor, self.args.tor_control_port, timing=self.args.timing) if not self._tor_manager.tor_available(): raise NoTorError() # For now, block everything until Tor has started. Soon: launch # tor in parallel with everything else, make sure the TorManager # can lazy-provide an endpoint, and overlap the startup process # with the user handing off the wormhole code yield self._tor_manager.start() wh = CLIWelcomeHandler(self.args.relay_url, __version__, self.args.stderr) w = create(self.args.appid or APPID, self.args.relay_url, self._reactor, tor_manager=self._tor_manager, timing=self.args.timing, welcome_handler=wh.handle_welcome) # I wanted to do this instead: # # try: # yield self._go(w, tor_manager) # finally: # yield w.close() # # but when _go had a UsageError, the stacktrace was always displayed # as coming from the "yield self._go" line, which wasn't very useful # for tracking it down. d = self._go(w) # if we succeed, we should close and return the w.close results # (which might be an error) @inlineCallbacks def _good(res): yield w.close() # wait for ack returnValue(res) # if we raise an error, we should close and then return the original # error (the close might give us an error, but it isn't as important # as the original one) @inlineCallbacks def _bad(f): try: yield w.close() # might be an error too except: pass returnValue(f) d.addCallbacks(_good, _bad) yield d
def sendFile(path): w = wormhole.create(app_id, relay_url, reactor) w.allocate_code() code = yield w.get_code() yield w.get_unverified_key() print("path is {}".format(path)) print("code is {}".format(code)) w.send_message(b"outbound data") print("tttttt1") yield w.close() print("tttttt")
def test_control(self): eq = EventualQueue(reactor) w1 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w2 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w1.allocate_code() code = yield w1.get_code() print("code is: {}".format(code)) w2.set_code(code) yield doBoth(w1.get_verifier(), w2.get_verifier()) print("connected") eps1 = w1.dilate() eps2 = w2.dilate() print("w.dilate ready") f1 = Factory() f1.protocol = L f1.d = Deferred() f1.d.addCallback(lambda data: eq.fire_eventually(data)) d1 = eps1.control.connect(f1) f2 = Factory() f2.protocol = L f2.d = Deferred() f2.d.addCallback(lambda data: eq.fire_eventually(data)) d2 = eps2.control.connect(f2) yield d1 yield d2 print("control endpoints connected") # note: I'm making some horrible assumptions about one-to-one writes # and reads across a TCP stack that isn't obligated to maintain such # a relationship, but it's much easier than doing this properly. If # the tests ever start failing, do the extra work, probably by # using a twisted.protocols.basic.LineOnlyReceiver data1 = yield f1.d data2 = yield f2.d self.assertEqual(data1, b"hello\n") self.assertEqual(data2, b"hello\n") yield w1.close() yield w2.close()
def build_provisioning_response(self, nickname): w = wormhole.create(APPID, MAILBOX_URL, self.reactor) w.allocate_code() code = yield w.get_code() d = w.get_message() d.addCallback(self.got_message, nickname.decode('utf-8')) d.addCallback(self.send_provisioning_response, w) f = open(cosmosConfigFile(self.opts['home'])) html = yield flattenString(None, ResponseElement(f.read(), code, nickname)) defer.returnValue(html)
def run(reactor, opts): basedir = FilePath(os.path.expanduser(opts["basedir"])) controllerFurl = basedir.child("controller.furl").getContent() if not opts.subCommand: raise usage.UsageError("pick a command") so = opts.subOptions if opts.subCommand == "add-host": w = create(APPID, MAILBOX_URL, reactor) if so.code: w.set_code(so.code) else: input_with_completion("Invitation code: ", w.input_code(), reactor) yield w.get_code() furl = yield w.get_message() c = yield getController(reactor, controllerFurl) hostname = yield c.callRemote("accept_add_host", furl) print("hostname '%s' added" % hostname) print("if you want to configure a post-update hook, edit:") print(" %s" % basedir.child(hostname).child("post-update-hook").path) print("(and make it executable)") w.send_message("ok") yield w.close() if opts.subCommand == "add-dyndns": w = create(APPID, MAILBOX_URL, reactor) if so.code: w.set_code(so.code) else: input_with_completion("Invitation code: ", w.input_code(), reactor) yield w.get_code() furl = yield w.get_message() c = yield getController(reactor, controllerFurl) yield c.callRemote("accept_add_dyndns", furl) print("dyndns hostname added for this client") w.send_message("ok") yield w.close()
def __init__( self, app_id=APPID, rendezvous_relay=RENDEZVOUS_RELAY, transit_relay=TRANSIT_RELAY ): """ Create a magic wormhole. """ self.app_id = app_id self.rendezvous_relay = rendezvous_relay self.transit_relay = transit_relay self.wormhole = create(self.app_id, self.rendezvous_relay, reactor) self.offer = None self.transit = None
def run_client(reactor, o, pkeyFile): def cleanup(): try: # Delete the basedir if we failed shutil.rmtree(o['basedir']) except FileNotFoundError: pass try: # Try to initialize the client print("initializing ag-solo", o['basedir']) doInit(o) # read the pubkey out of BASEDIR/ag-cosmos-helper-address f = open(pkeyFile) pubkey = f.read() f.close() pubkey = pubkey.strip() # Use the provisioning code to register our pubkey. w = wormhole.create(APPID, MAILBOX_URL, reactor) # Ensure cleanup gets called before aborting t = reactor.addSystemEventTrigger("before", "shutdown", cleanup) yield wormhole.input_with_completion("Provisioning code: ", w.input_code(), reactor) reactor.removeSystemEventTrigger(t) cm = json.dumps({ "pubkey": pubkey, }) w.send_message(cm.encode("utf-8")) server_message = yield w.get_message() sm = json.loads(server_message.decode("utf-8")) print("server message is", sm) yield w.close() if not sm['ok']: raise Exception("error from server: " + sm['error']) BASEDIR = o['basedir'] setIngress(sm) except: cleanup() raise restart()
def send(wormhole_code, data, reactor): """ Send data over to receiver with matching wormhole code, then wait for ack. :param wormhole_code: matching wormhole code :param bytes data: data (``hpos-config.json`` contents) :param reactor: :py:mod:`twisted.internet.reactor` object """ w = wormhole.create(APP_ID, _relay_url(), reactor) w.set_code(wormhole_code) yield w.send_message(data) ack_message = yield w.get_message() assert ack_message == ACK_MESSAGE yield w.close()
def wormhole_reverse_send(): w = wormhole.create(WORMHOLE_APPID, WORMHOLE_RELAY_URL, reactor) w.allocate_code() code = yield w.get_code() subprocess.run([ 'wall', "wormhole send --code {} --text - < hpos-state.json".format(code) ]) message = yield w.get_message() message = json.loads(message)['offer']['message'] yield w.send_message(WORMHOLE_ACK) yield w.close() return message
def go(self): assert isinstance(self._args.relay_url, type(u"")) if self._args.tor: with self._timing.add("import", which="tor_manager"): from ..tor_manager import get_tor # For now, block everything until Tor has started. Soon: launch # tor in parallel with everything else, make sure the Tor object # can lazy-provide an endpoint, and overlap the startup process # with the user handing off the wormhole code self._tor = yield get_tor(reactor, self._args.launch_tor, self._args.tor_control_port, timing=self._timing) w = create(self._args.appid or APPID, self._args.relay_url, self._reactor, tor=self._tor, timing=self._timing) if self._args.debug_state: w.debug_set_trace("send", which=" ".join(self._args.debug_state), file=self._args.stdout) d = self._go(w) # if we succeed, we should close and return the w.close results # (which might be an error) @inlineCallbacks def _good(res): yield w.close() # wait for ack returnValue(res) # if we raise an error, we should close and then return the original # error (the close might give us an error, but it isn't as important # as the original one) @inlineCallbacks def _bad(f): try: yield w.close() # might be an error too except Exception: pass returnValue(f) d.addCallbacks(_good, _bad) yield d
def run_client(reactor, o, pubkey): w = wormhole.create(APPID, MAILBOX_URL, reactor) wormhole.input_with_completion("Provisioning code: ", w.input_code(), reactor) cm = json.dumps({ "pubkey": pubkey, }) w.send_message(cm.encode("utf-8")) server_message = yield w.get_message() sm = json.loads(server_message.decode("utf-8")) print("server message is", sm) yield w.close() if not sm['ok']: print("error from server:", sm['error']) return BASEDIR = o['basedir'] setIngressAndRestart(sm)
def send(self): """I send data through a wormhole and return True/False depending on whether or not the hash matched at the receive side. """ def _confirm(input_message): if input_message == 'Confirmed!': self.confirmed = True yield self.start_tor() self._w = wormhole.create(u'axotor', RENDEZVOUS_RELAY, self._reactor, tor=self._tor, timing=self._timing) self._w.set_code(self._code) self._w.send_message(self.data+h.sha256(self.data).hexdigest()) yield self._w.get_message().addCallback(_confirm) yield self._w.close() self._reactor.stop() return
def run_client(reactor, o, pubkey): w = wormhole.create(APPID, MAILBOX_URL, reactor) # FIXME: Handle SIGINT! wormhole.input_with_completion("Provisioning code: ", w.input_code(), reactor) cm = json.dumps({ "pubkey": pubkey, }) w.send_message(cm.encode("utf-8")) server_message = yield w.get_message() sm = json.loads(server_message.decode("utf-8")) print("server message is", sm) yield w.close() if not sm['ok']: print("error from server:", sm['error']) return BASEDIR = o['basedir'] subprocess.run([AG_SOLO, 'set-gci-ingress', '--chainID=%s' % sm['chainName'], sm['gci'], *sm['rpcAddrs']], check=True) os.execvp(AG_SOLO, [AG_SOLO, 'start', '--role=client'])
def open(self, code): logging.debug("open wormhole") assert self._wormhole is None self._wormhole = wormhole.create( appid=APPID, relay_url=public_relay.RENDEZVOUS_RELAY, reactor=self._reactor, delegate=self._wormhole_delegate, versions={"v0": {"mode": "connect"}}, ) self._transit = TransitProtocolPair( self._reactor, self._wormhole, self._transit_delegate ) if code is None or code == "": self._wormhole.allocate_code() else: self._wormhole.set_code(code)
def receive(self): """I receive data+hash, check for a match, confirm or not confirm to the sender, and return the data payload. """ def _receive(input_message): self.data = input_message[:-64] _hash = input_message[-64:] if h.sha256(self.data).hexdigest() == _hash: self._w.send_message('Confirmed!') else: self._w.send_message('Not Confirmed!') yield self.start_tor() self._w = wormhole.create(u'axotor', RENDEZVOUS_RELAY, self._reactor, tor=self._tor, timing=self._timing) self._w.set_code(self._code) yield self._w.get_message().addCallback(_receive) yield self._w.close() self._reactor.stop() return
def start(self): log.info("Wormhole: Trying to receive a message with code: %s", self.code) self.stop() self.w = wormhole.create(self.app_id, RENDEZVOUS_RELAY, reactor) # The following mod is required for Python 2 support self.w.set_code("%s" % str(self.code)) try: message = yield self.w.get_message() m = decode_message(message) key_data = None offer = m.get("offer", None) if offer: key_data = offer.get("message", None) if key_data: log.info("Message received: %s", key_data) if self._is_verified(key_data.encode("utf-8")): log.debug("MAC is valid") success = True message = "" # send a reply with a message ack, this also ensures wormhole cli interoperability reply = {"answer": {"message_ack": "ok"}} reply_encoded = encode_message(reply) self.w.send_message(reply_encoded) returnValue((key_data.encode("utf-8"), success, message)) else: log.warning("The received key has a different MAC") self._reply_error(_("Wrong message authentication code")) self._handle_failure(WrongPasswordError()) else: log.info("Unrecognized message: %s", m) self._reply_error("Unrecognized message") self._handle_failure(TransferError()) except WrongPasswordError as wpe: log.info("A wrong password has been used") self._handle_failure(wpe) except LonelyError as le: log.info("Closed the connection before we found anyone") self._handle_failure(le)
def receive(on_wormhole_code, reactor): """Allocate wormhole code, wait for sender, and receive incoming data. :param on_wormhole_code: callback that runs with allocated wormhole code once it's available :param reactor: :mod:`twisted.internet.reactor` object :return: data (``hpos-config.json`` contents) :rtype: bytes """ w = wormhole.create(APP_ID, _relay_url(), reactor) w.allocate_code() wormhole_code = yield w.get_code() yield on_wormhole_code(wormhole_code) data = yield w.get_message() yield w.send_message(ACK_MESSAGE) yield w.close() return data
def __init__(self, app_id=APPID, rendezvous_relay=RENDEZVOUS_RELAY, transit_relay=TRANSIT_RELAY): """ Create a magic wormhole. """ self.app_id = app_id self.rendezvous_relay = rendezvous_relay self.transit_relay = transit_relay try: self.wormhole = create(self.app_id, self.rendezvous_relay, reactor) except Exception: raise ConnectionError( ('Cannot connect to the rendezvous server. ' 'In case you are not using the default server, ' 'you can double-check the URL in the config.')) self.offer = None self.transit = None
def go(self): assert isinstance(self._args.relay_url, type(u"")) if self._args.tor: with self._timing.add("import", which="tor_manager"): from ..tor_manager import get_tor # For now, block everything until Tor has started. Soon: launch # tor in parallel with everything else, make sure the Tor object # can lazy-provide an endpoint, and overlap the startup process # with the user handing off the wormhole code self._tor = yield get_tor(reactor, self._args.launch_tor, self._args.tor_control_port, timing=self._timing) w = create(self._args.appid or APPID, self._args.relay_url, self._reactor, tor=self._tor, timing=self._timing) d = self._go(w) # if we succeed, we should close and return the w.close results # (which might be an error) @inlineCallbacks def _good(res): yield w.close() # wait for ack returnValue(res) # if we raise an error, we should close and then return the original # error (the close might give us an error, but it isn't as important # as the original one) @inlineCallbacks def _bad(f): try: yield w.close() # might be an error too except: pass returnValue(f) d.addCallbacks(_good, _bad) yield d
def run(reactor, opts): basedir = FilePath(os.path.expanduser(opts["basedir"])) controllerFurl = basedir.child("controller.furl").getContent() if not opts.subCommand: raise usage.UsageError("pick a command") so = opts.subOptions if opts.subCommand == "add-zone": c = yield getController(reactor, controllerFurl) resp = yield c.callRemote("add_zone", so.zone_name, so.server_hostname) print("zone '%s': %s" % (so.zone_name, resp)) return if opts.subCommand == "add-host": c = yield getController(reactor, controllerFurl) furl = yield c.callRemote("add_host", so.host_name) print("host '%s': %s" % (so.host_name, furl)) w = wormhole.create(APPID, MAILBOX_URL, reactor) w.allocate_code() code = yield w.get_code() print("") print( "Please run 'python -m flancer.client add-host' on your LAN-side machine" ) print("and provide the following invitation code:") print() print(" %s" % code) print() print("(waiting for invitation to be accepted...)") w.send_message(furl) ack = yield w.get_message() if ack == "ok": print("invitation accepted, certificate issued") else: print("error: %s" % ack) yield w.close() if opts.subCommand == "add-dyndns": c = yield getController(reactor, controllerFurl) resp = yield c.callRemote("add_dyndns", so.host_name) if not resp[0]: print("error: %s", resp[1]) returnValue(1) furl = resp[1] print("dyndns hostname '%s': %s" % (so.host_name, furl)) w = wormhole.create(APPID, MAILBOX_URL, reactor) w.allocate_code() code = yield w.get_code() print("") print( "Please run 'python -m flancer.client add-dyndns' on your LAN-side machine" ) print("and provide the following invitation code:") print() print(" %s" % code) print() print("(waiting for invitation to be accepted...)") w.send_message(furl) ack = yield w.get_message() if ack == "ok": print("invitation accepted, dyndns registered") else: print("error: %s" % ack) yield w.close()
def test_data_while_offline(self): eq = EventualQueue(reactor) w1 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w2 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w1.allocate_code() code = yield w1.get_code() w2.set_code(code) yield doBoth(w1.get_verifier(), w2.get_verifier()) eps1 = w1.dilate() eps2 = w2.dilate() print("w.dilate ready") f1 = ReconF(eq); f2 = ReconF(eq) d1 = eps1.control.connect(f1); d2 = eps2.control.connect(f2) yield d1 yield d2 protocols = {} def p_connected(p, index): protocols[index] = p msg = "hello from %s\n" % index p.transport.write(msg.encode("ascii")) f1.deferreds["connectionMade"].addCallback(p_connected, 1) f2.deferreds["connectionMade"].addCallback(p_connected, 2) data1 = yield f1.deferreds["dataReceived"] data2 = yield f2.deferreds["dataReceived"] self.assertEqual(data1, b"hello from 2\n") self.assertEqual(data2, b"hello from 1\n") # the ACKs are now in flight and may not arrive before we kill the # connection f1.resetDeferred("connectionMade") f2.resetDeferred("connectionMade") d1 = f1.resetDeferred("dataReceived") d2 = f2.resetDeferred("dataReceived") # switch off connections assert w1._boss._D._manager._debug_stall_connector == False cd1 = Deferred(); cd2 = Deferred() w1._boss._D._manager._debug_stall_connector = cd1.callback w2._boss._D._manager._debug_stall_connector = cd2.callback # now we reach inside and drop the connection sc = protocols[1].transport orig_connection = sc._manager._connection orig_connection.disconnect() c1 = yield cd1 c2 = yield cd2 assert IDilationConnector.providedBy(c1) assert IDilationConnector.providedBy(c2) assert c1 is not orig_connection w1._boss._D._manager._debug_stall_connector = False w2._boss._D._manager._debug_stall_connector = False # now write some data while the connection is definitely offline protocols[1].transport.write(b"more 1->2\n") protocols[2].transport.write(b"more 2->1\n") # allow the connections to proceed c1.start() c2.start() # and wait for the data to arrive data2 = yield d2 self.assertEqual(data2, b"more 1->2\n") data1 = yield d1 self.assertEqual(data1, b"more 2->1\n") # the application-visible Protocol should not observe the # interruption self.assertNoResult(f1.deferreds["connectionMade"]) self.assertNoResult(f2.deferreds["connectionMade"]) self.assertNoResult(f1.deferreds["connectionLost"]) self.assertNoResult(f2.deferreds["connectionLost"]) yield w1.close() yield w2.close()
def test_reconnect(self): eq = EventualQueue(reactor) w1 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w2 = wormhole.create(APPID, self.relayurl, reactor, _enable_dilate=True) w1.allocate_code() code = yield w1.get_code() w2.set_code(code) yield doBoth(w1.get_verifier(), w2.get_verifier()) eps1 = w1.dilate() eps2 = w2.dilate() print("w.dilate ready") f1 = ReconF(eq); f2 = ReconF(eq) d1 = eps1.control.connect(f1); d2 = eps2.control.connect(f2) yield d1 yield d2 protocols = {} def p_connected(p, index): protocols[index] = p msg = "hello from %s\n" % index p.transport.write(msg.encode("ascii")) f1.deferreds["connectionMade"].addCallback(p_connected, 1) f2.deferreds["connectionMade"].addCallback(p_connected, 2) data1 = yield f1.deferreds["dataReceived"] data2 = yield f2.deferreds["dataReceived"] self.assertEqual(data1, b"hello from 2\n") self.assertEqual(data2, b"hello from 1\n") # the ACKs are now in flight and may not arrive before we kill the # connection f1.resetDeferred("connectionMade") f2.resetDeferred("connectionMade") d1 = f1.resetDeferred("dataReceived") d2 = f2.resetDeferred("dataReceived") # now we reach inside and drop the connection sc = protocols[1].transport orig_connection = sc._manager._connection orig_connection.disconnect() # stall until the connection has been replaced yield poll_until(lambda: sc._manager._connection and (orig_connection != sc._manager._connection)) # now write some more data, which should travel over the new # connection protocols[1].transport.write(b"more\n") data2 = yield d2 self.assertEqual(data2, b"more\n") replacement_connection = sc._manager._connection self.assertNotEqual(orig_connection, replacement_connection) # the application-visible Protocol should not observe the # interruption self.assertNoResult(f1.deferreds["connectionMade"]) self.assertNoResult(f2.deferreds["connectionMade"]) self.assertNoResult(f1.deferreds["connectionLost"]) self.assertNoResult(f2.deferreds["connectionLost"]) yield w1.close() yield w2.close()
def receiveFile(code): w = wormhole.create(app_id, relay_url, reactor) w.set_code(code) inbound = yield w.get_message() yield w.close() defer.returnValue("file received")