00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "bcast_spocketer.h"
00016
00017 #include <application/hoople_main.h>
00018 #include <basis/byte_array.h>
00019 #include <basis/astring.h>
00020 #include <loggers/program_wide_logger.h>
00021 #include <processes/launch_process.h>
00022 #include <structures/static_memory_gremlin.h>
00023 #include <sockets/internet_address.h>
00024 #include <timely/time_control.h>
00025 #include <unit_test/unit_base.h>
00026
00027 #include <stdio.h>
00028 #include <string.h>
00029
00030 using namespace application;
00031 using namespace basis;
00032 using namespace loggers;
00033 using namespace mathematics;
00034 using namespace processes;
00035 using namespace sockets;
00036 using namespace structures;
00037 using namespace textual;
00038 using namespace timely;
00039 using namespace unit_test;
00040
00041 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger().get(), astring(to_print))
00042
00043 const int INITIAL_DELAY = 1;
00044
00045 typedef abyte ip_address_holder[4];
00046
00047 class test_ucast_spocket : public virtual application_shell, public virtual unit_base
00048 {
00049 public:
00050 test_ucast_spocket() {}
00051 DEFINE_CLASS_NAME("test_ucast_spocket");
00052 virtual int execute();
00053
00054 bool parse_address(const astring &input, ip_address_holder &ip_address);
00055 };
00056
00057
00058 bool test_ucast_spocket::parse_address(const astring &input, ip_address_holder &ip_address)
00059 {
00060 int index = 0;
00061 int current_byte = 0;
00062 const char *last_period = 0;
00063 bool got_digit = false;
00064 for (const char *address = input.s(); *address; address++) {
00065 if ( (*address <= '9') && (*address >= '0') ) {
00066 current_byte *= 10;
00067 current_byte += *address - '0';
00068 got_digit = true;
00069 } else if (*address == '.') {
00070 got_digit = false;
00071 if (last_period + 1 == address) {
00072 LOG("The IP address entry has an empty digit. Exiting.");
00073 return false;
00074 }
00075 last_period = address;
00076 if (current_byte > 255) {
00077 LOG("The IP address entry has an illegal abyte. Exiting.");
00078 return false;
00079 }
00080 ip_address[index] = abyte(current_byte);
00081 current_byte = 0;
00082 index++;
00083 if (index > 3) break;
00084
00085 } else {
00086 LOG("The IP address entry has illegal characters. Exiting.");
00087 return false;
00088 }
00089 }
00090
00091 if ( (index == 3) && got_digit) {
00092 if (current_byte > 255) {
00093 LOG("The IP address entry has an illegal abyte. Exiting.");
00094 return false;
00095 }
00096 ip_address[index] = current_byte;
00097 } else if (index < 4) {
00098 LOG("The IP address entry is too short. Exiting.");
00099 return false;
00100 }
00101 return true;
00102 }
00103
00104 int test_ucast_spocket::execute()
00105 {
00106
00107
00108
00109 FUNCDEF("execute");
00110 ip_address_holder ip_address;
00111 ip_address_holder dest_addr;
00112 int rcv_port = 0;
00113 int send_port = 0;
00114 int send_size = 0;
00115 int send_count = 0;
00116
00117 const char *DEFAULT_HOST = "127.0.0.1";
00118 const int DEFAULT_PORT = 12342;
00119 const int DEFAULT_SEND_SIZE = 1008;
00120 const int DEFAULT_SEND_COUNT = 10;
00121
00122 if (_global_argc < 7) {
00123 if (_global_argc > 1) {
00124 LOG("\
00125 This program takes six command line arguments to begin operation.\n\
00126 These arguments (in order) are:\n\
00127 \tIP address for src\tIn the form w.x.y.z\n\
00128 \tIP address for dest\tIn the form w.x.y.z\n\
00129 \tReceive Port number\tAs a short integer\n\
00130 \tSending Port number\tAs a short integer\n\
00131 \tSend size\t\tThe size of the data to exchange.\n\
00132 \tSend count\t\tThe number of \"packets\" to exchange.\n\
00133 Note: it is expected that the testers have equal send sizes; this\n\
00134 allows the receiver to know when it's gotten all the data that's\n\
00135 expected during a cycle.");
00136 return 1;
00137 } else {
00138 parse_address(DEFAULT_HOST, ip_address);
00139 parse_address(DEFAULT_HOST, dest_addr);
00140 rcv_port = DEFAULT_PORT;
00141 send_port = DEFAULT_PORT + 1;
00142 send_size = DEFAULT_SEND_SIZE;
00143 send_count = DEFAULT_SEND_COUNT;
00144 }
00145 }
00146
00147
00148
00149 if (_global_argc >= 7) {
00150
00151 if (!parse_address(_global_argv[1], ip_address)) {
00152 LOG("failed to parse source address.");
00153 return 9283;
00154 }
00155
00156 LOG(a_sprintf("\tParsed a source of: \"%d.%d.%d.%d\".",
00157 (int)ip_address[0], (int)ip_address[1], (int)ip_address[2],
00158 (int)ip_address[3]));
00159
00160 if (!parse_address(_global_argv[2], dest_addr)) {
00161 LOG("failed to parse dest address.");
00162 return 9283;
00163 }
00164
00165 LOG(a_sprintf("\tParsed a destination of: \"%d.%d.%d.%d\".",
00166 (int)dest_addr[0], (int)dest_addr[1], (int)dest_addr[2],
00167 (int)dest_addr[3]));
00168
00169
00170 if (sscanf(_global_argv[3], "%d", &rcv_port) < 1) {
00171 LOG("The port entry is malformed. Exiting.");
00172 return 3;
00173 }
00174 LOG(a_sprintf("\tGot a receive port of %d.", rcv_port));
00175
00176
00177 if (sscanf(_global_argv[4], "%d", &send_port) < 1) {
00178 LOG("The port entry is malformed. Exiting.");
00179 return 3;
00180 }
00181 LOG(a_sprintf("\tGot a send port of %d.", send_port));
00182
00183
00184 if (sscanf(_global_argv[5], "%d", &send_size) < 1) {
00185 LOG("The send size entry is malformed. Exiting.");
00186 return 5;
00187 }
00188 LOG(a_sprintf("\tGot a send size of %d.", send_size));
00189
00190
00191 if (sscanf(_global_argv[6], "%d", &send_count) < 1) {
00192 LOG("The send count entry is malformed. Exiting.");
00193 return 5;
00194 }
00195 LOG(a_sprintf("\tGot a send count of %d.", send_count));
00196 }
00197
00198 if (_global_argc == 1) {
00199
00200 launch_process zingit;
00201 un_int kidnum;
00202 un_int result = zingit.run(_global_argv[0],
00203 astring(DEFAULT_HOST) + " " + DEFAULT_HOST + " "
00204
00205 + a_sprintf("%d", DEFAULT_PORT + 1) + " " + a_sprintf("%d", DEFAULT_PORT)
00206 + " " + a_sprintf("%d", DEFAULT_SEND_SIZE) + " " + a_sprintf("%d", DEFAULT_SEND_COUNT),
00207 launch_process::RETURN_IMMEDIATELY, kidnum);
00208 ASSERT_EQUAL(result, 0, "launching paired process should start successfully");
00209 }
00210
00211
00212 internet_address to_pass(byte_array(4, ip_address), "", rcv_port);
00213 internet_address dest(byte_array(4, dest_addr), "", send_port);
00214
00215
00216 broadcast_spocket_tester tester(to_pass, true);
00217
00218
00219 bool outcome = tester.connect();
00220 if (!outcome) {
00221 LOG(astring("Failed to connect on the tester."));
00222 return 10;
00223 }
00224
00225 LOG(a_sprintf("you now have %d seconds; get other side ready.",
00226 INITIAL_DELAY));
00227 time_control::sleep_ms(INITIAL_DELAY * SECOND_ms);
00228 LOG("starting test");
00229
00230
00231 testing_statistics stats;
00232 outcome = tester.perform_test(dest, send_size, send_count * 2, stats);
00233
00234 if (!outcome) {
00235 LOG("Failed out of send_data; maybe other side terminated.");
00236 }
00237
00238 stats.total_runs /= 2;
00239
00240 if (!stats.total_runs)
00241 stats.total_runs = 1;
00242
00243
00244 LOG(a_sprintf("Report for %d completed test cycles.", stats.total_runs));
00245 LOG("");
00246 LOG("\t\tsend stats\t\treceive stats");
00247 LOG("\t\t----------\t\t-------------");
00248 LOG(a_sprintf("bytes\t\t%d\t\t\t%d", stats.bytes_sent,
00249 stats.bytes_received));
00250 LOG(a_sprintf("time\t\t%d\t\t\t%d", stats.send_time, stats.receive_time));
00251 LOG(a_sprintf("avg. bytes\t%d\t\t\t%d", stats.bytes_sent
00252 / stats.total_runs / 2, stats.bytes_received / stats.total_runs / 2));
00253 LOG("");
00254 LOG(a_sprintf("round trip time: %d ms", stats.round_trip_time));
00255
00256 double bandwidth = double(stats.bytes_sent + stats.bytes_received)
00257 / stats.round_trip_time / 1024.0 * 1000.0;
00258 LOG(a_sprintf("bandwidth overall: %f K/s", bandwidth));
00259
00260 if (_global_argc == 1) return final_report();
00261 else return 0;
00262 }
00263
00264 HOOPLE_MAIN(test_ucast_spocket, );
00265