From b5cf2e8439d73b96f337ad83d212171406905c44 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 13 Apr 2013 21:16:04 +0000 Subject: [PATCH] generalize command line parsing of connection_tester and add feature to serve corrupt pieces every now and then --- examples/connection_tester.cpp | 179 ++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 58 deletions(-) diff --git a/examples/connection_tester.cpp b/examples/connection_tester.cpp index 72a89e319..c44604169 100644 --- a/examples/connection_tester.cpp +++ b/examples/connection_tester.cpp @@ -66,6 +66,10 @@ void generate_block(boost::uint32_t* buffer, int piece, int start, int length) int local_if_counter = 0; bool local_bind = false; +// if this is true, one block in 1000 will be sent corrupt. +// this only applies to dual and upload tests +bool test_corruption = false; + // number of seeds we've spawned. The test is terminated // when this reaches zero, for dual tests static boost::detail::atomic_count num_seeds(0); @@ -103,6 +107,7 @@ struct peer_conn , num_pieces(num_pieces) , start_time(time_now_hires()) { + corruption_counter = rand() % 1000; if (seed) ++num_seeds; pieces.reserve(num_pieces); if (local_bind) @@ -134,6 +139,7 @@ struct peer_conn boost::uint32_t write_buffer[17*1024/4]; boost::uint32_t buffer[17*1024/4]; int read_pos; + int corruption_counter; enum state_t { @@ -518,6 +524,16 @@ struct peer_conn void write_piece(int piece, int start, int length) { generate_block(write_buffer, piece, start, length); + + if (test_corruption) + { + --corruption_counter; + if (corruption_counter == 0) + { + corruption_counter = 1000; + memset(write_buffer, 0, 10); + } + } char* ptr = write_buf_proto; write_uint32(9 + length, ptr); assert(length == 0x4000); @@ -543,34 +559,36 @@ struct peer_conn void print_usage() { - fprintf(stderr, "usage: connection_tester command ...\n\n" + fprintf(stderr, "usage: connection_tester command [options]\n\n" "command is one of:\n" - " gen-torrent generate a test torrent\n" - " this command takes two extra arguments:\n" - " 1. the size of the torrent in megabytes\n" - " 2. the number of files in the test torrent\n" - " 3. the file to save the .torrent file to\n\n" - " gen-data generate the data file(s) for the test torrent\n" - " this command takes two extra arguments:\n" - " 1. the torrent file that was previously generated\n" - " 2. the path to where the data should be stored\n" - " gen-test-torrents generate many test torrents (cannot be used for up/down tests)\n" - " 1. number of torrents to generate\n" - " 2. number of files in each torrent\n" - " 3. base name of torrent files (index is appended)\n" - " upload start an uploader test\n" - " download start a downloader test\n" - " dual start a download and upload test\n" - " these commands set takes 4 additional arguments:\n" - " 1. num-connections - the number of connections to make to the target\n" - " 2. destination-IP - the IP address of the target\n" - " 3. destination-port - the port the target listens on\n" - " 4. torrent-file - the torrent file previously generated by gen-torrent\n\n" + " gen-torrent generate a test torrent\n" + " options for this command:\n" + " -s the size of the torrent in megabytes\n" + " -n the number of files in the test torrent\n" + " -t the file to save the .torrent file to\n\n" + " gen-data generate the data file(s) for the test torrent\n" + " options for this command:\n" + " -t the torrent file that was previously generated\n" + " -P the path to where the data should be stored\n\n" + " gen-test-torrents generate many test torrents (cannot be used for up/down tests)\n" + " options for this command:\n" + " -N number of torrents to generate\n" + " -n number of files in each torrent\n" + " -t base name of torrent files (index is appended)\n\n" + " upload start an uploader test\n" + " download start a downloader test\n" + " dual start a download and upload test\n" + " options for these commands:\n" + " -c the number of connections to make to the target\n" + " -d the IP address of the target\n" + " -p the port the target listens on\n" + " -t the torrent file previously generated by gen-torrent\n\n" + " -C send corrupt pieces sometimes (applies to upload and dual)\n\n" "examples:\n\n" - "connection_tester gen-torrent 1024 4 test.torrent\n" - "connection_tester upload 200 127.0.0.1 6881 test.torrent\n" - "connection_tester download 200 127.0.0.1 6881 test.torrent\n" - "connection_tester dual 200 127.0.0.1 6881 test.torrent\n"); + "connection_tester gen-torrent -s 1024 -n 4 -t test.torrent\n" + "connection_tester upload -c 200 -d 127.0.0.1 -p 6881 -t test.torrent\n" + "connection_tester download -c 200 -d 127.0.0.1 -p 6881 -t test.torrent\n" + "connection_tester dual -c 200 -d 127.0.0.1 -p 6881 -t test.torrent\n"); exit(1); } @@ -662,55 +680,101 @@ int main(int argc, char* argv[]) { if (argc <= 1) print_usage(); - if (strcmp(argv[1], "gen-torrent") == 0) - { - if (argc != 5) print_usage(); + char const* command = argv[1]; + int size = 1000; + int num_files = 10; + int num_torrents = 1; + char const* torrent_file = "benchmark.torrent"; + char const* data_path = "."; + int num_connections = 50; + char const* destination_ip = "127.0.0.1"; + int destination_port = 6881; - int size = atoi(argv[2]); - int num_files = atoi(argv[3]); + argv += 2; + argc -= 2; + + while (argc > 0) + { + char const* optname = argv[0]; + ++argv; + --argc; + + if (optname[0] != '-' || strlen(optname) != 2) + { + fprintf(stderr, "unknown option: %s\n", optname); + continue; + } + + // options with no arguments + switch (optname[1]) + { + case 'C': test_corruption = true; continue; + } + + if (argc == 0) + { + fprintf(stderr, "missing argument for option: %s\n", optname); + break; + } + + char const* optarg = argv[0]; + ++argv; + --argc; + + switch (optname[1]) + { + case 's': size = atoi(optarg); break; + case 'n': num_files = atoi(optarg); break; + case 'N': num_torrents = atoi(optarg); break; + case 't': torrent_file = optarg; break; + case 'P': data_path = optarg; break; + case 'c': num_connections = atoi(optarg); break; + case 'p': destination_port = atoi(optarg); break; + case 'd': destination_ip = optarg; break; + default: fprintf(stderr, "unknown option: %s\n", optname); + } + } + + if (strcmp(command, "gen-torrent") == 0) + { std::vector tmp; generate_torrent(tmp, size ? size : 1024, num_files ? num_files : 1); FILE* output = stdout; - if (strcmp("-", argv[4]) != 0) - output = fopen(argv[4], "wb+"); + if (strcmp("-", torrent_file) != 0) + output = fopen(torrent_file, "wb+"); + fprintf(stderr, "writing file to: %s\n", torrent_file); fwrite(&tmp[0], 1, tmp.size(), output); if (output != stdout) fclose(output); return 0; } - else if (strcmp(argv[1], "gen-data") == 0) + else if (strcmp(command, "gen-data") == 0) { - if (argc != 4) print_usage(); error_code ec; - torrent_info ti(argv[2], ec); + torrent_info ti(torrent_file, ec); if (ec) { fprintf(stderr, "ERROR LOADING .TORRENT: %s\n", ec.message().c_str()); return 1; } - generate_data(argv[3], ti.num_pieces(), ti.piece_length()); + generate_data(data_path, ti.num_pieces(), ti.piece_length()); return 0; } - else if (strcmp(argv[1], "gen-test-torrents") == 0) + else if (strcmp(command, "gen-test-torrents") == 0) { - if (argc != 5) print_usage(); - - int num_torrents = atoi(argv[2]); - int num_files = atoi(argv[3]); - char const* name = argv[4]; std::vector buf; for (int i = 0; i < num_torrents; ++i) { char torrent_name[100]; - snprintf(torrent_name, sizeof(torrent_name), "%s-%d.torrent", name, i); + snprintf(torrent_name, sizeof(torrent_name), "%s-%d.torrent", torrent_file, i); file_storage fs; for (int j = 0; j < num_files; ++j) { char file_name[100]; - snprintf(file_name, sizeof(file_name), "%s-%d/file-%d", name, i, j); + snprintf(file_name, sizeof(file_name), "%s-%d/file-%d", torrent_file, i, j); fs.add_file(file_name, size_type(j + i + 1) * 251); } // 1 MiB piece size @@ -741,33 +805,32 @@ int main(int argc, char* argv[]) } return 0; } - else if (strcmp(argv[1], "upload") == 0) + else if (strcmp(command, "upload") == 0) { - if (argc != 6) print_usage(); test_mode = upload_test; } - else if (strcmp(argv[1], "download") == 0) + else if (strcmp(command, "download") == 0) { - if (argc != 6) print_usage(); test_mode = download_test; } - else if (strcmp(argv[1], "dual") == 0) + else if (strcmp(command, "dual") == 0) { - if (argc != 6) print_usage(); test_mode = dual_test; } - else print_usage(); + else + { + fprintf(stderr, "unknown command: %s\n\n", command); + print_usage(); + } - int num_connections = atoi(argv[2]); error_code ec; - address_v4 addr = address_v4::from_string(argv[3], ec); + address_v4 addr = address_v4::from_string(destination_ip, ec); if (ec) { - fprintf(stderr, "ERROR RESOLVING %s: %s\n", argv[3], ec.message().c_str()); + fprintf(stderr, "ERROR RESOLVING %s: %s\n", destination_ip, ec.message().c_str()); return 1; } - int port = atoi(argv[4]); - tcp::endpoint ep(addr, port); + tcp::endpoint ep(addr, destination_port); #if !defined __APPLE__ // apparently darwin doesn't seems to let you bind to @@ -779,7 +842,7 @@ int main(int argc, char* argv[]) } #endif - torrent_info ti(argv[5], ec); + torrent_info ti(torrent_file, ec); if (ec) { fprintf(stderr, "ERROR LOADING .TORRENT: %s\n", ec.message().c_str());