def test_bad_hints(self): self.tubA = Tub() self.tubA.startService() self.services.append(self.tubA) self.tubB = Tub() self.tubB.startService() self.services.append(self.tubB) portnum = allocate_tcp_port() self.tubB.listenOn("tcp:%d:interface=127.0.0.1" % portnum) bad1 = "no-colon" bad2 = "unknown:foo" bad3 = "tcp:300.300.300.300:333" self.tubB.setLocation(bad1, bad2, bad3) target = HelperTarget("bob") url = self.tubB.registerReference(target) rc = self.tubA.connectTo(url, None) ri = rc.getReconnectionInfo() self.assertEqual(ri.state, "connecting") yield self.poll(lambda: rc.getReconnectionInfo().state != "connecting") # now look at the details ri = rc.getReconnectionInfo() self.assertEqual(ri.state, "waiting") ci = ri.connectionInfo self.assertEqual(ci.connected, False) self.assertEqual(ci.winningHint, None) s = ci.connectorStatuses self.assertEqual(set(s.keys()), set([bad1, bad2, bad3])) self.assertEqual(s[bad1], "bad hint: no colon") self.assertEqual(s[bad2], "bad hint: no handler registered") self.assertIn("DNS lookup failed", s[bad3]) ch = ci.connectionHandlers self.assertEqual(ch, {bad2: None, bad3: "tcp"})
def test_wait_for_brokers(self): """ The L{Deferred} returned by L{Tub.stopService} fires only after the L{Broker} connections belonging to the L{Tub} have disconnected. """ tub = Tub() tub.startService() another_tub = Tub() another_tub.startService() brokers = list(tub.brokerClass(None) for i in range(3)) for n, b in enumerate(brokers): b.makeConnection(StringTransport()) ref = SturdyRef(encode_furl(another_tub.tubID, [], str(n))) tub.brokerAttached(ref, b, isClient=(n % 2)==1) stopping = tub.stopService() d = flushEventualQueue() def event(ignored): self.assertNoResult(stopping) for b in brokers: b.connectionLost(failure.Failure(Exception("Connection lost"))) return flushEventualQueue() d.addCallback(event) def connectionsLost(ignored): self.successResultOf(stopping) d.addCallback(connectionsLost) return d
def testAuthenticated(self): url, portnum = self.makeServer() client = Tub() client.startService() self.services.append(client) d = client.getReference(url) return d
def test_cancel_pending_deliveries(self): # when a Tub is stopped, any deliveries that were pending should be # discarded. TubA sends remote_one+remote_two (and we hope they # arrive in the same chunk). TubB responds to remote_one by shutting # down. remote_two should be discarded. The bug was that remote_two # would cause an unhandled error on the TubB side. self.tubA = Tub() self.tubB = Tub() self.tubA.startService() self.tubB.startService() self.tubB.listenOn("tcp:0") d = self.tubB.setLocationAutomatically() r = Receiver(self.tubB) d.addCallback(lambda res: self.tubB.registerReference(r)) d.addCallback(lambda furl: self.tubA.getReference(furl)) def _go(rref): # we want these two to get sent and received in the same hunk rref.callRemoteOnly("one") rref.callRemoteOnly("two") return r.done_d d.addCallback(_go) # let remote_two do its log.err before we move on to the next test d.addCallback(self.stall, 1.0) return d
def do_remote_command(command, *args, **kwargs): client = AnyConsensoProcess() client.start() furl = client.furl() tub = Tub() tub.startService() def got_error(err): print "Error while calling command remotely", err reactor.stop() def got_result(res): print(res) def got_remote(remote): d = remote.callRemote(command, *args, **kwargs) d.addCallback(got_result) d.addCallback(lambda res: reactor.stop()) d.addErrback(got_error) return d d = tub.getReference(furl) d.addCallback(got_remote) d.addErrback(got_error) reactor.run()
def test_unreachable(self): t = Tub() t.setServiceParent(self.s) # we call neither .listenOn nor .setLocation self.failUnlessEqual(t.locationHints, []) self.failUnlessRaises(NoLocationError, t.registerReference, Referenceable())
def setUp(self): if not crypto_available: raise unittest.SkipTest("crypto not available") self.services = [] for i in range(self.num_services): s = Tub() s.startService() self.services.append(s)
def run_command(config): c = dispatch_table[config.subCommand]() tub = Tub() d = defer.succeed(None) d.addCallback(lambda _ign: tub.startService()) d.addCallback(lambda _ign: tub.getReference(config.furl)) d.addCallback(c.run, config.subOptions) # might provide tub here d.addBoth(lambda res: tub.stopService().addCallback(lambda _ign: res)) return d
def _testNoConnection_1(self, res, url): self.services.remove(self.tub) client = Tub() client.startService() self.services.append(client) d = client.getReference(url) d.addCallbacks(lambda res: self.fail("this is supposed to fail"), self._testNoConnection_fail) return d
def testHalfAuthenticated2(self): if not crypto_available: raise unittest.SkipTest("crypto not available") url, portnum = self.makeServer(False) client = Tub() client.startService() self.services.append(client) d = client.getReference(url) return d
def test_certfile(self): fn = "test_tub.TestCertFile.certfile" t1 = Tub(certFile=fn) self.failUnless(os.path.exists(fn)) data1 = t1.getCertData() t2 = Tub(certFile=fn) data2 = t2.getCertData() self.failUnless(data1 == data2)
class FlappCommand(object): def __init__(self, furlfile): self.flappclient_args = ["-f", furlfile, "run-command"] options = ClientOptions() options.parseOptions(self.flappclient_args) self.furl = options.furl self.tub = Tub() self.rref = None self.d = defer.succeed(None) def start(self): self.d.addCallback(lambda ign: self.tub.startService()) self.d.addCallback(lambda ign: self.tub.getReference(self.furl)) done = defer.Deferred() def _got_rref(rref): self.rref = rref done.callback(None) self.d.addCallbacks(_got_rref, done.errback) return done def run(self, content, stdout, stderr, when_done, when_failed): assert self.rref is not None options = ClientOptions() options.stdout = stdout options.stderr = stderr options.parseOptions(self.flappclient_args) def stdio(proto): proto.dataReceived(content) proto.connectionLost("EOF") options.subOptions.stdio = stdio options.subOptions.stdout = stdout options.subOptions.stderr = stderr def _go(ign): print >>stdout, "Starting..." return RunCommand().run(self.rref, options.subOptions) def _done(rc): if rc == 0: when_done() else: print >>stdout, "Command failed with exit code %r." % (rc,) when_failed() def _error(f): print >>stdout, str(f) when_failed() def _recover(f): try: print >>stderr, str(f) except Exception: print >>stderr, "something weird" self.d.addCallback(_go) self.d.addCallbacks(_done, _error) self.d.addErrback(_recover)
def setUp(self): self.s = service.MultiService() self.s.startService() self.target_tub = Tub() self.target_tub.setServiceParent(self.s) l = self.target_tub.listenOn("tcp:0:interface=127.0.0.1") self.target_tub.setLocation("127.0.0.1:%d" % l.getPortnum()) self.source_tub = Tub() self.source_tub.setServiceParent(self.s)
class LogTail: def __init__(self, options): self.options = options def run(self, target_furl): target_tubid = SturdyRef(target_furl).getTubRef().getTubID() d = fireEventually(target_furl) d.addCallback(self.start, target_tubid) d.addErrback(self._error) print "starting.." reactor.run() def _error(self, f): print "ERROR", f reactor.stop() def start(self, target_furl, target_tubid): print "Connecting.." self._tub = Tub() self._tub.startService() self._tub.connectTo(target_furl, self._got_logpublisher, target_tubid) def _got_logpublisher(self, publisher, target_tubid): d = publisher.callRemote("get_pid") def _announce(pid_or_failure): if isinstance(pid_or_failure, int): print "Connected (to pid %d)" % pid_or_failure return pid_or_failure else: # the logport is probably foolscap-0.2.8 or earlier and # doesn't offer get_pid() print "Connected (unable to get pid)" return None d.addBoth(_announce) publisher.notifyOnDisconnect(self._lost_logpublisher) lp = LogPrinter(self.options, target_tubid) def _ask_for_versions(pid): d = publisher.callRemote("get_versions") d.addCallback(lp.got_versions, pid) return d d.addCallback(_ask_for_versions) catch_up = bool(self.options["catch-up"]) if catch_up: d.addCallback(lambda res: publisher.callRemote("subscribe_to_all", lp, True)) else: # provide compatibility with foolscap-0.2.4 and earlier, which # didn't accept a catchup= argument d.addCallback(lambda res: publisher.callRemote("subscribe_to_all", lp)) d.addErrback(self._error) return d def _lost_logpublisher(publisher): print "Disconnected"
def TODO_testNonweakrefable(self): # what happens when we register a non-Referenceable? We don't really # need this yet, but as registerReference() becomes more generalized # into just plain register(), we'll want to provide references to # Copyables and ordinary data structures too. Let's just test that # this doesn't cause an error. target = [] tub = Tub() tub.setLocation("bogus:1234567") url = tub.registerReference(target) del url
def test_queue_until_connected(self): self.basedir = "introducer/QueueUntilConnected/queued" os.makedirs(self.basedir) self.create_tub() introducer = IntroducerService() introducer.setServiceParent(self.parent) iff = os.path.join(self.basedir, "introducer.furl") ifurl = self.central_tub.registerReference(introducer, furlFile=iff) tub2 = Tub() tub2.setServiceParent(self.parent) c = IntroducerClient(tub2, ifurl, u"nickname", "version", "oldest", {}, fakeseq, FilePath(self.mktemp())) furl1 = "pb://[email protected]:123/short" # base32("short") sk_s, vk_s = keyutil.make_keypair() sk, _ignored = keyutil.parse_privkey(sk_s) d = introducer.disownServiceParent() def _offline(ign): # now that the introducer server is offline, create a client and # publish some messages c.setServiceParent(self.parent) # this starts the reconnector c.publish("storage", make_ann(furl1), sk) introducer.setServiceParent(self.parent) # restart the server # now wait for the messages to be delivered def _got_announcement(): return bool(introducer.get_announcements()) return self.poll(_got_announcement) d.addCallback(_offline) def _done(ign): v = introducer.get_announcements()[0] furl = v.announcement["anonymous-storage-FURL"] self.failUnlessEqual(furl, furl1) d.addCallback(_done) # now let the ack get back def _wait_until_idle(ign): def _idle(): if c._debug_outstanding: return False if introducer._debug_outstanding: return False return True return self.poll(_idle) d.addCallback(_wait_until_idle) return d
def create_control_tub(self): # the control port uses a localhost-only ephemeral Tub, with no # control over the listening port or location self.control_tub = Tub() portnum = iputil.allocate_tcp_port() port = "tcp:%d:interface=127.0.0.1" % portnum location = "tcp:127.0.0.1:%d" % portnum self.control_tub.listenOn(port) self.control_tub.setLocation(location) self.log("Control Tub location set to %s" % (location, )) self.control_tub.setServiceParent(self)
def testClientTimeout(self): portnum = self.makeNullServer() # lower the connection timeout to 2 seconds client = Tub(_test_options={'connect_timeout': 1}) client.startService() self.services.append(client) url = "pb://[email protected]:%d/target" % portnum d = client.getReference(url) d.addCallbacks(lambda res: self.fail("hey! this is supposed to fail"), lambda f: f.trap(tokens.NegotiationError)) return d
class Server(unittest.TestCase, ShouldFailMixin): def setUp(self): self.s = service.MultiService() self.s.startService() def tearDown(self): return self.s.stopService() def run_cli(self, *args): argv = ["flappserver"] + list(args) d = defer.maybeDeferred(cli.run_flappserver, argv=argv, run_by_human=False) return d # fires with (rc,out,err) def test_run(self): basedir = "appserver/Server/run" os.makedirs(basedir) serverdir = os.path.join(basedir, "fl") incomingdir = os.path.join(basedir, "incoming") os.mkdir(incomingdir) self.tub = Tub() self.tub.setServiceParent(self.s) portnum = allocate_tcp_port() d = self.run_cli("create", "--location", "localhost:%d" % portnum, "--port", "tcp:%d" % portnum, serverdir) def _check((rc,out,err)): self.failUnlessEqual(rc, 0) self.failUnless(os.path.isdir(serverdir)) d.addCallback(_check) d.addCallback(lambda ign: self.run_cli("add", serverdir, "upload-file", incomingdir)) def _check_add((rc,out,err)): self.failUnlessEqual(rc, 0) lines = out.splitlines() self.failUnless(lines[1].startswith("FURL is pb://")) self.furl = lines[1].split()[-1] d.addCallback(_check_add) stdout = StringIO() def _start_server(ign): ap = server.AppServer(serverdir, stdout) ap.setServiceParent(self.s) d.addCallback(_start_server) # make sure the server can actually instantiate a service d.addCallback(lambda _ign: self.tub.getReference(self.furl)) def _got_rref(rref): # great! pass d.addCallback(_got_rref) d.addCallback(lambda ign: self.shouldFail(KeyError, "getReference(bogus)", "unable to find reference for name ", self.tub.getReference, self.furl+".bogus")) return d
def test_logport_furlfile1(self): basedir = "unreachable/References/logport_furlfile1" os.makedirs(basedir) furlfile = os.path.join(basedir, "logport.furl") t = Tub() # setOption before setServiceParent t.setOption("logport-furlfile", furlfile) t.setServiceParent(self.s) self.failUnlessRaises(NoLocationError, t.getLogPort) self.failUnlessRaises(NoLocationError, t.getLogPortFURL) self.failIf(os.path.exists(furlfile))
class Server(RequiresCryptoBase, unittest.TestCase, ShouldFailMixin): def setUp(self): RequiresCryptoBase.setUp(self) self.s = service.MultiService() self.s.startService() def tearDown(self): return self.s.stopService() def run_cli(self, *args): argv = ["flappserver"] + list(args) d = defer.maybeDeferred(cli.run_flappserver, argv=argv, run_by_human=False) return d # fires with (rc,out,err) def test_run(self): basedir = "appserver/Server/run" os.makedirs(basedir) serverdir = os.path.join(basedir, "fl") incomingdir = os.path.join(basedir, "incoming") os.mkdir(incomingdir) self.tub = Tub() self.tub.setServiceParent(self.s) d = self.run_cli("create", serverdir) def _check((rc,out,err)): self.failUnlessEqual(rc, 0) self.failUnless(os.path.isdir(serverdir)) d.addCallback(_check) d.addCallback(lambda ign: self.run_cli("add", serverdir, "upload-file", incomingdir)) def _check_add((rc,out,err)): self.failUnlessEqual(rc, 0) lines = out.splitlines() self.failUnless(lines[1].startswith("FURL is pb://")) self.furl = lines[1].split()[-1] d.addCallback(_check_add) stdout = StringIO() def _start_server(ign): ap = server.AppServer(serverdir, stdout) ap.setServiceParent(self.s) return ap.when_ready() d.addCallback(_start_server) # make sure the server can actually instantiate a service d.addCallback(lambda _ign: self.tub.getReference(self.furl)) def _got_rref(rref): # great! pass d.addCallback(_got_rref) d.addCallback(lambda ign: self.shouldFail(KeyError, "getReference(bogus)", "unable to find reference for name ", self.tub.getReference, self.furl+".bogus")) return d
def test_duplicate(self): basedir = "test_registration" os.makedirs(basedir) ff = os.path.join(basedir, "duplicate.furl") t1 = HelperTarget() tub = Tub() tub.setLocation("bogus:1234567") u1 = tub.registerReference(t1, "name", furlFile=ff) u2 = tub.registerReference(t1, "name", furlFile=ff) self.failUnlessEqual(u1, u2) self.failUnlessRaises(WrongNameError, tub.registerReference, t1, "newname", furlFile=ff)
def createSpecificServer(self, certData, negotiationClass=negotiate.Negotiation): tub = Tub(certData=certData) tub.negotiationClass = negotiationClass tub.startService() self.services.append(tub) portnum = allocate_tcp_port() tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum) tub.setLocation("127.0.0.1:%d" % portnum) target = Target() return tub, target, tub.registerReference(target), portnum
def _take2(res): t2 = Tub(certFile=cfn) t2.setServiceParent(self.s) t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % portnum) r2 = Referenceable() furl2 = t2.registerReference(r2, furlFile=ffn) self.failUnlessEqual(furl1, furl2) return t2.disownServiceParent()
def _take2(res): t2 = Tub() # gets a different key t2.setServiceParent(self.s) t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % portnum) r2 = Referenceable() self.assertRaises(WrongTubIdError, t2.registerReference, r2, furlFile=ffn) return t2.disownServiceParent()
def _take2(res): t2 = Tub(certFile=cfn) t2.setServiceParent(self.s) l = t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % l.getPortnum()) r2 = Referenceable() furl2 = t2.registerReference(r2, furlFile=ffn) self.failUnlessEqual(furl1, furl2) return t2.disownServiceParent()
def testFuture3(self): # same as testFuture1, but it is the listening server that # understands [1,2] url, portnum = self.makeSpecificServer(certData_high, NegotiationVbig) client = Tub(certData=certData_low) client.startService() self.services.append(client) d = client.getReference(url) def _check_version(rref): ver = rref.tracker.broker._banana_decision_version self.failUnlessEqual(ver, MAX_HANDLED_VERSION) d.addCallback(_check_version) return d
def setUp(self): TargetMixin.setUp(self) self.tubA, self.tubB = [Tub(), Tub()] self.services = [self.tubA, self.tubB] self.tubA.startService() self.tubB.startService() l = self.tubB.listenOn("tcp:0:interface=127.0.0.1") self.tubB.setLocation("127.0.0.1:%d" % l.getPortnum()) self.url_on_b = self.tubB.registerReference(Referenceable()) self.lookups = [] self.lookups2 = [] self.names = {} self.names2 = {}
def test_run(self): basedir = "appserver/Server/run" os.makedirs(basedir) serverdir = os.path.join(basedir, "fl") incomingdir = os.path.join(basedir, "incoming") os.mkdir(incomingdir) self.tub = Tub() self.tub.setServiceParent(self.s) portnum = allocate_tcp_port() d = self.run_cli("create", "--location", "localhost:%d" % portnum, "--port", "tcp:%d" % portnum, serverdir) def _check(rc_out_err): rc, out, err = rc_out_err self.assertEqual(rc, 0) self.assertTrue(os.path.isdir(serverdir)) d.addCallback(_check) d.addCallback(lambda ign: self.run_cli("add", serverdir, "upload-file", incomingdir)) def _check_add(rc_out_err): rc, out, err = rc_out_err self.assertEqual(rc, 0) lines = out.splitlines() self.assertTrue(lines[1].startswith("FURL is pb://")) self.furl = lines[1].split()[-1] d.addCallback(_check_add) stdout = StringIO() def _start_server(ign): ap = server.AppServer(serverdir, stdout) ap.setServiceParent(self.s) d.addCallback(_start_server) # make sure the server can actually instantiate a service d.addCallback(lambda _ign: self.tub.getReference(self.furl)) def _got_rref(rref): # great! pass d.addCallback(_got_rref) d.addCallback(lambda ign: self.shouldFail( KeyError, "getReference(bogus)", "unable to find reference for name ", self.tub.getReference, self. furl + ".bogus")) return d
def createSpecificServer(self, certData, negotiationClass=negotiate.Negotiation): tub = Tub(certData=certData) tub.negotiationClass = negotiationClass tub.startService() self.services.append(tub) l = tub.listenOn("tcp:0") tub.setLocation("127.0.0.1:%d" % l.getPortnum()) target = Target() return tub, target, tub.registerReference(target), l.getPortnum()
def testWeak(self): t1 = HelperTarget() tub = Tub() tub.setLocation("bogus:1234567") name = tub._assignName(t1) url = tub.buildURL(name) del url results = [] w1 = weakref.ref(t1, results.append) del t1 gc.collect() # t1 should be dead self.failIf(w1()) self.failUnlessEqual(len(results), 1)
def testVersusHTTPServerAuthenticated(self): portnum = self.makeHTTPServer() client = Tub() client.startService() self.services.append(client) url = "pb://%[email protected]:%d/target" % (tubid_low, portnum) d = client.getReference(url) d.addCallbacks(lambda res: self.fail("this is supposed to fail"), lambda f: f.trap(BananaError)) # the HTTP server needs a moment to notice that the connection has # gone away. Without this, trial flunks the test because of the # leftover HTTP server socket. d.addCallback(self.stall, 1) return d
class FlappCommand(object): def __init__(self, furlfile): self.flappclient_args = ["-f", furlfile, "run-command"] options = ClientOptions() options.parseOptions(self.flappclient_args) self.furl = options.furl self.tub = Tub() self.rref = None self.d = defer.succeed(None) def start(self): self.d.addCallback(lambda ign: self.tub.startService()) self.d.addCallback(lambda ign: self.tub.getReference(self.furl)) done = defer.Deferred() def _got_rref(rref): self.rref = rref done.callback(None) def _failed(f): done.errback(f) return f self.d.addCallbacks(_got_rref, _failed) return done def run(self, content, log): assert isinstance(content, bytes), (`content`, type(content)) assert self.rref is not None options = ClientOptions() options.parseOptions(self.flappclient_args) def stdio(proto): # This value is being sent to the stdin of the flapp. proto.dataReceived(content) proto.connectionLost("EOF") options.subOptions.stdio = stdio # These are not used. options.subOptions.stdout = None options.subOptions.stderr = None print >>log, "Starting command." self.d = RunCommand().run(self.rref, options.subOptions) def _log_return_code(rc): print >>log, "Command completed with exit code %r" % (rc,) def _log_failure(f): print >>log, "Command failed with %r" % (f,) self.d.addCallbacks(_log_return_code, _log_failure) return self.d
def test_set_location(self): t = Tub() t.listenOn("tcp:0") t.setServiceParent(self.s) t.setLocation("127.0.0.1:12345") # setLocation may only be called once self.failUnlessRaises(PBError, t.setLocation, "127.0.0.1:12345")
def test_retry(self): tubC = Tub(certData=self.tubB.getCertData()) connects = [] target = HelperTarget("bob") url = self.tubB.registerReference(target, "target") portb = self.tub_ports[1] d1 = defer.Deferred() notifiers = [d1] self.services.remove(self.tubB) # This will fail, since tubB is not listening anymore. Wait until it's # moved to the "waiting" state. yield self.tubB.stopService() rc = self.tubA.connectTo(url, self._connected, notifiers, connects) yield self.poll(lambda: rc.getReconnectionInfo().state == "waiting") self.failUnlessEqual(len(connects), 0) # now start tubC listening on the same port that tubB used to, which # should allow the connection to complete (since they both use the same # certData) self.services.append(tubC) tubC.startService() tubC.listenOn("tcp:%d:interface=127.0.0.1" % portb) tubC.setLocation("tcp:127.0.0.1:%d" % portb) url2 = tubC.registerReference(target, "target") assert url2 == url yield d1 self.failUnlessEqual(len(connects), 1) rc.stopConnecting()
def __init__(self, basedir): service.MultiService.__init__(self) if basedir is None: # This instance was created by a gatherer.tac file. Confirm that # we're running from the right directory (the one with the .tac # file), otherwise we'll put the logfiles in the wrong place. basedir = os.getcwd() tac = os.path.join(basedir, self.tacFile) if not os.path.exists(tac): raise RuntimeError("running in the wrong directory") self.basedir = basedir certFile = os.path.join(self.basedir, "gatherer.pem") portfile = os.path.join(self.basedir, "port") locationfile = os.path.join(self.basedir, "location") furlFile = os.path.join(self.basedir, self.furlFile) # Foolscap-0.11.0 was the last release that used # automatically-determined listening addresses and ports. New ones # (created with "flogtool create-gatherer" or # "create-incident-gathererer" now require --location and --port # arguments to provide these values. If you really don't want to # create a new one, you can write "tcp:3117" (or some other port # number of your choosing) to BASEDIR/port, and "tcp:$HOSTNAME:3117" # (with your hostname or IP address) to BASEDIR/location if (not os.path.exists(portfile) or not os.path.exists(locationfile)): raise ObsoleteGatherer("Please create a new gatherer, with both " "--port and --location") try: with open(portfile, "r") as f: port = f.read().strip() except EnvironmentError: raise ObsoleteGatherer("Please create a new gatherer, with both " "--port and --location") try: with open(locationfile, "r") as f: location = f.read().strip() except EnvironmentError: raise ObsoleteGatherer("Please create a new gatherer, with both " "--port and --location") self._tub = Tub(certFile=certFile) self._tub.setServiceParent(self) self._tub.listenOn(port) self._tub.setLocation(location) self.my_furl = self._tub.registerReference(self, furlFile=furlFile) if self.verbose: print "Gatherer waiting at:", self.my_furl
def test_furlfile(self): cfn = "test_tub.FurlFile.test_furlfile.certfile" t1 = Tub(certFile=cfn) t1.setServiceParent(self.s) portnum = allocate_tcp_port() port1 = "tcp:%d:interface=127.0.0.1" % portnum t1.listenOn(port1) t1.setLocation("127.0.0.1:%d" % portnum) r1 = Referenceable() ffn = "test_tub.FurlFile.test_furlfile.furlfile" furl1 = t1.registerReference(r1, furlFile=ffn) d = defer.maybeDeferred(t1.disownServiceParent) self.failUnless(os.path.exists(ffn)) self.failUnlessEqual(furl1, open(ffn,"r").read().strip()) def _take2(res): t2 = Tub(certFile=cfn) t2.setServiceParent(self.s) t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % portnum) r2 = Referenceable() furl2 = t2.registerReference(r2, furlFile=ffn) self.failUnlessEqual(furl1, furl2) return t2.disownServiceParent() d.addCallback(_take2) return d
class FlappCommand(object): def __init__(self, furl): self.flappclient_args = ["--furl", furl, "run-command"] options = ClientOptions() options.parseOptions(self.flappclient_args) self.furl = options.furl self.tub = Tub() self.rref = None self.d = defer.succeed(None) def start(self): self.d.addCallback(lambda ign: self.tub.startService()) self.d.addCallback(lambda ign: self.tub.getReference(self.furl)) done = defer.Deferred() def _got_rref(rref): self.rref = rref done.callback(None) def _failed(f): done.errback(f) return f self.d.addCallbacks(_got_rref, _failed) return done def run(self, content, log): assert isinstance(content, bytes), (`content`, type(content)) assert self.rref is not None options = ClientOptions() options.parseOptions(self.flappclient_args) def stdio(proto): # This value is being sent to the stdin of the flapp. proto.dataReceived(content) proto.connectionLost("EOF") options.subOptions.stdio = stdio # These are not used. options.subOptions.stdout = None options.subOptions.stderr = None print >>log, "Starting command." self.d = RunCommand().run(self.rref, options.subOptions) def _log_return_code(rc): print >>log, "Command completed with exit code %r" % (rc,) def _log_failure(f): print >>log, "Command failed with %r" % (f,) self.d.addCallbacks(_log_return_code, _log_failure) return self.d
def test_tubid_check(self): t1 = Tub() # gets a new key t1.setServiceParent(self.s) portnum = allocate_tcp_port() port1 = "tcp:%d:interface=127.0.0.1" % portnum t1.listenOn(port1) t1.setLocation("127.0.0.1:%d" % portnum) r1 = Referenceable() ffn = "test_tub.FurlFile.test_tubid_check.furlfile" furl1 = t1.registerReference(r1, furlFile=ffn) d = defer.maybeDeferred(t1.disownServiceParent) self.failUnless(os.path.exists(ffn)) self.failUnlessEqual(furl1, open(ffn,"r").read().strip()) def _take2(res): t2 = Tub() # gets a different key t2.setServiceParent(self.s) t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % portnum) r2 = Referenceable() self.failUnlessRaises(WrongTubIdError, t2.registerReference, r2, furlFile=ffn) return t2.disownServiceParent() d.addCallback(_take2) return d
def setUp(self): self.base_service.startService() self.tub = Tub() self.tub.setOption("expose-remote-exception-types", False) self.tub.setServiceParent(self.base_service) d = self.tub.getReference(self.control_furl) def _gotref(rref): self.client_rref = rref print "Got Client Control reference" return self.stall(5) d.addCallback(_gotref) return d
def run_command(config): c = dispatch_table[config.subCommand]() tub = Tub() try: from twisted.internet import reactor from twisted.internet.endpoints import clientFromString from foolscap.connections import tor CONTROL = os.environ.get("FOOLSCAP_TOR_CONTROL_PORT", "") SOCKS = os.environ.get("FOOLSCAP_TOR_SOCKS_PORT", "") if CONTROL: h = tor.control_endpoint(clientFromString(reactor, CONTROL)) tub.addConnectionHintHandler("tor", h) elif SOCKS: h = tor.socks_endpoint(clientFromString(reactor, SOCKS)) tub.addConnectionHintHandler("tor", h) #else: # h = tor.default_socks() # tub.addConnectionHintHandler("tor", h) except ImportError: pass d = defer.succeed(None) d.addCallback(lambda _ign: tub.startService()) d.addCallback(lambda _ign: tub.getReference(config.furl)) d.addCallback(c.run, config.subOptions) # might provide tub here d.addBoth(lambda res: tub.stopService().addCallback(lambda _ign: res)) return d
def test_furlfile(self): cfn = "test_tub.FurlFile.test_furlfile.certfile" t1 = Tub(certFile=cfn) t1.setServiceParent(self.s) l = t1.listenOn("tcp:0:interface=127.0.0.1") t1.setLocation("127.0.0.1:%d" % l.getPortnum()) port1 = "tcp:%d:interface=127.0.0.1" % l.getPortnum() r1 = Referenceable() ffn = "test_tub.FurlFile.test_furlfile.furlfile" furl1 = t1.registerReference(r1, furlFile=ffn) d = defer.maybeDeferred(t1.disownServiceParent) self.failUnless(os.path.exists(ffn)) self.failUnlessEqual(furl1, open(ffn, "r").read().strip()) def _take2(res): t2 = Tub(certFile=cfn) t2.setServiceParent(self.s) l = t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % l.getPortnum()) r2 = Referenceable() furl2 = t2.registerReference(r2, furlFile=ffn) self.failUnlessEqual(furl1, furl2) return t2.disownServiceParent() d.addCallback(_take2) return d
def test_failure(self): self.basedir = "introducer/NonV1Server/failure" os.makedirs(self.basedir) self.create_tub() i = TooNewServer() i.setServiceParent(self.parent) self.introducer_furl = self.central_tub.registerReference(i) tub = Tub() tub.setOption("expose-remote-exception-types", False) tub.setServiceParent(self.parent) l = tub.listenOn("tcp:0") portnum = l.getPortnum() tub.setLocation("localhost:%d" % portnum) c = IntroducerClient(tub, self.introducer_furl, u"nickname-client", "version", "oldest") announcements = {} def got(serverid, ann_d): announcements[serverid] = ann_d c.subscribe_to("storage", got) c.setServiceParent(self.parent) # now we wait for it to connect and notice the bad version def _got_bad(): return bool(c._introducer_error) or bool(c._publisher) d = self.poll(_got_bad) def _done(res): self.failUnless(c._introducer_error) self.failUnless(c._introducer_error.check(InsufficientVersionError)) d.addCallback(_done) return d
def test_tubid_check(self): t1 = Tub() # gets a new key t1.setServiceParent(self.s) l = t1.listenOn("tcp:0:interface=127.0.0.1") t1.setLocation("127.0.0.1:%d" % l.getPortnum()) port1 = "tcp:%d:interface=127.0.0.1" % l.getPortnum() r1 = Referenceable() ffn = "test_tub.FurlFile.test_tubid_check.furlfile" furl1 = t1.registerReference(r1, furlFile=ffn) d = defer.maybeDeferred(t1.disownServiceParent) self.failUnless(os.path.exists(ffn)) self.failUnlessEqual(furl1, open(ffn, "r").read().strip()) def _take2(res): t2 = Tub() # gets a different key t2.setServiceParent(self.s) l = t2.listenOn(port1) t2.setLocation("127.0.0.1:%d" % l.getPortnum()) r2 = Referenceable() self.failUnlessRaises(WrongTubIdError, t2.registerReference, r2, furlFile=ffn) return t2.disownServiceParent() d.addCallback(_take2) return d
def create_log_tub(self): # The logport uses a localhost-only ephemeral Tub, with no control # over the listening port or location. This might change if we # discover a compelling reason for it in the future (e.g. being able # to use "flogtool tail" against a remote server), but for now I # think we can live without it. self.log_tub = Tub() portnum = iputil.allocate_tcp_port() port = "tcp:%d:interface=127.0.0.1" % portnum location = "tcp:127.0.0.1:%d" % portnum self.log_tub.listenOn(port) self.log_tub.setLocation(location) self.log("Log Tub location set to %s" % (location, )) self.log_tub.setServiceParent(self)
def create_tub(tub_options, default_connection_handlers, foolscap_connection_handlers, handler_overrides={}, **kwargs): """ Create a Tub with the right options and handlers. It will be ephemeral unless the caller provides certFile= in kwargs :param handler_overrides: anything in this will override anything in `default_connection_handlers` for just this call. :param dict tub_options: every key-value pair in here will be set in the new Tub via `Tub.setOption` """ tub = Tub(**kwargs) for (name, value) in list(tub_options.items()): tub.setOption(name, value) handlers = default_connection_handlers.copy() handlers.update(handler_overrides) tub.removeAllConnectionHintHandlers() for hint_type, handler_name in list(handlers.items()): handler = foolscap_connection_handlers.get(handler_name) if handler: tub.addConnectionHintHandler(hint_type, handler) return tub
def makeServers(self, t1opts={}, t2opts={}, lo1={}, lo2={}, tubAauthenticated=True, tubBauthenticated=True): if tubAauthenticated or tubBauthenticated: self.requireCrypto() # first we create two Tubs if tubAauthenticated: a = Tub(options=t1opts) else: a = UnauthenticatedTub(options=t1opts) if tubBauthenticated: b = Tub(options=t1opts) else: b = UnauthenticatedTub(options=t1opts) # then we figure out which one will be the master, and call it tub1 if a.tubID > b.tubID: # a is the master tub1,tub2 = a,b else: tub1,tub2 = b,a if not self.tub1IsMaster: tub1,tub2 = tub2,tub1 self.tub1 = tub1 self.tub2 = tub2 # now fix up the options and everything else self.tub1phases = [] t1opts['debug_gatherPhases'] = self.tub1phases tub1.options = t1opts self.tub2phases = [] t2opts['debug_gatherPhases'] = self.tub2phases tub2.options = t2opts # connection[0], the winning connection, will be from tub1 to tub2 tub1.startService() self.services.append(tub1) l1 = tub1.listenOn("tcp:0", lo1) tub1.setLocation("127.0.0.1:%d" % l1.getPortnum()) self.target1 = Target() self.url1 = tub1.registerReference(self.target1) # connection[1], the abandoned connection, will be from tub2 to tub1 tub2.startService() self.services.append(tub2) l2 = tub2.listenOn("tcp:0", lo2) tub2.setLocation("127.0.0.1:%d" % l2.getPortnum()) self.target2 = Target() self.url2 = tub2.registerReference(self.target2)
def new_tahoe_configuration(deploy_config, bucketname, key_prefix, publichost, privatehost, introducer_port, storageserver_port): """ Create brand new secrets and configuration for use by an introducer/storage pair. """ base_name = dict( organizationName=b"Least Authority Enterprises", organizationalUnitName=b"S4", emailAddress=bucketname, ) keypair = KeyPair.generate(size=2048) introducer_certificate = keypair.selfSignedCert( serialNumber=1, commonName=b"introducer", **base_name ) storage_certificate = keypair.selfSignedCert( serialNumber=1, commonName=b"storage", **base_name ) def pem(key, cert): return b"\n".join((key.dump(FILETYPE_PEM), cert.dump(FILETYPE_PEM))) introducer_tub = Tub(certData=pem(keypair, introducer_certificate)) introducer_tub.setLocation("{}:{}".format(publichost, introducer_port)) storage_tub = Tub(certData=pem(keypair, storage_certificate)) return marshal_tahoe_configuration( introducer_pem=introducer_tub.getCertData().strip(), storage_pem=storage_tub.getCertData().strip(), storage_privkey=keyutil.make_keypair()[0] + b"\n", introducer_port=introducer_port, storageserver_port=storageserver_port, bucket_name=bucketname, key_prefix=key_prefix, publichost=publichost, privatehost=privatehost, # The object of the reference is irrelevant. The furl will # get hooked up to something else when Tahoe really runs. # Just need to pass something _weak referenceable_! Which # rules out a lot of things... introducer_furl=introducer_tub.registerReference(introducer_tub), s3_access_key_id=deploy_config.s3_access_key_id, s3_secret_key=deploy_config.s3_secret_key, log_gatherer_furl=deploy_config.log_gatherer_furl, stats_gatherer_furl=deploy_config.stats_gatherer_furl, )
def testTooFarInFuture4(self): # same as testTooFarInFuture2, but it is the listening server which # only understands [2] url, portnum = self.makeSpecificServer(certData_low, NegotiationVbigOnly) client = Tub(certData=certData_high) client.startService() self.services.append(client) d = client.getReference(url) def _oops_succeeded(rref): self.fail("hey! this is supposed to fail") def _check_failure(f): f.trap(tokens.NegotiationError, tokens.RemoteNegotiationError) d.addCallbacks(_oops_succeeded, _check_failure) return d
def test_set_location(self): t = Tub() portnum = allocate_tcp_port() t.listenOn("tcp:%d:interface=127.0.0.1" % portnum) t.setServiceParent(self.s) t.setLocation("127.0.0.1:12345") # setLocation may only be called once self.assertRaises(PBError, t.setLocation, "127.0.0.1:12345")
def __init__(self, basedir=".", stdout=sys.stdout): service.MultiService.__init__(self) self.basedir = os.path.abspath(basedir) try: umask = open(os.path.join(basedir, "umask")).read().strip() self.umask = int(umask, 8) # octal string like 0022 except EnvironmentError: self.umask = None self.port = open(os.path.join(basedir, "port")).read().strip() self.tub = Tub(certFile=os.path.join(basedir, "tub.pem")) self.tub.listenOn(self.port) self.tub.setServiceParent(self) self.tub.registerNameLookupHandler(self.lookup) self.setMyLocation() print >>stdout, "Server Running"
def get_tub(application): myserver = RemoteControl(application) tub = Tub(certFile=os.path.join(consenso.directories.foolscap_dir, "pb2server.pem")) tub.listenOn("tcp:12345") tub.setLocation("localhost:12345") tub.registerReference(myserver, "remote-control", furlFile=furlfile) return tub
class AppServer(service.MultiService): def __init__(self, basedir=".", stdout=sys.stdout): service.MultiService.__init__(self) self.basedir = os.path.abspath(basedir) try: umask = open(os.path.join(basedir, "umask")).read().strip() self.umask = int(umask, 8) # octal string like 0022 except EnvironmentError: self.umask = None port = open(os.path.join(basedir, "port")).read().strip() self.tub = Tub(certFile=os.path.join(basedir, "tub.pem")) self.tub.listenOn(port) self.tub.setServiceParent(self) self.tub.registerNameLookupHandler(self.lookup) print >> stdout, "Server Running" self.ready_observers = OneShotObserverList() # make sure we log any problems self.when_ready().addErrback(log.err) def when_ready(self): # return a Deferred that fires (with this AppServer instance) when # the service is running and the location is set. return self.ready_observers.whenFired() def startService(self): if self.umask is not None: os.umask(self.umask) service.MultiService.startService(self) d = self.setMyLocation() d.addBoth(self.ready_observers.fire) def setMyLocation(self): location = open(os.path.join(self.basedir, "location")).read().strip() if location: self.tub.setLocation(location) return defer.succeed(self) d = self.tub.setLocationAutomatically() d.addCallback(lambda ign: self) return d def lookup(self, name): # walk through our configured services, see if we know about this one services = load_service_data(self.basedir)["services"] s = services.get(name) if not s: return None service_basedir = os.path.join(self.basedir, s["relative_basedir"]) service_type = s["type"] service_args = s["args"] s = build_service(service_basedir, self.tub, service_type, service_args) s.setServiceParent(self) return s
def test_doublestop(self): tub = Tub() tub.startService() d = tub.stopService() d.addCallback(lambda res: self.shouldFail( RuntimeError, "test_doublestop_startService", "Sorry, but Tubs cannot be restarted", tub.startService)) d.addCallback(lambda res: self.shouldFail( RuntimeError, "test_doublestop_getReference", "Sorry, but this Tub has been shut down", tub.getReference, "furl") ) d.addCallback(lambda res: self.shouldFail( RuntimeError, "test_doublestop_connectTo", "Sorry, but this Tub has been shut down", tub.connectTo, "furl", None)) return d
class Failed(unittest.TestCase): def setUp(self): self.services = [] def tearDown(self): d = defer.DeferredList([s.stopService() for s in self.services]) d.addCallback(flushEventualQueue) return d @defer.inlineCallbacks def test_bad_hints(self): self.tubA = Tub() self.tubA.startService() self.services.append(self.tubA) self.tubB = Tub() self.tubB.startService() self.services.append(self.tubB) portnum = allocate_tcp_port() self.tubB.listenOn("tcp:%d:interface=127.0.0.1" % portnum) bad1 = "no-colon" bad2 = "unknown:foo" bad3 = "tcp:300.300.300.300:333" self.tubB.setLocation(bad1, bad2, bad3) target = HelperTarget("bob") url = self.tubB.registerReference(target) rc = self.tubA.connectTo(url, None) ri = rc.getReconnectionInfo() self.assertEqual(ri.state, "connecting") d = defer.Deferred() reactor.callLater(1.0, d.callback, None) yield d # now look at the details ri = rc.getReconnectionInfo() self.assertEqual(ri.state, "waiting") ci = ri.connectionInfo self.assertEqual(ci.connected, False) self.assertEqual(ci.winningHint, None) s = ci.connectorStatuses self.assertEqual(set(s.keys()), set([bad1, bad2, bad3])) self.assertEqual(s[bad1], "bad hint: no colon") self.assertEqual(s[bad2], "bad hint: no handler registered") self.assertIn("DNS lookup failed", s[bad3]) ch = ci.connectionHandlers self.assertEqual(ch, {bad2: None, bad3: "tcp"})