commit 9e7b717ad682914732a40da40f4f2c7f987ad3aa
parent 5c42452616a85c6877f5502a828dc82f61212a80
Author: Viknet <viknet@icloud.com>
Date: Sat, 28 Jul 2018 13:46:20 +0300
Merge pull request #1 from cnlohr/master
Update tree
Diffstat:
18 files changed, 1190 insertions(+), 911 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,3 +3,4 @@
cnping
cnping-mousey
searchnet
+tags
diff --git a/CNFGCocoaCGDriver.m b/CNFGCocoaCGDriver.m
@@ -0,0 +1,361 @@
+//Copyright (c) 2017 <>< David Chapman - Under the MIT/x11 or NewBSD License you choose.
+//Copyright (C) 2017 Viknet, MIT/x11 License or NewBSD License you choose.
+
+#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+
+#define RGB2Color(RGB) (RGB&0xFF)/256., ((RGB>>8)&0xFF)/256., ((RGB>>16)&0xFF)/256.
+
+#include "CNFGFunctions.h"
+
+id app_menubar, app_appMenuItem, app_appMenu, app_appName, app_quitMenuItem, app_quitTitle, app_quitMenuItem, app_window;
+NSView *app_imageView;
+CGColorSpaceRef colorSpace;
+CGContextRef bufferContext;
+uint32_t *bufferData;
+
+NSAutoreleasePool *app_pool;
+int app_sw=0, app_sh=0;
+NSRect frameRect;
+int app_mouseX=0, app_mouseY=0;
+BOOL inFullscreen = false;
+
+uint32_t CNFGColor( uint32_t RGB )
+{
+ CNFGLastColor = RGB;
+ unsigned char red = RGB & 0xFF;
+ unsigned char grn = ( RGB >> 8 ) & 0xFF;
+ unsigned char blu = ( RGB >> 16 ) & 0xFF;
+ CGContextSetRGBStrokeColor(bufferContext, RGB2Color(RGB), 1.0);
+ CGContextSetRGBFillColor(bufferContext, RGB2Color(RGB), 1.0);
+ return CNFGLastColor;
+}
+
+void CNFGTackPixel( short x, short y )
+{
+ y = app_sh - y - 1;
+ if( x < 0 || y < 0 || x >= app_sw || y >= app_sh ) return;
+ bufferData[x + app_sw * y] = CNFGLastColor;
+}
+
+// void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+// {
+// y1 = app_sh - y1 - 1;
+// y2 = app_sh - y2 - 1;
+// CGContextBeginPath(bufferContext);
+// CGContextMoveToPoint(bufferContext, x1, y1);
+// CGContextAddLineToPoint(bufferContext, x2, y2);
+// CGContextStrokePath(bufferContext);
+// }
+
+void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+{
+ short tx, ty;
+ float slope, lp;
+
+ short dx = x2 - x1;
+ short dy = y2 - y1;
+
+ if( dx < 0 ) dx = -dx;
+ if( dy < 0 ) dy = -dy;
+
+ if( dx > dy )
+ {
+ short minx = (x1 < x2)?x1:x2;
+ short maxx = (x1 < x2)?x2:x1;
+ short miny = (x1 < x2)?y1:y2;
+ short maxy = (x1 < x2)?y2:y1;
+ float thisy = miny;
+ slope = (float)(maxy-miny) / (float)(maxx-minx);
+
+ for( tx = minx; tx <= maxx; tx++ )
+ {
+ ty = thisy;
+ if( tx < 0 || ty < 0 || ty >= app_sh ) continue;
+ if( tx >= app_sw ) break;
+ bufferData[ty * app_sw + tx] = CNFGLastColor;
+ thisy += slope;
+ }
+ }
+ else
+ {
+ short minx = (y1 < y2)?x1:x2;
+ short maxx = (y1 < y2)?x2:x1;
+ short miny = (y1 < y2)?y1:y2;
+ short maxy = (y1 < y2)?y2:y1;
+ float thisx = minx;
+ slope = (float)(maxx-minx) / (float)(maxy-miny);
+
+ for( ty = miny; ty <= maxy; ty++ )
+ {
+ tx = thisx;
+ if( ty < 0 || tx < 0 || tx >= app_sw ) continue;
+ if( ty >= app_sh ) break;
+ bufferData[ty * app_sw + tx] = CNFGLastColor;
+ thisx += slope;
+ }
+ }
+}
+
+void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
+{
+ CGContextFillRect(bufferContext, CGRectMake (x1, app_sh - y1 - 1, x2, app_sh - y2 - 1 ));
+}
+
+void CNFGTackPoly( RDPoint * points, int verts )
+{
+ if (verts==0) return;
+ CGContextBeginPath(bufferContext);
+ CGContextMoveToPoint(bufferContext, points[0].x, app_sh - points[0].y - 1);
+ for (int i=1; i<verts; i++){
+ CGContextAddLineToPoint(bufferContext, points[i].x, app_sh - points[i].y - 1);
+ }
+ CGContextFillPath(bufferContext);
+}
+
+@interface MyView : NSView
+@end
+@implementation MyView
+- (id)initWithFrame:(NSRect)frame {
+ self = [super initWithFrame:frame];
+ if (self)
+ {
+ [self setWantsLayer:YES];
+ [self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawOnSetNeedsDisplay];
+ // [self setLayerContentsPlacement: NSViewLayerContentsPlacementCenter];
+ }
+ return self;
+}
+
+- (BOOL) wantsUpdateLayer
+{
+ return YES;
+}
+- (void) updateLayer
+{
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferData, 4*app_sw*app_sh, NULL);
+ CGImageRef frameImage = CGImageCreate(app_sw, app_sh, 8, 32, 4*app_sw, colorSpace, kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);
+
+ [app_imageView.layer setContents:(id)frameImage];
+
+ CGImageRelease(frameImage);
+ CGDataProviderRelease(provider);
+}
+@end
+
+CGContextRef createBitmapContext (int pixelsWide,
+ int pixelsHigh)
+{
+ int bitmapBytesPerRow = (pixelsWide * 4);
+
+ CGContextRef context = CGBitmapContextCreate (NULL,
+ pixelsWide,
+ pixelsHigh,
+ 8,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaNoneSkipLast);
+ bufferData = CGBitmapContextGetData(context);
+ CGContextSetInterpolationQuality(context, kCGInterpolationNone);
+ // CGContextSetShouldAntialias(context, NO);
+ // CGContextSetLineWidth(context, 0.5);
+
+ return context;
+}
+
+void initApp(){
+ [NSApplication sharedApplication];
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+ app_menubar = [[NSMenu new] autorelease];
+ app_appMenuItem = [[NSMenuItem new] autorelease];
+ [app_menubar addItem:app_appMenuItem];
+ [NSApp setMainMenu:app_menubar];
+ app_appMenu = [[NSMenu new] autorelease];
+ app_appName = [[NSProcessInfo processInfo] processName];
+ app_quitTitle = [@"Quit " stringByAppendingString:app_appName];
+ app_quitMenuItem = [[[NSMenuItem alloc] initWithTitle:app_quitTitle
+ action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
+ [app_appMenu addItem:app_quitMenuItem];
+ [app_appMenuItem setSubmenu:app_appMenu];
+ app_imageView = [MyView new];
+ colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
+}
+
+void CNFGSetupFullscreen( const char * WindowName, int screen_number )
+{
+ inFullscreen = YES;
+ initApp();
+
+ NSDictionary *fullScreenOptions = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:
+ (NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock) ],
+ NSFullScreenModeApplicationPresentationOptions, nil];
+ [app_imageView enterFullScreenMode:[[NSScreen screens] objectAtIndex:screen_number] withOptions:fullScreenOptions];
+ frameRect = [app_imageView frame];
+ CGSize app_imageSize = frameRect.size;
+ app_sw = app_imageSize.width; app_sh = app_imageSize.height;
+ bufferContext = createBitmapContext (app_sw, app_sh);
+ [NSApp finishLaunching];
+ [NSApp updateWindows];
+ app_pool = [NSAutoreleasePool new];
+}
+
+void CNFGSetup( const char * WindowName, int sw, int sh )
+{
+ app_sw=sw; app_sh=sh;
+ frameRect = NSMakeRect(0, 0, app_sw, app_sh);
+
+ initApp();
+
+ app_window = [[[NSWindow alloc]
+ initWithContentRect:frameRect
+ styleMask:
+ NSWindowStyleMaskBorderless |
+ NSWindowStyleMaskResizable |
+ NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable
+ backing:NSBackingStoreBuffered defer:NO]
+ autorelease];
+
+ NSString *title = [[[NSString alloc] initWithCString: WindowName encoding: NSUTF8StringEncoding] autorelease];
+ [app_window setTitle:title];
+ [app_window setContentView:app_imageView];
+ [app_window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
+ [app_window makeKeyAndOrderFront:nil];
+ [NSApp activateIgnoringOtherApps:YES];
+ bufferContext = createBitmapContext (app_sw, app_sh);
+ [NSApp finishLaunching];
+ [NSApp updateWindows];
+ app_pool = [NSAutoreleasePool new];
+}
+
+#define XK_Left 0xff51 /* Move left, left arrow */
+#define XK_Up 0xff52 /* Move up, up arrow */
+#define XK_Right 0xff53 /* Move right, right arrow */
+#define XK_Down 0xff54 /* Move down, down arrow */
+#define KEY_UNDEFINED 255
+#define KEY_LEFT_MOUSE 0
+
+static int keycode(key)
+{
+ if (key < 256) return key;
+ switch(key) {
+ case 63232: return XK_Up;
+ case 63233: return XK_Down;
+ case 63234: return XK_Left;
+ case 63235: return XK_Right;
+ }
+ return KEY_UNDEFINED;
+}
+
+void CNFGHandleInput()
+{
+ [app_pool release];
+ app_pool = [NSAutoreleasePool new];
+ // Quit if no open windows left
+ if ([[NSApp windows] count] == 0) [NSApp terminate: nil];
+
+ //----------------------
+ // Peek at the next event
+ //----------------------
+ NSDate *app_currDate = [NSDate new];
+ // If we have events, handle them!
+ NSEvent *event;
+ for (;(event = [NSApp
+ nextEventMatchingMask:NSEventMaskAny
+ untilDate:app_currDate
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES]);)
+ {
+ NSPoint local_point;
+ NSEventType type = [event type];
+ switch (type)
+ {
+ case NSEventTypeKeyDown:
+ for (int i=0; i<[event.characters length]; i++) {
+ unichar ch = [event.characters characterAtIndex: i];
+ HandleKey(keycode(ch), 1);
+ }
+ break;
+
+ case NSEventTypeKeyUp:
+ for (int i=0; i<[event.characters length]; i++) {
+ unichar ch = [event.characters characterAtIndex: i];
+ HandleKey(keycode(ch), 0);
+ }
+ break;
+
+ case NSEventTypeMouseMoved:
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeOtherMouseDragged:
+ if (inFullscreen){
+ local_point = [NSEvent mouseLocation];
+ } else {
+ if ([event window] == nil) break;
+ NSPoint event_location = event.locationInWindow;
+ local_point = [app_imageView convertPoint:event_location fromView:nil];
+ }
+ app_mouseX = fmax(fmin(local_point.x, app_sw), 0);
+ // Y coordinate must be inversed?
+ app_mouseY = fmax(fmin(app_sh - local_point.y, app_sh), 0);
+ HandleMotion(app_mouseX, app_mouseY, [NSEvent pressedMouseButtons]);
+ break;
+
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeOtherMouseDown:
+ // Button number start from 1?
+ HandleButton(app_mouseX, app_mouseY, event.buttonNumber+1, 1);
+ break;
+
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeOtherMouseUp:
+ HandleButton(app_mouseX, app_mouseY, event.buttonNumber+1, 0);
+ break;
+
+ default:
+ break;
+ }
+ [NSApp sendEvent:event];
+ }
+ [app_currDate release];
+}
+
+void CNFGGetDimensions( short * x, short * y )
+{
+ frameRect = [app_window frame];
+ CGSize app_imageSize = frameRect.size;
+ if (app_imageSize.width != app_sw || app_imageSize.height != app_sh)
+ {
+ app_sw = app_imageSize.width;
+ app_sh = app_imageSize.height;
+ if (bufferContext != NULL)
+ CGContextRelease(bufferContext);
+ bufferContext = createBitmapContext (app_sw, app_sh);
+ }
+ *x = app_sw;
+ *y = app_sh;
+}
+
+void CNFGClearFrame()
+{
+ CGContextSetRGBFillColor(bufferContext, RGB2Color(CNFGBGColor), 1.0);
+ CGContextFillRect(bufferContext, CGRectMake (0, 0, app_sw, app_sh ));
+}
+
+void CNFGSwapBuffers()
+{
+ [app_imageView setNeedsDisplay:YES];
+}
+
+void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
+{
+ CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, 4*w*h, NULL);
+ CGImageRef bitmap = CGImageCreate(w, h, 8, 32, 4*w, colorSpace, kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);
+ CGContextDrawImage(bufferContext, frameRect, bitmap);
+ CGImageRelease(bitmap);
+ CGDataProviderRelease(provider);
+}
diff --git a/CNFGXDriver.c b/CNFGXDriver.c
@@ -1,5 +1,5 @@
//Copyright (c) 2011, 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
-//portions from
+//portions from
//http://www.xmission.com/~georgeps/documentation/tutorials/Xlib_Beginner.html
//#define HAS_XINERAMA
@@ -128,8 +128,8 @@ void CNFGSetupFullscreen( const char * WindowName, int screen_no )
CNFGWindow = XCreateWindow(CNFGDisplay, XRootWindow(CNFGDisplay, screen),
xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height,
- 0, CNFGWinAtt.depth, InputOutput, CNFGVisual,
- CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder,
+ 0, CNFGWinAtt.depth, InputOutput, CNFGVisual,
+ CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder,
&setwinattr);
XMapWindow(CNFGDisplay, CNFGWindow);
@@ -173,7 +173,7 @@ void CNFGSetup( const char * WindowName, int w, int h )
#ifdef CNFGOGL
int attribs[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER,
+ GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
@@ -214,10 +214,9 @@ void CNFGHandleInput()
XEvent report;
int bKeyDirection = 1;
- int r;
while( XPending( CNFGDisplay ) )
{
- r=XNextEvent( CNFGDisplay, &report );
+ XNextEvent( CNFGDisplay, &report );
bKeyDirection = 1;
switch (report.type)
@@ -251,7 +250,8 @@ void CNFGHandleInput()
exit( 0 );
break;
default:
- printf( "Event: %d\n", report.type );
+ //printf( "Event: %d\n", report.type );
+ break;
}
}
}
@@ -262,8 +262,6 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
static XImage *xi;
static int depth;
static int lw, lh;
- static unsigned char * lbuffer;
- int r, ls;
if( !xi )
{
@@ -281,9 +279,6 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
lw = w;
lh = h;
}
-
- ls = lw * lh;
-
XPutImage(CNFGDisplay, CNFGWindow, CNFGWindowGC, xi, 0, 0, 0, 0, w, h );
}
@@ -323,7 +318,7 @@ uint32_t CNFGColor( uint32_t RGB )
void CNFGClearFrame()
{
XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt );
- XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) );
+ XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) );
XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, 0, 0, CNFGWinAtt.width, CNFGWinAtt.height );
}
@@ -338,6 +333,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/LICENSE b/LICENSE
@@ -1,22 +1,3 @@
-//The myping tool is licensed under the below license.
-//The rest of rawdraw and CNPing may be licensed feely under the MIT-x11
+//Rawdraw and CNPing may be licensed feely under the MIT-x11
//or NewBSD Licenses. You choose!
-/* myping.c
- *
- * Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in
- * whole or in part in accordance to the General Public License (GPL).
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
-*/
-
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
-all : cnping searchnet cnping-mousey
+all : cnping searchnet
-CFLAGS:=$(CFLAGS) -g -Os -I/opt/X11/include
+CFLAGS:=$(CFLAGS) -g -Os -I/opt/X11/include -Wall
CXXFLAGS:=$(CFLAGS)
LDFLAGS:=-g -L/opt/X11/lib/
@@ -10,23 +10,26 @@ 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
+ $(MINGW32)gcc -g -fno-ident -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
- gcc $(CFLAGS) -o $@ $^ -lX11 -lm -lpthread $(LDFLAGS)
+cnping_mac : cnping.c CNFGFunctions.c CNFGCocoaCGDriver.m os_generic.c ping.c httping.o
+ gcc -o cnping $^ -x objective-c -framework Cocoa -framework QuartzCore -lm -lpthread
searchnet : os_generic.o ping.o searchnet.o
gcc $(CFLAGS) -o $@ $^ -lpthread
linuxinstall : cnping
+ sudo rm -f /usr/local/bin/cnping
sudo cp cnping /usr/local/bin/
- sudo chmod +s /usr/local/bin/cnping
+ sudo setcap cap_net_raw+ep /usr/local/bin/cnping
+# sudo chmod +t /usr/local/bin/cnping #One option - set the stuid bit.
+# sudo install cnping /usr/local/bin/ #Another option - using install.
clean :
- rm -rf *.o *~ cnping cnping.exe cnping-mousey searchnet
+ rm -rf *.o *~ cnping cnping.exe cnping_mac searchnet
diff --git a/README.md b/README.md
@@ -1,31 +1,44 @@
cnping
======
-Minimal Graphical IPV4 Ping Tool. (also comes with searchnet, like nmap but smaller and simpler). It uses rawdraw so it is OS independent.
-
-Usage: cnping [host] [period] [extra size] [y-axis scaling]
-
- [host] -- domain or IP address of ping target
- [period] -- period in seconds (optional), default 0.02
- [extra size] -- ping packet extra size (above 12), optional, default = 0
- [const y-axis scaling] -- use a fixed scaling factor instead of auto scaling (optional)
+Minimal Graphical IPV4 Ping/HTTP Ping Tool. (also comes with searchnet, like nmap but smaller and simpler). It uses rawdraw so it is OS independent.
+```
+Usage: cnping [host] [period] [extra size] [y-axis scaling] [window title]
+ [host] -- domain or IP address of ICMP ping target, or http://[host] i.e. http://google.com
+ [period] -- period in seconds (optional), default 0.02
+ [extra size] -- ping packet extra size (above 12), optional, default = 0
+ [const y-axis scaling] -- use a fixed scaling factor instead of auto scaling (optional)
+ [window title] -- the title of the window (optional)
+```
Picture:
<IMG SRC=cnping.png>
-To build on ubuntu, please run:
+If an http host is listed, the default request is ```HEAD /favicon.ico HTTP/1.1``` since this is usually a very fast, easy operation for the server. If a specific file or uri is requested, that will be requested instead, i.e. http://github.com/cnlohr will request ```HEAD /cnlohr HTTP/1.1```.
+
+If a regular hostname is requested instead, ICMP (regular ping) will be used.
+
+This allows cnping to be operated in environments where ICMP is prohibited by local computer or network policies.
+
+## Installation:
+
+### Ubuntu:
```
sudo apt install libxinerama-dev libxext-dev libx11-dev build-essential
make linuxinstall
```
-'linuxinstall' builds the tool and copies it to your usr/local/bin folder, and sets the sticky bit allowing it to run as though it were root, allowing it to create raw sockets.
+'linuxinstall' builds the tool and copies it to your usr/local/bin folder, and sets the sticky bit or appropriate permissions allowing it to run as though it were root, allowing it to create raw sockets.
```
- sudo cp cnping /usr/local/bin/
- sudo chmod +s /usr/local/bin/cnping
+sudo cp cnping /usr/local/bin/
+sudo chmod +s /usr/local/bin/cnping
```
+Note that if only http pinging is requested, you do not need root access.
+
+### Archlinux:
+ [cnping-git](https://aur.archlinux.org/packages/cnping-git/) in the [Arch User Repository](https://wiki.archlinux.org/index.php/Arch_User_Repository)
diff --git a/cnping-mousey.c b/cnping-mousey.c
@@ -1,453 +0,0 @@
-//Copyright (c) 2011-2014 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <errno.h>
-#include <string.h>
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <sys/socket.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <arpa/inet.h>
-#include <sys/select.h>
-#include <netdb.h>
-#endif
-#include "CNFGFunctions.h"
-#include "os_generic.h"
-#include "ping.h"
-
-unsigned frames = 0;
-unsigned long iframeno = 0;
-short screenx, screeny;
-const char * pinghost;
-float pingperiod;
-extern int precise_ping;
-uint8_t pattern[8];
-
-int notemode = 0;
-
-#define PINGCYCLEWIDTH 1024
-#define TIMEOUT 4
-
-double PingSendTimes[PINGCYCLEWIDTH];
-double PingRecvTimes[PINGCYCLEWIDTH];
-int current_cycle = 0;
-
-int ExtraPingSize = 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();
-}
-
-int load_ping_packet( uint8_t * buffer, int bufflen )
-{
- buffer[0] = current_cycle >> 24;
- buffer[1] = current_cycle >> 16;
- buffer[2] = current_cycle >> 8;
- buffer[3] = current_cycle >> 0;
-
- memcpy( buffer+4, pattern, 8 );
-
- PingSendTimes[current_cycle&(PINGCYCLEWIDTH-1)] = OGGetAbsoluteTime();
- PingRecvTimes[current_cycle&(PINGCYCLEWIDTH-1)] = 0;
-
- current_cycle++;
-
- return 12 + ExtraPingSize;
-}
-
-void * PingListen( void * r )
-{
- listener();
- printf( "Fault on listen.\n" );
- exit( -2 );
-}
-
-void * PingSend( void * r )
-{
- do_pinger( pinghost );
- printf( "Fault on ping.\n" );
- exit( -1 );
-}
-
-double lastnote;
-double lastnoteupdown = 0;
-
-void HandleKey( int keycode, int bDown )
-{
- double note;
- if( keycode == 'n' && bDown )
- {
- notemode = !notemode;
- }
- note = -1;
-
- switch( keycode )
- {
- case 'a': note = 0; break;
- case 'w': note = 1; break;
- case 's': note = 2; break;
- case 'e': note = 3; break;
- case 'd': note = 4; break;
- case 'f': note = 5; break;
- case 't': note = 6; break;
- case 'g': note = 7; break;
- case 'y': note = 8; break;
- case 'h': note = 9; break;
- case 'u': note = 10; break;
- case 'j': note = 11; break;
- case 'k': note = 12; break;
- case 'o': note = 13; break;
- case 'l': note = 14; break;
- case 'p': note = 15; break;
- case ';': note = 16; break;
- case '\'': note = 17; break;
- }
-
- if( note >= 0 )
- {
- double per = (2.0 / pow(2.0, (note/12.0) ) ) * (1/440.);
- if( bDown )
- {
- printf( "%f\n", note );
- pingperiod = per;
- lastnoteupdown = 0;
- lastnote = note;
- }
- else
- {
- if( note == lastnote )
- lastnoteupdown = OGGetAbsoluteTime();
- }
- }
-}
-void HandleButton( int x, int y, int button, int bDown ){}
-void HandleMotion( int x, int y, int mask )
-{
- if( mask )
- {
- float per = (2.0 / pow(2.0, x / 120.0)) * 0.02;
- if( !notemode )
- {
- pingperiod = per;
- }
-
- if( y > 0 )
- ExtraPingSize = y*2;
-
- }
-}
-
-void DrawFrame( void )
-{
- int i, x, y;
-
- double now = OGGetAbsoluteTime();
-
- double totaltime = 0;
- int totalcountok = 0;
- double mintime = 100;
- double maxtime = 0;
- double stddev = 0;
- double last = -1;
-
- precise_ping = 1;
-
- for( i = 0; i < screenx; i++ )
- {
- int index = ((current_cycle - i - 1) + PINGCYCLEWIDTH) & (PINGCYCLEWIDTH-1);
- double st = PingSendTimes[index];
- double rt = PingRecvTimes[index];
-
- double dt = 0;
-
- if( rt > st )
- {
- CNFGColor( 0xffffff );
- dt = rt - st;
- dt *= 1000;
- totaltime += dt;
- if( dt < mintime ) mintime = dt;
- if( dt > maxtime ) maxtime = dt;
- totalcountok++;
- }
- else
- {
- CNFGColor( 0xff );
- dt = now - st;
- dt *= 1000;
-
- }
-
- if( last < 0 && rt > st )
- last = dt;
- int h = dt*10;
- int top = screeny - h;
- if( top < 0 ) top = 0;
- CNFGTackSegment( i, screeny-1, i, top );
- }
-
- double avg = totaltime / totalcountok;
-
- for( i = 0; i < screenx; i++ )
- {
- int index = ((current_cycle - i - 1) + PINGCYCLEWIDTH) & (PINGCYCLEWIDTH-1);
- double st = PingSendTimes[index];
- double rt = PingRecvTimes[index];
-
- double dt = 0;
- if( rt > st )
- {
- dt = rt - st;
- dt *= 1000;
- stddev += (dt-avg)*(dt-avg);
- }
- }
-
- stddev /= totalcountok;
-
- stddev = sqrt(stddev);
-
- CNFGColor( 0xff00 );
- int l = avg*10;
- CNFGTackSegment( 0, screeny-l, screenx, screeny - l );
- l = (avg + stddev)*10;
- CNFGTackSegment( 0, screeny-l, screenx, screeny - l );
- l = (avg - stddev)*10;
- CNFGTackSegment( 0, screeny-l, screenx, screeny - l );
-
- char stbuf[1024];
- char * sptr = &stbuf[0];
- sptr += sprintf( sptr, "Last: %5.2f ms\n", last );
- sptr += sprintf( sptr, "Min : %5.2f ms\n", mintime );
- sptr += sprintf( sptr, "Max : %5.2f ms\n", maxtime );
- sptr += sprintf( sptr, "Avg : %5.2f ms\n", avg );
- sptr += sprintf( sptr, "Std : %5.2f ms\n", stddev );
- sptr += sprintf( sptr, "EPS : %d / PP: %.2f ms\n", ExtraPingSize, pingperiod*1000.0 );
- sptr += sprintf( sptr, "Notemode: %d\n", notemode );
-
- 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 );
- OGUSleep( 10000 );
-}
-
-#ifdef WIN32
-int mymain( int argc, const char ** argv )
-#else
-int main( int argc, const char ** argv )
-#endif
-{
- char title[1024];
- int i, x, y, r;
- double ThisTime;
- double LastFPSTime = OGGetAbsoluteTime();
- double LastFrameTime = OGGetAbsoluteTime();
- double SecToWait;
- int linesegs = 0;
-// struct in_addr dst;
- struct addrinfo *result;
-
- srand( (int)(OGGetAbsoluteTime()*100000) );
-
- for( i = 0; i < sizeof( pattern ); i++ )
- {
- pattern[i] = rand();
- }
- CNFGBGColor = 0x800000;
- CNFGDialogColor = 0x444444;
- for( i = 0; i < PINGCYCLEWIDTH; i++ )
- {
- PingSendTimes[i] = 0;
- PingRecvTimes[i] = 0;
- }
-
- if( argc < 2 )
- {
- ERRM( "Usage: cnping-mousey [host] [ping period in seconds (optional) default 0.02] [ping packet extra size (above 12), default = 0]\n" );
- return -1;
- }
-
- if( argc > 3 )
- {
- ExtraPingSize = atoi( argv[3] );
- printf( "Extra ping size added: %d\n", ExtraPingSize );
- }
-
- sprintf( title, "%s - cnping-mousey", argv[1] );
- CNFGSetup( title, 300, 115 );
-
- ping_setup();
-
- pinghost = argv[1];
- pingperiod = (argc>=3)?atof( argv[2] ):.02;
-
- OGCreateThread( PingSend, 0 );
- OGCreateThread( PingListen, 0 );
-
- while(1)
- {
- int i, pos;
- float f;
- iframeno++;
- RDPoint pto[3];
-
-
- if( notemode && lastnoteupdown > 0 && OGGetAbsoluteTime() - lastnoteupdown > .05 )
- {
- pingperiod = 1000;
- }
- CNFGHandleInput();
-
- CNFGClearFrame();
- CNFGColor( 0xFFFFFF );
- CNFGGetDimensions( &screenx, &screeny );
-
- DrawFrame();
-
- frames++;
- CNFGSwapBuffers();
-
- ThisTime = OGGetAbsoluteTime();
- if( ThisTime > LastFPSTime + 1 )
- {
- frames = 0;
- linesegs = 0;
- LastFPSTime+=1;
- }
-
- SecToWait = .030 - ( ThisTime - LastFrameTime );
- LastFrameTime += .030;
- if( SecToWait > 0 )
- OGUSleep( (int)( SecToWait * 1000000 ) );
- }
-
- return(0);
-}
-
-#ifdef WIN32
-
-//from: http://alter.org.ua/docs/win/args/
- PCHAR*
- CommandLineToArgvA(
- PCHAR CmdLine,
- int* _argc
- )
- {
- PCHAR* argv;
- PCHAR _argv;
- ULONG len;
- ULONG argc;
- CHAR a;
- ULONG i, j;
-
- BOOLEAN in_QM;
- BOOLEAN in_TEXT;
- BOOLEAN in_SPACE;
-
- len = strlen(CmdLine);
- i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID);
-
- argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
- i + (len+2)*sizeof(CHAR));
-
- _argv = (PCHAR)(((PUCHAR)argv)+i);
-
- argc = 0;
- argv[argc] = _argv;
- in_QM = FALSE;
- in_TEXT = FALSE;
- in_SPACE = TRUE;
- i = 0;
- j = 0;
-
- while( a = CmdLine[i] ) {
- if(in_QM) {
- if(a == '\"') {
- in_QM = FALSE;
- } else {
- _argv[j] = a;
- j++;
- }
- } else {
- switch(a) {
- case '\"':
- in_QM = TRUE;
- in_TEXT = TRUE;
- if(in_SPACE) {
- argv[argc] = _argv+j;
- argc++;
- }
- in_SPACE = FALSE;
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- if(in_TEXT) {
- _argv[j] = '\0';
- j++;
- }
- in_TEXT = FALSE;
- in_SPACE = TRUE;
- break;
- default:
- in_TEXT = TRUE;
- if(in_SPACE) {
- argv[argc] = _argv+j;
- argc++;
- }
- _argv[j] = a;
- j++;
- in_SPACE = FALSE;
- break;
- }
- }
- i++;
- }
- _argv[j] = '\0';
- argv[argc] = NULL;
-
- (*_argc) = argc;
- return argv;
- }
-
-
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
-{
- int argc;
- char cts[8192];
- sprintf( cts, "%s %s", GetCommandLine(), lpCmdLine );
-
- ShowWindow (GetConsoleWindow(), SW_HIDE);
- char ** argv = CommandLineToArgvA(
- cts,
- &argc
- );
-// MessageBox( 0, argv[1], "X", 0 );
- return mymain( argc-1, (const char**)argv );
-}
-
-#endif
diff --git a/cnping.c b/cnping.c
@@ -6,6 +6,9 @@
#include <errno.h>
#include <string.h>
#ifdef WIN32
+#ifdef _MSC_VER
+#define strdup _strdup
+#endif
#include <windows.h>
#else
#include <sys/socket.h>
@@ -18,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;
@@ -25,11 +30,14 @@ 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];
-#define PINGCYCLEWIDTH 2048
+#define PINGCYCLEWIDTH 8192
#define TIMEOUT 4
double PingSendTimes[PINGCYCLEWIDTH];
@@ -37,22 +45,83 @@ double PingRecvTimes[PINGCYCLEWIDTH];
int current_cycle = 0;
int ExtraPingSize;
+int in_histogram_mode, in_frame_mode = 1;
+void HandleGotPacket( int seqno, int timeout );
-void display(uint8_t *buf, int bytes)
+#define MAX_HISTO_MARKS (TIMEOUT*10000)
+uint64_t hist_counts[MAX_HISTO_MARKS];
+
+void HandleNewPacket( int seqno )
{
- int reqid = (buf[0] << 24) | (buf[1]<<16) | (buf[2]<<8) | (buf[3]);
- reqid &= (PINGCYCLEWIDTH-1);
+ double Now = OGGetAbsoluteTime();
+ PingSendTimes[seqno] = Now;
+ PingRecvTimes[seqno] = 0;
+ static int timeoutmark;
- double STime = PingSendTimes[reqid];
- double LRTime = PingRecvTimes[reqid];
+ while( Now - PingSendTimes[timeoutmark] > TIMEOUT )
+ {
+ if( PingRecvTimes[timeoutmark] < PingSendTimes[timeoutmark] )
+ {
+ HandleGotPacket( timeoutmark, 1 );
+ }
+ timeoutmark++;
+ if( timeoutmark >= PINGCYCLEWIDTH ) timeoutmark = 0;
+ }
+}
- if( memcmp( buf+4, pattern, 8 ) != 0 ) return;
- if( LRTime > STime ) return;
- if( STime < 1 ) return;
+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;
- //Otherwise this is a legit packet.
+ 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]++;
- PingRecvTimes[reqid] = OGGetAbsoluteTime();
+ if( globlast > 0.5 )
+ {
+ if( Now - globlast > globinterval ) globinterval = Now - globlast;
+ }
+ globlast = Now;
+ globalrx++;
+}
+
+
+void HTTPingCallbackStart( int seqno )
+{
+ current_cycle = seqno;
+ HandleNewPacket( seqno );
+}
+
+void HTTPingCallbackGot( int seqno )
+{
+ 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);
+ if( memcmp( buf+4, pattern, 8 ) != 0 ) return;
+ HandleGotPacket( reqid, 0 );
}
int load_ping_packet( uint8_t * buffer, int bufflen )
@@ -64,8 +133,12 @@ int load_ping_packet( uint8_t * buffer, int bufflen )
memcpy( buffer+4, pattern, 8 );
- PingSendTimes[current_cycle&(PINGCYCLEWIDTH-1)] = OGGetAbsoluteTime();
- PingRecvTimes[current_cycle&(PINGCYCLEWIDTH-1)] = 0;
+ if( ping_failed_to_send )
+ {
+ PingSendTimes[(current_cycle+PINGCYCLEWIDTH-1)&(PINGCYCLEWIDTH-1)] = 0; //Unset ping send.
+ }
+
+ HandleNewPacket( current_cycle&(PINGCYCLEWIDTH-1) );
current_cycle++;
@@ -89,12 +162,39 @@ void * PingSend( void * r )
-void HandleKey( int keycode, int bDown ){}
+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;
+
+ }
+}
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;
@@ -118,12 +218,159 @@ 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 <= 2 )
+ {
+ goto nodata;
+ }
+ else
+ {
+ int skips = ( (slots)/categories ) + 1;
+ int slotsmax = maxpingslot / skips + 1;
+ int slotsmin = minpingslot / skips;
+ slots = slotsmax - slotsmin;
+ if( slots <= 0 ) goto nodata;
+
+ uint64_t samples[slots+2];
+ int ssmsMIN[slots+2];
+ int ssmsMAX[slots+2];
+ int samp = minpingslot - 1;
+
+ if( slots <= 1 ) 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, "%I64u", 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];
+#ifdef WIN32
+ snprintf( stt, 1024, "Host: %s\nHistorical max %9.2fms\nBiggest interval%9.2fms\nHistorical packet loss %I64u/%I64u = %6.3f%%",
+#else
+ snprintf( stt, 1024, "Host: %s\nHistorical max %9.2fms\nBiggest interval%9.2fms\nHistorical packet loss %lu/%lu = %6.3f%%",
+#endif
+ 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;
@@ -133,6 +380,7 @@ void DrawFrame( void )
double stddev = 0;
double last = -1;
double loss = 100.00;
+ double windmaxtime = GetWindMaxPingTime();
for( i = 0; i < screenx; i++ )
{
@@ -159,7 +407,7 @@ void DrawFrame( void )
CNFGColor( 0xff );
dt = now - st;
dt *= 1000;
- totalcountloss++;
+ if( i > 5 ) totalcountloss++; //Get a freebie on the first 5.
}
else // no ping sent for this point in time (after startup)
{
@@ -169,7 +417,7 @@ void DrawFrame( void )
if (!GuiYscaleFactorIsConstant)
{
- GuiYScaleFactor = (screeny - 50) / globmaxtime;
+ GuiYScaleFactor = (screeny - 50) / windmaxtime;
}
int h = dt*GuiYScaleFactor;
@@ -213,23 +461,23 @@ 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", last );
- sptr += sprintf( sptr, "Min : %5.2f ms\n", mintime );
- sptr += sprintf( sptr, "Max : %5.2f ms\n", maxtime );
- sptr += sprintf( sptr, "Avg : %5.2f ms\n", avg );
- sptr += sprintf( sptr, "Std : %5.2f ms\n", stddev );
- sptr += sprintf( sptr, "Loss: %5.1f %%\n", loss );
- 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 );
+
+ sptr += sprintf( sptr,
+ "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"
+#ifdef WIN32
+ "Std :%6.2f ms Historical loss: %I64u/%I64u %5.3f%%\n"
+#else
+ "Std :%6.2f ms Historical loss: %lu/%lu %5.3f%%\n"
+#endif
+ "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 );
}
@@ -238,21 +486,11 @@ void DrawFrame( void )
const char * glargv[10];
int glargc = 0;
-INT_PTR CALLBACK TextEntry( HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam )
+INT_PTR CALLBACK TextEntry( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
-// printf( "%d %d %d\n", uMsg, wParam, lParam );
switch( uMsg )
{
- //case IDC_SAVESETS:
- // GetDlgItemText(DLG_SETS, IDC_SETS1, stringVariable, sizeof(stringVariable));
-// case 31:
-// printf( "Exit\n" );
-// exit( 0 );
-// return 0;
case WM_INITDIALOG:
SetDlgItemText(hwndDlg, 4, "0.02");
SetDlgItemText(hwndDlg, 5, "0" );
@@ -295,19 +533,11 @@ INT_PTR CALLBACK TextEntry( HWND hwndDlg,
}
}
}
-
-// printf( "+++%s\n", stringVariable );
-// printf( "Commit %p/%d\n", lParam, id );
EndDialog(hwndDlg, 0);
return 0; //User pressed enter.
}
}
-
-//case IDC_SAVESETS: http://www.cplusplus.com/forum/beginner/19843/
-//GetDlgItemText(DLG_SETS, IDC_SETS1, stringVariable, sizeof(stringVariable));
-
- //printf( "cmd %p %p %p\n", uMsg, wParam, lParam );
- return 0;
+/* return 0;
case WM_CTLCOLORBTN:
//printf( "ctr %p %p %p\n", uMsg, wParam, lParam );
//return 0;
@@ -316,25 +546,24 @@ INT_PTR CALLBACK TextEntry( HWND hwndDlg,
case 8: case 312: case 15: case 71: case 133: case 307:
case 20: case 310: case 33:
return 0;
+*/
}
- //MessageBox( 0, "XXX", "cnping", 0 );
- //printf( "XXX %d %d %d\n", uMsg, wParam, lParam );
return 0;
}
-int mymain( int argc, const char ** argv )
-#else
-int main( int argc, const char ** argv )
#endif
+int main( int argc, const char ** argv )
{
char title[1024];
- int i, x, y, r;
+ int i;
double ThisTime;
double LastFPSTime = OGGetAbsoluteTime();
double LastFrameTime = OGGetAbsoluteTime();
double SecToWait;
- int linesegs = 0;
-// struct in_addr dst;
- struct addrinfo *result;
+ double frameperiodseconds;
+
+#ifdef WIN32
+ ShowWindow (GetConsoleWindow(), SW_HIDE);
+#endif
srand( (int)(OGGetAbsoluteTime()*100000) );
@@ -344,92 +573,138 @@ int main( int argc, const char ** argv )
}
CNFGBGColor = 0x800000;
CNFGDialogColor = 0x444444;
- for( i = 0; i < PINGCYCLEWIDTH; i++ )
- {
- PingSendTimes[i] = 0;
- PingRecvTimes[i] = 0;
- }
-
#ifdef WIN32
if( argc < 2 )
{
- int ret = DialogBox(0, "IPDialog", 0, TextEntry );
+ DialogBox(0, "IPDialog", 0, TextEntry );
argc = glargc;
argv = glargv;
}
#endif
-
- if( argc < 2 )
+ pingperiodseconds = 0.02;
+ ExtraPingSize = 0;
+ title[0] = 0;
+ GuiYScaleFactor = 0;
+
+ //We need to process all the unmarked parameters.
+ int argcunmarked = 1;
+ int displayhelp = 0;
+
+ for( i = 1; i < argc; i++ )
{
-#ifdef WIN32
- ERRM( "Need at least a host address to ping.\n" );
-#else
- ERRM( "Usage: cnping [host] [period] [extra size] [y-axis scaling]\n"
-
- " [host] -- domain or IP address of ping target \n"
- " [period] -- period in seconds (optional), default 0.02 \n"
- " [extra size] -- ping packet extra size (above 12), optional, default = 0 \n"
- " [const y-axis scaling] -- use a fixed scaling factor instead of auto scaling (optional)\n");
-#endif
- return -1;
+ const char * thisargv = argv[i];
+ if( thisargv[0] == '-' )
+ {
+ int np = ++i;
+ if( np >= argc )
+ {
+ displayhelp = 1;
+ break;
+ }
+ const char * nextargv = argv[np];
+ //Parameter-based field.
+ switch( thisargv[1] )
+ {
+ case 'h': pinghost = nextargv; break;
+ case 'p': pingperiodseconds = atof( nextargv ); break;
+ 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;
+ }
+ }
+ else
+ {
+ //Unmarked fields
+ switch( argcunmarked++ )
+ {
+ case 1: pinghost = thisargv; break;
+ case 2: pingperiodseconds = atof( thisargv ); break;
+ case 3: ExtraPingSize = atoi( thisargv ); break;
+ case 4: GuiYScaleFactor = atof( thisargv ); break;
+ case 5: sprintf(title, "%s", thisargv ); break;
+ default: displayhelp = 1;
+ }
+ }
}
-
- if( argc > 2 )
+ if( title[0] == 0 )
{
- pingperiod = atof( argv[2] );
- printf( "Extra ping period: %f\n", pingperiod );
+ sprintf( title, "%s - cnping", pinghost );
}
- else
+
+ if( GuiYScaleFactor > 0 )
{
- pingperiod = 0.02;
+ GuiYscaleFactorIsConstant = 1;
}
- if( argc > 3 )
+ if( !pinghost )
{
- ExtraPingSize = atoi( argv[3] );
- printf( "Extra ping size: %d\n", ExtraPingSize );
+ displayhelp = 1;
}
- else
+
+ if( displayhelp )
{
- ExtraPingSize = 0;
+ #ifdef WIN32
+ 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, 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"
+ " (-t) [window title] -- the title of the window (optional)\n");
+ #endif
+ return -1;
}
+
+ CNFGSetup( title, 320, 155 );
- if( argc > 4 )
+ if( memcmp( pinghost, "http://", 7 ) == 0 )
{
- GuiYScaleFactor = atof( argv[4] );
- GuiYscaleFactorIsConstant = 1;
- printf( "GuiYScaleFactor: %f\n", GuiYScaleFactor );
+ StartHTTPing( pinghost+7, pingperiodseconds );
}
else
{
- printf( "GuiYScaleFactor: %s\n", "dynamic" );
+ ping_setup();
+ OGCreateThread( PingSend, 0 );
+ OGCreateThread( PingListen, 0 );
}
- pinghost = argv[1];
- sprintf( title, "%s - cnping", pinghost );
- CNFGSetup( title, 320, 155 );
-
- ping_setup();
-
- OGCreateThread( PingSend, 0 );
- OGCreateThread( PingListen, 0 );
+ frameperiodseconds = fmin(.2, fmax(.03, pingperiodseconds));
while(1)
{
- int i, pos;
- float f;
iframeno++;
- RDPoint pto[3];
-
CNFGHandleInput();
CNFGClearFrame();
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();
@@ -438,12 +713,12 @@ int main( int argc, const char ** argv )
if( ThisTime > LastFPSTime + 1 )
{
frames = 0;
- linesegs = 0;
LastFPSTime+=1;
}
- SecToWait = .030 - ( ThisTime - LastFrameTime );
- LastFrameTime += .030;
+ SecToWait = frameperiodseconds - ( ThisTime - LastFrameTime );
+ LastFrameTime += frameperiodseconds;
+ //printf("iframeno = %d; SecToWait = %f; pingperiodseconds = %f; frameperiodseconds = %f \n", iframeno, SecToWait, pingperiodseconds, frameperiodseconds);
if( SecToWait > 0 )
OGUSleep( (int)( SecToWait * 1000000 ) );
}
@@ -451,107 +726,3 @@ int main( int argc, const char ** argv )
return(0);
}
-#ifdef WIN32
-
-//from: http://alter.org.ua/docs/win/args/
- PCHAR*
- CommandLineToArgvA(
- PCHAR CmdLine,
- int* _argc
- )
- {
- PCHAR* argv;
- PCHAR _argv;
- ULONG len;
- ULONG argc;
- CHAR a;
- ULONG i, j;
-
- BOOLEAN in_QM;
- BOOLEAN in_TEXT;
- BOOLEAN in_SPACE;
-
- len = strlen(CmdLine);
- i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID);
-
- argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
- i + (len+2)*sizeof(CHAR));
-
- _argv = (PCHAR)(((PUCHAR)argv)+i);
-
- argc = 0;
- argv[argc] = _argv;
- in_QM = FALSE;
- in_TEXT = FALSE;
- in_SPACE = TRUE;
- i = 0;
- j = 0;
-
- while( a = CmdLine[i] ) {
- if(in_QM) {
- if(a == '\"') {
- in_QM = FALSE;
- } else {
- _argv[j] = a;
- j++;
- }
- } else {
- switch(a) {
- case '\"':
- in_QM = TRUE;
- in_TEXT = TRUE;
- if(in_SPACE) {
- argv[argc] = _argv+j;
- argc++;
- }
- in_SPACE = FALSE;
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- if(in_TEXT) {
- _argv[j] = '\0';
- j++;
- }
- in_TEXT = FALSE;
- in_SPACE = TRUE;
- break;
- default:
- in_TEXT = TRUE;
- if(in_SPACE) {
- argv[argc] = _argv+j;
- argc++;
- }
- _argv[j] = a;
- j++;
- in_SPACE = FALSE;
- break;
- }
- }
- i++;
- }
- _argv[j] = '\0';
- argv[argc] = NULL;
-
- (*_argc) = argc;
- return argv;
- }
-
-
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
-{
- int argc;
- char cts[8192];
- sprintf( cts, "%s %s", GetCommandLine(), lpCmdLine );
-
- ShowWindow (GetConsoleWindow(), SW_HIDE);
- char ** argv = CommandLineToArgvA(
- cts,
- &argc
- );
-// MessageBox( 0, argv[1], "X", 0 );
- return mymain( argc-1, (const char**)argv );
-}
-
-#endif
diff --git a/cnping.exe b/cnping.exe
Binary files differ.
diff --git a/error_handling.h b/error_handling.h
@@ -0,0 +1,24 @@
+#ifndef _ERROR_HANDLING
+#define _ERROR_HANDLING
+
+extern char errbuffer[1024];
+
+#ifdef WIN32
+
+#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 ERRMB(x...) { sprintf( errbuffer, x); fprintf( stderr, x ); }
+
+#endif
+
+
+#endif
diff --git a/httping.c b/httping.c
@@ -0,0 +1,232 @@
+#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>
+#else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+#endif
+
+#include "os_generic.h"
+#include "error_handling.h"
+
+#ifndef MSG_NOSIGNAL
+ #define MSG_NOSIGNAL 0
+#endif
+
+#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];
+ memcpy( hostname, addy, addylen + 1 );
+ char * eportmarker = strchr( hostname, ':' );
+ char * eurl = strchr( hostname, '/' );
+
+ int portno = 80;
+
+ (*seqnoptr) ++;
+ HTTPingCallbackStart( *seqnoptr );
+
+ if( eportmarker )
+ {
+ portno = atoi( eportmarker+1 );
+ *eportmarker = 0;
+ }
+ else
+ {
+ if( eurl )
+ *eurl = 0;
+ }
+
+ /* gethostbyname: get the server's DNS entry */
+ *getting_host_by_name = 1;
+ server = gethostbyname(hostname);
+ *getting_host_by_name = 0;
+ if (server == NULL) {
+ ERRMB("ERROR, no such host as %s\n", hostname);
+ goto fail;
+ }
+
+ /* build the server's Internet address */
+ 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);
+
+reconnect:
+ *socketptr = httpsock = socket(AF_INET, SOCK_STREAM, 0);
+ if (httpsock < 0)
+ {
+ ERRMB( "Error opening socket\n" );
+ return;
+ }
+
+ /* connect: create a connection with the server */
+ if (connect(httpsock, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
+ {
+ ERRMB( "%s: ERROR connecting\n", hostname );
+ goto fail;
+ }
+
+#ifdef __APPLE__
+ int opt = 1;
+ setsockopt(httpsock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
+#endif
+
+ 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" );
+ int rs = send( httpsock, buf, n, MSG_NOSIGNAL );
+ double starttime = *timeouttime = OGGetAbsoluteTime();
+ 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;
+
+ 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' && i == n-1) 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 );
+ if( !breakout ) {
+#ifdef WIN32
+ closesocket( httpsock );
+#else
+ close( httpsock );
+#endif
+ goto reconnect;
+ }
+ }
+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/os_generic.c b/os_generic.c
@@ -1,6 +1,5 @@
#include "os_generic.h"
-
#ifdef USE_WINDOWS
#include <windows.h>
@@ -56,6 +55,7 @@ void * OGJoinThread( og_thread_t ot )
{
WaitForSingleObject( ot, INFINITE );
CloseHandle( ot );
+ return 0;
}
void OGCancelThread( og_thread_t ot )
diff --git a/os_generic.h b/os_generic.h
@@ -1,7 +1,7 @@
#ifndef _OS_GENERIC_H
#define _OS_GENERIC_H
-#ifdef WIN32
+#if defined( WIN32 ) || defined (WINDOWS) || defined( _WIN32)
#define USE_WINDOWS
#endif
@@ -25,7 +25,7 @@ og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter );
void * OGJoinThread( og_thread_t ot );
void OGCancelThread( og_thread_t ot );
-//Always a recrusive mutex.
+//Always a recursive mutex.
og_mutex_t OGCreateMutex();
void OGLockMutex( og_mutex_t om );
void OGUnlockMutex( og_mutex_t om );
diff --git a/ping.c b/ping.c
@@ -1,155 +1,122 @@
-/* myping.c
- *
- * Copyright (c) 2000 Sean Walton and Macmillan Publishers. Use may be in
- * whole or in part in accordance to the General Public License (GPL).
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
-*/
-
-/*****************************************************************************/
-/*** ping.c ***/
-/*** ***/
-/*** Use the ICMP protocol to request "echo" from destination. ***/
-/*****************************************************************************/
+//Copyright 2017 <>< C. Lohr, under the MIT/x11 License
+//Rewritten from Sean Walton and Macmillan Publishers.
+//Most of it was rewritten but the header was never updated.
+//Now I finished the job.
#include <string.h>
#include <fcntl.h>
#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "ping.h"
#include "os_generic.h"
-#ifdef WIN32
-#include <winsock2.h>
-#define SOL_IP 0
-#define F_SETFL 4
-#define ICMP_ECHO 8
-#define IP_TTL 2
-# define O_NONBLOCK 04000
-
-#ifndef _MSC_VER
-void bzero(void *location,__LONG32 count);
-#else
-#pragma comment(lib, "Ws2_32.lib")
-void bzero(void * loc, int len)
-{
- memset(loc, 0, len);
-}
-#endif
-void usleep(int x) {
- Sleep(x / 1000);
-}
-#include <windows.h>
-#include <stdio.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <stdint.h>
+#include "error_handling.h"
+
+#ifdef WIN32
+ #include <winsock2.h>
+ #define SOL_IP 0
+ #define F_SETFL 4
+ #define ICMP_ECHO 8
+ #define IP_TTL 2
+ #define O_NONBLOCK 04000
+ #pragma comment(lib, "Ws2_32.lib")
+ #include <windows.h>
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #include <stdint.h>
#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <resolv.h>
-#include <netdb.h>
-#ifdef __APPLE__
-#ifndef SOL_IP
-#define SOL_IP IPPROTO_IP
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <resolv.h>
+ #include <netdb.h>
+ #ifdef __APPLE__
+ #ifndef SOL_IP
+ #define SOL_IP IPPROTO_IP
+ #endif
+ #endif
+ #include <netinet/ip.h>
+ #include <netinet/ip_icmp.h>
#endif
-#endif
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#endif
-#include <stdlib.h>
#if defined WIN32 || defined __APPLE__
-struct icmphdr {
- uint8_t type;
- uint8_t code;
- uint16_t checksum;
- union {
- struct {
- uint16_t id;
- uint16_t sequence;
- } echo;
- uint32_t gateway;
- struct {
- uint16_t __unused;
- uint16_t mtu;
- } frag;
- } un;
+struct icmphdr
+{
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ union
+ {
+ struct
+ {
+ uint16_t id;
+ uint16_t sequence;
+ } echo;
+ uint32_t gateway;
+ struct
+ {
+ uint16_t __unused;
+ uint16_t mtu;
+ } frag;
+ } un;
};
#endif
-float pingperiod;
+float pingperiodseconds;
int precise_ping;
-#define PACKETSIZE 1500
+#define PACKETSIZE 65536
+
struct packet
{
struct icmphdr hdr;
- char msg[PACKETSIZE-sizeof(struct icmphdr)];
+ unsigned char msg[PACKETSIZE-sizeof(struct icmphdr)];
};
int sd;
int pid=-1;
-struct protoent *proto=NULL;
+int ping_failed_to_send;
struct sockaddr_in psaddr;
-/*--------------------------------------------------------------------*/
-/*--- checksum - standard 1s complement checksum ---*/
-/*--------------------------------------------------------------------*/
-unsigned short checksum(void *b, int len)
-{ unsigned short *buf = b;
- unsigned int sum=0;
- unsigned short result;
-
- for ( sum = 0; len > 1; len -= 2 )
- sum += *buf++;
- if ( len == 1 )
- sum += *(unsigned char*)buf;
- sum = (sum >> 16) + (sum & 0xFFFF);
- sum += (sum >> 16);
- result = ~sum;
- return result;
+uint16_t checksum( const unsigned char * start, uint16_t len )
+{
+ uint16_t i;
+ const uint16_t * wptr = (uint16_t*) start;
+ uint32_t csum = 0;
+ for (i=1;i<len;i+=2)
+ csum += (uint32_t)(*(wptr++));
+ if( len & 1 ) //See if there's an odd number of bytes?
+ csum += *(uint8_t*)wptr;
+ if (csum>>16)
+ csum = (csum & 0xFFFF)+(csum >> 16);
+ //csum = (csum>>8) | ((csum&0xff)<<8);
+ return ~csum;
}
-
-/*--------------------------------------------------------------------*/
-/*--- listener - separate process to listen for and collect messages--*/
-/*--------------------------------------------------------------------*/
-void listener(void)
+void listener()
{
#ifndef WIN32
const int val=255;
- int sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
+ int sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
{
- ERRM("Erro: could not set TTL option\n");
+ ERRM("Error: could not set TTL option - did you forget to run as root or sticky bit cnping?\n");
exit( -1 );
}
-
#endif
struct sockaddr_in addr;
- unsigned char buf[8192];
+ unsigned char buf[66000];
#ifdef WIN32
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
#endif
for (;;)
{
- int i;
- int bytes, len=sizeof(addr);
+ socklen_t addrlenval=sizeof(addr);
+ int bytes;
- bzero(buf, sizeof(buf));
#ifdef WIN32
WSAPOLLFD fda[1];
fda[0].fd = sd;
@@ -157,8 +124,9 @@ void listener(void)
WSAPoll(fda, 1, 10);
#endif
keep_retry_quick:
- bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
- if (bytes == -1) continue;
+
+ bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &addrlenval );
+ if( bytes == -1 ) continue;
if( buf[20] != 0 ) continue; //Make sure ping response.
if( buf[9] != 1 ) continue; //ICMP
if( addr.sin_addr.s_addr != psaddr.sin_addr.s_addr ) continue;
@@ -166,35 +134,25 @@ void listener(void)
if ( bytes > 0 )
display(buf + 28, bytes - 28 );
else
- perror("recvfrom");
+ {
+ ERRM("Error: recvfrom failed");
+ }
goto keep_retry_quick;
}
- printf( "Fault on listen.\n" );
- exit(0);
+ ERRM( "Fault on listen.\n" );
+ exit( 0 );
}
-/*--------------------------------------------------------------------*/
-/*--- ping - Create message and send it. ---*/
-/*--------------------------------------------------------------------*/
void ping(struct sockaddr_in *addr )
{
+ int cnt=1;
#ifdef WIN32
- const char val=255;
-#else
- const int val=255;
-#endif
- int i, cnt=1;
- struct packet pckt;
- struct sockaddr_in r_addr;
-#ifdef WIN32
{
- //this /was/ recommended.
+ //Setup windows socket for nonblocking io.
unsigned long iMode = 1;
ioctlsocket(sd, FIONBIO, &iMode);
-
-
}
#else
if ( fcntl(sd, F_SETFL, O_NONBLOCK) != 0 )
@@ -203,24 +161,28 @@ void ping(struct sockaddr_in *addr )
double stime = OGGetAbsoluteTime();
+ struct packet pckt;
do
- { int len=sizeof(r_addr);
+ {
+ int rsize = load_ping_packet( pckt.msg, sizeof( pckt.msg ) );
+ memset( &pckt.hdr, 0, sizeof( pckt.hdr ) ); //This needs to be here, but I don't know why, since I think the struct is fully populated.
-// printf("Msg #%d\n", cnt);
-// if ( recvfrom(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr, &len) > 0 )
- {
- //printf("***Got message!***\n");
- }
- bzero(&pckt, sizeof(pckt));
+ pckt.hdr.code = 0;
pckt.hdr.type = ICMP_ECHO;
pckt.hdr.un.echo.id = pid;
- int rsize = load_ping_packet( pckt.msg, sizeof( pckt.msg ) );
pckt.hdr.un.echo.sequence = cnt++;
- pckt.hdr.checksum = checksum(&pckt, sizeof(pckt) - sizeof( pckt.msg ) + rsize );
+ pckt.hdr.checksum = checksum((const unsigned char *)&pckt, sizeof( pckt.hdr ) + rsize );
- if ( sendto(sd, (char*)&pckt, sizeof(pckt) - sizeof( pckt.msg ) + rsize , 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0 )
- perror("sendto");
+ int sr = sendto(sd, (char*)&pckt, sizeof( pckt.hdr ) + rsize , 0, (struct sockaddr*)addr, sizeof(*addr));
+ if( sr <= 0 )
+ {
+ ping_failed_to_send = 1;
+ }
+ else
+ {
+ ping_failed_to_send = 0;
+ }
if( precise_ping )
{
@@ -228,32 +190,27 @@ void ping(struct sockaddr_in *addr )
do
{
ctime = OGGetAbsoluteTime();
- if( pingperiod >= 1000 ) stime = ctime;
- } while( ctime < stime + pingperiod );
- stime += pingperiod;
+ if( pingperiodseconds >= 1000 ) stime = ctime;
+ } while( ctime < stime + pingperiodseconds );
+ stime += pingperiodseconds;
}
else
{
- if( pingperiod > 0 )
+ if( pingperiodseconds > 0 )
{
- uint32_t dlw = 1000000.0*pingperiod;
- usleep( dlw );
+ uint32_t dlw = 1000000.0*pingperiodseconds;
+ OGUSleep( dlw );
}
}
- } while( pingperiod >= 0 );
+ } while( pingperiodseconds >= 0 );
//close( sd ); //Hacky, we don't close here because SD doesn't come from here, rather from ping_setup. We may want to run this multiple times.
}
void ping_setup()
{
pid = getpid();
- proto = getprotobyname("ICMP");
#ifdef WIN32
-/*
- WSADATA wsaData;
- int r = WSAStartup(0x0202, &wsaData );
-*/
WSADATA wsaData;
int r = WSAStartup(MAKEWORD(2,2), &wsaData);
if( r )
@@ -268,19 +225,19 @@ void ping_setup()
sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, WSA_FLAG_OVERLAPPED);
{
int lttl = 0xff;
- if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)<tl,
- sizeof(lttl)) == SOCKET_ERROR) {
+ if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)<tl, sizeof(lttl)) == SOCKET_ERROR)
+ {
printf( "Warning: No IP_TTL.\n" );
}
}
#else
const int val=255;
- sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
+ sd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
{
- ERRM("Error: Failed to set TTL option\n");
+ ERRM("Error: Failed to set TTL option. Are you root? Or can do sock_raw sockets?\n");
exit( -1 );
}
@@ -298,7 +255,7 @@ void do_pinger( const char * strhost )
struct hostent *hname;
hname = gethostbyname(strhost);
- bzero(&psaddr, sizeof(psaddr));
+ memset(&psaddr, 0, sizeof(psaddr));
psaddr.sin_family = hname->h_addrtype;
psaddr.sin_port = 0;
psaddr.sin_addr.s_addr = *(long*)hname->h_addr;
diff --git a/ping.h b/ping.h
@@ -5,7 +5,7 @@
struct sockaddr_in;
-unsigned short checksum(void *b, int len);
+unsigned short checksum(const unsigned char *b, uint16_t len);
//Callback (when received)
void display(uint8_t *buf, int bytes);
@@ -14,26 +14,16 @@ void display(uint8_t *buf, int bytes);
//return value = # of bytes to send in ping message.
int load_ping_packet( uint8_t * buffer, int buffersize );
-void listener(void);
+void listener();
void ping(struct sockaddr_in *addr );
void do_pinger( const char * strhost );
-//If pingperiod = -1, run ping/do_pinger once and exit.
-extern float pingperiod;
+//If pingperiodseconds = -1, run ping/do_pinger once and exit.
+extern float pingperiodseconds;
extern int precise_ping; //if 0, use minimal CPU, but ping send-outs are only approximate, if 1, spinlock until precise time for ping is hit.
-
+extern int ping_failed_to_send;
void ping_setup();
-#ifdef WIN32
-
-extern char errbuffer[1024];
-#define ERRM(x...) { sprintf( errbuffer, x ); MessageBox( 0, errbuffer, "cnping", 0 ); }
-
-#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
diff --git a/searchnet.c b/searchnet.c
@@ -19,17 +19,8 @@ void * PingListen( void * r )
void display(uint8_t *buf, int bytes)
{
- int i;
uint32_t reqid = ((uint32_t)buf[0+1] << 24) | (buf[1+1]<<16) | (buf[2+1]<<8) | (buf[3+1]);
-/* for( i = 0; i < bytes; i++ )
- {
- printf( "%02x ", buf[i] );
- }
- printf( "\n" );
- printf( "REQ: %08x %08x\n", reqid, my_random_key );
-/// printf( "%d.%d.%d.%d\n", buf[4], buf[5], buf[6], buf[7] );
-*/
if( reqid != my_random_key ) return;
printf( "%d.%d.%d.%d\n", buf[4+1], buf[5+1], buf[6+1], buf[7+1] );
@@ -85,7 +76,7 @@ int main( int argc, char ** argv )
send_id[2] = (cur>>8)&0xff;
send_id[3] = (cur)&0xff;
// printf( "Pinging: %s\n", dispip );
- pingperiod = -1;
+ pingperiodseconds = -1;
do_pinger( dispip );
OGUSleep( (int)(speed * 1000000) );