commit bd6f825d46a69b4e648be8137026b39d1f99442b Author: Carsten Larsen Date: Fri Sep 1 00:03:35 2017 +0200 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d39959e --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +# Portable Makefile generated by configure + +all: http_ping help + +CC = m68k-amigaos-gcc +CFLAGS = -O2 -noixemul $(SSL_DEFS) $(SSL_INC) -Iinclude -Wall +LDFLAGS = -s -lm $(SSL_LIBS) + +http_ping.o: http_ping.c port.h + +http_ping_amiga.o: http_ping_amiga.c version.h + +time_timer.o: time_timer.c + + +http_ping: http_ping.o http_ping_amiga.o time_timer.o + ${CC} ${CFLAGS} -o http_ping http_ping.o http_ping_amiga.o time_timer.o ${LDFLAGS} + +help: + nroff -man http_ping.1 > http_ping.help + +clean: + rm -f http_ping.o http_ping_amiga.o time_timer.o http_ping http_ping.help + +depend: + @echo Dependencies already done diff --git a/README b/README new file mode 100644 index 0000000..1fff418 --- /dev/null +++ b/README @@ -0,0 +1,22 @@ + http_ping - measure HTTP latency + +http_ping runs an HTTP fetch every few seconds, timing how long it takes. +See the manual entry for more details. + +Files in this distribution: + + README this + Makefile guess + http_ping.c source file + http_ping.1 manual entry + port.h portability defines + +To build: If you're on a SysV-like machine (which includes old Linux systems +but not new Linux systems), edit the Makefile and uncomment the SYSV_LIBS +line. If you're doing SSL, uncomment those lines too. Otherwise, just do +a make. + +Feedback is welcome - send bug reports, enhancements, checks, money +orders, etc. to the addresses below. + + Jef Poskanzer jef@mail.acme.com http://www.acme.com/jef/ diff --git a/configure b/configure new file mode 100644 index 0000000..00861c3 --- /dev/null +++ b/configure @@ -0,0 +1,126 @@ +#!/bin/sh +# +# Copyright (c) 2015 Carsten Larsen +# Copyright (c) 2014 Poul-Henning Kamp +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +# + +set -e + +# CONFIGURE: If you want to compile in support for https, uncomment these +# definitions. You will need to have already built OpenSSL, available at +# http://www.openssl.org/ Make sure the SSL_TREE definition points to the +# tree with your OpenSSL installation - depending on how you installed it, +# it may be in /usr/local instead of /usr/local/ssl. +#SSL_TREE = /usr/local/ssl +#SSL_DEFS = -DUSE_SSL +#SSL_INC = -I$(SSL_TREE)/include +#SSL_LIBS = -L$(SSL_TREE)/lib -lssl -lcrypto + +EXEC='http_ping' + +HDRS=' + port.h + version.h +' + +SRCS=' + http_ping.c + http_ping_amiga.c + time_timer.c +' + +if make -v 2>&1 | grep GNU > /dev/null 2>&1 ; then + echo "make is GNU make." + VALID=true +#else +# echo "Wrong version of make." +# VALID=false +fi + +if $VALID ; then + ( + echo '# Portable Makefile generated by configure' + echo '' + echo "all: $EXEC help" + echo '' + if [ -n "$1" ] && [ $1 = "AMIGA" ] ; then + echo 'CC = m68k-amigaos-gcc' + echo "CFLAGS = -O2 -noixemul \$(SSL_DEFS) \$(SSL_INC) -Iinclude -Wall" + echo "LDFLAGS = -s -lm \$(SSL_LIBS)" + elif [ -n "$1" ] && [ $1 = "AROS" ] ; then + echo 'CC = gcc' + echo "CFLAGS = -O2 -noixemul \$(SSL_DEFS) \$(SSL_INC) -Iinclude -Wall" + echo "LDFLAGS = -lm \$(SSL_LIBS)" + else + echo "CFLAGS = -O2 -Wall -Werror" + echo "LDFLAGS = -s -lm \$(SSL_LIBS)" + fi + echo '' + + for f in ${HDRS} + do + b=`basename $f .h` + i=`sed -n -e '/#include.*"/{ + s/"$// + s/.*"// + p + }' $f | sort -u` + if [ "x${i}" != "x" ] ; then + echo "${b}.h: " ${i} + echo " touch ${b}.h" + echo + fi + done + + l="" + for f in ${SRCS} + do + b=`basename $f .c` + i=`sed -n -e '/#include.*"/{ + s/"$// + s/.*"// + p + }' $f | sort -u` + echo "${b}.o: ${b}.c" ${i} + echo + l="${l} ${b}.o" + done + + echo + echo "$EXEC: ${l}" + echo " \${CC} \${CFLAGS} -o $EXEC ${l} \${LDFLAGS}" + echo + echo "help:" + echo " nroff -man $EXEC.1 > $EXEC.help" + echo + echo "clean:" + echo " rm -f ${l} $EXEC $EXEC.help" + echo + echo "depend:" + echo " @echo Dependencies already done" + ) > Makefile + + echo "Makefile generated" +fi diff --git a/http_ping.1 b/http_ping.1 new file mode 100644 index 0000000..13734a4 --- /dev/null +++ b/http_ping.1 @@ -0,0 +1,75 @@ +.TH http_ping 1 "01 November 2015" +.SH NAME +http_ping - measure HTTP latency +.SH SYNOPSIS +.B http_ping +.RB [ -count +.IR n ] +.RB [ -interval +.IR n ] +.RB [ -quiet ] +.RB [ -proxy +.IR host:port ] +.I url +.SH DESCRIPTION +.PP +.I http_ping +runs an HTTP fetch every few seconds, timing how long it takes. +.PP +Sample run: +.nf + % http_ping http://www.example.com/ + 7816 bytes from http://www.example.com/: 246.602 ms (9.923c/23.074r/213.605d) + 7816 bytes from http://www.example.com/: 189.997 ms (11.619c/22.971r/155.407d) + 7816 bytes from http://www.example.com/: 190.463 ms (8.994c/25.091r/156.378d) + 7816 bytes from http://www.example.com/: 190.07 ms (9.234c/23.9r/156.936d) + 7816 bytes from http://www.example.com/: 190.706 ms (10.142c/46.579r/133.985d) + ^C + --- http://www.example.com/ http_ping statistics --- + 5 fetches started, 5 completed (100%), 0 failures (0%), 0 timeouts (0%) + total min/avg/max = 189.997/201.568/246.602 ms + connect min/avg/max = 8.994/9.9824/11.619 ms + response min/avg/max = 22.971/28.323/46.579 ms + data min/avg/max = 133.985/163.262/213.605 ms +.fi +.SH OPTIONS +.TP +.B -count +Stop after the specified number of fetches. +Without this option, http_ping will continue until interrupted. +.TP +.B -interval +Wait the specified number of seconds between fetches. +The default is five seconds. +.TP +.B -quiet +Only display the summary info at the end. +.TP +.B -proxy +Specifies a proxy host and port to use. +.SH "SEE ALSO" +http_load, http_get, ping +.SH AUTHOR +Copyright © 1998,1999,2001,2002 by Jef Poskanzer . +Copyright © 2015 by Carsten Larsen . +All rights reserved. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/http_ping.c b/http_ping.c new file mode 100644 index 0000000..3f72670 --- /dev/null +++ b/http_ping.c @@ -0,0 +1,1181 @@ +/* http_ping - measure HTTP latency +** +** Copyright © 1998,1999,2001,2002 by Jef Poskanzer . +** Copyright 2015 by Carsten Larsen . +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_SSL +#include +#include +#include +#endif + +#include "port.h" + +#define INTERVAL 5 +#define TIMEOUT 15 + +#define max(a,b) ((a)>=(b)?(a):(b)) +#define min(a,b) ((a)<=(b)?(a):(b)) + +static char* url; +static int url_protocol; +static char url_host[5000]; +static unsigned short url_port; +static char* url_filename; + +/* Protocol symbols. */ +#define PROTO_HTTP 0 +#ifdef USE_SSL +#define PROTO_HTTPS 1 +#endif + +static unsigned short port; +static int conn_fd; +#ifdef USE_SSL +static SSL* ssl; +#endif +static int conn_state; +static int got_response; +static struct timeval started_at, connect_at, response_at, finished_at; +static long content_length; +static long bytes; + +#define ST_BOL 0 +#define ST_TEXT 1 +#define ST_LF 2 +#define ST_CR 3 +#define ST_CRLF 4 +#define ST_CRLFCR 5 +#define ST_C 6 +#define ST_CO 7 +#define ST_CON 8 +#define ST_CONT 9 +#define ST_CONTE 10 +#define ST_CONTEN 11 +#define ST_CONTENT 12 +#define ST_CONTENT_ 13 +#define ST_CONTENT_L 14 +#define ST_CONTENT_LE 15 +#define ST_CONTENT_LEN 16 +#define ST_CONTENT_LENG 17 +#define ST_CONTENT_LENGT 18 +#define ST_CONTENT_LENGTH 19 +#define ST_CONTENT_LENGTH_COLON 20 +#define ST_CONTENT_LENGTH_COLON_WHITESPACE 21 +#define ST_CONTENT_LENGTH_COLON_WHITESPACE_NUM 22 +#define ST_DATA 23 + +static char* argv0; +static int count; +static int interval; +static int quiet; +static int do_proxy; +static char* proxy_host; +static unsigned short proxy_port; + +static int terminate; +static int count_started, count_completed, count_failures, count_timeouts; +static long total_bytes; +static jmp_buf jb; + +static float min_total, min_connect, min_response, min_data; +static float max_total, max_connect, max_response, max_data; +static float sum_total, sum_connect, sum_response, sum_data; + +#ifdef USE_SSL +static SSL_CTX* ssl_ctx = (SSL_CTX*) 0; +#endif + + +/* Forwards. */ +static void usage( void ); +static void parse_url( void ); +static void init_net( void ); +static int start_connection( void ); +static void lookup_address( char* hostname, unsigned short p ); +static int open_client_socket( void ); +static int handle_read( void ); +static void handle_term( int sig ); +static void handle_alarm( int sig ); +static void close_connection( void ); +static long long delta_timeval( struct timeval* start, struct timeval* finish ); + + +int +main( int argc, char** argv ) +{ + int argn; + float elapsed_total, elapsed_connect, elapsed_response, elapsed_data; + + open_libs(); + + /* Parse args. */ + argv0 = argv[0]; + argn = 1; + count = -1; + interval = INTERVAL; + quiet = 0; + do_proxy = 0; + while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) + { + if ( strncmp( argv[argn], "-count", strlen( argv[argn] ) ) == 0 && argn + 1 < argc ) + { + count = atoi( argv[++argn] ); + if ( count <= 0 ) + { + (void) fprintf( stderr, "%s: count must be positive\n", argv0 ); + exit( 1 ); + } + } + else if ( strncmp( argv[argn], "-interval", strlen( argv[argn] ) ) == 0 && argn + 1 < argc ) + { + interval = atoi( argv[++argn] ); + if ( interval < 1 ) + { + (void) fprintf( stderr, "%s: interval must be at least one\n", argv0 ); + exit( 1 ); + } + } + else if ( strncmp( argv[argn], "-quiet", strlen( argv[argn] ) ) == 0 ) + { + quiet = 1; + } + else if ( strncmp( argv[argn], "-proxy", strlen( argv[argn] ) ) == 0 && argn + 1 < argc ) + { + char* colon; + do_proxy = 1; + proxy_host = argv[++argn]; + colon = strchr( proxy_host, ':' ); + if ( colon == (char*) 0 ) + proxy_port = 80; + else + { + proxy_port = (unsigned short) atoi( colon + 1 ); + *colon = '\0'; + } + } + else + usage(); + ++argn; + } + if ( argn + 1 != argc ) + usage(); + url = argv[argn]; + + /* Parse the URL. */ + parse_url(); + + /* Initialize the network stuff. */ + init_net(); + + /* Initialize the statistics. */ + count_started = count_completed = count_failures = count_timeouts = 0; + total_bytes = 0; + min_total = min_connect = min_response = min_data = 1000000000.0; + max_total = max_connect = max_response = max_data = -1000000000.0; + sum_total = sum_connect = sum_response = sum_data = 0.0; + + /* Initialize the random number generator. */ +#ifdef HAVE_SRANDOMDEV + srandomdev(); +#else + srandom( (int) time( (time_t*) 0 ) ^ getpid() ); +#endif + + /* Initialize the rest. */ +#ifdef HAVE_SIGSET + (void) sigset( SIGTERM, handle_term ); + (void) sigset( SIGINT, handle_term ); + (void) sigset( SIGPIPE, SIG_IGN ); + (void) sigset( SIGALRM, handle_alarm ); +#else /* HAVE_SIGSET */ + (void) signal( SIGTERM, handle_term ); + (void) signal( SIGINT, handle_term ); + (void) signal( SIGPIPE, SIG_IGN ); + (void) signal( SIGALRM, handle_alarm ); +#endif /* HAVE_SIGSET */ + + /* Main loop. */ + terminate = 0; + for (;;) + { + (void) setjmp( jb ); + if ( count == 0 || terminate ) + break; + if ( count > 0 ) + --count; + ++count_started; + alarm( TIMEOUT ); + if ( ! start_connection() ) + ++count_failures; + else + { + if ( ! handle_read() ) + ++count_failures; + else + { + ++count_completed; + elapsed_total = + delta_timeval( &started_at, &finished_at ) / 1000.0; + elapsed_connect = + delta_timeval( &started_at, &connect_at ) / 1000.0; + elapsed_response = + delta_timeval( &connect_at, &response_at ) / 1000.0; + elapsed_data = + delta_timeval( &response_at, &finished_at ) / 1000.0; + if ( ! quiet ) + (void) printf( + "%ld bytes from %s: %g ms (%gc/%gr/%gd)\n", + bytes, url, elapsed_total, elapsed_connect, + elapsed_response, elapsed_data ); + min_total = min( min_total, elapsed_total ); + min_connect = min( min_connect, elapsed_connect ); + min_response = min( min_response, elapsed_response ); + min_data = min( min_data, elapsed_data ); + max_total = max( max_total, elapsed_total ); + max_connect = max( max_connect, elapsed_connect ); + max_response = max( max_response, elapsed_response ); + max_data = max( max_data, elapsed_data ); + sum_total += elapsed_total; + sum_connect += elapsed_connect; + sum_response += elapsed_response; + sum_data += elapsed_data; + } + } + alarm( 0 ); + if ( count == 0 || terminate ) + break; + sleep( interval ); + } + + /* Report statistics. */ + (void) printf( "\n" ); + (void) printf( "--- %s http_ping statistics ---\n", url ); + (void) printf( + "%d fetches started, %d completed (%d%%), %d failures (%d%%), %d timeouts (%d%%)\n", + count_started, count_completed, count_completed * 100 / count_started, + count_failures, count_failures * 100 / count_started, + count_timeouts, count_timeouts * 100 / count_started ); + if ( count_completed > 0 ) + { + (void) printf( + "total min/avg/max = %g/%g/%g ms\n", + min_total, sum_total / count_completed, max_total ); + (void) printf( + "connect min/avg/max = %g/%g/%g ms\n", + min_connect, sum_connect / count_completed, max_connect ); + (void) printf( + "response min/avg/max = %g/%g/%g ms\n", + min_response, sum_response / count_completed, max_response ); + (void) printf( + "data min/avg/max = %g/%g/%g ms\n", + min_data, sum_data / count_completed, max_data ); + } + + /* Done. */ +#ifdef USE_SSL + if ( ssl_ctx != (SSL_CTX*) 0 ) + SSL_CTX_free( ssl_ctx ); +#endif + exit( 0 ); +} + + +static void +usage( void ) +{ + (void) fprintf( stderr, "usage: %s [-count n] [-interval n] [-quiet] [-proxy host:port] url\n", argv0 ); + exit( 1 ); +} + + +static void +parse_url( void ) +{ + char* http = "http://"; + int http_len = strlen( http ); +#ifdef USE_SSL + char* https = "https://"; + int https_len = strlen( https ); +#endif + int proto_len, host_len; + char* cp; + + if ( strncmp( http, url, http_len ) == 0 ) + { + proto_len = http_len; + url_protocol = PROTO_HTTP; + } +#ifdef USE_SSL + else if ( strncmp( https, url, https_len ) == 0 ) + { + proto_len = https_len; + url_protocol = PROTO_HTTPS; + } +#endif + else + { + (void) fprintf( stderr, "%s: unknown protocol - %s\n", argv0, url ); + exit( 1 ); + } + for ( cp = url + proto_len; + *cp != '\0' && *cp != ':' && *cp != '/'; ++cp ) + ; + host_len = cp - url; + host_len -= proto_len; + host_len = min( host_len, sizeof(url_host) - 1 ); + strncpy( url_host, url + proto_len, host_len ); + url_host[host_len] = '\0'; + if ( *cp == ':' ) + { + url_port = (unsigned short) atoi( ++cp ); + while ( *cp != '\0' && *cp != '/' ) + ++cp; + } + else +#ifdef USE_SSL + if ( url_protocol == PROTO_HTTPS ) + url_port = 443; + else + url_port = 80; +#else + url_port = 80; +#endif + if ( *cp == '\0' ) + url_filename = "/"; + else + url_filename = cp; +} + + +static void +init_net( void ) +{ + char* host; + + if ( do_proxy ) + { + host = proxy_host; + port = proxy_port; + } + else + { + host = url_host; + port = url_port; + } + lookup_address( host, port ); +} + + +static int +start_connection( void ) +{ + char buf[600]; + int b, r; + + (void) gettimeofday( &started_at, (struct timezone*) 0 ); + got_response = 0; + content_length = -1; + bytes = 0; + + conn_fd = open_client_socket(); + if ( conn_fd < 0 ) + return 0; + +#ifdef USE_SSL + if ( url_protocol == PROTO_HTTPS ) + { + /* Complete the SSL connection. */ + if ( ssl_ctx == (SSL_CTX*) 0 ) + { + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); + ssl_ctx = SSL_CTX_new( SSLv23_client_method() ); + } + if ( ! RAND_status() ) + { + unsigned char rb[1024]; + int i; + for ( i = 0; i < sizeof(rb); ++i ) + rb[i] = random() % 0xff; + RAND_seed( rb, sizeof(rb) ); + } + ssl = SSL_new( ssl_ctx ); + SSL_set_fd( ssl, conn_fd ); + r = SSL_connect( ssl ); + if ( r <= 0 ) + { + (void) fprintf( + stderr, "%s: SSL connection failed - %d\n", argv0, r ); + ERR_print_errors_fp( stderr ); + close_connection(); + return 0; + } + } +#endif + (void) gettimeofday( &connect_at, (struct timezone*) 0 ); + + /* Format the request. */ + if ( do_proxy ) + { +#ifdef USE_SSL + b = snprintf( + buf, sizeof(buf), "GET %s://%.500s:%d%.500s HTTP/1.0\r\n", + url_protocol == PROTO_HTTPS ? "https" : "http", url_host, + (int) url_port, url_filename ); +#else + b = snprintf( + buf, sizeof(buf), "GET http://%.500s:%d%.500s HTTP/1.0\r\n", + url_host, (int) url_port, url_filename ); +#endif + } + else + b = snprintf( + buf, sizeof(buf), "GET %.500s HTTP/1.0\r\n", url_filename ); + b += snprintf( &buf[b], sizeof(buf) - b, "Host: %s\r\n", url_host ); + b += snprintf( &buf[b], sizeof(buf) - b, "User-Agent: http_ping\r\n" ); + b += snprintf( &buf[b], sizeof(buf) - b, "\r\n" ); + + /* Send the request. */ +#ifdef USE_SSL + if ( url_protocol == PROTO_HTTPS ) + r = SSL_write( ssl, buf, b ); + else + r = Send( conn_fd, buf, b, 0 ); +#else + r = Send( conn_fd, buf, b, 0 ); +#endif + if ( r < 0 ) + { + perror( "write" ); + close_connection(); + return 0; + } + conn_state = ST_BOL; + return 1; +} + + +#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED) +#define USE_IPV6 +#endif + +#ifdef USE_IPV6 +static struct sockaddr_in6 sa_in; +#else /* USE_IPV6 */ +static struct sockaddr_in sa_in; +#endif /* USE_IPV6 */ +static int sa_len, sock_family, sock_type, sock_protocol; + + +static void +lookup_address( char* hostname, unsigned short p ) +{ +#ifdef USE_IPV6 + struct addrinfo hints; + char portstr[10]; + int gaierr; + struct addrinfo* ai; + struct addrinfo* ai2; + struct addrinfo* aiv4; + struct addrinfo* aiv6; +#else /* USE_IPV6 */ + struct hostent *he; +#endif /* USE_IPV6 */ + + (void) memset( (void*) &sa_in, 0, sizeof(sa_in) ); + +#ifdef USE_IPV6 + + (void) memset( &hints, 0, sizeof(hints) ); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + (void) snprintf( portstr, sizeof(portstr), "%d", (int) p ); + if ( (gaierr = getaddrinfo( hostname, portstr, &hints, &ai )) != 0 ) + { + (void) fprintf( + stderr, "%s: getaddrinfo %s - %s\n", argv0, hostname, + gai_strerror( gaierr ) ); + exit( 1 ); + } + + /* Find the first IPv4 and IPv6 entries. */ + aiv4 = (struct addrinfo*) 0; + aiv6 = (struct addrinfo*) 0; + for ( ai2 = ai; ai2 != (struct addrinfo*) 0; ai2 = ai2->ai_next ) + { + switch ( ai2->ai_family ) + { + case AF_INET: + if ( aiv4 == (struct addrinfo*) 0 ) + aiv4 = ai2; + break; + case AF_INET6: + if ( aiv6 == (struct addrinfo*) 0 ) + aiv6 = ai2; + break; + } + } + + /* If there's an IPv4 address, use that, otherwise try IPv6. */ + if ( aiv4 != (struct addrinfo*) 0 ) + { + if ( sizeof(sa_in) < aiv4->ai_addrlen ) + { + (void) fprintf( + stderr, "%s - sockaddr too small (%lu < %lu)\n", + hostname, (unsigned long) sizeof(sa_in), + (unsigned long) aiv4->ai_addrlen ); + exit( 1 ); + } + sock_family = aiv4->ai_family; + sock_type = aiv4->ai_socktype; + sock_protocol = aiv4->ai_protocol; + sa_len = aiv4->ai_addrlen; + (void) memmove( &sa_in, aiv4->ai_addr, sa_len ); + freeaddrinfo( ai ); + return; + } + if ( aiv6 != (struct addrinfo*) 0 ) + { + if ( sizeof(sa_in) < aiv6->ai_addrlen ) + { + (void) fprintf( + stderr, "%s - sockaddr too small (%lu < %lu)\n", + hostname, (unsigned long) sizeof(sa_in), + (unsigned long) aiv6->ai_addrlen ); + exit( 1 ); + } + sock_family = aiv6->ai_family; + sock_type = aiv6->ai_socktype; + sock_protocol = aiv6->ai_protocol; + sa_len = aiv6->ai_addrlen; + (void) memmove( &sa_in, aiv6->ai_addr, sa_len ); + freeaddrinfo( ai ); + return; + } + + (void) fprintf( + stderr, "%s: no valid address found for host %s\n", argv0, hostname ); + exit( 1 ); + +#else /* USE_IPV6 */ + + he = gethostbyname( hostname ); + if ( he == (struct hostent*) 0 ) + { + (void) fprintf( stderr, "%s: unknown host - %s\n", argv0, hostname ); + exit( 1 ); + } + sock_family = sa_in.sin_family = he->h_addrtype; + sock_type = SOCK_STREAM; + sock_protocol = 0; + sa_len = sizeof(sa_in); + (void) memmove( &sa_in.sin_addr, he->h_addr, he->h_length ); + sa_in.sin_port = htons( p ); + +#endif /* USE_IPV6 */ + +} + + +static int +open_client_socket( void ) +{ + int sockfd; + + sockfd = Socket( sock_family, sock_type, sock_protocol ); + if ( sockfd < 0 ) + { + perror( "socket" ); + return -1; + } + + if ( Connect( sockfd, (struct sockaddr*) &sa_in, sa_len ) < 0 ) + { + perror( "connect" ); + (void) CloseSocket( sockfd ); + return -1; + } + + return sockfd; +} + + +static int +handle_read( void ) +{ + char buf[5000]; + int bytes_to_read, bytes_read, bytes_handled; + + for (;;) + { + bytes_to_read = sizeof(buf); +#ifdef USE_SSL + if ( url_protocol == PROTO_HTTPS ) + bytes_read = SSL_read( ssl, buf, bytes_to_read ); + else + bytes_read = Recv( conn_fd, buf, bytes_to_read, 0 ); +#else + bytes_read = Recv( conn_fd, buf, bytes_to_read, 0 ); +#endif + if ( bytes_read < 0 ) + { + perror( "read" ); + close_connection(); + return 0; + } + if ( ! got_response ) + { + got_response = 1; + (void) gettimeofday( &response_at, (struct timezone*) 0 ); + } + if ( bytes_read == 0 ) + { + close_connection(); + (void) gettimeofday( &finished_at, (struct timezone*) 0 ); + return 1; + } + + for ( bytes_handled = 0; bytes_handled < bytes_read; ++bytes_handled ) + { + switch ( conn_state ) + { + case ST_BOL: + switch ( buf[bytes_handled] ) + { + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + case 'C': + case 'c': + conn_state = ST_C; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_TEXT: + switch ( buf[bytes_handled] ) + { + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + break; + } + break; + + case ST_LF: + switch ( buf[bytes_handled] ) + { + case '\n': + conn_state = ST_DATA; + break; + case '\r': + conn_state = ST_CR; + break; + case 'C': + case 'c': + conn_state = ST_C; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CR: + switch ( buf[bytes_handled] ) + { + case '\n': + conn_state = ST_CRLF; + break; + case '\r': + conn_state = ST_DATA; + break; + case 'C': + case 'c': + conn_state = ST_C; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CRLF: + switch ( buf[bytes_handled] ) + { + case '\n': + conn_state = ST_DATA; + break; + case '\r': + conn_state = ST_CRLFCR; + break; + case 'C': + case 'c': + conn_state = ST_C; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CRLFCR: + switch ( buf[bytes_handled] ) + { + case '\n': + case '\r': + conn_state = ST_DATA; + break; + case 'C': + case 'c': + conn_state = ST_C; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_C: + switch ( buf[bytes_handled] ) + { + case 'O': + case 'o': + conn_state = ST_CO; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CO: + switch ( buf[bytes_handled] ) + { + case 'N': + case 'n': + conn_state = ST_CON; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CON: + switch ( buf[bytes_handled] ) + { + case 'T': + case 't': + conn_state = ST_CONT; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONT: + switch ( buf[bytes_handled] ) + { + case 'E': + case 'e': + conn_state = ST_CONTE; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTE: + switch ( buf[bytes_handled] ) + { + case 'N': + case 'n': + conn_state = ST_CONTEN; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTEN: + switch ( buf[bytes_handled] ) + { + case 'T': + case 't': + conn_state = ST_CONTENT; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT: + switch ( buf[bytes_handled] ) + { + case '-': + conn_state = ST_CONTENT_; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_: + switch ( buf[bytes_handled] ) + { + case 'L': + case 'l': + conn_state = ST_CONTENT_L; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_L: + switch ( buf[bytes_handled] ) + { + case 'E': + case 'e': + conn_state = ST_CONTENT_LE; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LE: + switch ( buf[bytes_handled] ) + { + case 'N': + case 'n': + conn_state = ST_CONTENT_LEN; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LEN: + switch ( buf[bytes_handled] ) + { + case 'G': + case 'g': + conn_state = ST_CONTENT_LENG; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENG: + switch ( buf[bytes_handled] ) + { + case 'T': + case 't': + conn_state = ST_CONTENT_LENGT; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENGT: + switch ( buf[bytes_handled] ) + { + case 'H': + case 'h': + conn_state = ST_CONTENT_LENGTH; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENGTH: + switch ( buf[bytes_handled] ) + { + case ':': + conn_state = ST_CONTENT_LENGTH_COLON; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENGTH_COLON: + switch ( buf[bytes_handled] ) + { + case ' ': + case '\t': + conn_state = ST_CONTENT_LENGTH_COLON_WHITESPACE; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENGTH_COLON_WHITESPACE: + switch ( buf[bytes_handled] ) + { + case ' ': + case '\t': + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + content_length = buf[bytes_handled] - '0'; + conn_state = ST_CONTENT_LENGTH_COLON_WHITESPACE_NUM; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_CONTENT_LENGTH_COLON_WHITESPACE_NUM: + switch ( buf[bytes_handled] ) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + content_length = + content_length * 10 + buf[bytes_handled] - '0'; + break; + case '\n': + conn_state = ST_LF; + break; + case '\r': + conn_state = ST_CR; + break; + default: + conn_state = ST_TEXT; + break; + } + break; + + case ST_DATA: + bytes += bytes_read - bytes_handled; + total_bytes += bytes_read - bytes_handled; + bytes_handled = bytes_read; + if ( content_length != -1 && bytes >= content_length ) + { + close_connection(); + (void) gettimeofday( &finished_at, (struct timezone*) 0 ); + return 1; + } + break; + } + } + } +} + + +static void +handle_term( int sig ) +{ + terminate = 1; +} + + +static void +handle_alarm( int sig ) +{ + close_connection(); + (void) fprintf( stderr, "%s: timed out\n", url ); + ++count_timeouts; + longjmp( jb, 0 ); +} + + +static void +close_connection( void ) +{ +#ifdef USE_SSL + if ( url_protocol == PROTO_HTTPS ) + SSL_free( ssl ); +#endif + (void) CloseSocket ( conn_fd ); +} + + +static long long +delta_timeval( struct timeval* start, struct timeval* finish ) +{ + long long delta_secs = finish->tv_sec - start->tv_sec; + long long delta_usecs = finish->tv_usec - start->tv_usec; + return delta_secs * (long long) 1000000L + delta_usecs; +} diff --git a/http_ping.guide b/http_ping.guide new file mode 100644 index 0000000..1f3be38 --- /dev/null +++ b/http_ping.guide @@ -0,0 +1,53 @@ +@database http_ping.guide +@author Carsten Larsen +@(c) Carsten Larsen +@$VER: http_ping.guide 1.10 (01.11.2015) +@node Main "HTTP Ping" +@title "HTTP Ping" + +NAME + http_ping - measure HTTP latency + +SYNOPSIS + http_ping [-count n] [-interval n] [-quiet] [-proxy host:port] url + +DESCRIPTION + http_ping runs an HTTP fetch every few seconds, timing how long it + takes. + + Sample run: + % http_ping http://www.example.com/ + 7816 bytes from http://www.example.com/: 246.602 ms (9.923c/23.074r/213.605d) + 7816 bytes from http://www.example.com/: 189.997 ms (11.619c/22.971r/155.407d) + 7816 bytes from http://www.example.com/: 190.463 ms (8.994c/25.091r/156.378d) + 7816 bytes from http://www.example.com/: 190.07 ms (9.234c/23.9r/156.936d) + 7816 bytes from http://www.example.com/: 190.706 ms (10.142c/46.579r/133.985d) + ^C + --- http://www.example.com/ http_ping statistics --- + 5 fetches started, 5 completed (100%), 0 failures (0%), 0 timeouts (0%) + total min/avg/max = 189.997/201.568/246.602 ms + connect min/avg/max = 8.994/9.9824/11.619 ms + response min/avg/max = 22.971/28.323/46.579 ms + data min/avg/max = 133.985/163.262/213.605 ms + +OPTIONS + -count Stop after the specified number of fetches. Without this + option, http_ping will continue until interrupted. + + -interval + Wait the specified number of seconds between fetches. The + default is five seconds. + + -quiet Only display the summary info at the end. + + -proxy Specifies a proxy host and port to use. + +SEE ALSO + http_load, http_get, ping + +AUTHOR + Copyright (C) 1998,1999,2001,2002 by Jef Poskanzer . + Copyright (C) 2015 by Carsten Larsen . + All rights reserved. + +@endnode diff --git a/http_ping_amiga.c b/http_ping_amiga.c new file mode 100644 index 0000000..023ba63 --- /dev/null +++ b/http_ping_amiga.c @@ -0,0 +1,98 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "version.h" + +#define OPEN_ERROR "Cannot open %s.\n" +#define OPEN_VER_ERROR "Cannot open %s (%d.0)\n" +#define DOSLIB_NAME "dos.library" +#define DOSLIB_REV 33L +#define BSDLIB_NAME "bsdsocket.library" +#define BSDLIB_REV 03L + +int CreateTimer(); +void DeleteTimer(); + +const char *vers = "\0$VER: " PACKAGE_NAME " " PACKAGE_VERSION " (" PACKAGE_DATE ")"; + +struct Library *DOSBase; +struct Library *SocketBase; + +void amiga_open_error(char *name) +{ + printf(OPEN_ERROR, name); +} + +void amiga_open_lib_error(char *name, int version) +{ + printf(OPEN_VER_ERROR, name, version); +} + +void close_libs() +{ + if (DOSBase != NULL) { + CloseLibrary(DOSBase); + DOSBase = NULL; + } + + if (SocketBase != NULL) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } +} + +int open_libs() +{ + atexit(close_libs); + + if(!(DOSBase = OpenLibrary((STRPTR)DOSLIB_NAME, DOSLIB_REV))) { + amiga_open_lib_error(DOSLIB_NAME, DOSLIB_REV); + return 5; + } + + if(!(SocketBase = OpenLibrary((STRPTR)BSDLIB_NAME, BSDLIB_REV))) { + amiga_open_lib_error(BSDLIB_NAME, BSDLIB_REV); + return 5; + } + + return 0; +} + +int gettimeofday(struct timeval *tv, struct timezone* tz) +{ + struct timeval tv1; + + if (CreateTimer() != 0) { + tv->tv_secs = 0; + tv->tv_micro = 0; + return -1; + } + + GetSysTime(&tv1); + *tv = tv1; + + DeleteTimer(); + return 0; +} + +void srandom(unsigned int x) { } + +#ifdef USE_SSL +int getuid() { return 55; } +void sigaction(int signum, void *act, void *oldact) { } +void tcgetattr(int fd, void *termios_p) { } +int tcsetattr(int fd, void *termios_p) { return 0; } +#endif diff --git a/include/clib/amitcp_protos.h b/include/clib/amitcp_protos.h new file mode 100644 index 0000000..856a082 --- /dev/null +++ b/include/clib/amitcp_protos.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#ifndef _SOCKET_AMITCP_H +#define _SOCKET_AMITCP_H +//--------------------------------------------------------------------------// +#define AMITCP_BASE_NAME SocketBase +#include "inline/amitcp.h" +//--------------------------------------------------------------------------// +#define socket Socket +#define bind Bind +#define listen Listen +#define accept Accept +#define connect Connect +#define send Send +#define sendto SendTo +#define sendmsg SendMsg +#define recv Recv +#define recvfrom RecvFrom +#define recvmsg RecvMsg +#define select Select +#define shutdown ShutDown +#define setsockopt SetSockOpt +#define getsockopt GetSockOpt +#define getsockname GetSockName +#define getpeername GetPeerName +#define inet_addr Inet_Addr +#define inet_network Inet_Network +#define inet_ntoa Inet_NtoA +#define gethostbyname GetHostByName +#define gethostbyaddr GetHostByAddr +#define getnetbyname GetNetByName +#define getnetbyaddr GetNetByAddr +#define getservbyname GetServByName +#define getservbyport GetServByPort +#define getprotobyname GetProtoByName +#define getprotobynumber GetProtoByNumber +#define getdtablesize GetDTableSize +#define gethostname GetHostName +#define gethostid GetHostId +#define vsyslog SyslogA +#define syslog Syslog +//--------------------------------------------------------------------------// +#define Accept TCP_Accept +#define Bind TCP_Bind +#define CloseSocket TCP_CloseSocket +#define Connect TCP_Connect +#define Dup2Socket TCP_Dup2Socket +#define Errno TCP_Errno +#define GetDTableSize TCP_GetDTableSize +#define GetHostByAddr TCP_GetHostByAddr +#define GetHostByName TCP_GetHostByName +#define GetHostId TCP_GetHostId +#define GetHostName TCP_GetHostName +#define GetNetByAddr TCP_GetNetByAddr +#define GetNetByName TCP_GetNetByName +#define GetPeerName TCP_GetPeerName +#define GetProtoByName TCP_GetProtoByName +#define GetProtoByNumber TCP_GetProtoByNumber +#define GetServByName TCP_GetServByName +#define GetServByPort TCP_GetServByPort +#define GetSockName TCP_GetSockName +#define GetSockOpt TCP_GetSockOpt +#define GetSocketEvents TCP_GetSocketEvents +#define Inet_Addr TCP_Inet_Addr +#define Inet_LnaOf TCP_Inet_LnaOf +#define Inet_MakeAddr TCP_Inet_MakeAddr +#define Inet_NetOf TCP_Inet_NetOf +#define Inet_Network TCP_Inet_Network +#define Inet_NtoA(x) TCP_Inet_NtoA((x).s_addr) +#define IoctlSocket TCP_IoctlSocket +#define Listen TCP_Listen +#define ObtainSocket TCP_ObtainSocket +#define Recv TCP_Recv +#define RecvFrom TCP_RecvFrom +#define RecvMsg TCP_RecvMsg +#define ReleaseCopyOfSocket TCP_ReleaseCopyOfSocket +#define ReleaseSocket TCP_ReleaseSocket +#define Send TCP_Send +#define SendMsg TCP_SendMsg +#define SendTo TCP_SendTo +#define SetErrnoPtr TCP_SetErrnoPtr +#define SetSockOpt TCP_SetSockOpt +#define SetSocketSignals TCP_SetSocketSignals +#define ShutDown TCP_ShutDown +#define Socket TCP_Socket +#define SocketBaseTagList TCP_SocketBaseTagList +#define SocketBaseTags TCP_SocketBaseTags +#define SyslogA TCP_SyslogA +#define WaitSelect TCP_WaitSelect +#define Select(n,r,w,e,t) TCP_WaitSelect(n,r,w,e,t,0) +//--------------------------------------------------------------------------// +#endif diff --git a/include/inline/amitcp.h b/include/inline/amitcp.h new file mode 100644 index 0000000..1ee4f30 --- /dev/null +++ b/include/inline/amitcp.h @@ -0,0 +1,203 @@ +/* Automatically generated header! Do not edit! */ + +#ifndef _INLINE_AMITCP_H +#define _INLINE_AMITCP_H + +#ifndef __INLINE_MACROS_H +#include +#endif /* !__INLINE_MACROS_H */ + +#ifndef AMITCP_BASE_NAME +#define AMITCP_BASE_NAME lss->lx_BsdSocketBase +#endif /* !AMITCP_BASE_NAME */ + +#define TCP_Accept(s, addr, addrlen) \ + LP3(0x30, LONG, TCP_Accept, LONG, s, d0, struct sockaddr *, addr, a0, int *, addrlen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_Bind(s, name, namelen) \ + LP3(0x24, LONG, TCP_Bind, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_CloseSocket(d) \ + LP1(0x78, LONG, TCP_CloseSocket, LONG, d, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Connect(s, name, namelen) \ + LP3(0x36, LONG, TCP_Connect, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Dup2Socket(fd1, fd2) \ + LP2(0x108, LONG, TCP_Dup2Socket, LONG, fd1, d0, LONG, fd2, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Errno() \ + LP0(0xa2, LONG, TCP_Errno, \ + , AMITCP_BASE_NAME) + +#define TCP_GetDTableSize() \ + LP0(0x8a, LONG, TCP_GetDTableSize, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostByAddr(addr, len, type) \ + LP3(0xd8, struct hostent *, TCP_GetHostByAddr, const UBYTE *, addr, a0, LONG, len, d0, LONG, type, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostByName(name) \ + LP1(0xd2, struct hostent *, TCP_GetHostByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostId() \ + LP0(0x120, ULONG, TCP_GetHostId, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostName(hostname, size) \ + LP2(0x11a, LONG, TCP_GetHostName, STRPTR, hostname, a0, LONG, size, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetNetByAddr(net, type) \ + LP2(0xe4, struct netent *, TCP_GetNetByAddr, LONG, net, d0, LONG, type, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetNetByName(name) \ + LP1(0xde, struct netent *, TCP_GetNetByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetPeerName(s, hostname, namelen) \ + LP3(0x6c, LONG, TCP_GetPeerName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetProtoByName(name) \ + LP1(0xf6, struct protoent *, TCP_GetProtoByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetProtoByNumber(proto) \ + LP1(0xfc, struct protoent *, TCP_GetProtoByNumber, LONG, proto, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetServByName(name, proto) \ + LP2(0xea, struct servent *, TCP_GetServByName, const UBYTE *, name, a0, const UBYTE *, proto, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetServByPort(port, proto) \ + LP2(0xf0, struct servent *, TCP_GetServByPort, LONG, port, d0, const UBYTE *, proto, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSockName(s, hostname, namelen) \ + LP3(0x66, LONG, TCP_GetSockName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSockOpt(s, level, optname, optval, optlen) \ + LP5(0x60, LONG, TCP_GetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, void *, optval, a0, int *, optlen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSocketEvents(eventmaskp) \ + LP1(0x12c, LONG, TCP_GetSocketEvents, ULONG *, eventmaskp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_Addr(cp) \ + LP1(0xb4, ULONG, TCP_Inet_Addr, const UBYTE *, cp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_LnaOf(in) \ + LP1(0xba, ULONG, TCP_Inet_LnaOf, LONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_MakeAddr(net, host) \ + LP2(0xc6, ULONG, TCP_Inet_MakeAddr, ULONG, net, d0, ULONG, host, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_NetOf(in) \ + LP1(0xc0, ULONG, TCP_Inet_NetOf, LONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_Network(cp) \ + LP1(0xcc, ULONG, TCP_Inet_Network, const UBYTE *, cp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_NtoA(in) \ + LP1(0xae, char *, TCP_Inet_NtoA, ULONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_IoctlSocket(d, request, argp) \ + LP3(0x72, LONG, TCP_IoctlSocket, LONG, d, d0, ULONG, request, d1, char *, argp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Listen(s, backlog) \ + LP2(0x2a, LONG, TCP_Listen, LONG, s, d0, LONG, backlog, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ObtainSocket(id, domain, type, protocol) \ + LP4(0x90, LONG, TCP_ObtainSocket, LONG, id, d0, LONG, domain, d1, LONG, type, d2, LONG, protocol, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_Recv(s, buf, len, flags) \ + LP4(0x4e, LONG, TCP_Recv, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_RecvFrom(s, buf, len, flags, from, fromlen) \ + LP6(0x48, LONG, TCP_RecvFrom, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, struct sockaddr *, from, a1, int *, fromlen, a2, \ + , AMITCP_BASE_NAME) + +#define TCP_RecvMsg(s, msg, flags) \ + LP3(0x114, LONG, TCP_RecvMsg, LONG, s, d0, struct msghdr *, msg, a0, LONG, flags, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ReleaseCopyOfSocket(fd, id) \ + LP2(0x9c, LONG, TCP_ReleaseCopyOfSocket, LONG, fd, d0, LONG, id, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ReleaseSocket(fd, id) \ + LP2(0x96, LONG, TCP_ReleaseSocket, LONG, fd, d0, LONG, id, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Send(s, msg, len, flags) \ + LP4(0x42, LONG, TCP_Send, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_SendMsg(s, msg, flags) \ + LP3(0x10e, LONG, TCP_SendMsg, LONG, s, d0, const struct msghdr *, msg, a0, LONG, flags, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_SendTo(s, msg, len, flags, to, tolen) \ + LP6(0x3c, LONG, TCP_SendTo, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, const struct sockaddr *, to, a1, LONG, tolen, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_SetErrnoPtr(errno_p, size) \ + LP2(0xa8, LONG, TCP_SetErrnoPtr, void *, errno_p, a0, LONG, size, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_SetSockOpt(s, level, optname, optval, optlen) \ + LP5(0x5a, LONG, TCP_SetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, const void *, optval, a0, LONG, optlen, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_SetSocketSignals(SIGINTR, SIGIO, SIGURG) \ + LP3NR(0x84, TCP_SetSocketSignals, ULONG, SIGINTR, d0, ULONG, SIGIO, d1, ULONG, SIGURG, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_ShutDown(s, how) \ + LP2(0x54, LONG, TCP_ShutDown, LONG, s, d0, LONG, how, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Socket(domain, type, protocol) \ + LP3(0x1e, LONG, TCP_Socket, LONG, domain, d0, LONG, type, d1, LONG, protocol, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_SocketBaseTagList(taglist) \ + LP1(0x126, LONG, TCP_SocketBaseTagList, struct TagItem *, taglist, a0, \ + , AMITCP_BASE_NAME) + +#ifndef NO_INLINE_STDARG +#define TCP_SocketBaseTags(tags...) \ + ({ULONG _tags[] = { tags }; TCP_SocketBaseTagList((struct TagItem *)_tags);}) +#endif + +#define TCP_SyslogA(level, format, ap) \ + LP3NR(0x102, TCP_SyslogA, ULONG, level, d0, const char *, format, a0, va_list, ap, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_WaitSelect(nfds, readfds, writefds, execptfds, timeout, maskp) \ + LP6(0x7e, LONG, TCP_WaitSelect, LONG, nfds, d0, fd_set *, readfds, a0, fd_set *, writefds, a1, fd_set *, execptfds, a2, struct timeval *, timeout, a3, ULONG *, maskp, d1, \ + , AMITCP_BASE_NAME) + +#endif /* !_INLINE_AMITCP_H */ diff --git a/port.h b/port.h new file mode 100644 index 0000000..3b2d7d1 --- /dev/null +++ b/port.h @@ -0,0 +1,122 @@ +/* port.h - portability defines */ + +#if defined(__FreeBSD__) +# define OS_FreeBSD +# define ARCH "FreeBSD" +#elif defined(__OpenBSD__) +# define OS_OpenBSD +# define ARCH "OpenBSD" +#elif defined(__NetBSD__) +# define OS_NetBSD +# define ARCH "NetBSD" +#elif defined(linux) +# define OS_Linux +# define ARCH "Linux" +#elif defined(sun) +# define OS_Solaris +# define ARCH "Solaris" +#elif defined(__osf__) +# define OS_DigitalUnix +# define ARCH "DigitalUnix" +#elif defined(__svr4__) +# define OS_SysV +# define ARCH "SysV" +#else +# define OS_UNKNOWN +# define ARCH "UNKNOWN" +#endif + +#ifdef OS_FreeBSD +# include +# define HAVE_DAEMON +# define HAVE_SETSID +# define HAVE_SETLOGIN +# define HAVE_WAITPID +# define HAVE_HSTRERROR +# define HAVE_TM_GMTOFF +# define HAVE_SENDFILE +# define HAVE_SCANDIR +# define HAVE_INT64T +# define HAVE_SRANDOMDEV +# ifdef SO_ACCEPTFILTER +# define HAVE_ACCEPT_FILTERS +# if ( __FreeBSD_version >= 411000 ) +# define ACCEPT_FILTER_NAME "httpready" +# else +# define ACCEPT_FILTER_NAME "dataready" +# endif +# endif /* SO_ACCEPTFILTER */ +#endif /* OS_FreeBSD */ + +#ifdef OS_OpenBSD +# define HAVE_DAEMON +# define HAVE_SETSID +# define HAVE_SETLOGIN +# define HAVE_WAITPID +# define HAVE_HSTRERROR +# define HAVE_TM_GMTOFF +# define HAVE_SCANDIR +# define HAVE_INT64T +#endif /* OS_OpenBSD */ + +#ifdef OS_NetBSD +# define HAVE_DAEMON +# define HAVE_SETSID +# define HAVE_SETLOGIN +# define HAVE_WAITPID +# define HAVE_HSTRERROR +# define HAVE_TM_GMTOFF +# define HAVE_SCANDIR +# define HAVE_INT64T +#endif /* OS_NetBSD */ + +#ifdef OS_Linux +# define HAVE_DAEMON +# define HAVE_SETSID +# define HAVE_WAITPID +# define HAVE_TM_GMTOFF +# define HAVE_SENDFILE +# define HAVE_LINUX_SENDFILE +# define HAVE_SCANDIR +# define HAVE_INT64T +#endif /* OS_Linux */ + +#ifdef OS_Solaris +# define HAVE_SETSID +# define HAVE_WAITPID +# define HAVE_MEMORY_H +# define HAVE_SIGSET +# define HAVE_INT64T +# define HAVE_RAND +#endif /* OS_Solaris */ + +#ifdef OS_DigitalUnix +# define HAVE_SETSID +# define HAVE_SETLOGIN +# define HAVE_WAITPID +# define HAVE_SCANDIR +# define HAVE_TM_GMTOFF +# define NO_SNPRINTF +/* # define HAVE_INT64T */ /* Digital Unix 4.0d doesn't have int64_t */ +#endif /* OS_DigitalUnix */ + +#ifdef OS_SysV +# define HAVE_SETSID +# define HAVE_WAITPID +# define HAVE_MEMORY_H +# define HAVE_SIGSET +# define HAVE_RAND +#endif /* OS_Solaris */ + +#ifdef HAVE_RAND +# define srandom srand +# define random rand +#endif /* HAVE_RAND */ + +#ifdef __AMIGA__ +# include +# include +# define alarm(x) ; +int open_libs(); +extern struct Library *SocketBase; +#endif diff --git a/time_timer.c b/time_timer.c new file mode 100644 index 0000000..bb0fe32 --- /dev/null +++ b/time_timer.c @@ -0,0 +1,72 @@ +//--------------------------------------------------------------------------// +// This file is in the public domain. // +//--------------------------------------------------------------------------// + +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#include +#include +#include + +struct Device* TimerBase; +struct MsgPort* TimerPort; +struct timerequest* TimeRequest; + +int CreateTimer() +{ + int error; + + TimerPort = CreateMsgPort(); + if (TimerPort == NULL) { + return 1; + } + + TimeRequest = (struct timerequest*)CreateIORequest( + TimerPort, + sizeof(struct timerequest) + ); + + if (TimeRequest == NULL) { + DeleteMsgPort(TimerPort); + return 2; + } + + error = OpenDevice( + (STRPTR)TIMERNAME, + UNIT_MICROHZ, + (struct IORequest*)TimeRequest, + 0 + ); + + if (error != 0) + { + DeleteIORequest((struct IORequest*)TimeRequest); + DeleteMsgPort(TimerPort); + return 3; + } + + TimerBase = (struct Device*)TimeRequest->tr_node.io_Device; + return 0; +} + +void DeleteTimer() +{ + if (TimeRequest != NULL) { + if (!CheckIO((struct IORequest*)TimeRequest)) { + WaitIO((struct IORequest*)TimeRequest); + } + + CloseDevice((struct IORequest*)TimeRequest); + DeleteIORequest((struct IORequest*)TimeRequest); + + TimeRequest = NULL; + } + + if (TimerPort != NULL) { + DeleteMsgPort(TimerPort); + TimerPort = NULL; + } +} diff --git a/version.h b/version.h new file mode 100644 index 0000000..ca69d76 --- /dev/null +++ b/version.h @@ -0,0 +1,3 @@ +#define PACKAGE_NAME "http_ping" +#define PACKAGE_VERSION "1.10" +#define PACKAGE_DATE "01.11.2015"