I am trying to update squidclient support multiple protocol request
messages (HTTP/1, HTTP/2, HTCP, ICP).
The attached patch begins breaking the existing code into modules. The
"ping mode" operations and command line processing are broken out from
the main squidclient.cc into Ping.* files.
To keep the tool code files clearly identifiable now that they are
multiplying they are shuffled into tools/squidclient/
A mechanism is added to allow each module to have its own option set.
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.
Amos
=== modified file 'configure.ac'
--- configure.ac 2014-02-13 07:02:35 +0000
+++ configure.ac 2014-02-16 12:15:21 +0000
@@ -3483,6 +3483,7 @@
helpers/storeid_rewrite/Makefile
helpers/storeid_rewrite/file/Makefile
tools/Makefile
+ tools/squidclient/Makefile
tools/purge/Makefile
])
=== modified file 'src/cbdata.cc'
--- src/cbdata.cc 2014-02-11 12:02:07 +0000
+++ src/cbdata.cc 2014-02-16 21:03:42 +0000
@@ -48,9 +48,9 @@
#include "squid.h"
#include "cbdata.h"
+#include "Generic.h"
#include "mgr/Registration.h"
#include "Store.h"
-#include "Generic.h"
#if HAVE_LIMITS_H
#include <limits.h>
=== modified file 'tools/Makefile.am'
--- tools/Makefile.am 2013-06-01 13:05:38 +0000
+++ tools/Makefile.am 2014-02-16 21:04:32 +0000
@@ -11,7 +11,7 @@
## we need our local files too (but avoid -I. at all costs)
INCLUDES += -I$(srcdir)
-SUBDIRS = purge
+SUBDIRS = squidclient purge
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/Parameters.h'
--- tools/squidclient/Parameters.h 1970-01-01 00:00:00 +0000
+++ tools/squidclient/Parameters.h 2014-02-16 21:10:45 +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-16 21:13:54 +0000
@@ -0,0 +1,205 @@
+#include "squid.h"
+#include "SquidTime.h"
+#include "tools/squidclient/Parameters.h"
+#include "tools/squidclient/Ping.h"
+
+#include <iostream>
+
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#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-16 21:04:33 +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-16 21:48:35 +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-16 21:17:08 +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)
{