t_bcast_spocket.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_bcast_spocket                                                *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    This is the "main" program for our sockets tester.  It parses command    *
00009 *  line parameters and starts up the tester class.                            *
00010 *                                                                             *
00011 *******************************************************************************
00012 * Copyright (c) 2001-$now By Author.  This program is free software; you can  *
00013 * redistribute it and/or modify it under the terms of the GNU General Public  *
00014 * License as published by the Free Software Foundation; either version 2 of   *
00015 * the License or (at your option) any later version.  This is online at:      *
00016 *     http://www.fsf.org/copyleft/gpl.html                                    *
00017 * Please send any updates to: fred@gruntose.com                               *
00018 \*****************************************************************************/
00019 
00020 #include "bcast_spocketer.h"
00021 
00022 #include <basis/byte_array.h>
00023 #include <basis/istring.h>
00024 #include <loggers/file_logger.h>
00025 #include <data_struct/static_memory_gremlin.h>
00026 #include <sockets/address.h>
00027 
00028 #include <stdio.h>
00029 #include <string.h>
00030 
00031 const int INITIAL_DELAY = 10;  // number of seconds before starting sends.
00032 
00033 HOOPLE_STARTUP_CODE;
00034 
00035 #define LOG(s) program_wide_logger().log(s)
00036 
00037 typedef byte ip_address_holder[4];
00038 
00039 //hmmm: extract this to function in sockets.
00040 bool parse_address(const istring &input, ip_address_holder &ip_address)
00041 {
00042   int index = 0;  // current storage position in our array.
00043   int current_byte = 0;
00044   const char *last_period = 0;  // helps check for non-empty numbers.
00045   bool got_digit = false;
00046   for (const char *address = input.s(); *address; address++) {
00047     if ( (*address <= '9') && (*address >= '0') ) {
00048       current_byte *= 10;  // shift over.
00049       current_byte += *address - '0';  // add in current character.
00050       got_digit = true;
00051     } else if (*address == '.') {
00052       got_digit = false;
00053       if (last_period + 1 == address) {
00054         LOG("The IP address entry has an empty digit.  Exiting.");
00055         return false;
00056       }
00057       last_period = address;  // set our last period location.
00058       if (current_byte > 255) {
00059         LOG("The IP address entry has an illegal byte.  Exiting.");
00060         return false;
00061       }
00062       ip_address[index] = byte(current_byte);  // store current byte.
00063       current_byte = 0;  // reset.
00064       index++;  // next place in array.
00065       if (index > 3) break;
00066         // stop if there are too many periods, but keep accumulated address.
00067     } else {
00068       LOG("The IP address entry has illegal characters.  Exiting.");
00069       return false;
00070     }
00071   }
00072   // catch the case where we ran out of chars before adding the last byte.
00073   if ( (index == 3) && got_digit) {
00074     if (current_byte > 255) {
00075       LOG("The IP address entry has an illegal byte.  Exiting.");
00076       return false;
00077     }
00078     ip_address[index] = current_byte;
00079   } else if (index < 4) {
00080     LOG("The IP address entry is too short.  Exiting.");
00081     return false;
00082   }
00083   return true;
00084 }
00085 
00086 int main(int argc, char *argv[])
00087 {
00088   SET_DEFAULT_COMBO_LOGGER;
00089 
00090   if (argc < 7) {
00091     LOG("\
00092 This program takes six command line arguments to begin operation.\n\
00093 These arguments (in order) are:\n\
00094 \tIP address for src\tIn the form w.x.y.z\n\
00095 \tIP address for dest\tIn the form w.x.y.z\n\
00096 \tReceive Port number\tAs a short integer\n\
00097 \tSending Port number\tAs a short integer\n\
00098 \tSend size\t\tThe size of the data to exchange.\n\
00099 \tSend count\t\tThe number of \"packets\" to exchange.\n\
00100 Note: it is expected that the testers have equal send sizes; this\n\
00101 allows the receiver to know when it's gotten all the data that's\n\
00102 expected during a cycle.");
00103     return 1;
00104   }
00105 
00106   ip_address_holder ip_address;  // accumulates the source address.
00107 
00108   if (!parse_address(argv[1], ip_address)) {
00109     LOG("failed to parse source address.");
00110     return 9283;
00111   }
00112 
00113   LOG(isprintf("\tParsed a source of: \"%d.%d.%d.%d\".",
00114       (int)ip_address[0], (int)ip_address[1], (int)ip_address[2],
00115       (int)ip_address[3]));
00116 
00117   ip_address_holder dest_addr;  // where to send stuff to.
00118 
00119   if (!parse_address(argv[2], dest_addr)) {
00120     LOG("failed to parse dest address.");
00121     return 9283;
00122   }
00123 
00124   LOG(isprintf("\tParsed a destination of: \"%d.%d.%d.%d\".",
00125       (int)dest_addr[0], (int)dest_addr[1], (int)dest_addr[2],
00126       (int)dest_addr[3]));
00127 
00128   // parse the third parameter: the port.
00129   int rcv_port = 0;
00130   if (sscanf(argv[3], "%d", &rcv_port) < 1) {
00131     LOG("The port entry is malformed.  Exiting.");
00132     return 3;
00133   }
00134   LOG(isprintf("\tGot a receive port of %d.", rcv_port));
00135 
00136   // parse the fourth parameter: the port.
00137   int send_port = 0;
00138   if (sscanf(argv[4], "%d", &send_port) < 1) {
00139     LOG("The port entry is malformed.  Exiting.");
00140     return 3;
00141   }
00142   LOG(isprintf("\tGot a send port of %d.", send_port));
00143 
00144   // parse the fifth parameter: the size of the sends.
00145   int send_size = 0;
00146   if (sscanf(argv[5], "%d", &send_size) < 1) {
00147     LOG("The send size entry is malformed.  Exiting.");
00148     return 5;
00149   }
00150   LOG(isprintf("\tGot a send size of %d.", send_size));
00151 
00152   // parse the sixth parameter: the number of sends.
00153   int send_count = 0;
00154   if (sscanf(argv[6], "%d", &send_count) < 1) {
00155     LOG("The send count entry is malformed.  Exiting.");
00156     return 5;
00157   }
00158   LOG(isprintf("\tGot a send count of %d.", send_count));
00159 
00160   // package our parameters in a form the tester likes.
00161   internet_address to_pass(byte_array(4, ip_address), "", rcv_port);
00162   internet_address dest(byte_array(4, dest_addr), "", send_port);
00163 
00164   // now, construct our tester object.
00165   broadcast_spocket_tester tester(to_pass);
00166 
00167   // choose the appropriate action based on our role.
00168   bool outcome = tester.connect();
00169   if (!outcome) {
00170     LOG(istring("Failed to connect on the tester."));
00171     return 10;
00172   }
00173 
00174   LOG(isprintf("you now have %d seconds; get other side ready.",
00175       INITIAL_DELAY));
00176   portable::sleep_ms(INITIAL_DELAY * SECOND_ms);
00177   LOG("starting test");
00178 
00179   // so, we're connected.  try sending the test packages out.
00180   testing_statistics stats;  // to be filled by the tester.
00181   outcome = tester.perform_test(dest, send_size, send_count * 2, stats);
00182     // multiply send_count since we count each side as one.
00183   if (!outcome) {
00184     LOG("Failed out of send_data; maybe other side terminated.");
00185   }
00186 
00187   stats.total_runs /= 2;  // cut down to the real number of tests.
00188 
00189   if (!stats.total_runs)
00190     stats.total_runs = 1;
00191 
00192   // now report on the stats that we get from the data sending.
00193   LOG(isprintf("Report for %d completed test cycles.", stats.total_runs));
00194   LOG("");
00195   LOG("\t\tsend stats\t\treceive stats");
00196   LOG("\t\t----------\t\t-------------");
00197   LOG(isprintf("bytes\t\t%d\t\t\t%d", stats.bytes_sent,
00198       stats.bytes_received));
00199   LOG(isprintf("time\t\t%d\t\t\t%d", stats.send_time, stats.receive_time));
00200   LOG(isprintf("avg. bytes\t%d\t\t\t%d", stats.bytes_sent
00201       / stats.total_runs / 2, stats.bytes_received / stats.total_runs / 2));
00202   LOG("");
00203   LOG(isprintf("round trip time: %d ms", stats.round_trip_time));
00204 //hmmm: use the bandwidth measurer object!!!
00205   double bandwidth = double(stats.bytes_sent + stats.bytes_received)
00206       / stats.round_trip_time / 1024.0 * 1000.0;
00207   LOG(isprintf("bandwidth overall: %f K/s", bandwidth));
00208 
00209   return 0;
00210 }
00211 

Generated on Fri Nov 21 04:30:01 2008 for HOOPLE Libraries by  doxygen 1.5.1