class hostbroker(Handler, DatagramProtocol): def __init__(self, server, addr, call_later): self.server = server self.addr = addr self.call_later = call_later def actually_start(self, transport, max_ul_rate, config, rlcount): self.transport = transport self.rltransport = KRateLimiter(transport, max_ul_rate, self.call_later, rlcount, config['max_rate_period']) self.connections = Cache(touch_on_access=True) self.hammerlock = Hammerlock(100, self.call_later) self.expire_connections(loop=True) self.config = config if not self.config.has_key('pause'): self.config['pause'] = False def expire_connections(self, loop=False): self.connections.expire(bttime() - KRPC_CONNECTION_CACHE_TIME) if loop: self.call_later(KRPC_CONNECTION_CACHE_TIME, self.expire_connections, True) def datagramReceived(self, datagram, addr): self.data_came_in(addr, datagram) def data_came_in(self, addr, datagram): #if addr != self.addr: if not self.config['pause'] and self.hammerlock.check(addr): c = self.connectionForAddr(addr) c.datagramReceived(datagram, addr) def connection_lost(self, socket): ## this is like, bad print ">>> connection lost!", socket def connectionForAddr(self, addr): if addr == self.addr: raise KRPCSelfNodeError() if not self.connections.has_key(addr): conn = KRPC(addr, self.server, self.transport, self.rltransport, self.call_later) self.connections[addr] = conn else: conn = self.connections[addr] return conn
class UTKhashmir(khashmir.KhashmirBase): _Node = UTNode def setup(self, host, port, data_dir, rlcount, checkpoint=True): khashmir.KhashmirBase.setup(self, host, port, data_dir, rlcount, checkpoint) self.cur_token = self.last_token = sha('') self.tcache = Cache() self.gen_token(loop=True) self.expire_cached_tokens(loop=True) def expire_cached_tokens(self, loop=False): self.tcache.expire(time() - TOKEN_UPDATE_INTERVAL) if loop: self.add_task(TOKEN_UPDATE_INTERVAL, self.expire_cached_tokens, True) def gen_token(self, loop=False): self.last_token = self.cur_token self.cur_token = sha(newID()) if loop: self.add_task(TOKEN_UPDATE_INTERVAL, self.gen_token, True) def get_token(self, host, port): x = self.cur_token.copy() x.update("%s%s" % (host, port)) h = x.digest() return h def val_token(self, token, host, port): x = self.cur_token.copy() x.update("%s%s" % (host, port)) a = x.digest() if token == a: return True x = self.last_token.copy() x.update("%s%s" % (host, port)) b = x.digest() if token == b: return True return False def add_contact(self, host, port, callback=None): if khashmir.ip_pat.match(host): self._got_host(host, port, callback) else: d = getHostByName(host) d.addCallback(self._got_host, port, callback) d.addErrback(log_ex, "failed to lookup address for host=%s" % (host)) def _got_host(self, host, port, callback): khashmir.KhashmirBase.add_contact(self, host, port, callback) def announce_peer(self, info_hash, port, callback=None): """ stores the value for key in the global table, returns immediately, no status in this implementation, peers respond but don't indicate status to storing values a key can have many values """ def _storeValueForKey(nodes, key=info_hash, value=port, response=callback , table=self.table): if not response: # default callback def _storedValueHandler(sender): pass response=_storedValueHandler action = UTStoreValue(self, key, value, response, self.add_task, "announce_peer") self.add_task(0, action.goWithNodes, nodes) # this call is asynch self.findNode(info_hash, _storeValueForKey) def krpc_announce_peer(self, info_hash, port, id, token, _krpc_sender): sender = {'id' : id} sender['host'] = _krpc_sender[0] sender['port'] = _krpc_sender[1] if not self.val_token(token, sender['host'], sender['port']): raise KRPCProtocolError("Invalid Write Token") value = compact_peer_info(_krpc_sender[0], port) self.store[info_hash] = value n = self.Node().initWithDict(sender) self.insertNode(n, contacted=0) return {"id" : self.node.id} def retrieve_values(self, key): try: l = self.store.sample(key, NUM_PEERS) except KeyError: l = [] return l def get_peers(self, info_hash, callback, searchlocal = 1): """ returns the values found for key in global table callback will be called with a list of values for each peer that returns unique values final callback will be an empty list - probably should change to 'more coming' arg """ nodes = self.table.findNodes(info_hash, invalid=True) l = [x for x in nodes if x.invalid] if len(l) > 4: nodes = sample(l , 4) + self.table.findNodes(info_hash, invalid=False)[:4] # get locals if searchlocal: l = self.retrieve_values(info_hash) if len(l) > 0: self.add_task(0, callback, [reducePeers(l)]) else: l = [] # create our search state state = GetValue(self, info_hash, callback, self.add_task, 'get_peers') self.add_task(0, state.goWithNodes, nodes, l) def get_peers_and_announce(self, info_hash, port, callback, searchlocal = 1): """ returns the values found for key in global table callback will be called with a list of values for each peer that returns unique values final callback will be an empty list - probably should change to 'more coming' arg """ nodes = self.table.findNodes(info_hash, invalid=False) nodes += self.table.findNodes(info_hash, invalid=True) # get locals if searchlocal: l = self.retrieve_values(info_hash) if len(l) > 0: self.add_task(0, callback, [reducePeers(l)]) else: l = [] # create our search state x = lambda a: a state = GetAndStore(self, info_hash, port, callback, x, self.add_task, 'get_peers', "announce_peer") self.add_task(0, state.goWithNodes, nodes, l) def krpc_get_peers(self, info_hash, id, _krpc_sender): sender = {'id' : id} sender['host'] = _krpc_sender[0] sender['port'] = _krpc_sender[1] n = self.Node().initWithDict(sender) self.insertNode(n, contacted=0) l = self.retrieve_values(info_hash) if len(l) > 0: return {'values' : [reducePeers(l)], "id": self.node.id, "token" : self.get_token(sender['host'], sender['port'])} else: nodes = self.table.findNodes(info_hash, invalid=False) nodes = [node.senderDict() for node in nodes] return {'nodes' : packNodes(nodes), "id": self.node.id, "token" : self.get_token(sender['host'], sender['port'])}
class UTKhashmir(khashmir.KhashmirBase): _Node = UTNode def setup(self, host, port, data_dir, rlcount, checkpoint=True): khashmir.KhashmirBase.setup(self, host, port, data_dir, rlcount, checkpoint) self.cur_token = self.last_token = sha('') self.tcache = Cache() self.gen_token(loop=True) self.expire_cached_tokens(loop=True) def expire_cached_tokens(self, loop=False): self.tcache.expire(time() - TOKEN_UPDATE_INTERVAL) if loop: self.add_task(TOKEN_UPDATE_INTERVAL, self.expire_cached_tokens, True) def gen_token(self, loop=False): self.last_token = self.cur_token self.cur_token = sha(newID()) if loop: self.add_task(TOKEN_UPDATE_INTERVAL, self.gen_token, True) def get_token(self, host, port): x = self.cur_token.copy() x.update("%s%s" % (host, port)) h = x.digest() return h def val_token(self, token, host, port): x = self.cur_token.copy() x.update("%s%s" % (host, port)) a = x.digest() if token == a: return True x = self.last_token.copy() x.update("%s%s" % (host, port)) b = x.digest() if token == b: return True return False def add_contact(self, host, port, callback=None): if khashmir.ip_pat.match(host): self._got_host(host, port, callback) else: d = getHostByName(host) d.addCallback(self._got_host, port, callback) d.addErrback(log_ex, "failed to lookup address for host=%s" % (host)) def _got_host(self, host, port, callback): khashmir.KhashmirBase.add_contact(self, host, port, callback) def announce_peer(self, info_hash, port, callback=None): """ stores the value for key in the global table, returns immediately, no status in this implementation, peers respond but don't indicate status to storing values a key can have many values """ def _storeValueForKey(nodes, key=info_hash, value=port, response=callback, table=self.table): if not response: # default callback def _storedValueHandler(sender): pass response = _storedValueHandler action = UTStoreValue(self, key, value, response, self.add_task, "announce_peer") self.add_task(0, action.goWithNodes, nodes) # this call is asynch self.findNode(info_hash, _storeValueForKey) def krpc_announce_peer(self, info_hash, port, id, token, _krpc_sender): sender = {'id': id} sender['host'] = _krpc_sender[0] sender['port'] = _krpc_sender[1] if not self.val_token(token, sender['host'], sender['port']): raise KRPCProtocolError("Invalid Write Token") value = compact_peer_info(_krpc_sender[0], port) self.store[info_hash] = value n = self.Node().initWithDict(sender) self.insertNode(n, contacted=0) return {"id": self.node.id} def retrieve_values(self, key): try: l = self.store.sample(key, NUM_PEERS) except KeyError: l = [] return l def get_peers(self, info_hash, callback, searchlocal=1): """ returns the values found for key in global table callback will be called with a list of values for each peer that returns unique values final callback will be an empty list - probably should change to 'more coming' arg """ nodes = self.table.findNodes(info_hash, invalid=True) l = [x for x in nodes if x.invalid] if len(l) > 4: nodes = sample(l, 4) + self.table.findNodes(info_hash, invalid=False)[:4] # get locals if searchlocal: l = self.retrieve_values(info_hash) if len(l) > 0: self.add_task(0, callback, [reducePeers(l)]) else: l = [] # create our search state state = GetValue(self, info_hash, callback, self.add_task, 'get_peers') self.add_task(0, state.goWithNodes, nodes, l) def get_peers_and_announce(self, info_hash, port, callback, searchlocal=1): """ returns the values found for key in global table callback will be called with a list of values for each peer that returns unique values final callback will be an empty list - probably should change to 'more coming' arg """ nodes = self.table.findNodes(info_hash, invalid=False) nodes += self.table.findNodes(info_hash, invalid=True) # get locals if searchlocal: l = self.retrieve_values(info_hash) if len(l) > 0: self.add_task(0, callback, [reducePeers(l)]) else: l = [] # create our search state x = lambda a: a state = GetAndStore(self, info_hash, port, callback, x, self.add_task, 'get_peers', "announce_peer") self.add_task(0, state.goWithNodes, nodes, l) def krpc_get_peers(self, info_hash, id, _krpc_sender): sender = {'id': id} sender['host'] = _krpc_sender[0] sender['port'] = _krpc_sender[1] n = self.Node().initWithDict(sender) self.insertNode(n, contacted=0) l = self.retrieve_values(info_hash) if len(l) > 0: return { 'values': [reducePeers(l)], "id": self.node.id, "token": self.get_token(sender['host'], sender['port']) } else: nodes = self.table.findNodes(info_hash, invalid=False) nodes = [node.senderDict() for node in nodes] return { 'nodes': packNodes(nodes), "id": self.node.id, "token": self.get_token(sender['host'], sender['port']) }