I’m stuck on Stage #FI9, where we have to discover peers
I’ve tried a lot of bit manipulation. I also did research to see if there was a way to handle big endian in C. I saw htons() and ntohs(), but I struggle to understand how that quite works.
Here are my logs:
When I run locally:
sinmi@Sinmi:~/codecrafters-bittorrent-c$ gcc -g -o main app/*.c -lcrypto -lcurl -lssl -lm
sinmi@Sinmi:~/codecrafters-bittorrent-c$ ./main peers app/sample.torrent
165.232.41.73:51556
165.232.38.164:51493
165.232.35.114:51476
I suspect that this is wrong, because the ports of the last 2 ip address does not match what is expected from sample.torrent. However, I do not know what else to do because I am stuck
Here are the logs when I run on codecrafters
remote: [tester::#FI9] Running tests for Stage #FI9 (Discover peers)
remote: [tester::#FI9] Running ./your_bittorrent.sh peers /tmp/torrents1964150527/test.torrent
remote: [tester::#FI9] Tracker started on address 127.0.0.1:32791...
remote: [tester::#FI9]
remote: [your_program] 188.119.61.177:65505
remote: [your_program] 185.107.13.235:54542
remote: [your_program] 88.99.2.101:65505
remote: [tester::#FI9] Expected stdout to contain "188.119.61.177:6881", got: "188.119.61.177:65505\n185.107.13.235:54542\n88.99.2.101:65505\n"
remote: [tester::#FI9] Test failed
And here’s a snippet of my code:
Peers *get_peers(TrackerResp *response){
Peers *all_peers = malloc(sizeof(Peers));
// create a copy of response and find how many peers exist
char haystack[1024];
strcpy(haystack, response->data);
char *temp = strstr(haystack, "peers");
temp += strlen("peers");
// find out where peers start from in Tracker rESP
char *peers = NULL;
int peer_size = strtol(temp, &peers, 10);
peers += 1; // skip the ':'
// init peers struct.
all_peers->num_peers = peer_size / 6; // due to the compact
all_peers->peer = malloc(peer_size * sizeof(char *));
temp = peers;
int idx = 0;
for (int i = 0; i < all_peers->num_peers; i++)
{
// construct ip address and port number
uint8_t octet_1 = temp[idx] & 0xFF;
uint8_t octet_2 = temp[idx + 1] & 0xFF;
uint8_t octet_3 = temp[idx + 2] & 0xFF;
uint8_t octet_4 = temp[idx + 3] & 0xFF;
uint16_t port = (temp[idx + 4] << 8 | temp[idx + 5]);
// size required to store ip address and port
char temp_buf[1024];
int total = snprintf(temp_buf, 1024,
"%d.%d.%d.%d:%d",
octet_1, octet_2, octet_3, octet_4, port);
// save peer
char *peer_ip = malloc(total + 1);
strncpy(peer_ip, temp_buf, total);
peer_ip[total] = '\0';
all_peers->peer[i] = peer_ip;
idx += 6;
}
return all_peers;
}
The idea nehind calculating the port is that I need 2 bytes after the first 4 bytes. Given that each 8 bit is 1 byte, I figured the big endian implementation would be to put the 5th byte as upper 8 bits, and 6th byte as lower 8bits to give 16 bits in all, to represent the port.
At first, I though it was because snprintf writes null to a buffer by default, maybe that messed up my bit positioning, but I double checked, anmd that is not the case
Is my understanding wrong? If full code is needed, please let me know and I will post it