brnby
brnby

Reputation: 1523

How to store two bytes in a BYTE array as an int (or something similar)?

I am writing a bittorrent client in C++ that receives a message from a tracker (server) containing several 6 byte strings. The first 4 bytes represent the IP address of a peer and the next 2 bytes represent the port number that the peer is listening on.

I have worked out how to convert the ip bytes into a human readable ip address but am struggling to convert the two bytes representing the port number into an int (or something similar)

Here are my efforts so far:

BYTE portbinary[2];
unsigned short peerport;

//trackers[i]->peersBinary[j * 6 + 4] is the first byte
portbinary[0] = trackers[i]->peersBinary[j * 6 + 4];
//trackers[i]->peersBinary[j * 6 + 5] is the second byte
portbinary[1] = trackers[i]->peersBinary[j * 6 + 5];
peerport = *portbinary;

Upon examination peerport only seems to contain the integer representation of the first byte, how might I be able to fix this?

Thanks in advance :)

Upvotes: 0

Views: 1791

Answers (4)

Roman Saveljev
Roman Saveljev

Reputation: 2594

Solution with unions:

union port_extractor
{
    BYTE raw_port[2];
    unsigned short port_assembled;
};

This will work if your computer endianess is the same as of representation you fetch from the network. Sorry, I dont know how it comes by bittorrent protocol.

If the endianess is the opposite, then the solution you are bound to use is not as nice:

unsigned short port_assembled = (unsigned short)raw_port[first_byte] | ((unsigned short)raw_port[second_byte] << 8);
// first_byte = 0, second_byte = 1 or vice versa 
// depending on source data endianess

Upvotes: -1

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234484

I prefer using bitwise operations instead of type punning because it brings no issues with endianness at all (the port number comes as a big endian number, and many systems today are little endian).

int peerport = (portbinary[0] << 8) | portbinary[1];

Upvotes: 3

jxh
jxh

Reputation: 70412

Since portbinary is an array of BYTE, then *portbinary is equivalent to portbinary[0].

A portable way to to achieve your result could be:

peerport = portbinary[0];
peerport = 256*peerport + portbinary[1];

This assumes portbinary was delivered in network byte order.

Upvotes: 1

Ben Voigt
Ben Voigt

Reputation: 283684

Since it seems like the data is aligned, you can just use

peerport = ntohs(*(uint16_t *)(trackers[i]->peersBinary + j * 6 + 4));

Upvotes: 1

Related Questions