def _query_decoder(rpc_dict): """ Decode the given KRPC dictionary into a valid Query @see decode @return krpc_types.Query """ q = Query() q._from = basic_coder.decode_network_id(rpc_dict['a']['id']) q.rpctype = rpctype = rpc_dict['q'] if rpctype == 'ping': pass elif rpctype == 'find_node': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['target']) elif rpctype == 'get_peers': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['info_hash']) elif rpctype == 'announce_peer': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['info_hash']) # Try encoding the port (to ensure it is within range) basic_coder.encode_port(rpc_dict['a']['port']) q.port = rpc_dict['a']['port'] q.token = basic_coder.btol(rpc_dict['a']['token']) else: raise _ProtocolFormatError() return q
def test_ltob_and_btol(self): bijection = lambda num: btol(ltob(num)) self.assertEqual(0, bijection(0)) self.assertEqual(512, bijection(512)) self.assertEqual(1024, bijection(1024)) self.assertEqual(9120890186313616, bijection(9120890186313616)) self.assertEqual(2**150, bijection(2**150)) self.assertEqual(2**133, bijection(2**133))
def _decode(packet): """@see decode""" # Decode the bencoded dict into a python dict rpc_dict = bdecode(packet) # Decode the message into one of Query/Response/Error (as found # in message_types) msgtype = rpc_dict["y"] message_decoders = {'q': _query_decoder, 'r': _response_decoder, 'e': _error_decoder} rpc = message_decoders[msgtype](rpc_dict) # Attach the transaction id rpc._transaction_id = basic_coder.btol(rpc_dict['t']) return rpc
def _decode(packet): """@see decode""" # Decode the bencoded dict into a python dict rpc_dict = bdecode(packet) # Decode the message into one of Query/Response/Error (as found # in message_types) msgtype = rpc_dict["y"] message_decoders = { 'q': _query_decoder, 'r': _response_decoder, 'e': _error_decoder } rpc = message_decoders[msgtype](rpc_dict) # Attach the transaction id rpc._transaction_id = basic_coder.btol(rpc_dict['t']) return rpc
def _get_hash(self, query, address, secret): """ Create the hash code for the given query/address/secret combination """ node_id = query._from infohash = query.target_id hash = self.hash_constructor() # The hash code relies on the querying node's ID, # the target infohash of the query, the address of # the querier, and a secret that changes every # constants._secret_timeout seconds hash.update(basic_coder.encode_network_id(node_id)) hash.update(basic_coder.encode_network_id(infohash)) hash.update(basic_coder.encode_address(address)) hash.update(secret) # Return the hash as a number rather than a string numeric_hash_value = basic_coder.btol(hash.digest()) return numeric_hash_value
def _response_decoder(rpc_dict): """ Decode the given KRPC dictionary into a valid Response @see decode @return krpc_types.Response """ r = Response() # All responses have querier IDs r._from = basic_coder.decode_network_id(rpc_dict['r']['id']) # find_node always returns a list of nodes # get_peers sometimes returns a list of nodes if 'nodes' in rpc_dict['r']: r.nodes = _decode_nodes(rpc_dict['r']['nodes']) # get_peers always returns a list of peers if 'values' in rpc_dict['r']: r.peers = _decode_addresses(rpc_dict['r']['values']) # get_peers returns a token if 'token' in rpc_dict['r']: r.token = basic_coder.btol(rpc_dict['r']['token']) return r
def __hash__(self): return basic_coder.btol(encode_node(self))