1

I decoded the nodes of find_node response from router.bittorrent.com to string, and sent a find_node request to the decoded "nodes" , but i never reviced find_node response from that "nodes", i doubt the way decode "node" is wrong, this is the code:

        byte[] nodesBytes = ((String)nodes).getBytes();
        ByteBuffer buffer = ByteBuffer.wrap(nodesBytes);
        int size = nodesBytes.length / 26;
        for (int i = 0; i < size; i++) {

            byte[] bytes = new byte[26];
            byte[] nodeIdBytes = Arrays.copyOfRange(bytes, 0, 20);
            byte[] ipBytes = Arrays.copyOfRange(bytes, 20, 24);
            byte[] portBytes = Arrays.copyOfRange(bytes, 24, 26);
            RoutingTable.RoutingNode routingNode = new RoutingTable.RoutingNode();
            try {
                routingNode.nodeId = nodeIdBytes;
                routingNode.ip = InetAddress.getByAddress(ipBytes);
                routingNode.port = (((((short)portBytes[1]) << 8) & 0xFF00) + (((short)portBytes[0]) & 0x00FF));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            send(routingNode);
        }

And the decode string code is

  private static String decodeString(ByteBuffer byteBuffer) {
    try {
        StringBuilder buffer = new StringBuilder();
        int type = byteBuffer.get();
        buffer.append((char) type);
        do {
            byte a = byteBuffer.get();
            if (a == SEPARATOR) {
                break;
            } else {
                buffer.append((char) a);
            }
        } while (true);

        int length = Integer.parseInt(buffer.toString());
        byte[] bytes = new byte[length];
        byteBuffer.get(bytes);
        String value = new String(bytes, "UTF-8");
        logger.debug(value);
        return value;
    } catch (Exception e) {
        logger.error("", e);
    }
    return "";
}

Any problem is there ?

PS: the send() function work well.

the8472
  • 40,999
  • 5
  • 70
  • 122
wang ming
  • 199
  • 2
  • 9

1 Answers1

0

((String)nodes).getBytes();

That assumes a particular encoding, which may not be appropriate for this case. It depends on what the bdecoder implementation you're using does. Ideally you should use a method that returns a byte[] or ByteBuffer directly from the bencoded data, without going through String

routingNode.port = (((((short)portBytes[1]) << 8) & 0xFF00) + (((short)portBytes[0]) & 0x00FF));

You should use | instead of +. Additionaly short is a signed type in java but ports are in the unsigned range of 0-65535, so you should expand to int instead. And the network format is bigendian, so the most significant bits of the port come in the 0th byte and the lower half in the 1st one, so you got that backwards too.

Using ByteBuffer instead of byte[] as I do in my own implementation can make this far less errorprone since it allows you to get a short directly and then convert it to an unsigned int.

the8472
  • 40,999
  • 5
  • 70
  • 122
  • I don't see how that is related. It's not even called in your code and doesn't address anything I have said. The identifiable issues in your code are bdecoding (String vs. ByteBuffer), endianness conversion and bit operations. – the8472 Aug 16 '17 at 16:55