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