commit dab665d732902fa3d3fe697af5ae8d46045909f0
parent 64051c4c40c8f7b35fca7ff4a8577bde9946dd51
Author: cnlohr <charles@cnlohr.com>
Date: Sat, 17 Feb 2018 03:10:54 -0500
Update - include http:// as an optional protocol to cnping.
Diffstat:
10 files changed, 279 insertions(+), 22 deletions(-)
diff --git a/Makefile b/Makefile
@@ -10,11 +10,11 @@ LDFLAGS:=-g -L/opt/X11/lib/
#MINGW32:=/usr/bin/i686-w64-mingw32-
MINGW32:=i686-w64-mingw32-
-cnping.exe : cnping.c CNFGFunctions.c CNFGWinDriver.c os_generic.c ping.c
+cnping.exe : cnping.c CNFGFunctions.c CNFGWinDriver.c os_generic.c ping.c httping.c
$(MINGW32)windres resources.rc -o resources.o
$(MINGW32)gcc -g -mwindows -m32 $(CFLAGS) resources.o -o $@ $^ -lgdi32 -lws2_32 -s -D_WIN32_WINNT=0x0600 -DWIN32
-cnping : cnping.o CNFGFunctions.o CNFGXDriver.o os_generic.o ping.o
+cnping : cnping.o CNFGFunctions.o CNFGXDriver.o os_generic.o ping.o httping.o
gcc $(CFLAGS) -o $@ $^ -lX11 -lm -lpthread $(LDFLAGS)
cnping-mousey : cnping-mousey.o CNFGFunctions.o CNFGXDriver.o os_generic.o ping.o
diff --git a/cnping-mousey.c b/cnping-mousey.c
@@ -18,6 +18,7 @@
#include "CNFGFunctions.h"
#include "os_generic.h"
#include "ping.h"
+#include "error_handling.h"
unsigned frames = 0;
unsigned long iframeno = 0;
diff --git a/cnping.c b/cnping.c
@@ -21,6 +21,8 @@
#include "CNFGFunctions.h"
#include "os_generic.h"
#include "ping.h"
+#include "error_handling.h"
+#include "httping.h"
unsigned frames = 0;
unsigned long iframeno = 0;
@@ -41,6 +43,20 @@ int current_cycle = 0;
int ExtraPingSize;
+
+void HTTPingCallbackStart( int seqno )
+{
+ current_cycle = seqno;
+
+ PingSendTimes[seqno] = OGGetAbsoluteTime();
+ PingRecvTimes[seqno] = 0;
+}
+
+void HTTPingCallbackGot( int seqno )
+{
+ PingRecvTimes[seqno] = OGGetAbsoluteTime();
+}
+
void display(uint8_t *buf, int bytes)
{
int reqid = (buf[0] << 24) | (buf[1]<<16) | (buf[2]<<8) | (buf[3]);
@@ -420,7 +436,7 @@ int main( int argc, const char ** argv )
ERRM( "Need at least a host address to ping.\n" );
#else
ERRM( "Usage: cnping [host] [period] [extra size] [y-axis scaling] [window title]\n"
- " (-h) [host] -- domain or IP address of ping target \n"
+ " (-h) [host] -- domain, IP address of ping target for ICMP or http host, i.e. http://google.com\n"
" (-p) [period] -- period in seconds (optional), default 0.02 \n"
" (-s) [extra size] -- ping packet extra size (above 12), optional, default = 0 \n"
" (-y) [const y-axis scaling] -- use a fixed scaling factor instead of auto scaling (optional)\n"
@@ -431,10 +447,16 @@ int main( int argc, const char ** argv )
CNFGSetup( title, 320, 155 );
- ping_setup();
-
- OGCreateThread( PingSend, 0 );
- OGCreateThread( PingListen, 0 );
+ if( memcmp( pinghost, "http://", 7 ) == 0 )
+ {
+ StartHTTPing( pinghost+7, pingperiodseconds );
+ }
+ else
+ {
+ ping_setup();
+ OGCreateThread( PingSend, 0 );
+ OGCreateThread( PingListen, 0 );
+ }
while(1)
{
diff --git a/cnping.exe b/cnping.exe
Binary files differ.
diff --git a/error_handling.h b/error_handling.h
@@ -0,0 +1,20 @@
+#ifndef _ERROR_HANDLING
+#define _ERROR_HANDLING
+
+#ifdef WIN32
+
+extern char errbuffer[1024];
+#ifndef _MSC_VER
+#define ERRM(x...) { sprintf( errbuffer, x ); MessageBox( 0, errbuffer, "cnping", 0 ); }
+#else
+#define ERRM(...) { sprintf( errbuffer, __VA_ARGS__ ); MessageBox( 0, errbuffer, "cnping", 0 ); }
+#endif
+
+#else
+
+#define ERRM(x...) fprintf( stderr, x );
+
+#endif
+
+
+#endif
diff --git a/httping.c b/httping.c
@@ -0,0 +1,213 @@
+#include "httping.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef WIN32
+ #include <winsock2.h>
+ #ifndef MSG_NOSIGNAL
+ #define MSG_NOSIGNAL 0
+ #endif
+
+#else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+#endif
+
+#include "os_generic.h"
+#include "error_handling.h"
+
+
+#define HTTPTIMEOUT 3.0
+
+//Callbacks (when started/received)
+void HTTPingCallbackStart( int seqno );
+void HTTPingCallbackGot( int seqno );
+
+//Don't dynamically allocate resources here, since execution may be stopped arbitrarily.
+void DoHTTPing( const char * addy, double minperiod, int * seqnoptr, volatile double * timeouttime, int * socketptr, volatile int * getting_host_by_name )
+{
+ struct sockaddr_in serveraddr;
+ struct hostent *server;
+ int httpsock;
+ int addylen = strlen(addy);
+ char hostname[addylen+1];
+ char * eportmarker = strchr( hostname, ':' );
+ char * eurl = strchr( hostname, '/' );
+
+ int portno = 80;
+
+ (*seqnoptr) ++;
+ HTTPingCallbackStart( *seqnoptr );
+
+ memcpy( hostname, addy, addylen + 1 );
+
+ if( eportmarker )
+ {
+ portno = atoi( eportmarker+1 );
+ *eportmarker = 0;
+ }
+ else
+ {
+ if( eurl )
+ *eurl = 0;
+ }
+
+ *socketptr = httpsock = socket(AF_INET, SOCK_STREAM, 0);
+ if (httpsock < 0)
+ {
+ ERRM( "Error opening socket\n" );
+ return;
+ }
+
+ /* gethostbyname: get the server's DNS entry */
+ *getting_host_by_name = 1;
+ server = gethostbyname(hostname);
+ *getting_host_by_name = 0;
+ if (server == NULL) {
+ ERRM("ERROR, no such host as %s\n", hostname);
+ goto fail;
+ }
+
+ /* build the server's Internet address */
+ bzero((char *) &serveraddr, sizeof(serveraddr));
+ serveraddr.sin_family = AF_INET;
+ memcpy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length);
+ serveraddr.sin_port = htons(portno);
+
+ /* connect: create a connection with the server */
+ if (connect(httpsock, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
+ {
+ ERRM( "%s: ERROR connecting\n", hostname );
+ goto fail;
+ }
+
+
+ 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 );
+ double starttime = *timeouttime = OGGetAbsoluteTime();
+
+ int endstate = 0;
+ int breakout = 0;
+ while( !breakout )
+ {
+ n = read( httpsock, buf, sizeof(buf)-1 );
+ if( n < 0 ) return;
+ int i;
+ for( i = 0; i < n; i++ )
+ {
+ char c = buf[i];
+ switch( endstate )
+ {
+ case 0: if( c == '\r' ) endstate++; break;
+ case 1: if( c == '\n' ) endstate++; else endstate = 0; break;
+ case 2: if( c == '\r' ) endstate++; else endstate = 0; break;
+ case 3: if( c == '\n' ) breakout = 1; else endstate = 0; break;
+ }
+ }
+ }
+
+ *timeouttime = OGGetAbsoluteTime();
+
+ HTTPingCallbackGot( *seqnoptr );
+
+ double delay_time = minperiod - (*timeouttime - starttime);
+ if( delay_time > 0 )
+ usleep( (int)(delay_time * 1000000) );
+ (*seqnoptr) ++;
+ HTTPingCallbackStart( *seqnoptr );
+
+
+ }
+fail:
+ return;
+}
+
+
+struct HTTPPingLaunch
+{
+ const char * addy;
+ double minperiod;
+
+ volatile double timeout_time;
+ volatile int failed;
+ int seqno;
+ int socket;
+ volatile int getting_host_by_name;
+};
+
+static void * DeployPing( void * v )
+{
+ struct HTTPPingLaunch *hpl = (struct HTTPPingLaunch*)v;
+ hpl->socket = 0;
+ hpl->getting_host_by_name = 0;
+ DoHTTPing( hpl->addy, hpl->minperiod, &hpl->seqno, &hpl->timeout_time, &hpl->socket, &hpl->getting_host_by_name );
+ hpl->failed = 1;
+ return 0;
+}
+
+
+static void * PingRunner( void * v )
+{
+ struct HTTPPingLaunch *hpl = (struct HTTPPingLaunch*)v;
+ hpl->seqno = 0;
+ while( 1 )
+ {
+ hpl->timeout_time = OGGetAbsoluteTime();
+ og_thread_t thd = OGCreateThread( DeployPing, hpl );
+ while( 1 )
+ {
+ double Now = OGGetAbsoluteTime();
+ double usl = hpl->timeout_time - Now + HTTPTIMEOUT;
+ if( usl > 0 ) usleep( (int)(usl*1000000 + 1000));
+ else usleep( 10000 );
+
+ if( hpl->timeout_time + HTTPTIMEOUT < Now && !hpl->getting_host_by_name ) //Can't terminate in the middle of a gethostbyname operation otherwise bad things can happen.
+ {
+ if( hpl->socket )
+ {
+#ifdef WIN32
+ closesocket( hpl->socket );
+#else
+ close( hpl->socket );
+#endif
+ }
+
+ OGCancelThread( thd );
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+int StartHTTPing( const char * addy, double minperiod )
+{
+
+#ifdef WIN32
+ WSADATA wsaData;
+ int r = WSAStartup(MAKEWORD(2,2), &wsaData);
+ if( r )
+ {
+ ERRM( "Fault in WSAStartup\n" );
+ exit( -2 );
+ }
+#endif
+
+ struct HTTPPingLaunch *hpl = malloc( sizeof( struct HTTPPingLaunch ) );
+ hpl->addy = addy;
+ hpl->minperiod = minperiod;
+ OGCreateThread( PingRunner, hpl );
+ return 0;
+}
+
+
+
diff --git a/httping.h b/httping.h
@@ -0,0 +1,12 @@
+#ifndef _HTTPING_H
+#define _HTTPING_H
+
+//Callbacks (when started/received)
+void HTTPingCallbackStart( int seqno );
+void HTTPingCallbackGot( int seqno );
+
+//addy should be google.com/blah or something like that. Do not include prefixing http://. Port numbers OK.
+int StartHTTPing( const char * addy, double minperiod );
+
+#endif
+
diff --git a/ping.c b/ping.c
@@ -11,6 +11,9 @@
#include "ping.h"
#include "os_generic.h"
+
+#include "error_handling.h"
+
#ifdef WIN32
#include <winsock2.h>
#define SOL_IP 0
diff --git a/ping.h b/ping.h
@@ -24,20 +24,6 @@ extern int precise_ping; //if 0, use minimal CPU, but ping send-outs are only ap
extern int ping_failed_to_send;
void ping_setup();
-#ifdef WIN32
-
-extern char errbuffer[1024];
-#ifndef _MSC_VER
-#define ERRM(x...) { sprintf( errbuffer, x ); MessageBox( 0, errbuffer, "cnping", 0 ); }
-#else
-#define ERRM(...) { sprintf( errbuffer, __VA_ARGS__ ); MessageBox( 0, errbuffer, "cnping", 0 ); }
-#endif
-
-#else
-
-#define ERRM(x...) fprintf( stderr, x );
-
-#endif
#endif
diff --git a/resources.rc b/resources.rc
@@ -8,7 +8,7 @@ STYLE WS_CAPTION | WS_SYSMENU
CAPTION "cnping"
BEGIN
LTEXT "Usage: cnping [host] [period] [extra size] [y-axis scaling]", 0, 60, 0, 300, 20, SS_LEFT
- LTEXT "[host] -- domain or IP address of ping target", 0, 60, 15, 300, 20, SS_LEFT
+ LTEXT "[host] -- domain or IP address of icmp ping, or http://host", 0, 60, 15, 300, 20, SS_LEFT
LTEXT "[period] -- period in seconds (optional), default is 0.02", 0, 60, 30, 300, 20, SS_LEFT
LTEXT "[extra size] -- ping packet extra size (above 12), optional, default = 0", 0, 60, 45, 300, 10, SS_LEFT
LTEXT "[const y-axis scaling] -- use a fixed scaling factor instead of auto scaling", 0, 60, 60, 300, 10, SS_LEFT