Authority = Node.create(3, { "tag": "a", "authority": 1, "relay": 1, "torrc": "authority.tmpl" }) Relay = Node.create(10, { "tag": "r", "relay": 1, "torrc": "intro.tmpl" }) Client = Node.create(6, { "tag": "c", "torrc": "client.tmpl" }) # hidden service (hs) nodes hs_node_1 = Node( tag="h", hiddenservice=1, torrc="hidden-service.tmpl", hiddenservicetarget="127.0.0.1:8081" ) hs_node_2 = Node( tag="h", hiddenservice=1, torrc="hidden-service.tmpl", hiddenservicetarget="127.0.0.1:8082" ) hs_nodes = (hs_node_1, hs_node_2) initial_nodes = Authority + Relay + Client + [ hs_node_1 ] nodes_by_fingerprint = {} #{ nodenum: { circuit: "fingerprint", circuit: "fingerprint" } } # Introduction Point Tracking node_intro_circuits = {} node_intro_events = {} introduction_point_circuits = {} def track_hs_node(node): nodenum = node._env["nodenum"] nodenick = node._env["nick"] node_intro_circuits[nodenum] = {} node_intro_events[nodenum] = Queue.Queue() def listener(logevent): prefix = "rend_service_intro_has_opened(): Established circuit " if logevent.message.startswith(prefix): circuit = logevent.message[len(prefix):].split(" ")[0] fingerprint = logevent.message[len(prefix):].split(" ")[1][1:] node_intro_circuits[nodenum][circuit] = fingerprint added_intro_node = nodes_by_fingerprint[fingerprint] log("%s: added %s (%s)" % (nodenick, added_intro_node._env["nick"], fingerprint)) node_intro_events[nodenum].put(("added", fingerprint)) prefix = "rend_services_introduce(): Giving up on " if logevent.message.startswith(prefix) or "Giving up on" in logevent.message: log(logevent.message) fingerprint = logevent.message[len(prefix):].split(" ")[0][1:41] for_deletion = [] for circuit, fp in node_intro_circuits[nodenum].iteritems(): #log("circuit " + str(circuit) + " fp " + str(fp)) if fingerprint == fp: for_deletion.append(circuit) if len(for_deletion) == 0: log("got log message " + logevent.message + " but not deleting an introduction point") for circuit in for_deletion: fingerprint = node_intro_circuits[nodenum][circuit] removed_intro_node = nodes_by_fingerprint[fingerprint] log("%s: removed %s (%s)" % (nodenick, removed_intro_node._env["nick"], fingerprint)) node_intro_events[nodenum].put(("removed", fingerprint)) del node_intro_circuits[nodenum][circuit] node.getStemController().add_event_listener(listener, EventType.INFO) log("Tracking introduction points for " + node._env["nick"]) def track_introduction_point(node): nodenum = node._env["nodenum"] nodenick = node._env["nick"] introduction_point_circuits[node] = {} def listener(logevent): prefix = "rend_mid_introduce" if logevent.message.startswith(prefix): print(logevent.message) node.getStemController().add_event_listener(listener, EventType.INFO) log("Tracking introduction points for " + node._env["nick"]) # Use twisted to create web servers in this script class Site(resource.Resource): isLeaf = True numberRequests = 0 def __init__(self, siteNum): self.siteNum = siteNum def render_GET(self, request): self.numberRequests += 1 request.setHeader("content-type", "text/plain") return str(self.siteNum) def start_test(): log("Starting test") port8081 = reactor.listenTCP(8081, server.Site(Site(1))) port8082 = reactor.listenTCP(8082, server.Site(Site(2))) def cleanup(): port8081.stopListening() log("stopped 8081") port8082.stopListening() log("stopped 8082") reactor.stop() log("stopped the reactor") def connection_test(): log("connecting to clients") responses = {"1": 0, "2": 0} for c in Client: result = c.query("http://2oiifbe3wne4iaqb.onion/"); if result in responses: responses[result] += 1 else: log("Unknown response:") log(responses) def test(): connection_test() connection_test() cleanup() stop() thread.start_new_thread(test, ()) log("running reactor") reactor.run(installSignalHandlers=0) def check_same_intro_points(): intro_sets = [] for introduction_points in node_intro_circuits.values(): intro_sets.append(set(introduction_points.values())) if intro_sets[0].issubset(intro_sets[1]) and intro_sets[1].issubset(intro_sets[0]): log("Same introduction points") for fingerprint in node_intro_circuits.values()[0].values(): node = nodes_by_fingerprint[fingerprint] log(" - " + node._env["nick"] + "(" + fingerprint + ")") return True else: log("Not the same introduction points") for num, circuits in node_intro_circuits.items(): log("node %i" % num) for fingerprint in circuits.values(): node = nodes_by_fingerprint[fingerprint] log(" - " + node._env["nick"] + "(" + fingerprint + ")") return False def start(): log("Starting round robin test") if not all([ n.getController().start() for n in initial_nodes ]): return False log("All initial nodes running") for node in Authority + Relay: fingerprint = node.getStemController().get_info("fingerprint") nodes_by_fingerprint[fingerprint] = node track_introduction_point(node) track_hs_node(hs_node_1) def log_listener(logevent): if "Successfully uploaded v2 rend descriptors" in logevent.message: hs_node_1.getStemController().remove_event_listener(log_listener) def start_listener(logevent): # Probably after what needs waiting for if "Successfully uploaded v2 rend descriptors" in logevent.message: hs_node_2.getStemController().remove_event_listener(start_listener) if check_same_intro_points(): thread.start_new_thread(start_test, ()) log("finished running start_test in another thread") hs_node_2.getController().start() track_hs_node(hs_node_2) hs_node_2.getStemController().add_event_listener(start_listener, EventType.INFO) hs_node_1.getStemController().add_event_listener(log_listener, EventType.INFO)