user3421416
user3421416

Reputation:

How can I decode the peers value in the tracker response (Bittorent)

I am trying to implement the bittorent protocl by myself, and I have problem with decoding the "Peers" value within the tracker response using c++.

Accordign to the bittorent protocol documentation:

peers: (binary model) Instead of using the dictionary model described above, the peers value may be a string consisting of multiples of 6 bytes. First 4 bytes are the IP address and last 2 bytes are the port number. All in network (big endian) notation.

How can I decode these ip and port number using c++?

I have treid this code, bit it is not correct:

void DecodePeers(OrderedMap<std::string, int> &map, const char * buffer, int i)
{
    int counter = 0;



    while (*(buffer + counter) != NULL)
    {

        //std::vector<TByte> portNum;
        short port;

        for (int i = counter; i < counter + 4; i++)
        {
            //*(peerIp + i - counter) = *(buffer + i);
        }

        counter += 4;

        //*(peerIp + 4) = '\0';
        char twobytes[2];

        twobytes[0] = *(buffer + counter + 0);
        twobytes[1] = *(buffer + counter + 1);

        unsigned int x;
        std::stringstream ss;
        ss << std::hex << twobytes[0];
        ss >> x;
        // output it as a signed type
        std::cout << static_cast<int>(x) << std::endl;

        port = ((twobytes[1] << 8) | twobytes[0]);
        //port = (short) twobytes;
        counter += 2;

        //std::string str(portNum.begin(), portNum.end());

        std::cout << std::endl;

        std::cout << port << std::endl ;

        char  * bbuffer = new char[100];

        for (int i = 0; i < 1; i++) {
            //unsigned int inte = (unsigned int)str;(
            //_itoa_s((int) *str.c_str(), bbuffer, 100, 10);
            //sprintf_s(bbuffer, 50, (const char *) "%d", str.c_str());
        }

        std::cout << std::endl;
        //int port = atoi(portNum);
        //map.Insert(str, port);
    }

}

Someone know how can I translate this numbers to a number - readable response?

Example of peers value: P^L♠*j.t╤u→πe199711

Upvotes: 1

Views: 368

Answers (2)

Marco
Marco

Reputation: 2020

I tried to use this code on your buffer to decode bittorrent protocol peers

#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    char *buf = "P^L♠*j.t╤u→πe199711";
    int chunks = strlen(buf) / 6 ;
    int offset =  0;
    unsigned char *ip;
    unsigned short *port;
    int recsDone = 0;
    while (recsDone++ <= chunks){
        ip   = (unsigned char *) buf+offset;
        port = (unsigned short *) buf+offset+4;
        printf("%s - %d\n",inet_ntoa(*(in_addr*)ip),ntohs(*port));
        offset+=6;
    }
}

and I get this as output:

80.94.76.226 - 11892 42.106.46.116 - 12601

Please let us know ifit works.

Upvotes: 2

rodolk
rodolk

Reputation: 5907

I haven't worked with this protocol and the code shown is a bit confusing. I don't know what is peerIp for example. But based on the description of the field in peer_id, https://wiki.theory.org/BitTorrentSpecification#peer_id, I would suggest:

#include <arpa/inet.h>
#include <stdint.h>
#include <stdio.h>

uint32_t *peerIPAux;

struct sockaddr_in peer_data;
char str[INET_ADDRSTRLEN];
uint16_t *peer_port_ptr;
uint16_t peer_port;

//Here we need to test if IPv4 address, represented in an integer value is 
//actually in network notation or not. First assume what documentation says 
//is true (it is in network notation)

//INSIDE THE WHILE LOOP

peerIPAux = (uint32_t *)(buffer + counter);
peer_data.sin_addr.s_addr = ntohl(*peerIPAux); //If this doesn't work try without ntohl

//http://linux.die.net/man/3/inet_ntop

inet_ntop(AF_INET, &(peer_data.sin_addr), str, INET_ADDRSTRLEN); //check error code here

printf("%s\n", str); // or std::cout << str << std::endl;

counter += 4;
peer_port_ptr = (uint16_t *) (buffer + counter);

peer_port = ntohs(*peer_port_ptr);

printf("PORT: %d", peer_port); // in C
....

Upvotes: 0

Related Questions