def create_runtime(id, players, options): """Create a :class:`Runtime` and connect to the other players. This function should be used in normal programs instead of instantiating the Runtime directly. This function makes sure that the Runtime is correctly connected to the other players. """ assert 2 * options.threshold < len(players) # The import is put here because of circular depencencies # between viff.runtime and viff.passive. from viff.passive import PassiveRuntime # This will yield a Runtime when all protocols are connected. result = Deferred() # Create a runtime that knows about no other players than itself. # It will eventually be returned in result when the factory has # determined that all needed protocols are ready. runtime = PassiveRuntime(players[id], options) if len(players) == 1: result.callback(runtime) return result if options.host: for i in xrange(len(options.host)): players[i + 1].host, port_str = options.host[i].rsplit(":") players[i + 1].port = int(port_str) factory = ShareExchangerFactory(runtime, players, result) port = players[id].port runtime.port = None delay = 2 while runtime.port is None: # We keep trying to listen on the port, but with an # exponentially increasing delay between each attempt. try: runtime.port = reactor.listenTCP(port, factory) except CannotListenError, e: if options.no_socket_retry: raise delay *= 1 + rand.random() print "Error listening on port %d: %s" % (port, e.socketError[1]) print "Will try again in %d seconds" % delay time.sleep(delay)
def setUp(self): """Configure and connect three Runtimes. .. warning:: Subclasses that override this method *must* remember to do a super-call to it. Otherwise the runtimes wont be connected and :meth:`tearDown` wont work. """ # Our standard 65 bit Blum prime self.Zp = GF(30916444023318367583) configs = self.generate_configs(self.num_players, self.threshold) self.protocols = {} # initialize the dictionary of random generators seed = rand.random() self.shared_rand = dict([(player_id, Random(seed)) for player_id in range(1, self.num_players + 1)]) # This will be a list of Deferreds which will trigger when the # virtual connections between the players are closed. self.close_sentinels = [] self.runtimes = [] for id in reversed(range(1, self.num_players+1)): _, players = load_config(configs[id]) self.create_loopback_runtime(id, players) if isinstance(reactor, ViffReactor): def set_loop_call(runtimes): self.i = 0 # This loop call should ensure the queues of the parties are # processed in a more or less fair manner. This is necessary # because we have only one reactor for all parties here. def loop_call(): i = self.i for j in range(len(runtimes)): self.i = (self.i + 1) % len(runtimes) runtimes[(i + j) % len(runtimes)].process_deferred_queue() reactor.setLoopCall(loop_call) gatherResults(self.runtimes).addCallback(set_loop_call)
print "Not using SSL" listen = lambda port: reactor.listenTCP(port, factory) connect = lambda host, port: reactor.connectTCP(host, port, factory) port = players[id].port runtime.port = None delay = 2 while runtime.port is None: # We keep trying to listen on the port, but with an # exponentially increasing delay between each attempt. try: runtime.port = listen(port) except CannotListenError, e: if options and options.no_socket_retry: raise delay *= 1 + rand.random() print "Error listening on port %d: %s" % (port, e.socketError[1]) print "Will try again in %d seconds" % delay time.sleep(delay) print "Listening on port %d" % port for peer_id, player in players.iteritems(): if peer_id > id: print "Will connect to %s" % player connect(player.host, player.port) if runtime.using_viff_reactor: # Process the deferred queue after every reactor iteration. reactor.setLoopCall(runtime.process_deferred_queue) return result