------------------------------------------------------------ revno: 13288 revision-id: squid3@treenet.co.nz-20140220130307-p52hc3wafnuxw2f4 parent: squid3@treenet.co.nz-20140220015039-ccwnkdw4bc3mzffm committer: Amos Jeffries branch nick: trunk timestamp: Thu 2014-02-20 06:03:07 -0700 message: squidclient: --ping mode module support Module support: Update squidclient support modules with different logics and configuration option sets as a basis for multiple protocol support. A mechanism is added to allow each module to have its own command line option set. Any option unknown to the current module handler drops back to the main loop for processing. --ping mode module: Break the existing code "ping mode" operations and command line processing out from the main squidclient.cc into Ping.* Ping-specific short command line options are now only parsed after a mode flag (--ping) is presented. This frees up the -g and -I options for use by other non-ping modules in future. Also, shuffle squidclient code into its own directory tools/squidclient/ to keep the tool code files clearly identifiable now that they are multiplying. ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20140220130307-p52hc3wafnuxw2f4 # target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # testament_sha1: 46b467847cc0d73fcd059970cd28f2fcf59d036b # timestamp: 2014-02-20 13:53:54 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # base_revision_id: squid3@treenet.co.nz-20140220015039-\ # ccwnkdw4bc3mzffm # # Begin patch === modified file 'configure.ac' --- configure.ac 2014-02-18 13:57:16 +0000 +++ configure.ac 2014-02-20 13:03:07 +0000 @@ -3483,6 +3483,7 @@ helpers/storeid_rewrite/Makefile helpers/storeid_rewrite/file/Makefile tools/Makefile + tools/squidclient/Makefile tools/purge/Makefile ]) === modified file 'tools/Makefile.am' --- tools/Makefile.am 2013-06-01 13:05:38 +0000 +++ tools/Makefile.am 2014-02-20 13:03:07 +0000 @@ -11,7 +11,7 @@ ## we need our local files too (but avoid -I. at all costs) INCLUDES += -I$(srcdir) -SUBDIRS = purge +SUBDIRS = purge squidclient EXTRA_DIST = man_MANS = DISTCLEANFILES = @@ -52,19 +52,6 @@ ## Test Scripts EXTRA_DIST += helper-ok-dying.pl helper-ok.pl -## ##### squidclient ##### - -bin_PROGRAMS = squidclient - -squidclient_SOURCES = squidclient.cc \ - stub_debug.cc \ - test_tools.cc \ - time.cc - -EXTRA_DIST += squidclient.1 -man_MANS += squidclient.1 - - ## ##### cachemgr.cgi ##### === added directory 'tools/squidclient' === added file 'tools/squidclient/Makefile.am' --- tools/squidclient/Makefile.am 1970-01-01 00:00:00 +0000 +++ tools/squidclient/Makefile.am 2014-02-20 13:03:07 +0000 @@ -0,0 +1,49 @@ +include $(top_srcdir)/src/Common.am + +AUTOMAKE_OPTIONS = subdir-objects + +SUBDIRS = +EXTRA_DIST = squidclient.1 +man_MANS = squidclient.1 +DISTCLEANFILES = + +LDADD = \ + $(top_builddir)/src/ip/libip.la \ + $(top_builddir)/lib/libmiscencoding.la \ + $(top_builddir)/lib/libmiscutil.la \ + $(COMPAT_LIB) \ + $(KRB5LIBS) \ + $(XTRA_LIBS) + +include $(top_srcdir)/doc/manuals/Substitute.am + +## Several files need to be shared but we cannot depend on the other +## directories to be built. +test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc + cp $(top_srcdir)/test-suite/test_tools.cc . + +stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc + cp $(top_srcdir)/src/tests/stub_debug.cc . + +time.cc: $(top_srcdir)/src/time.cc + cp $(top_srcdir)/src/time.cc . + +# stock tools for unit tests - library independent versions of dlink_list +# etc. +# globals.cc is needed by test_tools.cc. +# Neither of these should be disted from here. +TESTSOURCES= test_tools.cc +CLEANFILES += test_tools.cc stub_debug.cc time.cc + +## ##### squidclient ##### + +bin_PROGRAMS = squidclient + +squidclient_SOURCES = \ + Parameters.h \ + Ping.cc \ + Ping.h \ + squidclient.cc \ + stub_debug.cc \ + test_tools.cc \ + time.cc === added file 'tools/squidclient/Parameters.h' --- tools/squidclient/Parameters.h 1970-01-01 00:00:00 +0000 +++ tools/squidclient/Parameters.h 2014-02-20 13:03:07 +0000 @@ -0,0 +1,25 @@ +#ifndef _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H +#define _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H + +/** + * squidclient command line parameters. + */ +class Parameters +{ +public: + Parameters() : verbosityLevel(0) {} + + /** + * What verbosity level to display. + * + * 0 : display no debug traces + * 1 : display outgoing request message + * 2+ : display all actions taken + */ + int verbosityLevel; +}; + +/// global squidcleint parameters +extern Parameters scParams; + +#endif /* _SQUID_TOOLS_SQUIDCLIENT_PARAMETERS_H */ === added file 'tools/squidclient/Ping.cc' --- tools/squidclient/Ping.cc 1970-01-01 00:00:00 +0000 +++ tools/squidclient/Ping.cc 2014-02-20 13:03:07 +0000 @@ -0,0 +1,205 @@ +#include "squid.h" +#include "SquidTime.h" +#include "tools/squidclient/Parameters.h" +#include "tools/squidclient/Ping.h" + +#include + +#if HAVE_GETOPT_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif + +namespace Ping +{ +Ping::TheConfig Config; + +/// measurements collected by the squidclient ping mode logics +class pingStats_ +{ +public: + pingStats_() {memset(this, 0, sizeof(pingStats_));} + + long counted; ///< number of transactions which have so far been measured + long pMin; ///< shortest transaction time seen + long pMax; ///< longest transaction time seen + long sum; ///< total time so far spent waiting on transactions + +} stats; + +} // namespace Ping + +/** + * Signal interrupt handler for squidclient ping. + * Displays final statistics and disables further pings. + */ +static void +catchSignal(int sig) +{ + Ping::DisplayStats(); + Ping::Config.enable = false; + std::cerr << "SIGNAL " << sig << " Interrupted." << std::endl; +} + +uint32_t +Ping::Init() +{ + if (Ping::Config.enable) { +#if HAVE_SIGACTION + struct sigaction sa, osa; + if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { + sa.sa_handler = catchSignal; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + (void) sigaction(SIGINT, &sa, NULL); + } +#else + void (*osig) (int); + if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL) + (void) signal(SIGINT, osig); +#endif + return Ping::Config.count; + } + + return 1; +} + +static struct timeval tv1, tv2; + +void +Ping::TimerStart() +{ + if (!Ping::Config.enable) + return; + +#if GETTIMEOFDAY_NO_TZP + (void)gettimeofday(&tv1); +#else + (void)gettimeofday(&tv1, NULL); +#endif +} + +void +Ping::TimerStop(size_t fsize) +{ + if (!Ping::Config.enable) + return; + + struct tm *tmp; + time_t t2s; + long elapsed_msec; + +#if GETTIMEOFDAY_NO_TZP + (void)gettimeofday(&tv2); +#else + (void)gettimeofday(&tv2, NULL); +#endif + + elapsed_msec = tvSubMsec(tv1, tv2); + t2s = tv2.tv_sec; + tmp = localtime(&t2s); + char tbuf[4096]; + snprintf(tbuf, sizeof(tbuf)-1, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, stats.counted + 1, + elapsed_msec / 1000, elapsed_msec % 1000, + elapsed_msec ? (double) fsize / elapsed_msec : -1.0); + std::cerr << tbuf << std::endl; + + if (!stats.counted || elapsed_msec < stats.pMin) + stats.pMin = elapsed_msec; + + if (!stats.counted || elapsed_msec > stats.pMax) + stats.pMax = elapsed_msec; + + stats.sum += elapsed_msec; + + ++stats.counted; + + /* Delay until next "ping.interval" boundary */ + if (!LoopDone(stats.counted) && elapsed_msec < Ping::Config.interval) { + + struct timeval tvs; + long msec_left = Ping::Config.interval - elapsed_msec; + + tvs.tv_sec = msec_left / 1000; + tvs.tv_usec = (msec_left % 1000) * 1000; + select(0, NULL, NULL, NULL, &tvs); + } +} + +void +Ping::DisplayStats() +{ + if (Ping::Config.enable && stats.counted) { + long mean = stats.sum / stats.counted; + std::cerr << stats.counted << " requests, round-trip (secs) min/avg/max = " + << (stats.pMin/1000) << "." << (stats.pMin%1000) + << "/" << (mean/1000) << "." << (mean%1000) + << "/" << (stats.pMax/1000) << "." << (stats.pMax%1000) + << std::endl; + } +} + +void +Ping::TheConfig::usage() +{ + std::cerr << "Ping Mode" << std::endl + << " --ping [options] Enable ping mode." << std::endl + << std::endl + << " options:" << std::endl + << " -g count Ping iteration count (default, loop until interrupted)." << std::endl + << " -I interval Ping interval in seconds (default 1 second)." << std::endl + << std::endl; +} + +bool +Ping::TheConfig::parseCommandOpts(int argc, char *argv[], int c, int &optIndex) +{ + // to get here --ping was seen + enable = true; + count = 0; // default is infinite loop + interval = 1 * 1000; // default is 1s intervals + + const char *shortOpStr = "g:I:?"; + + // options for controlling squidclient ping mode + static struct option pingOptions[] = { + {"count", no_argument, 0, 'g'}, + {"interval", no_argument, 0, 'I'}, + {0, 0, 0, 0} + }; + + int saved_opterr = opterr; + opterr = 0; // suppress errors from getopt + while ((c = getopt_long(argc, argv, shortOpStr, pingOptions, &optIndex)) != -1) { + switch (c) { + case 'g': + if (optarg) + count = atoi(optarg); + else { + std::cerr << "ERROR: -g ping count missing parameter." << std::endl; + usage(); + } + break; + + case 'I': + if ((interval = atoi(optarg) * 1000) <= 0) { + std::cerr << "ERROR: -I ping interval out of range (0-" << (INT_MAX/1000) << ")." << std::endl; + usage(); + } + break; + + default: + // rewind and let the caller handle unknown options + --optind; + opterr = saved_opterr; + return true; + } + } + + opterr = saved_opterr; + return false; +} === added file 'tools/squidclient/Ping.h' --- tools/squidclient/Ping.h 1970-01-01 00:00:00 +0000 +++ tools/squidclient/Ping.h 2014-02-20 13:03:07 +0000 @@ -0,0 +1,54 @@ +#ifndef _SQUID_TOOLS_CLIENT_PING_H +#define _SQUID_TOOLS_CLIENT_PING_H + +/** + * API for looping the squidclient request message + * repeatedly. + */ +namespace Ping +{ + +/// parameters controlling 'ping' mode message looping. +class TheConfig +{ +public: + TheConfig() : enable(false), count(0), interval(1*1000) {} + + /// display Ping Options command line help to stderr + void usage(); + + /** + * parse --ping command line options + * \return true if there are other options still to parse + */ + bool parseCommandOpts(int argc, char *argv[], int c, int &optIndex); + + bool enable; + int count; + int interval; +}; + +extern TheConfig Config; + +/// initialize the squidclient ping mode +uint32_t Init(); + +/// whether ping loop is completed at the given iteration. +inline bool LoopDone(int i) +{ + return !Ping::Config.enable || (Ping::Config.count && i >= Ping::Config.count); +} + +/// start timing a new transaction +void TimerStart(); + +/// calculate and display the statictics for a complete transaction +/// \param fsize number of bytes transferred during this transaction (for KB/s measure) +void TimerStop(size_t fsize); + +/// display summary of ping data collected +void DisplayStats(); + +} // namespace Ping + +#endif /* _SQUID_TOOLS_CLIENT_PING_H */ === renamed file 'tools/squidclient.1' => 'tools/squidclient/squidclient.1' --- tools/squidclient.1 2013-04-23 12:25:33 +0000 +++ tools/squidclient/squidclient.1 2014-02-20 13:03:07 +0000 @@ -7,18 +7,15 @@ . .SH SYNOPSIS .if !'po4a'hide' .B squidclient +.if !'po4a'hide' .B "[ \-\-ping [ping-options] ] " .if !'po4a'hide' .B "[ \-aknNrsv ] [ \-A" string -.if !'po4a'hide' .B "] [ \-g" -count .if !'po4a'hide' .B "] [ \-h" remote host .if !'po4a'hide' .B "] [ \-H '" string .if !'po4a'hide' .B "' ] [ \-i" IMS -.if !'po4a'hide' .B "] [ \-I" -ping interval .if !'po4a'hide' .B "] [ \-j '" Host header .if !'po4a'hide' .B "' ] [ \-l" @@ -46,6 +43,12 @@ .if !'po4a'hide' .B "] " url . +.if !'po4a'hide' .B "Ping options: [ \-g" +count +.if !'po4a'hide' .B "] [ \-I" +interval +.if !'po4a'hide' .B "] " +. .SH DESCRIPTION .B squidclient is a tool providing a command line interface for retrieving URLs. @@ -67,12 +70,6 @@ as User-Agent: header. To omit the header completely set string to empty (''). . .if !'po4a'hide' .TP -.if !'po4a'hide' .B "\-g count" -Ping mode, perform -.I count -iterations (0 to loop until interrupted). -. -.if !'po4a'hide' .TP .if !'po4a'hide' .B "\-h host" Retrieve URL from cache on hostname. Default is .B localhost @@ -88,10 +85,6 @@ If\-Modified\-Since time (in Epoch seconds). . .if !'po4a'hide' .TP -.if !'po4a'hide' .B "\-I interval" -Ping interval in seconds (default 1 second). -. -.if !'po4a'hide' .TP .if !'po4a'hide' .B "\-j hosthdr" Host header content . @@ -184,6 +177,21 @@ .if !'po4a'hide' .B "\-W password" WWW authentication password . +.if !'po4a'hide' .TP 10 +.if !'po4a'hide' .B "\-\-ping [options]" +Enable ping mode. Optional \-g and \-I parameters must follow immediately if used. +Repeated use resets to default ping settings. +. +.if !'po4a'hide' .TP 12 +.if !'po4a'hide' .B "\-g count" +Ping mode, perform +.I count +iterations (default is to loop until interrupted). +. +.if !'po4a'hide' .TP +.if !'po4a'hide' .B "\-I interval" +Ping interval in seconds (default 1 second). +. .SH AUTHOR Derived from Harvest. Further developed by by numerous individuals from the internet community. Development is led by Duane Wessels of the === renamed file 'tools/squidclient.cc' => 'tools/squidclient/squidclient.cc' --- tools/squidclient.cc 2014-02-16 09:50:29 +0000 +++ tools/squidclient/squidclient.cc 2014-02-20 13:03:07 +0000 @@ -35,7 +35,8 @@ #include "ip/Address.h" #include "ip/tools.h" #include "rfc1123.h" -#include "SquidTime.h" +#include "tools/squidclient/Parameters.h" +#include "tools/squidclient/Ping.h" #if _SQUID_WINDOWS_ /** \cond AUTODOCS-IGNORE */ @@ -118,29 +119,17 @@ #define HEADERLEN 65536 #endif -typedef void SIGHDLR(int sig); - /// display debug messages at varying verbosity levels #define debugVerbose(LEVEL, MESSAGE) \ - while ((LEVEL) <= verbosityLevel) {std::cerr << MESSAGE << std::endl; break;} - -/** - * What verbosity level to display. - * - * 0 : display no debug traces - * 1 : display outgoing request message - * 2+ : display all actions taken - */ -int verbosityLevel = 0; + while ((LEVEL) <= scParams.verbosityLevel) {std::cerr << MESSAGE << std::endl; break;} /* Local functions */ static int client_comm_bind(int, const Ip::Address &); -static int client_comm_connect(int, const Ip::Address &, struct timeval *); +static int client_comm_connect(int, const Ip::Address &); static void usage(const char *progname); -static int Now(struct timeval *); -SIGHDLR catchSignal; +typedef void SIGHDLR(int sig); SIGHDLR pipe_handler; static void set_our_signal(void); static ssize_t myread(int fd, void *buf, size_t len); @@ -151,6 +140,8 @@ static char *GSSAPI_token(const char *server); #endif +Parameters scParams; + static int put_fd; static char *put_file = NULL; @@ -178,54 +169,52 @@ usage(const char *progname) { std::cerr << "Version: " << VERSION << std::endl - << "Usage: " << progname << " [Basic Options] [HTTP Options]" << std::endl - << std::endl - << "Basic Options:" << std::endl - << " -g count Ping mode, perform \"count\" iterations (0 to loop until interrupted)." << std::endl - << " -h host Send message to server on 'host'. Default is localhost." << std::endl - << " -I interval Ping interval in seconds (default 1 second)." << std::endl - << " -l host Specify a local IP address to bind to. Default is none." << std::endl - << " -p port Port number on server to contact. Default is " << CACHE_HTTP_PORT << "." << std::endl - << " -s | --quiet Silent. Do not print response message to stdout." << std::endl - << " -T timeout Timeout value (seconds) for read/write operations" << std::endl - << " -v | --verbose Verbose debugging. Repeat (-vv) to increase output level." << std::endl - << " Levels:" << std::endl - << " 1 - Print outgoing request message to stderr." << std::endl - << " 2 - Print action trace to stderr." << std::endl - << " --help Display this help text." << std::endl - << std::endl - << "HTTP Options:" << std::endl - << " -a Do NOT include Accept: header." << std::endl - << " -A User-Agent: header. Use \"\" to omit." << std::endl - << " -H 'string' Extra headers to send. Use '\\n' for new lines." << std::endl - << " -i IMS If-Modified-Since time (in Epoch seconds)." << std::endl - << " -j hosthdr Host header content" << std::endl - << " -k Keep the connection active. Default is to do only one request then close." << std::endl - << " -m method Request method, default is GET." << std::endl + << "Usage: " << progname << " [Basic Options] [HTTP Options]" << std::endl + << std::endl + << "Basic Options:" << std::endl + << " -h host Send message to server on 'host'. Default is localhost." << std::endl + << " -l host Specify a local IP address to bind to. Default is none." << std::endl + << " -p port Port number on server to contact. Default is " << CACHE_HTTP_PORT << "." << std::endl + << " -s | --quiet Silent. Do not print response message to stdout." << std::endl + << " -T timeout Timeout value (seconds) for read/write operations" << std::endl + << " -v | --verbose Verbose debugging. Repeat (-vv) to increase output level." << std::endl + << " Levels:" << std::endl + << " 1 - Print outgoing request message to stderr." << std::endl + << " 2 - Print action trace to stderr." << std::endl + << " --help Display this help text." << std::endl + << std::endl; + Ping::Config.usage(); + std::cerr + << "HTTP Options:" << std::endl + << " -a Do NOT include Accept: header." << std::endl + << " -A User-Agent: header. Use \"\" to omit." << std::endl + << " -H 'string' Extra headers to send. Use '\\n' for new lines." << std::endl + << " -i IMS If-Modified-Since time (in Epoch seconds)." << std::endl + << " -j hosthdr Host header content" << std::endl + << " -k Keep the connection active. Default is to do only one request then close." << std::endl + << " -m method Request method, default is GET." << std::endl #if HAVE_GSSAPI - << " -n Proxy Negotiate(Kerberos) authentication" << std::endl - << " -N WWW Negotiate(Kerberos) authentication" << std::endl + << " -n Proxy Negotiate(Kerberos) authentication" << std::endl + << " -N WWW Negotiate(Kerberos) authentication" << std::endl #endif - << " -P file Send content from the named file as request payload" << std::endl - << " -r Force cache to reload URL" << std::endl - << " -t count Trace count cache-hops" << std::endl - << " -u user Proxy authentication username" << std::endl - << " -U user WWW authentication username" << std::endl - << " -V version HTTP Version. Use '-' for HTTP/0.9 omitted case" << std::endl - << " -w password Proxy authentication password" << std::endl - << " -W password WWW authentication password" << std::endl - ; + << " -P file Send content from the named file as request payload" << std::endl + << " -r Force cache to reload URL" << std::endl + << " -t count Trace count cache-hops" << std::endl + << " -u user Proxy authentication username" << std::endl + << " -U user WWW authentication username" << std::endl + << " -V version HTTP Version. Use '-' for HTTP/0.9 omitted case" << std::endl + << " -w password Proxy authentication password" << std::endl + << " -W password WWW authentication password" << std::endl + ; exit(1); } -static int interrupted = 0; int main(int argc, char *argv[]) { int conn, len, bytesWritten; uint16_t port; bool to_stdout, reload; - int ping, pcount; int keep_alive = 0; int opt_noaccept = 0; #if HAVE_GSSAPI @@ -240,10 +229,7 @@ time_t ims = 0; int max_forwards = -1; - struct timeval tv1, tv2; - int i = 0, loops; - long ping_int; - long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0; + int i = 0; const char *proxy_user = NULL; const char *proxy_password = NULL; const char *www_user = NULL; @@ -259,9 +245,6 @@ port = CACHE_HTTP_PORT; to_stdout = true; reload = false; - ping = 0; - pcount = 0; - ping_int = 1 * 1000; Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing. if (argc < 2 || argv[argc-1][0] == '-') { @@ -271,21 +254,37 @@ url[BUFSIZ - 1] = '\0'; int optIndex = 0; - const char *shortOpStr = "aA:h:j:V:l:P:i:kmnN:p:rsvt:g:p:I:H:T:u:U:w:W:?"; + const char *shortOpStr = "aA:h:j:V:l:P:i:kmnN:p:rsvt:p:H:T:u:U:w:W:?"; // options for controlling squidclient - static struct option basicOptions[] = - { - /* These are the generic options for squidclient itself */ - {"help", no_argument, 0, '?'}, - {"verbose", no_argument, 0, 'v'}, - {"quiet", no_argument, 0, 's'}, - {0, 0, 0, 0} + static struct option basicOptions[] = { + /* These are the generic options for squidclient itself */ + {"help", no_argument, 0, '?'}, + {"verbose", no_argument, 0, 'v'}, + {"quiet", no_argument, 0, 's'}, + {"ping", no_argument, 0, '\1'}, + {0, 0, 0, 0} }; int c; while ((c = getopt_long(argc, argv, shortOpStr, basicOptions, &optIndex)) != -1) { - switch (c) { + + // modules parse their own specific options + switch (c) { + case '\1': + to_stdout = 0; + if (Ping::Config.parseCommandOpts(argc, argv, c, optIndex)) + continue; + break; + + default: // fall through to next switch + break; + } + + switch (c) { + + case '\0': // dummy value for end-of-options + break; case 'a': opt_noaccept = 1; @@ -346,17 +345,6 @@ max_forwards = atoi(optarg); break; - case 'g': - ping = 1; - pcount = atoi(optarg); - to_stdout = 0; - break; - - case 'I': - if ((ping_int = atoi(optarg) * 1000) <= 0) - usage(argv[0]); - break; - case 'H': if (strlen(optarg)) { char *t; @@ -406,8 +394,8 @@ case 'v': /* undocumented: may increase verb-level by giving more -v's */ - ++verbosityLevel; - debugVerbose(2, "verbosity level set to " << verbosityLevel); + ++scParams.verbosityLevel; + debugVerbose(2, "verbosity level set to " << scParams.verbosityLevel); break; case '?': /* usage */ @@ -575,30 +563,10 @@ debugVerbose(1, "Request:" << std::endl << msg << std::endl << "."); - if (ping) { -#if HAVE_SIGACTION - - struct sigaction sa, osa; - - if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { - sa.sa_handler = catchSignal; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - (void) sigaction(SIGINT, &sa, NULL); - } -#else - void (*osig) (int); - - if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL) - (void) signal(SIGINT, osig); - -#endif - - } - loops = ping ? pcount : 1; + uint32_t loops = Ping::Init(); for (i = 0; loops == 0 || i < loops; ++i) { - int fsize = 0; + size_t fsize = 0; struct addrinfo *AI = NULL; debugVerbose(2, "Resolving... " << hostname); @@ -642,7 +610,7 @@ debugVerbose(2, "Connecting... " << hostname << " (" << iaddr << ")"); - if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) { + if (client_comm_connect(conn, iaddr) < 0) { char hostnameBuf[MAX_IPSTRLEN]; iaddr.toUrl(hostnameBuf, MAX_IPSTRLEN); std::cerr << "ERROR: Cannot connect to " << hostnameBuf @@ -702,56 +670,13 @@ (void) close(conn); /* done with socket */ - if (interrupted) + if (Ping::LoopDone(i)) break; - if (ping) { - - struct tm *tmp; - time_t t2s; - long elapsed_msec; - - (void) Now(&tv2); - elapsed_msec = tvSubMsec(tv1, tv2); - t2s = tv2.tv_sec; - tmp = localtime(&t2s); - char tbuf[4096]; - snprintf(tbuf, sizeof(tbuf)-1, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s", - tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, - elapsed_msec / 1000, elapsed_msec % 1000, - elapsed_msec ? (double) fsize / elapsed_msec : -1.0); - std::cerr << tbuf << std::endl; - - if (i == 0 || elapsed_msec < ping_min) - ping_min = elapsed_msec; - - if (i == 0 || elapsed_msec > ping_max) - ping_max = elapsed_msec; - - ping_sum += elapsed_msec; - - /* Delay until next "ping_int" boundary */ - if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { - - struct timeval tvs; - long msec_left = ping_int - elapsed_msec; - - tvs.tv_sec = msec_left / 1000; - tvs.tv_usec = (msec_left % 1000) * 1000; - select(0, NULL, NULL, NULL, &tvs); - } - } - } - - if (ping && i) { - ping_mean = ping_sum / i; - std::cerr << i << " requests, round-trip (secs) min/avg/max = " - << (ping_min/1000) << "." << (ping_min%1000) - << "/" << (ping_mean/1000) << "." << (ping_mean%1000) - << "/" << (ping_max/1000) << "." << (ping_max%1000) - << std::endl; - } + Ping::TimerStop(fsize); + } + + Ping::DisplayStats(); return 0; } @@ -768,34 +693,16 @@ /// Set up the destination socket address for message to send to. static int -client_comm_connect(int sock, const Ip::Address &addr, struct timeval *tvp) +client_comm_connect(int sock, const Ip::Address &addr) { static struct addrinfo *AI = NULL; addr.getAddrInfo(AI); int res = connect(sock, AI->ai_addr, AI->ai_addrlen); Ip::Address::FreeAddrInfo(AI); - if (tvp) - (void) Now(tvp); + Ping::TimerStart(); return res; } -static int -Now(struct timeval *tp) -{ -#if GETTIMEOFDAY_NO_TZP - return gettimeofday(tp); -#else - return gettimeofday(tp, NULL); -#endif -} - -void -catchSignal(int sig) -{ - interrupted = 1; - std::cerr << "SIGNAL " << sig << " Interrupted." << std::endl; -} - void pipe_handler(int sig) {