Stuck at Discover peers #fi9

I’m stuck on Stage #fi9

According to me, my code is working fine, but the tests themselves are failing. I suppose that the IP of the peers is changing and the tests aren’t updated. Can someone confirm if the tests are fine?

Here are my logs:

$ ./Debug/bittorrent.exe peers sample.torrent
165.232.41.73:51556
232.41.73.201:25765
41.73.201.100:42472

Here are the test logs

remote:
remote: [tester::#FI9] Running tests for Stage #FI9 (Discover peers)
remote: [tester::#FI9] Running ./your_bittorrent.sh peers /tmp/torrents1422977794/test.torrent
remote: [your_program] 188.119.61.177:6881
remote: [your_program] 119.61.177.26:57671
remote: [your_program] 61.177.26.225:18400
remote: [your_program] 177.26.225.71:57344
remote: [your_program] 26.225.71.224:29
remote: [your_program] 225.71.224.0:7624
remote: [your_program] 71.224.0.29:51414
remote: [your_program] 224.0.29.200:54846
remote: [your_program] 0.29.200.214:16025
remote: [tester::#FI9] Expected stdout to contain "62.153.208.98:3652", got: "188.119.61.177:6881\n119.61.177.26:57671\n61.177.26.225:18400\n177.26.225.71:57344\n26.225.71.224:29\n225.71.224.0:7624\n71.224.0.29:51414\n224.0.29.200:54846\n0.29.200.214:16025\n"
remote: [tester::#FI9] Test failed (try setting 'debug: true' in your codecrafters.yml to see more details)
remote:

And here’s a snippet of my code:

std::vector<uint8_t> convert_string_to_bytes(const std::string& pieceHashes) {
    // std::cout << "hash size: " << pieceHashes.size() << "\n";
    std::vector<uint8_t> byteList(pieceHashes.size());
    int idx = 0;
    for (char c : pieceHashes) {
        byteList[idx++] = c;
    }

    return std::move(byteList);
}

main(){
    if (command == "peers") {
        if (argc < 3) {
            std::cerr << "Usage: " << argv[0] << " peers <path/to/torrent/file>" << std::endl;
            return 1;
        }

        std::string torrent_path = argv[2];
        json decoded_value = parse_torrent_file(torrent_path);

        std::string tracker_url;
        decoded_value["announce"].get_to(tracker_url);

        std::string domain = tracker_url.substr(0, tracker_url.find_last_of('/'));
        std::string endpoint = tracker_url.substr(tracker_url.find_last_of('/'));

        httplib::Client cli(domain);

        std::string infoHash = getInfoHash(decoded_value["info"]);
        std::string httpEncodedHash = "";
        for (int i = 0; i < infoHash.size(); i += 2) {
            httpEncodedHash += '%' + infoHash.substr(i, 2);
        }

        std::string peer_id = "hahahahahahahahahaha";
        
        int uploaded = 0;
        int downloaded = 0;
        int left = decoded_value["info"]["length"];
        int compact = 1;

        httplib::Params params{
            {"peer_id", peer_id},
            {"port", "6881"},
            {"uploaded", "0"},
            {"downloaded", "0"},
            {"left", std::to_string(left)},
            {"compact", "1"}
        };
        httplib::Headers headers{};

        auto res = cli.Get(endpoint + "?info_hash=" + httpEncodedHash, params, headers);
        json responseJson = decode_bencoded_value(res->body);
        //std::cout << responseJson["interval"];

        const auto peers = responseJson["peers"];
        auto peerBytes = convert_string_to_bytes(peers);

        const int numPeers = peerBytes.size() / 6; //size of each peer is 6 bytes. First 4 bytes are the IP, last 2 are the port
        std::vector<std::string> out(numPeers);
        for (int i = 0; i < numPeers; i++) {
            std::ostringstream os;
            const std::string ipAddr = std::to_string(peerBytes[i]) + "." + std::to_string(peerBytes[i+1]) + "." + std::to_string(peerBytes[i+2]) + "." + std::to_string(peerBytes[i+3]);
            const int port = ((int)peerBytes[i + 4] << 8) + (int)peerBytes[i + 5];
            os << ipAddr << ":" << port;
            out[i] = os.str();
            std::cout << out[i]<<'\n';
        }

    }
}

Hi nukex1122,
Tests are up to date, your IP address conversion is incorrect. These are the peers you should see with sample.torrent

165.232.41.73:51556
165.232.38.164:51532
165.232.35.114:51437

Could you help me in figuring out what’s wrong with it?

nevermind. Figured it out. I’m choosing the wrong bytes. i is getting incremented by 1 but I’m not multiplying by 6 when fetching the bytes

2 Likes

I am still stuck I dont know whats wrong

    axios
      .get(requestUrl, { responseType: "arraybuffer" })
      .then((response: { data: any }) => {
        const decodedResponse = decodeBencode(
          response.data.toString("binary")
        ) as unknown as TrackerResponse;
        // console.log(decodedResponse);
        const peers: any = Buffer.from(decodedResponse.peers);
        // console.log("Peers:", peers);
        const peerList: string[] = [];
        for (let i = 0; i < peers.length; i += 6) {
          const ip = `${peers[i]}.${peers[i + 1]}.${peers[i + 2]}.${
            peers[i + 3]
          }`;
          const port = (peers[i + 4] << 8) + peers[i + 5];
          peerList.push(`${ip}:${port}`);
        }
        // console.log("Peers: ");
        peerList.forEach((x) => console.log(x));
      })
      .catch((error: { message: any }) => {
        console.error(error.message);
      });
  }

@rafterjob1 if you expect help on this forum, you’ll need to share proper details. No one can help you if all you do is paste a bunch of code (that too without formatting!) and mention nothing about what’s wrong.

I’d recommend opening a separate thread with more details.