cnping

Minimal Graphical Ping Tool
git clone https://git.sinitax.com/cnlohr/cnping
Log | Files | Refs | Submodules | README | LICENSE | sfeed.txt

commit 50d754a4603888ea6703f4155ac10b752c0b9429
parent 03517f921daf448c7740aab4a1c13623d1fd92cb
Author: cnlohr <lohr85@gmail.com>
Date:   Thu, 23 Feb 2017 21:36:47 -0500

Fix Windows driver to use almost no CPU

Diffstat:
MMakefile | 2+-
MWinDriver.c | 406++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mcnping.exe | 0
Mping.c | 591+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Aresources.rc | 22++++++++++++++++++++++
Auac.manifest | 11+++++++++++
6 files changed, 674 insertions(+), 358 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,7 +8,7 @@ MINGW32:=/usr/bin/i686-w64-mingw32- cnping.exe : cnping.c DrawFunctions.c WinDriver.c os_generic.c ping.c $(MINGW32)windres resources.rc -o resources.o - $(MINGW32)gcc -g -mwindows -m32 $(CFLAGS) resources.o -o $@ $^ -lgdi32 -lws2_32 -s + $(MINGW32)gcc -g -mwindows -m32 $(CFLAGS) resources.o -o $@ $^ -lgdi32 -lws2_32 -s -D_WIN32_WINNT=0x0600 cnping : cnping.o DrawFunctions.o XDriver.o os_generic.o ping.o gcc $(CFLAGS) -o $@ $^ -lX11 -lm -lpthread -lXinerama -lXext $(LDFLAGS) diff --git a/WinDriver.c b/WinDriver.c @@ -7,75 +7,46 @@ #include <stdlib.h> #include <malloc.h> //for alloca +static HBITMAP lsBitmap; static HINSTANCE lhInstance; static HWND lsHWND; -static HDC lsHDC; -static HBITMAP lsBackBitmap; static HDC lsWindowHDC; -static HBRUSH lsHBR; -static HPEN lsHPEN; -static HBRUSH lsClearBrush; -static unsigned int lsLastWidth; -static unsigned int lsLastHeight; - -static void InternalHandleResize() -{ - DeleteObject( lsBackBitmap ); - lsBackBitmap = CreateCompatibleBitmap( lsHDC, lsLastWidth, lsLastHeight ); - SelectObject( lsHDC, lsBackBitmap ); - -} - -uint32_t CNFGColor( uint32_t RGB ) -{ - CNFGLastColor = RGB; - - DeleteObject( lsHBR ); - lsHBR = CreateSolidBrush( RGB ); - SelectObject( lsHDC, lsHBR ); - - DeleteObject( lsHPEN ); - lsHPEN = CreatePen( PS_SOLID, 0, RGB ); - SelectObject( lsHDC, lsHPEN ); - - return RGB; -} +static HDC lsHDC; +static unsigned int bufferx; +static unsigned int buffery; +static uint32_t * buffer = 0; -void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +void CNFGClearFrame() { - POINT pt[2] = { {x1, y1}, {x2, y2} }; - Polyline( lsHDC, pt, 2 ); - SetPixel( lsHDC, x1, y1, CNFGLastColor ); - SetPixel( lsHDC, x2, y2, CNFGLastColor ); + uint32_t col = CNFGColor( CNFGBGColor ); + int i; + for( i = bufferx * buffery - 1; i>=0; i-- ) + { + buffer[i] = col; + } } -void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +void InternalHandleResize() { - RECT r; - if( x1 < x2 ) { r.left = x1; r.right = x2; } - else { r.left = x2; r.right = x1; } - if( y1 < y2 ) { r.top = y1; r.bottom = y2; } - else { r.top = y2; r.bottom = y1; } - FillRect( lsHDC, &r, lsHBR ); -} + if( lsBitmap ) DeleteObject( lsBitmap ); -void CNFGClearFrame() -{ - RECT r = { 0, 0, lsLastWidth, lsLastHeight }; - DeleteObject( lsClearBrush ); - lsClearBrush = CreateSolidBrush( CNFGBGColor ); - SelectObject( lsHDC, lsClearBrush ); + if( buffer ) free( buffer ); + buffer = malloc( bufferx * buffery * 4 ); - FillRect( lsHDC, &r, lsClearBrush ); + lsBitmap = CreateBitmap( bufferx, buffery, 1, 32, buffer ); + SelectObject( lsHDC, lsBitmap ); } void CNFGSwapBuffers() { int thisw, thish; RECT r; - BitBlt( lsWindowHDC, 0, 0, lsLastWidth, lsLastHeight, lsHDC, 0, 0, SRCCOPY ); + + int a = SetBitmapBits(lsBitmap,bufferx*buffery*4,buffer); + a = BitBlt(lsWindowHDC, 0, 0, bufferx, buffery, lsHDC, 0, 0, SRCCOPY); UpdateWindow( lsHWND ); + //Check to see if the window is closed. if( !IsWindow( lsHWND ) ) { @@ -85,36 +56,218 @@ void CNFGSwapBuffers() GetClientRect( lsHWND, &r ); thisw = r.right - r.left; thish = r.bottom - r.top; - if( thisw != lsLastWidth || thish != lsLastHeight ) + if( thisw != bufferx || thish != buffery ) { - lsLastWidth = thisw; - lsLastHeight = thish; + bufferx = thisw; + buffery = thish; InternalHandleResize(); } } -void CNFGTackPoly( RDPoint * points, int verts ) + +static uint32_t SWAPS( uint32_t r ) { - int i; - POINT * t = (POINT*)alloca( sizeof( POINT ) * verts ); - for( i = 0; i < verts; i++ ) + uint32_t ret = (r&0xFF)<<16; + r>>=8; + ret |= (r&0xff)<<8; + r>>=8; + ret |= r; + return ret; +} + +uint32_t CNFGColor( uint32_t RGB ) +{ + CNFGLastColor = SWAPS(RGB); + return CNFGLastColor; +} + +void CNFGTackPixel( short tx, short ty ) +{ + buffer[ty * bufferx + tx] = CNFGLastColor; +} + +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( !buffer ) return; + + if( dx < 0 ) dx = -dx; + if( dy < 0 ) dy = -dy; + + if( dx > dy ) { - t[i].x = points[i].x; - t[i].y = points[i].y; + 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 >= buffery ) continue; + if( tx >= bufferx ) break; + buffer[ty * bufferx + 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 >= bufferx ) continue; + if( ty >= buffery ) break; + buffer[ty * bufferx + tx] = CNFGLastColor; + thisx += slope; + } } - Polygon( lsHDC, t, verts ); } +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + short minx = (x1<x2)?x1:x2; + short miny = (y1<y2)?y1:y2; + short maxx = (x1>=x2)?x1:x2; + short maxy = (y1>=y2)?y1:y2; -void CNFGTackPixel( short x1, short y1 ) + short x, y; + + if( minx < 0 ) minx = 0; + if( miny < 0 ) miny = 0; + if( maxx >= bufferx ) maxx = bufferx-1; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + uint32_t * bufferstart = &buffer[y * bufferx + minx]; + for( x = minx; x <= maxx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +} + +void CNFGTackPoly( RDPoint * points, int verts ) { - SetPixel( lsHDC, x1, y1, CNFGLastColor ); + short minx = 10000, miny = 10000; + short maxx =-10000, maxy =-10000; + short i, x, y; + + //Just in case... + if( verts > 32767 ) return; + + for( i = 0; i < verts; i++ ) + { + RDPoint * p = &points[i]; + if( p->x < minx ) minx = p->x; + if( p->y < miny ) miny = p->y; + if( p->x > maxx ) maxx = p->x; + if( p->y > maxy ) maxy = p->y; + } + + if( miny < 0 ) miny = 0; + if( maxy >= buffery ) maxy = buffery-1; + + for( y = miny; y <= maxy; y++ ) + { + short startfillx = maxx; + short endfillx = minx; + + //Figure out what line segments intersect this line. + for( i = 0; i < verts; i++ ) + { + short pl = i + 1; + if( pl == verts ) pl = 0; + + RDPoint ptop; + RDPoint pbot; + + ptop.x = points[i].x; + ptop.y = points[i].y; + pbot.x = points[pl].x; + pbot.y = points[pl].y; +//printf( "Poly: %d %d\n", pbot.y, ptop.y ); + + if( pbot.y < ptop.y ) + { + RDPoint ptmp; + ptmp.x = pbot.x; + ptmp.y = pbot.y; + pbot.x = ptop.x; + pbot.y = ptop.y; + ptop.x = ptmp.x; + ptop.y = ptmp.y; + } + + //Make sure this line segment is within our range. +//printf( "PT: %d %d %d\n", y, ptop.y, pbot.y ); + if( ptop.y <= y && pbot.y >= y ) + { + short diffy = pbot.y - ptop.y; + uint32_t placey = (uint32_t)(y - ptop.y)<<16; //Scale by 16 so we can do integer math. + short diffx = pbot.x - ptop.x; + short isectx; + + if( diffy == 0 ) + { + if( pbot.x < ptop.x ) + { + if( startfillx > pbot.x ) startfillx = pbot.x; + if( endfillx < ptop.x ) endfillx = ptop.x; + } + else + { + if( startfillx > ptop.x ) startfillx = ptop.x; + if( endfillx < pbot.x ) endfillx = pbot.x; + } + } + else + { + //Inner part is scaled by 65536, outer part must be scaled back. + isectx = (( (placey / diffy) * diffx + 32768 )>>16) + ptop.x; + if( isectx < startfillx ) startfillx = isectx; + if( isectx > endfillx ) endfillx = isectx; + } +//printf( "R: %d %d %d\n", pbot.x, ptop.x, isectx ); + } + } + +//printf( "%d %d %d\n", y, startfillx, endfillx ); + + if( endfillx >= bufferx ) endfillx = bufferx - 1; + if( endfillx >= bufferx ) endfillx = buffery - 1; + if( startfillx < 0 ) startfillx = 0; + if( startfillx < 0 ) startfillx = 0; + + unsigned int * bufferstart = &buffer[y * bufferx + startfillx]; + for( x = startfillx; x <= endfillx; x++ ) + { + (*bufferstart++) = CNFGLastColor; + } + } +//exit(1); } + + void CNFGGetDimensions( short * x, short * y ) { - *x = lsLastWidth; - *y = lsLastHeight; + *x = bufferx; + *y = buffery; } //This was from the article @@ -143,8 +296,8 @@ void CNFGSetup( const char * name_of_window, int width, int height ) int w, h, wd, hd; HINSTANCE hInstance = GetModuleHandle(NULL); - lsLastWidth = width; - lsLastHeight = height; + bufferx = width; + buffery = height; wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later wnd.lpfnWndProc = MyWndProc; @@ -167,8 +320,8 @@ void CNFGSetup( const char * name_of_window, int width, int height ) WS_OVERLAPPEDWINDOW, //basic window style CW_USEDEFAULT, CW_USEDEFAULT, //set starting point to default value - lsLastWidth, - lsLastHeight, //set all the dimensions to default value + bufferx, + buffery, //set all the dimensions to default value NULL, //no parent window NULL, //no menu hInstance, @@ -176,13 +329,14 @@ void CNFGSetup( const char * name_of_window, int width, int height ) lsWindowHDC = GetDC( lsHWND ); + lsHDC = CreateCompatibleDC( lsWindowHDC ); - lsBackBitmap = CreateCompatibleBitmap( lsWindowHDC, lsLastWidth, lsLastHeight ); - SelectObject( lsHDC, lsBackBitmap ); + //lsBackBitmap = CreateCompatibleBitmap( lsWindowHDC, lsLastWidth, buffery ); + //SelectObject( lsHDC, lsBackBitmap ); - lsClearBrush = CreateSolidBrush( CNFGBGColor ); - lsHBR = CreateSolidBrush( 0xFFFFFF ); - lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF ); + //lsClearBrush = CreateSolidBrush( CNFGBGColor ); + //lsHBR = CreateSolidBrush( 0xFFFFFF ); + //lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF ); ShowWindow(lsHWND, 1); //display the window on the screen @@ -193,7 +347,7 @@ void CNFGSetup( const char * name_of_window, int width, int height ) h = ( window.bottom - window.top); wd = w - client.right; hd = h - client.bottom; - MoveWindow( lsHWND, window.left, window.top, lsLastWidth + wd, lsLastHeight + hd, 1 ); + MoveWindow( lsHWND, window.left, window.top, bufferx + wd, buffery + hd, 1 ); InternalHandleResize(); } @@ -229,3 +383,105 @@ void CNFGHandleInput() } } + +/* +static HBITMAP lsBackBitmap; +static HDC lsWindowHDC; +static HBRUSH lsHBR; +static HPEN lsHPEN; +static HBRUSH lsClearBrush; + +static void InternalHandleResize() +{ + DeleteObject( lsBackBitmap ); + lsBackBitmap = CreateCompatibleBitmap( lsHDC, lsLastWidth, lsLastHeight ); + SelectObject( lsHDC, lsBackBitmap ); + +} + +uint32_t CNFGColor( uint32_t RGB ) +{ + CNFGLastColor = RGB; + + DeleteObject( lsHBR ); + lsHBR = CreateSolidBrush( RGB ); + SelectObject( lsHDC, lsHBR ); + + DeleteObject( lsHPEN ); + lsHPEN = CreatePen( PS_SOLID, 0, RGB ); + SelectObject( lsHDC, lsHPEN ); + + return RGB; +} + +void CNFGTackSegment( short x1, short y1, short x2, short y2 ) +{ + POINT pt[2] = { {x1, y1}, {x2, y2} }; + Polyline( lsHDC, pt, 2 ); + SetPixel( lsHDC, x1, y1, CNFGLastColor ); + SetPixel( lsHDC, x2, y2, CNFGLastColor ); +} + +void CNFGTackRectangle( short x1, short y1, short x2, short y2 ) +{ + RECT r; + if( x1 < x2 ) { r.left = x1; r.right = x2; } + else { r.left = x2; r.right = x1; } + if( y1 < y2 ) { r.top = y1; r.bottom = y2; } + else { r.top = y2; r.bottom = y1; } + FillRect( lsHDC, &r, lsHBR ); +} + +void CNFGClearFrame() +{ + RECT r = { 0, 0, lsLastWidth, lsLastHeight }; + DeleteObject( lsClearBrush ); + lsClearBrush = CreateSolidBrush( CNFGBGColor ); + SelectObject( lsHDC, lsClearBrush ); + + FillRect( lsHDC, &r, lsClearBrush ); +} + +void CNFGSwapBuffers() +{ + int thisw, thish; + RECT r; + BitBlt( lsWindowHDC, 0, 0, lsLastWidth, lsLastHeight, lsHDC, 0, 0, SRCCOPY ); + UpdateWindow( lsHWND ); + + //Check to see if the window is closed. + if( !IsWindow( lsHWND ) ) + { + exit( 0 ); + } + + GetClientRect( lsHWND, &r ); + thisw = r.right - r.left; + thish = r.bottom - r.top; + if( thisw != lsLastWidth || thish != lsLastHeight ) + { + lsLastWidth = thisw; + lsLastHeight = thish; + InternalHandleResize(); + } +} + +void CNFGTackPoly( RDPoint * points, int verts ) +{ + int i; + POINT * t = (POINT*)alloca( sizeof( POINT ) * verts ); + for( i = 0; i < verts; i++ ) + { + t[i].x = points[i].x; + t[i].y = points[i].y; + } + Polygon( lsHDC, t, verts ); +} + + +void CNFGTackPixel( short x1, short y1 ) +{ + SetPixel( lsHDC, x1, y1, CNFGLastColor ); +} +*/ + diff --git a/cnping.exe b/cnping.exe Binary files differ. diff --git a/ping.c b/ping.c @@ -1,282 +1,309 @@ -/* 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. ***/ -/*****************************************************************************/ - -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <strings.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 -void bzero(void *location,__LONG32 count); -#include <windows.h> -#include <stdio.h> -#include <winsock2.h> -#include <ws2tcpip.h> -#include <stdint.h> -#else -#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 -#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; -}; -#endif - -float pingperiod; -int precise_ping; - -#define PACKETSIZE 1500 -struct packet -{ - struct icmphdr hdr; - char msg[PACKETSIZE-sizeof(struct icmphdr)]; -}; - -int sd; -int pid=-1; -struct protoent *proto=NULL; -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; -} - - -/*--------------------------------------------------------------------*/ -/*--- listener - separate process to listen for and collect messages--*/ -/*--------------------------------------------------------------------*/ -void listener(void) -{ -#ifndef WIN32 - const int val=255; - - int sd = socket(PF_INET, SOCK_RAW, proto->p_proto); - - if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) - { - ERRM("Erro: could not set TTL option\n"); - exit( -1 ); - } - -#endif - - struct sockaddr_in addr; - unsigned char buf[1024]; - - for (;;) - { - int i; - int bytes, len=sizeof(addr); - - bzero(buf, sizeof(buf)); - bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len); - 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; - - if ( bytes > 0 ) - display(buf + 28, bytes - 28 ); - else - perror("recvfrom"); - } - printf( "Fault on listen.\n" ); - exit(0); -} - -/*--------------------------------------------------------------------*/ -/*--- ping - Create message and send it. ---*/ -/*--------------------------------------------------------------------*/ -void ping(struct sockaddr_in *addr ) -{ - -#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. - unsigned long iMode = 1; - ioctlsocket(sd, FIONBIO, &iMode); - } -#else - if ( fcntl(sd, F_SETFL, O_NONBLOCK) != 0 ) - ERRM("Warning: Request nonblocking I/O failed."); -#endif - - double stime = OGGetAbsoluteTime(); - - do - { int len=sizeof(r_addr); - -// 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.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 ); - if ( sendto(sd, (char*)&pckt, sizeof(pckt) - sizeof( pckt.msg ) + rsize , 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0 ) - perror("sendto"); - - - if( precise_ping ) - { - double ctime; - do - { - ctime = OGGetAbsoluteTime(); - if( pingperiod >= 1000 ) stime = ctime; - } while( ctime < stime + pingperiod ); - stime += pingperiod; - } - else - { - if( pingperiod > 0 ) - { - uint32_t dlw = 1000000.0*pingperiod; - usleep( dlw ); - } - } - } while( pingperiod >= 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 ) - { - ERRM( "Fault in WSAStartup\n" ); - exit( -2 ); - } -#endif - - -#ifdef WIN32 - sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0); - { - int lttl = 0xff; - if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&lttl, - sizeof(lttl)) == SOCKET_ERROR) { - printf( "Warning: No IP_TTL.\n" ); - } - } -#else - const int val=255; - - sd = socket(PF_INET, SOCK_RAW, proto->p_proto); - - if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) - { - ERRM("Error: Failed to set TTL option\n"); - exit( -1 ); - } - -#endif - if ( sd < 0 ) - { - ERRM("Error: Could not create raw socket\n"); - exit(0); - } - -} - -void do_pinger( const char * strhost ) -{ - struct hostent *hname; - hname = gethostbyname(strhost); - - bzero(&psaddr, sizeof(psaddr)); - psaddr.sin_family = hname->h_addrtype; - psaddr.sin_port = 0; - psaddr.sin_addr.s_addr = *(long*)hname->h_addr; - ping(&psaddr ); -} - -char errbuffer[1024]; - - +/* 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. ***/ +/*****************************************************************************/ + +#include <string.h> +#include <fcntl.h> +#include <errno.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 usleep(int x) { + Sleep(x / 1000); +} +void bzero(void * loc, int len) +{ + memset(loc, 0, len); +} +#endif + +#include <windows.h> +#include <stdio.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 +#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; +}; +#endif + +float pingperiod; +int precise_ping; + +#define PACKETSIZE 1500 +struct packet +{ + struct icmphdr hdr; + char msg[PACKETSIZE-sizeof(struct icmphdr)]; +}; + +int sd; +int pid=-1; +struct protoent *proto=NULL; +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; +} + + +/*--------------------------------------------------------------------*/ +/*--- listener - separate process to listen for and collect messages--*/ +/*--------------------------------------------------------------------*/ +void listener(void) +{ +#ifndef WIN32 + const int val=255; + + int sd = socket(PF_INET, SOCK_RAW, proto->p_proto); + + if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) + { + ERRM("Erro: could not set TTL option\n"); + exit( -1 ); + } + +#endif + + struct sockaddr_in addr; + unsigned char buf[8192]; +#ifdef WIN32 + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); +#endif + for (;;) + { + int i; + int bytes, len=sizeof(addr); + + bzero(buf, sizeof(buf)); +#ifdef WIN32 + WSAPOLLFD fda[1]; + fda[0].fd = sd; + fda[0].events = POLLIN; + WSAPoll(fda, 1, 10); +#endif + keep_retry_quick: + bytes = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len); + 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; + + if ( bytes > 0 ) + display(buf + 28, bytes - 28 ); + else + perror("recvfrom"); + + goto keep_retry_quick; + } + printf( "Fault on listen.\n" ); + exit(0); +} + +/*--------------------------------------------------------------------*/ +/*--- ping - Create message and send it. ---*/ +/*--------------------------------------------------------------------*/ +void ping(struct sockaddr_in *addr ) +{ + +#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. + unsigned long iMode = 1; + ioctlsocket(sd, FIONBIO, &iMode); + + + } +#else + if ( fcntl(sd, F_SETFL, O_NONBLOCK) != 0 ) + ERRM("Warning: Request nonblocking I/O failed."); +#endif + + double stime = OGGetAbsoluteTime(); + + do + { int len=sizeof(r_addr); + +// 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.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 ); + + if ( sendto(sd, (char*)&pckt, sizeof(pckt) - sizeof( pckt.msg ) + rsize , 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0 ) + perror("sendto"); + + + if( precise_ping ) + { + double ctime; + do + { + ctime = OGGetAbsoluteTime(); + if( pingperiod >= 1000 ) stime = ctime; + } while( ctime < stime + pingperiod ); + stime += pingperiod; + } + else + { + if( pingperiod > 0 ) + { + uint32_t dlw = 1000000.0*pingperiod; + usleep( dlw ); + } + } + } while( pingperiod >= 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 ) + { + ERRM( "Fault in WSAStartup\n" ); + exit( -2 ); + } +#endif + + +#ifdef WIN32 + 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*)&lttl, + sizeof(lttl)) == SOCKET_ERROR) { + printf( "Warning: No IP_TTL.\n" ); + } + } +#else + const int val=255; + + sd = socket(PF_INET, SOCK_RAW, proto->p_proto); + + if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0) + { + ERRM("Error: Failed to set TTL option\n"); + exit( -1 ); + } + +#endif + if ( sd < 0 ) + { + ERRM("Error: Could not create raw socket\n"); + exit(0); + } + +} + +void do_pinger( const char * strhost ) +{ + struct hostent *hname; + hname = gethostbyname(strhost); + + bzero(&psaddr, sizeof(psaddr)); + psaddr.sin_family = hname->h_addrtype; + psaddr.sin_port = 0; + psaddr.sin_addr.s_addr = *(long*)hname->h_addr; + ping(&psaddr ); +} + +char errbuffer[1024]; + + diff --git a/resources.rc b/resources.rc @@ -0,0 +1,22 @@ +1 24 "uac.manifest" + +#include <windows.h> + +LANGUAGE 9, SUBLANG_DEFAULT +IPDialog DIALOG 10, 10, 300, 100 +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 "[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 + EDITTEXT 3, 1, 15, 58, 12 + EDITTEXT 4, 1, 30, 58, 12 + EDITTEXT 5, 1, 45, 58, 12 + EDITTEXT 6, 1, 60, 58, 12 + PUSHBUTTON "&Ping", 7, 25, 80, 100, 10 + PUSHBUTTON "&Close", 8, 175, 80, 100, 10 +END + diff --git a/uac.manifest b/uac.manifest @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="cnping" type="win32"/> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly>