#NV6 Why the same stage, in the nv6 stage in cant work?

else if(command == "magnet_info") {
    string magnet_link = argv[2];
    auto key_val = parse_magnet(magnet_link);
    vector<string> ips;
    vector<uint16_t> ports;
    handle_magnet_peers(key_val["tr"], key_val["xt"], ips, ports);
    int metadata_id = 0;
    int sockfd = handle_magnet_handshake(ips[0], ports[0], key_val["xt"], metadata_id);
    json metadata = handle_magnet_info(sockfd, metadata_id, 0);
    /*
    Tracker URL: http://bittorrent-test-tracker.codecrafters.io/announce
    Length: 92063
    Info Hash: d69f91e6b2ae4c542468d1073a71d4ea13879a7f
    Piece Length: 32768
    Piece Hashes:
    6e2275e604a0766656736e81ff10b55204ad8d35
    e876f67a2a8886e8f36b136726c30fa29703022d
    f00d937a0213df1982bc8d097227ad9e909acc17
    */
    for (auto it = metadata.begin(); it != metadata.end(); ++it) {
        std::cout << it.key() << std::endl;
    }
    cout << "Tracker URL: " << key_val["tr"] << "\n";
    cout << "Length: " << metadata.at("length") << "\n";
    cout << "Info Hash: " << key_val["xt"] << "\n";
    cout << "Piece Length: " <<  metadata.at("piece length") << "\n";
    cout << "Piece Hashes:" << "\n";
    string hashes  = metadata.at("pieces").get<string>();
    vector<uint8_t> pieces(hashes.begin(), hashes.end());
    for (size_t i = 0; i < pieces.size(); ++i) {
        if(i % 20 == 0 && i) {
            cout << "\n";
        }
        printf("%02x", pieces[i]);
    }
    cout << "\n";
  } else if(command == "magnet_download_piece") {
    // ./your_program.sh magnet_download_piece -o /tmp/test-piece-0 <magnet-link> 0
    string magnet_link = "magnet:?xt=urn:btih:ad42ce8109f54c99613ce38f9b4d87e70f24a165&dn=magnet1.gif&tr=http%3A%2F%2Fbittorrent-test-tracker.codecrafters.io%2Fannounce";
    auto key_val = parse_magnet(magnet_link);
    vector<string> ips;
    vector<uint16_t> ports;
    handle_magnet_peers(key_val["tr"], key_val["xt"], ips, ports);
    int metadata_id = 0;
    int sockfd = handle_magnet_handshake(ips[0], ports[0], key_val["xt"], metadata_id);
    unsigned piece_index = atoi(argv[5]);
    cout << "download piece: " << piece_index << "\n";
    json metadata = handle_magnet_info(sockfd, metadata_id, piece_index);
    int64_t piece_length = metadata.at("piece length").get<int64_t>();
    int64_t length = metadata.at("length").get<int64_t>();
    cout << "Tracker URL: " << key_val["tr"] << "\n";
    cout << "Length: " << metadata.at("length") << "\n";
    cout << "Info Hash: " << key_val["xt"] << "\n";
    cout << "Piece Length: " <<  metadata.at("piece length") << "\n";
    cout << "Piece Hashes:" << "\n";
    string hashes  = metadata.at("pieces").get<string>();
    vector<uint8_t> pieces_tmp(hashes.begin(), hashes.end());
    for (size_t i = 0; i < pieces_tmp.size(); ++i) {
        if(i % 20 == 0 && i) {
            cout << "\n";
        }
        printf("%02x", pieces_tmp[i]);
    }
    cout << "\n";
    int piece_cnt = (length + piece_length) / piece_length;
    int cur_piece_length = (piece_index + 1 == piece_cnt) ? length - (piece_index) * piece_length : piece_length;
    int block_count = (cur_piece_length + 16383) / 16384;
    // cout << "block_count = " << block_count << endl;
    vector<struct Piece> pieces;
    for(int i = 0; i < block_count; i++) {
      int cur_length = (i == block_count - 1) ? cur_piece_length - (i) * 16384 : 16384;
      unsigned begin_index = i * 16384;
      download_block(sockfd, piece_index, begin_index, cur_length);
      struct Piece piece = wait_block(sockfd);
      pieces.emplace_back(piece);
    }
    
    return write_to_file(argv[3], pieces) && handle_wave(sockfd);
  } 

remote: [your_program] 139.59.184.255:51465
remote: [your_program] 165.232.35.139:51427
remote: [your_program] 167.71.143.54:51547
remote: [your_program] Peer ID: 2d524e302e302e302da410a9e293e56db57b9c92
remote: [your_program] Peer Metadata Extension ID: 1
remote: [your_program] download piece: 1
remote: [your_program] before recv metadata recv n = 0
remote: [your_program] recv n = 0
remote: [tester::#QV6] Application didn’t terminate successfully without errors. Expected 0 as exit code, got: 139
remote: [tester::#QV6] Test failed (try setting ‘debug: true’ in your codecrafters.yml to see more details)

json handle_magnet_info(const int sockfd, unsigned char metadata_id, unsigned int piece) {
    // send Request metadata
    unsigned char send_data[1024];
    send_data[4] = 20;
    send_data[5] = metadata_id; // use ut_metadata extended message id from peer
    json object;
    object["msg_type"] = 0;
    object["piece"] = piece;
    string object_str = encode_bencode_value(object);
    unsigned int msg_len = htonl(2 + object_str.size()); // length prefix = 1 (ID only)
    memcpy(send_data, &msg_len, 4);
    memcpy(send_data + 6, object_str.c_str(), object_str.size());
    if(send(sockfd, send_data, 4 + 1 + 1 + object_str.size(), 0) != 4 + 1 + 1 + object_str.size()) {
      cout << "fuck send" << endl;
      return object;
    }


    // recv metadata
    vector<uint8_t> recv_buf;
    ssize_t n = 0;
    unsigned int prefix_len;
    cout << "before recv metadata recv n = " << n << endl;
    n = read_nbytes(sockfd, recv_buf, 5);
    cout << "recv n = " << n << endl;

They all call the function(handle_magnet_info), but in the NV6 stage, it can not recv bytes

Hey @mmjwxbc, could you upload your code to GitHub and share the link? It will be much easier to debug if I can run it directly.

This is my github link: mmjwxbc/codecrafters-bittorrent-cpp. I’m so confused about the magent_info and magnet_download_piece function, they both has same stage(parse_magnet, find_peers, tcp connect, magnet_handshake), but it failed in the magnet_download_piece stage.

think I may have solved this problem. When downloading a file from a magnet link in BitTorrent, do I also need to send an “interested” message?