commit 8edb9035f9ff7dc2c5e8b5275488d5da7360d562
parent 3951f0e911382622fc48e0c30f83c4743b7c64b5
Author: cnlohr <lohr85@gmail.com>
Date: Fri, 22 Jun 2018 00:46:21 -0400
Add feature for histograms.
Diffstat:
6 files changed, 282 insertions(+), 55 deletions(-)
diff --git a/CNFGXDriver.c b/CNFGXDriver.c
@@ -339,6 +339,7 @@ void CNFGSwapBuffers()
void CNFGTackSegment( short x1, short y1, short x2, short y2 )
{
XDrawLine( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2, y2 );
+ XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1 );
}
void CNFGTackPixel( short x1, short y1 )
diff --git a/cnping.c b/cnping.c
@@ -30,7 +30,10 @@ short screenx, screeny;
const char * pinghost;
float GuiYScaleFactor;
int GuiYscaleFactorIsConstant;
-
+double globmaxtime, globmintime = 1e20;
+double globinterval, globlast;
+uint64_t globalrx;
+uint64_t globallost;
uint8_t pattern[8];
@@ -42,36 +45,82 @@ double PingRecvTimes[PINGCYCLEWIDTH];
int current_cycle = 0;
int ExtraPingSize;
+int in_histogram_mode, in_frame_mode = 1;
+void HandleGotPacket( int seqno, int timeout );
+
+#define MAX_HISTO_MARKS (TIMEOUT*10000)
+uint64_t hist_counts[MAX_HISTO_MARKS];
+
+void HandleNewPacket( int seqno )
+{
+ double Now = OGGetAbsoluteTime();
+ PingSendTimes[seqno] = Now;
+ PingRecvTimes[seqno] = 0;
+ static int timeoutmark;
+
+ while( Now - PingSendTimes[timeoutmark] > TIMEOUT )
+ {
+ if( PingRecvTimes[timeoutmark] < PingSendTimes[timeoutmark] )
+ {
+ HandleGotPacket( timeoutmark, 1 );
+ }
+ timeoutmark++;
+ }
+}
+
+void HandleGotPacket( int seqno, int timeout )
+{
+ double Now = OGGetAbsoluteTime();
+
+ if( timeout )
+ {
+ if( PingRecvTimes[seqno] < -0.5 ) return;
+
+ globallost++;
+ PingRecvTimes[seqno] = -1;
+ hist_counts[MAX_HISTO_MARKS-1]++;
+ return;
+ }
+
+ if( PingRecvTimes[seqno] >= PingSendTimes[seqno] ) return;
+ if( PingSendTimes[seqno] < 1 ) return;
+ if( Now - PingSendTimes[seqno] > TIMEOUT ) return;
+
+ PingRecvTimes[seqno] = OGGetAbsoluteTime();
+ double Delta = PingRecvTimes[seqno] - PingSendTimes[seqno];
+ if( Delta > globmaxtime ) { globmaxtime = Delta; }
+ if( Delta < globmintime ) { globmintime = Delta; }
+ int slot = Delta * 10000;
+ if( slot >= MAX_HISTO_MARKS ) slot = MAX_HISTO_MARKS-1;
+ if( slot < 0 ) slot = 0;
+ hist_counts[slot]++;
+
+ if( globlast > 0.5 )
+ {
+ if( Now - globlast > globinterval ) globinterval = Now - globlast;
+ }
+ globlast = Now;
+ globalrx++;
+}
void HTTPingCallbackStart( int seqno )
{
current_cycle = seqno;
-
- PingSendTimes[seqno] = OGGetAbsoluteTime();
- PingRecvTimes[seqno] = 0;
+ HandleNewPacket( seqno );
}
void HTTPingCallbackGot( int seqno )
{
- PingRecvTimes[seqno] = OGGetAbsoluteTime();
+ HandleGotPacket( seqno, 0 );
}
void display(uint8_t *buf, int bytes)
{
int reqid = (buf[0] << 24) | (buf[1]<<16) | (buf[2]<<8) | (buf[3]);
reqid &= (PINGCYCLEWIDTH-1);
-
- double STime = PingSendTimes[reqid];
- double LRTime = PingRecvTimes[reqid];
-
if( memcmp( buf+4, pattern, 8 ) != 0 ) return;
- if( LRTime > STime ) return;
- if( STime < 1 ) return;
-
- //Otherwise this is a legit packet.
-
- PingRecvTimes[reqid] = OGGetAbsoluteTime();
+ HandleGotPacket( reqid, 0 );
}
int load_ping_packet( uint8_t * buffer, int bufflen )
@@ -88,8 +137,7 @@ int load_ping_packet( uint8_t * buffer, int bufflen )
PingSendTimes[(current_cycle+PINGCYCLEWIDTH-1)&(PINGCYCLEWIDTH-1)] = 0; //Unset ping send.
}
- PingSendTimes[current_cycle&(PINGCYCLEWIDTH-1)] = OGGetAbsoluteTime();
- PingRecvTimes[current_cycle&(PINGCYCLEWIDTH-1)] = 0;
+ HandleNewPacket( current_cycle&(PINGCYCLEWIDTH-1) );
current_cycle++;
@@ -117,6 +165,23 @@ void HandleKey( int keycode, int bDown )
{
switch( keycode )
{
+ case 'f':
+ if( bDown ) in_frame_mode = !in_frame_mode;
+ if( !in_frame_mode ) in_histogram_mode = 1;
+ break;
+ case 'm':
+ if( bDown ) in_histogram_mode = !in_histogram_mode;
+ if( !in_histogram_mode ) in_frame_mode = 1;
+ break;
+ case 'c':
+ memset( hist_counts, 0, sizeof( hist_counts ) );
+ globmaxtime = 0;
+ globmintime = 1e20;
+ globinterval = 0;
+ globlast = 0;
+ globalrx = 0;
+ globallost = 0;
+ break;
case 'q':
exit(0);
break;
@@ -127,7 +192,8 @@ void HandleButton( int x, int y, int button, int bDown ){}
void HandleMotion( int x, int y, int mask ){}
void HandleDestroy() { exit(0); }
-double GetGlobMaxPingTime( void )
+
+double GetWindMaxPingTime( void )
{
int i;
double maxtime = 0;
@@ -151,12 +217,152 @@ double GetGlobMaxPingTime( void )
return maxtime;
}
+void DrawMainText( const char * stbuf )
+{
+ int x, y;
+ CNFGColor( 0x00 );
+ for( x = -1; x < 2; x++ ) for( y = -1; y < 2; y++ )
+ {
+ CNFGPenX = 10+x; CNFGPenY = 10+y;
+ CNFGDrawText( stbuf, 2 );
+ }
+ CNFGColor( 0xffffff );
+ CNFGPenX = 10; CNFGPenY = 10;
+ CNFGDrawText( stbuf, 2 );
+}
+
+void DrawFrameHistogram()
+{
+ int i;
+// double Now = OGGetAbsoluteTime();
+ const int colwid = 50;
+ int categories = (screenx-50)/colwid;
+ int maxpingslot = ( globmaxtime*10000.0 );
+ int minpingslot = ( globmintime*10000.0 );
+ int slots = maxpingslot-minpingslot;
+
+ if( categories <= 1 )
+ {
+ goto nodata;
+ }
+ else
+ {
+ int skips = ( (slots)/categories ) + 1;
+ int slotsmax = maxpingslot / skips + 1;
+ int slotsmin = minpingslot / skips;
+ slots = slotsmax - slotsmin;
+ uint64_t samples[slots+2];
+ int ssmsMIN[slots+2];
+ int ssmsMAX[slots+2];
+ int samp = minpingslot - 1;
+
+ if( slots <= 0 ) goto nodata;
+
+ memset( samples, 0, sizeof( samples ) );
+ if( samp < 0 ) samp = 0;
+
+ uint64_t highestchart = 0;
+ int tslot = 0;
+ for( i = slotsmin; i <= slotsmax; i++ )
+ {
+ int j;
+ uint64_t total = 0;
+ ssmsMIN[tslot] = samp;
+ for( j = 0; j < skips; j++ )
+ {
+ total += hist_counts[samp++];
+ }
+
+ ssmsMAX[tslot] = samp;
+ if( total > highestchart ) highestchart = total;
+ samples[tslot++] = total;
+ }
+
+ if( highestchart <= 0 )
+ {
+ goto nodata;
+ }
+
+ int rslots = 0;
+ for( i = 0; i < slots+1; i++ )
+ {
+ if( samples[i] ) rslots = i;
+ }
+ rslots++;
+
+ for( i = 0; i < rslots; i++ )
+ {
+ CNFGColor( 0x33cc33 );
+ int top = 30;
+ uint64_t samps = samples[i];
+ int bottom = screeny - 50;
+ int height = samps?(samps * (bottom-top) / highestchart + 1):0;
+ int startx = (i+1) * (screenx-50) / rslots;
+ int endx = (i+2) * (screenx-50) / rslots;
+
+ if( !in_frame_mode )
+ {
+ CNFGTackRectangle( startx, bottom-height, endx, bottom + 1 );
+ CNFGColor( 0x00 );
+ }
+ else
+ {
+ CNFGColor( 0x8080ff );
+ }
+ CNFGTackSegment( startx, bottom+1, endx, bottom+1 );
+
+ CNFGTackSegment( startx, bottom-height, startx, bottom+1 );
+ CNFGTackSegment( endx, bottom-height, endx, bottom+1 );
+
+ CNFGTackSegment( startx, bottom-height, endx, bottom-height );
+ char stbuf[1024];
+ int log10 = 1;
+ int64_t ll = samps;
+ while( ll >= 10 )
+ {
+ ll /= 10;
+ log10++;
+ }
+
+ if( !in_frame_mode )
+ {
+ CNFGColor( 0xffffff );
+ }
+ else
+ {
+ CNFGColor( 0x8080ff );
+ }
+
+
+ CNFGPenX = startx + (8-log10) * 4; CNFGPenY = bottom+3;
+#ifdef WIN32
+ sprintf( stbuf, "%llu", samps );
+#else
+ sprintf( stbuf, "%lu", samps );
+#endif
+ CNFGDrawText( stbuf, 2 );
+
+ CNFGPenX = startx; CNFGPenY = bottom+14;
+ sprintf( stbuf, "%5.1fms\n%5.1fms", ssmsMIN[i]/10.0, ssmsMAX[i]/10.0 );
+ CNFGDrawText( stbuf, 2 );
+ }
+ char stt[1024];
+ snprintf( stt, 1024, "Host: %s\nHistorical max %9.2fms\nBiggest interval%9.2fms\nHistorical packet loss %lu/%lu = %6.2f%%", pinghost, globmaxtime*1000.0, globinterval*1000.0, globallost, globalrx, globallost*100.0/(globalrx+globallost) );
+ if( !in_frame_mode )
+ DrawMainText( stt );
+ return;
+ }
+nodata:
+ DrawMainText( "No data.\n" );
+ return;
+}
+
+
void DrawFrame( void )
{
- int i, x, y;
+ int i;
double now = OGGetAbsoluteTime();
- double globmaxtime = GetGlobMaxPingTime();
double totaltime = 0;
int totalcountok = 0;
@@ -166,6 +372,7 @@ void DrawFrame( void )
double stddev = 0;
double last = -1;
double loss = 100.00;
+ double windmaxtime = GetWindMaxPingTime();
for( i = 0; i < screenx; i++ )
{
@@ -202,7 +409,7 @@ void DrawFrame( void )
if (!GuiYscaleFactorIsConstant)
{
- GuiYScaleFactor = (screeny - 50) / globmaxtime;
+ GuiYScaleFactor = (screeny - 50) / windmaxtime;
}
int h = dt*GuiYScaleFactor;
@@ -246,26 +453,19 @@ void DrawFrame( void )
l = (avg_gui) - (stddev_gui);
CNFGTackSegment( 0, screeny-l, screenx, screeny - l );
- char stbuf[1024];
+ char stbuf[2048];
char * sptr = &stbuf[0];
sptr += sprintf( sptr,
- "Last: %5.2f ms\n"
- "Min : %5.2f ms\n"
- "Max : %5.2f ms\n"
- "Avg : %5.2f ms\n"
- "Std : %5.2f ms\n"
- "Loss: %5.1f %%\n\n%s", last, mintime, maxtime, avg, stddev, loss, (ping_failed_to_send?"Could not send ping.\nIs target reachable?\nDo you have sock_raw to privileges?":"") );
-
- CNFGColor( 0x00 );
- for( x = -1; x < 2; x++ ) for( y = -1; y < 2; y++ )
- {
- CNFGPenX = 10+x; CNFGPenY = 10+y;
- CNFGDrawText( stbuf, 2 );
- }
- CNFGColor( 0xffffff );
- CNFGPenX = 10; CNFGPenY = 10;
- CNFGDrawText( stbuf, 2 );
+ "Last:%6.2f ms Host: %s\n"
+ "Min :%6.2f ms\n"
+ "Max :%6.2f ms Historical max: %5.2f ms\n"
+ "Avg :%6.2f ms Biggest interval: %5.2f ms\n"
+ "Std :%6.2f ms Historical loss: %lu/%lu %5.2f%%\n"
+ "Loss:%6.1f %%", last, pinghost, mintime, maxtime, globmaxtime*1000, avg, globinterval*1000.0, stddev,
+ globallost, globalrx, globallost*100.0f/(globalrx+globallost), loss );
+
+ DrawMainText( stbuf );
OGUSleep( 1000 );
}
@@ -397,6 +597,7 @@ int main( int argc, const char ** argv )
case 's': ExtraPingSize = atoi( nextargv ); break;
case 'y': GuiYScaleFactor = atof( nextargv ); break;
case 't': sprintf(title, "%s", nextargv); break;
+ case 'm': in_histogram_mode = 1; break;
default: displayhelp = 1; break;
}
}
@@ -467,7 +668,27 @@ int main( int argc, const char ** argv )
CNFGColor( 0xFFFFFF );
CNFGGetDimensions( &screenx, &screeny );
- DrawFrame();
+ if( in_frame_mode )
+ {
+ DrawFrame();
+ }
+
+ if( in_histogram_mode )
+ {
+ DrawFrameHistogram();
+ }
+
+ CNFGPenX = 100; CNFGPenY = 100;
+ CNFGColor( 0xff );
+ if( ping_failed_to_send )
+ {
+ CNFGDrawText( "Could not send ping.\nIs target reachable?\nDo you have sock_raw to privileges?", 3 );
+ }
+ else
+ {
+ CNFGDrawText( errbuffer, 3 );
+ }
+
frames++;
CNFGSwapBuffers();
diff --git a/cnping.exe b/cnping.exe
Binary files differ.
diff --git a/error_handling.h b/error_handling.h
@@ -1,18 +1,22 @@
#ifndef _ERROR_HANDLING
#define _ERROR_HANDLING
+extern char errbuffer[1024];
+
#ifdef WIN32
-extern char errbuffer[1024];
#ifndef _MSC_VER
#define ERRM(x...) { sprintf( errbuffer, x ); MessageBox( 0, errbuffer, "cnping", 0 ); }
+#define ERRMB(x...) { sprintf( errbuffer, x ); }
#else
#define ERRM(...) { sprintf( errbuffer, __VA_ARGS__ ); MessageBox( 0, errbuffer, "cnping", 0 ); }
+#define ERRMB(...) { sprintf( errbuffer, __VA_ARGS__ ); }
#endif
#else
-#define ERRM(x...) fprintf( stderr, x );
+#define ERRM(x...) { fprintf( stderr, x ); }
+#define ERRMB(x...) { sprintf( errbuffer, x); fprintf( stderr, x ); }
#endif
diff --git a/httping.c b/httping.c
@@ -61,12 +61,12 @@ void DoHTTPing( const char * addy, double minperiod, int * seqnoptr, volatile do
server = gethostbyname(hostname);
*getting_host_by_name = 0;
if (server == NULL) {
- ERRM("ERROR, no such host as %s\n", hostname);
+ ERRMB("ERROR, no such host as %s\n", hostname);
goto fail;
}
/* build the server's Internet address */
- bzero((char *) &serveraddr, sizeof(serveraddr));
+ memset((char *) &serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
memcpy((char *)&serveraddr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serveraddr.sin_port = htons(portno);
@@ -75,32 +75,39 @@ reconnect:
*socketptr = httpsock = socket(AF_INET, SOCK_STREAM, 0);
if (httpsock < 0)
{
- ERRM( "Error opening socket\n" );
+ ERRMB( "Error opening socket\n" );
return;
}
/* connect: create a connection with the server */
if (connect(httpsock, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
{
- ERRM( "%s: ERROR connecting\n", hostname );
+ ERRMB( "%s: ERROR connecting\n", hostname );
goto fail;
}
+ errbuffer[0] = 0;
+
while( 1 )
{
char buf[8192];
int n = sprintf( buf, "HEAD %s HTTP/1.1\r\nConnection: keep-alive\r\n\r\n", eurl?eurl:"/favicon.ico" );
- send( httpsock, buf, n, MSG_NOSIGNAL );
+ int rs = send( httpsock, buf, n, MSG_NOSIGNAL );
double starttime = *timeouttime = OGGetAbsoluteTime();
-
- int endstate = 0;
int breakout = 0;
+ if( rs != n ) breakout = 1;
+ int endstate = 0;
while( !breakout )
{
+#ifdef WIN32
+ n = recv( httpsock, buf, sizeof(buf)-1, 0);
+#else
n = recv( httpsock, buf, sizeof(buf)-1, MSG_PEEK);
if( n > 0 ) n = read( httpsock, buf, sizeof(buf)-1);
else if( n == 0 ) break; //FIN received
+#endif
+
if( n < 0 ) return;
diff --git a/ping.c b/ping.c
@@ -146,13 +146,7 @@ void listener()
void ping(struct sockaddr_in *addr )
{
-#ifdef WIN32
- const char val=255;
-#else
- const int val=255;
-#endif
- int i, cnt=1;
- struct sockaddr_in r_addr;
+ int cnt=1;
#ifdef WIN32
{