def test_bytes(self):
        self.assertEqual(bencode(b''), b'0:')
        self.assertEqual(bencode(b'spam'), b'4:spam')
        self.assertEqual(bencode(b'4:spam'), b'6:4:spam')
        self.assertEqual(bencode(bytearray(b'spam')), b'4:spam')

        self.assertEqual(bdecode(b'0:'), b'')
        self.assertEqual(bdecode(b'4:spam'), b'spam')
        self.assertEqual(bdecode(b'6:4:spam'), b'4:spam')
Example #2
0
 def _sendResponse(self, contact, rpcID, response):
     """ Send a RPC response to the specified contact
     """
     msg = msgtypes.ResponseMessage(rpcID, self._node.node_id, response)
     msgPrimitive = self._translator.toPrimitive(msg)
     encodedMsg = encoding.bencode(msgPrimitive)
     self._send(encodedMsg, rpcID, (contact.address, contact.port))
    def test_mixed(self):
        self.assertEqual(
            bencode([[b'abc', b'127.0.0.1', 1919],
                     [b'def', b'127.0.0.1', 1921]]),
            b'll3:abc9:127.0.0.1i1919eel3:def9:127.0.0.1i1921eee')

        self.assertEqual(
            bdecode(b'll3:abc9:127.0.0.1i1919eel3:def9:127.0.0.1i1921eee'),
            [[b'abc', b'127.0.0.1', 1919], [b'def', b'127.0.0.1', 1921]])
Example #4
0
 def _sendError(self, contact, rpcID, exceptionType, exceptionMessage):
     """ Send an RPC error message to the specified contact
     """
     exceptionMessage = exceptionMessage.encode()
     msg = msgtypes.ErrorMessage(rpcID, self._node.node_id, exceptionType,
                                 exceptionMessage)
     msgPrimitive = self._translator.toPrimitive(msg)
     encodedMsg = encoding.bencode(msgPrimitive)
     self._send(encodedMsg, rpcID, (contact.address, contact.port))
    def test_dict(self):
        self.assertEqual(bencode({
            b'foo': 42,
            b'bar': b'spam'
        }), b'd3:bar4:spam3:fooi42ee')

        self.assertEqual(bdecode(b'd3:bar4:spam3:fooi42ee'), {
            b'foo': 42,
            b'bar': b'spam'
        })
    def test_integer(self):
        self.assertEqual(bencode(42), b'i42e')

        self.assertEqual(bdecode(b'i42e'), 42)
    def test_list(self):
        self.assertEqual(bencode([b'spam', 42]), b'l4:spami42ee')

        self.assertEqual(bdecode(b'l4:spami42ee'), [b'spam', 42])
 def test_string(self):
     self.assertEqual(bencode(''), b'0:')
     self.assertEqual(bencode('spam'), b'4:spam')
     self.assertEqual(bencode('4:spam'), b'6:4:spam')
Example #9
0
    def _sendRPC(self, contact, method, args):
        """
        Sends an RPC to the specified contact

        @param contact: The contact (remote node) to send the RPC to
        @type contact: kademlia.contacts.Contact
        @param method: The name of remote method to invoke
        @type method: str
        @param args: A list of (non-keyword) arguments to pass to the remote
                    method, in the correct order
        @type args: tuple

        @return: This immediately returns a deferred object, which will return
                 the result of the RPC call, or raise the relevant exception
                 if the remote node raised one. If C{rawResponse} is set to
                 C{True}, however, it will always return the actual response
                 message (which may be a C{ResponseMessage} or an
                 C{ErrorMessage}).
        @rtype: twisted.internet.defer.Deferred
        """
        msg = msgtypes.RequestMessage(
            self._node.node_id, method,
            self._migrate_outgoing_rpc_args(contact, method, *args))
        msgPrimitive = self._translator.toPrimitive(msg)
        encodedMsg = encoding.bencode(msgPrimitive)

        if args:
            log.debug("%s:%i SEND CALL %s(%s) TO %s:%i",
                      self._node.externalIP, self._node.port, method,
                      hexlify(args[0]), contact.address, contact.port)
        else:
            log.debug("%s:%i SEND CALL %s TO %s:%i", self._node.externalIP,
                      self._node.port, method, contact.address, contact.port)

        df = defer.Deferred()

        def _remove_contact(
            failure
        ):  # remove the contact from the routing table and track the failure
            contact.update_last_failed()
            try:
                if not contact.contact_is_good:
                    self._node.removeContact(contact)
            except (ValueError, IndexError):
                pass
            return failure

        def _update_contact(
                result):  # refresh the contact in the routing table
            contact.update_last_replied()
            if method == b'findValue':
                if b'token' in result:
                    contact.update_token(result[b'token'])
                if b'protocolVersion' not in result:
                    contact.update_protocol_version(0)
                else:
                    contact.update_protocol_version(
                        result.pop(b'protocolVersion'))
            d = self._node.addContact(contact)
            d.addCallback(lambda _: result)
            return d

        df.addCallbacks(_update_contact, _remove_contact)

        # Set the RPC timeout timer
        timeoutCall, cancelTimeout = self._node.reactor_callLater(
            constants.rpcTimeout, self._msgTimeout, msg.id)

        # Transmit the data
        self._send(encodedMsg, msg.id, (contact.address, contact.port))
        self._sentMessages[msg.id] = (contact, df, timeoutCall, cancelTimeout,
                                      method, args)

        df.addErrback(cancelTimeout)
        return df