diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-05-03 15:15:24 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-05-03 15:15:24 +0000 |
commit | 0bb49aa2f14aeca9d32b11ee6bb61ed6b88a1718 (patch) | |
tree | b61b1c0ca4e65ceb0121dbea55268e8d74d95e44 /openwrt/package | |
parent | 4bc625906f5a03e861356c41fcf57477cbf66032 (diff) |
add ttcp utility
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@793 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'openwrt/package')
-rw-r--r-- | openwrt/package/Config.in | 1 | ||||
-rw-r--r-- | openwrt/package/Makefile | 1 | ||||
-rw-r--r-- | openwrt/package/ttcp/Config.in | 5 | ||||
-rw-r--r-- | openwrt/package/ttcp/Makefile | 31 | ||||
-rw-r--r-- | openwrt/package/ttcp/ttcp.c | 2374 | ||||
-rw-r--r-- | openwrt/package/ttcp/ttcp.control | 6 |
6 files changed, 2418 insertions, 0 deletions
diff --git a/openwrt/package/Config.in b/openwrt/package/Config.in index cec59679d..98a59f349 100644 --- a/openwrt/package/Config.in +++ b/openwrt/package/Config.in @@ -59,6 +59,7 @@ source "package/l2tpd/Config.in" source "package/tinc/Config.in" source "package/fprobe/Config.in" source "package/maradns/Config.in" +source "package/ttcp/Config.in" comment "Libraries" source "package/libpthread/Config.in" diff --git a/openwrt/package/Makefile b/openwrt/package/Makefile index 5560d4c3a..fec065e18 100644 --- a/openwrt/package/Makefile +++ b/openwrt/package/Makefile @@ -65,6 +65,7 @@ package-$(BR2_PACKAGE_SPEEX) += speex package-$(BR2_PACKAGE_STRACE) += strace package-$(BR2_PACKAGE_TCPDUMP) += tcpdump package-$(BR2_PACKAGE_TINC) += tinc +package-$(BR2_PACKAGE_TTCP) += ttcp package-$(BR2_PACKAGE_UCLIBCXX) += uclibc++ package-$(BR2_PACKAGE_USBUTILS) += usbutils package-$(BR2_PACKAGE_WIRELESS_TOOLS) += wireless-tools diff --git a/openwrt/package/ttcp/Config.in b/openwrt/package/ttcp/Config.in new file mode 100644 index 000000000..681ee2bf4 --- /dev/null +++ b/openwrt/package/ttcp/Config.in @@ -0,0 +1,5 @@ +config BR2_PACKAGE_TTCP + tristate "ttcp" + default m if CONFIG_DEVEL + help + A small utility to test TCP connection performance diff --git a/openwrt/package/ttcp/Makefile b/openwrt/package/ttcp/Makefile new file mode 100644 index 000000000..ec91ef735 --- /dev/null +++ b/openwrt/package/ttcp/Makefile @@ -0,0 +1,31 @@ +# $Id$ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=ttcp +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/ttcp +PKG_IPK_DIR:=$(PKG_BUILD_DIR) +PKG_IPK:=$(PACKAGE_DIR)/$(PKG_NAME)_$(PKG_RELEASE)_$(ARCH).ipk + +$(PKG_BUILD_DIR)/usr/bin/ttcp: + mkdir -p $(PKG_BUILD_DIR)/usr/bin + $(TARGET_CC) -o $@ ttcp.c + $(STRIP) $@ + +$(PKG_IPK): $(PKG_BUILD_DIR)/usr/bin/ttcp + $(SCRIPT_DIR)/make-ipkg-dir.sh $(PKG_IPK_DIR) $(PKG_NAME).control $(PKG_RELEASE) $(ARCH) + $(IPKG_BUILD) $(PKG_IPK_DIR) $(PACKAGE_DIR) + +$(IPKG_STATE_DIR)/info/$(PKG_NAME).list: + $(IPKG) install $(PKG_IPK) + +source: +prepare: +compile: $(PKG_IPK) +install: $(IPKG_STATE_DIR)/info/$(PKG_NAME).list + +clean: + rm -rf $(PKG_BUILD_DIR) + rm -f $(PKG_IPK) diff --git a/openwrt/package/ttcp/ttcp.c b/openwrt/package/ttcp/ttcp.c new file mode 100644 index 000000000..456209333 --- /dev/null +++ b/openwrt/package/ttcp/ttcp.c @@ -0,0 +1,2374 @@ +/* + * T T C P . C + * + * Test TCP connection. Makes a connection on port 5001 + * and transfers fabricated buffers or data copied from stdin. + * + * Usable on 4.2, 4.3, and 4.1a systems by defining one of + * BSD42 BSD43 (BSD41a) + * Machines using System V with BSD sockets should define SYSV. + * + * Modified for operation under 4.2BSD, 18 Dec 84 + * T.C. Slattery, USNA + * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85. + * Modified in 1989 at Silicon Graphics, Inc. + * catch SIGPIPE to be able to print stats when receiver has died + * for tcp, don't look for sentinel during reads to allow small transfers + * increased default buffer size to 8K, nbuf to 2K to transfer 16MB + * moved default port to 5001, beyond IPPORT_USERRESERVED + * make sinkmode default because it is more popular, + * -s now means don't sink/source + * count number of read/write system calls to see effects of + * blocking from full socket buffers + * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt) + * buffer alignment options, -A and -O + * print stats in a format that's a bit easier to use with grep & awk + * for SYSV, mimic BSD routines to use most of the existing timing code + * Modified by Steve Miller of the University of Maryland, College Park + * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF) + * Modified Sept. 1989 at Silicon Graphics, Inc. + * restored -s sense at request of tcs@brl + * Modified Oct. 1991 at Silicon Graphics, Inc. + * use getopt(3) for option processing, add -f and -T options. + * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV. + * + * Modified --> Nov 1996 at CERN (Daniel DAVIDS) + * printout of the Socket-Buffer-Sizes + * configured for HP-UX 9000 OS + * configured for Windows NT OS + * Modified Dec 1996 at CERN (Jacques ROCHEZ) + * severe cleanup + * addaptation to the gcc compiler (ANSI) + * configured for Lynx OS + * automatic format for the rate display (G/M/K/)bytes/sec + * added log (L) and more help (h) options. + * Modified May 1997 at CERN (Jacques ROCHEZ) + * removed the mes() function following err() function. + * changed the default port to 5010 + * Modified jul 1997 at CERN (Jacques ROCHEZ) + * adapted the timing calculation in microseconds + * addapted the code for Vsisual C++ under NT4.0 + * Modified aug 1997 at CERN (Jacques ROCHEZ) + * initialise to 0 the variables nbytes, numcalls + * moved the buffer pre-load outside the measured timed area + * Distribution Status - + * Public Domain. Distribution Unlimited. + * Modified jun 1998 at Epigram + * - print hash marks to indicate prograss on transmitting side + * - sleep between bursts of buffers + * - set number of buffers/burst + * Modified jul 1998 at Epigram + * - send random size buffers + * Modified jan 1999 at Epigram (WES) + * - added start and end patterns to UDP start and end packets + * - added handling of missed start, end, or data packets for UDP tests + */ +#ifndef lint +static char RCSid[] = "ttcp.c $- CERN Revision: 3.8 (dev level) -$"; +#endif + +static char VersDate[] = "Epigram 15-jul-98"; + +/* system dependent setting + * ------------------------ + * uname -a,gcc -v a.c are the tools used + * + * Platform/OS #define MACRO predefined + * ----------- ------- --------------------------------------------------- + * SunOS OS BSD43 __unix__ __sun__ __sparc__ + * SUN Solaris SYSV __unix__ __sun__ __sparc__ __svr4__ + * SGI-IRIX < 3.3 SYSV set as #define sgi + * HP-UX 9000 SYSV __unix__ __hpux__ __hp9k8__ + * OSF/1 V3.2 SYSV __unix__ __osf__ __alpha__ + * OSF/1 V4.0 SYSV __unix__ __osf__ __alpha__ _CFE + * LynxOS SYSV __unix__ __lynx__ __powerpc__ + * Windows NT SYSV __WINNT__ __i386__ __M_COFF__ + * AIX SYSV _AIX _AIX32 _POWER _IBMR2 _ARCH_PWR + + + * Micosoft Visual C++ compiler under WindowNT 4.0 + * Windows NT _WINDOWS WIN32 + + * Unix BSD 41a BSD41a + * 42 BSD42 + * 43 BSD43 + + * Machines using System V with BSD sockets should define SYSV. + * + * Compiler commands + * ----------------- + * LynxOS : gcc -c ttcp.c -o ttcp.o | gcc -o ttcp -O ttcp.o -lnetinet -lc_p -lc + */ + +/* -------------attempt to set an automatic UNIX OS family detection -------*/ + +#if defined(__hp9k8__) || defined(__osf__) || defined(__srv4__) +#define SYSV +#endif +#if defined(__lynx__) +#define SYSV +#endif +/* for solaris (__srv4__) the parameters SYSV is already set */ + +/* version A.09.01 'key words' differs from A.09.05 A */ +#if defined(__hpux) +#define __hpux__ +#endif + +#if defined(__sun__)&&!defined(__srv4__) +#define BSD43 /* changed by BSD42 if necessary */ +#endif + +#if defined(_WIN32) /* Window NT 4.0 compiled with VisualC++ 4 */ +#define __NTVIS__ +#define SYSV +#endif + +#if defined(__FreeBSD__) +#define BSD43 +#endif + +#if defined(__linux__) +#define BSD43 +#endif +/*--------------------------------------------------------------------------*/ + +#if !defined(UNDER_CE) +#include <signal.h> +#include <ctype.h> +#include <errno.h> +#include <sys/types.h> +#endif + +#if defined(SYSV) + +#if defined(__osf__) +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/time.h> /* struct timeval */ +#include <sys/resource.h> /* definition of struct rusage */ + +#else /* else of __osf__ */ +#if defined(__NTVIS__) +#include <winsock2.h> +#include <windows.h> /* required for all Windows applications */ +#include <ws2tcpip.h> +#include <memory.h> +#include <time.h> +#if !defined(UNDER_CE) +#include <sys\timeb.h> +#include <fcntl.h> +#endif +#include <stdlib.h> +#include <io.h> +struct rusage { struct timeval ru_utime, ru_stime; }; +#define RUSAGE_SELF 0 +#else /* else of __NTVIS__ */ +#if defined(__lynx__) +#include <socket.h> /* located in /usr/include/..... */ +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <time.h> +#include <resource.h> /* definition of struct rusage */ +#include <sys/times.h> +#define RUSAGE_SELF 0 +#include <conf.h> /* definition of TICKSPERSEC (HZ) */ +#include <sys/param.h> + +#else /* else of __Lynx__ */ +#if defined(__svr4__) +#include <sys/socket.h> +#include <sys/uio.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/time.h> /* struct timeval */ +#include <sys/resource.h> /* definition of struct rusage */ +#include <sys/times.h> +#define RUSAGE_SELF 0 +#include <sys/param.h> + +#else /* else of __svr4__ all SYSV cases except those mentionned before */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/time.h> /* struct timeval */ +#include <sys/resource.h> /* definition of struct rusage */ +#include <sys/times.h> +#define RUSAGE_SELF 0 +#include <sys/param.h> + +#endif /* __svr4__ */ +#endif /* __lynx__ */ +#endif /* __NTVIS__ */ +#endif /* __osf__ */ + +#else /* else of SYSV it is a BSD OS */ +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#if defined(__linux__) +#include <time.h> /* struct timeval */ +#else +#include <sys/time.h> /* struct timeval */ +#endif +#include <sys/resource.h> /* definition of struct rusage */ +#include <unistd.h> /* for usleep() - henry */ +#define SOCKET_ERROR -1 + +#endif /* SYSV */ + +#if defined(__NTVIS__) + +#if defined(_DEBUG) /* usual debug symbol for VC++ */ +#define DEBUG 1 +#endif + +void usleep(unsigned int microseconds); + +#define bcopy(a,b,n) memcpy((b), (a), (n)) +#define bzero(a,n) memset((a), 0, (n)) + +#ifndef _GETOPT_ +#define _GETOPT_ +int getopt(int argc, char **argv, char *optstring); + +extern char *optarg; // returned arg to go with this option +extern int optind; // index to next argv element to process +extern int opterr; // should error messages be printed? +extern int optopt; // + +#define BADCH ('?') +#endif // _GETOPT + +/* get option letter from argument vector */ +int + opterr = 1, // should error messages be printed? + optind = 1, // index into parent argv vector + optopt; // character checked for validity +char *optarg; // argument associated with option + +#define EMSG "" +char *progname; // may also be defined elsewhere +#endif /*__NTVIS__*/ + +/* sockaddr_in == file server address structure + * + * Socket address, internet style. declared in : /netinet/in.h + * struct sockaddr_in {short sin_family; + * u_short sin_port; + * struct in_addr sin_addr; + * char sin_zero[8]; + * }; + * + * Structure used by kernel to store most addresses. declared in ./sys/socket.h + * struct sockaddr{u_short sa_family; address family + * char sa_data[14]; up to 14 bytes of direct address + * }; + * PS : sin stand for "socket internet number" + */ + +#ifndef __NTVIS__ +#define FAR +#endif + +#if defined(__CONST_SOCKADDR_ARG) +#define SOCKADDR_CAST (__CONST_SOCKADDR_ARG) +#elif defined(__lynx__) || defined(__sun__) || defined(_AIX) || defined(__FreeBSD__) || defined(__NTVIS__) +#define SOCKADDR_CAST (struct sockaddr FAR *) +#else +#define SOCKADDR_CAST +#endif + +#if defined(__sun__) +struct sockaddr_in sockaddr; /* done in ./X11/Xdmcp.h */ +#endif + +struct sockaddr_in sinme; /* is the socket struct. in the local host */ +struct sockaddr_in sinhim; /* is the socket struc. in the remote host */ + +#if defined(__lynx__) || defined(__svr4__) || defined(_AIX) +struct sockaddr frominet; +#else +struct sockaddr_in frominet; +#endif /* __lynx__ */ + +int domain, fromlen; + +#if !defined(__NTVIS__) +#define SOCKET int +#endif /* __NTVIS__ */ +SOCKET fd; /* fd of network socket */ + +#if !defined(__lynx__) +extern int errno; +#endif + +#include <stdio.h> + +FILE *fplog = NULL; /* file pointer for the log file */ +char logfile[100]; /* file name for the log */ +static char logfile_head[] ="ttcp_log"; /* header name for the log */ +int buflen = 8 * 1024; /* length of buffer */ +char *buf; /* ptr to dynamic buffer */ +int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */ + +#define START_PKT_LEN 4 +#define START_PATTERN_LEN 4 +#define END_PKT_LEN 8 +#define END_PATTERN_LEN 4 +#define MIN_UDP_LEN 5 + +char start_pattern[START_PATTERN_LEN] = {1, 2, 3, 4}; +char end_pattern[END_PATTERN_LEN] = {2, 2, 2, 2}; + +int bufoffset = 0; /* align buffer to this */ +int bufalign = 16*1024; /* modulo this */ + +int udp = 0; /* 0 = tcp, !0 = udp */ +int options = 0; /* socket options */ +int one = 1; /* for 4.3 BSD style setsockopt() */ +short port = 5010; /* TCP port number */ +char *host; /* ptr to name of host */ +int rndm = 0; /* 0="normal", !0=random data */ +int trans; /* 0=receive, !0=transmit mode */ +int timeout; /* read timeout in millisec */ +int debug = 0; /* 0=No-Debug, 1=Debug-Set-On */ +int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */ +int verbose = 0; /* 0=print basic info, 1=print cpu rate, + * proc resource usage. */ +int nodelay = 0; /* set TCP_NODELAY socket option */ +int pri = 0; /* link layer priority */ +int b_flag = 0; /* use mread() */ +int log_cnt = 0; /* append result to a log */ +int sockbufsize = 0; /* socket buffer size to use */ +char fmt = 'A'; /* output format: + * b = bits, B = bytes, + * k = kilobits, K = kilobytes, + * m = megabits, M = megabytes, + * g = gigabits, G = gigabytes, + * A = automatic Xbytes (default) */ +int touchdata = 0; /* access data after reading */ +int seq_info = 0; /* report out of order seq nums */ + +int hash = 0; /* print hash marks for each buffer */ +int udpsleep = 0; /* sleep in between udp buffers */ +int burstn = 1; /* number of buffers per burst */ +int bufmin = -1; /* minimum buffer size to use when + sending random-size buffers */ +unsigned int seed = 1; /* seed for random number generator + used for random buffer lengths */ +int no_start = 0; /* skip the start frames for UDP */ +int no_data = 0; /* skip all data frames for UDP */ +int no_end = 0; /* skip the end frames for UDP */ + +double nbytes; /* bytes on net */ +unsigned long numCalls; /* # of I/O system calls */ + +struct hostent *addr; +extern int optind; +extern char *optarg; + +#if defined(UNDER_CE) +static int errno; +static char *weekday[] ={"Sun", "Mon","Tues", "Wed", "Thurs", "Fri", "Sat"}; +static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "July", "Aug", "Sep", "Oct", "Nov", "Dec"}; +#define perror printf +#endif + +/*--------------------------------------------------------------------------*/ +static struct timeval time0; /* Time at which timing started */ +static struct timeval time1; +static struct rusage ru0; /* Resource utilization at the start */ +static struct rusage ru1; +static struct tm *tms; /* system time structure */ + + +/*-----------Prototype functions definitions -------------------------------*/ +/*--------------------------------------------------------------------------*/ + + /* ANSI input/output functions (stdio.h) */ + +#if defined(__lynx__) +int getopt(int, char**, char*); +int gettimeofday(struct timeval *tp, struct timezone *tzp); + +#else +#if defined(__svr4__) + +#else +#if defined(_AIX) + +#else +#if defined(__hpux__) +#else +#if defined(__NTVIS__) +#else +#if defined(BSD42) || defined(BSD43) +#else + +int printf( char*, ...); +int fprintf(FILE*,char*, ...); +void perror(char*); +int getopt(int, char**, char*); +int gettimeofday(struct timeval *tp, struct timezone *tzp); +#endif /* BSD42 || BSD43 */ +#endif /* __NTVIS__ */ +#endif /* __hpux__ */ +#endif /* _AIX */ +#endif /* __svr4__ */ +#endif /* __lynx__ */ + +int main(int argc, char* argv[]); +#if ( (!(defined(BSD42))) && (!(defined(BSD43))) && (!(defined(__NTVIS__))) ) +int read(int, char*, int); +int write(int, char*, int); +int close(int); +#endif /* !(BSD42) && !(BSD43) */ +int fclose(FILE *stream); + +#if !defined(BSD43) && !defined(__NTVIS__) +void bzero(char*,int); +void bcopy(char*, char*, int); +char strncpy(char *s1,char *s2,size_t n); +int atoi(char*); +int malloc(int); +#endif + + + /* ANSI socket functions prototype /sys/socket.h */ +#if defined(__lynx__) +int select(int, fd_set*, fd_set*, fd_set*, struct timeval*); + +#else +#if defined(__svr4__) && !defined(sparc) + +/* informations in : /usr/include/sys/socket.h */ +int socket(int, int, int); +int connect(int, struct sockaddr *, int); +int bind(int, struct sockaddr *, int); +int listen(int, int); +int accept(int, struct sockaddr *, int *); +int sendto(int, const char *, int, int, const struct sockaddr *, int); +int recvfrom(int, char *, int, int, struct sockaddr *, int *); +int getpeername(int, struct sockaddr *, int *); +int getsockopt(int, int, int, char *, int *); +int select(int, fd_set*, fd_set*, fd_set*, struct timeval*); + +#else +#if defined(_AIX) +int select(unsigned long, void *, void *, void *, struct timeval *); + +#else +#if defined(__hpux__) +int getrusage(int who,struct rusage *rusage); + +#else +#if defined(__NTVIS__) + +#else +#if defined(BSD42) || defined(BSD43) + +#else + +int socket(int, int, int); +int connect(int s,struct sockaddr_in *name, int namelen); +int bind(int s,struct sockaddr *name,int namelen); +int listen(int, int); +int accept(int, struct sockaddr_in *, int *); +int sendto(int, char *, int, int, struct sockaddr_in *, int); +int recvfrom(int, char *, int, int, struct sockaddr_in *, int *); +int getpeername(int, struct sockaddr *, int *); +int setsockopt(int, int, int, char *, int); + +int getsockopt(int, int, int, char*, int*); +int select(int, fd_set*, fd_set*, fd_set*, struct timeval*); + +#endif /* BSD42 || BSD43 */ +#endif /* __hpux__ */ +#endif /* _AIX */ +#endif /* __svr4__ */ +#endif /* __lynx__ */ +#endif /* __NTVIS__ */ + +/* ttcp prototype functions */ +void udp_rcv_test(void); +double calc_cpu_time(struct rusage *r0, struct rusage *r1); +double calc_real_time(struct timeval *t0, struct timeval *t1); +int getrusage(int who,struct rusage *rusage); +void sockets_err(char*); +void err(char *); +void mes(char *); +void pattern(char *, int); +int Nread(SOCKET, void *, int); +int Nwrite(int, void *, int); +void delay(int); +int mread(int, char *,unsigned); +char *outfmt(char format, double b); +void prep_timer(void); +void read_timer(void); +void result_summary(void); +void prusage(struct rusage*, struct rusage*, + struct timeval*, struct timeval*); +void tvadd(struct timeval *tsum, struct timeval *t0,struct timeval *t1); +void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0); +void psecs(int); +void open_log(void); +void close_log(void); +void do_Usage(void); +void do_help(void); + +/*--------------------------------------------------------------------------*/ +#if !defined(__NTVIS__) +void +sigpipe() +{; +} +#endif +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + unsigned long addr_tmp; + int c,k; + int sockbufsndsize,sockbufrcvsize; + int sockbuflen; + struct sockaddr_in peer; + int peerlen = sizeof(peer); + +#if defined(__NTVIS__) + extern char *optarg; + WSADATA WSAData; + WSAStartup(MAKEWORD(1,1), &WSAData); +#endif /* __NTVIS__ */ + + if (argc < 2) { do_Usage(); exit(1); } + + while (1) { + while ((c=getopt(argc, argv, "hidrstuvxHVBDTLb:f:l:n:p:A:O:S:N:P:R:I:w:")) != -1) { + switch (c) { + case 'w': + timeout = atoi(optarg); + break; + case 'I': + seed = atoi(optarg); + break; + case 'N': + burstn = atoi(optarg); + break; + case 'P': +#if defined(__linux__) + pri = atoi(optarg); + break; +#else + fprintf(stderr, "ttcp: -P option not supported on this OS\n"); + exit(1); +#endif + case 'R': + bufmin = atoi(optarg); + break; + case 'S': + udpsleep = atoi(optarg); + if (udpsleep < 0) udpsleep = 0; + /* convert msec arg to usec for usleep, minimum 10ms */ + udpsleep = udpsleep * 1000; + break; + case 'H': + hash = 1; + break; + case 'V': + fprintf(stdout,"%s %s\n" , RCSid , VersDate ); + exit(0); + case 'B': + b_flag = 1; + break; + case 'L': + log_cnt = 1; + break; + case 'h': + do_help(); + exit(1); + break; + case 't': + trans = 1; + break; + case 'r': + trans = 0; + break; + case 'x': + rndm = 1; + break; + case 'd': + options |= SO_DEBUG; + break; + case 'D': +#ifdef TCP_NODELAY + nodelay = 1; +#else + fprintf(stderr, + "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n"); +#endif + break; + case 'n': + nbuf = atoi(optarg); + break; + case 'l': + buflen = atoi(optarg); + break; + case 's': + sinkmode = !sinkmode; + break; + case 'p': + port = atoi(optarg); + break; + case 'u': + udp = 1; + break; + case 'v': + verbose = 1; + break; + case 'A': + bufalign = atoi(optarg); + break; + case 'O': + bufoffset = atoi(optarg); + break; + case 'b': +#if defined(SO_SNDBUF) || defined(SO_RCVBUF) + sockbufsize = atoi(optarg); +#else + fprintf(stderr, +"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n"); +#endif + break; + case 'f': + fmt = *optarg; + break; + case 'T': + touchdata = 1; + break; + case 'i': + seq_info = 1; + break; + + default: + {do_Usage(); exit(1);} + }/*switch */ + }/* while getopt() */ + + argc -= optind; + argv += optind; + optind = 0; + + /* check for '--' args */ + if (argc == 0) { + /* no more args */ + break; /* while (1) */ +#if defined(DEBUG) + } else if (!strcmp(argv[0], "--nostart")) { + no_start = 1; + argc--; argv++; + } else if (!strcmp(argv[0], "--nodata")) { + no_data = 1; + argc--; argv++; + } else if (!strcmp(argv[0], "--noend")) { + no_end = 1; + argc--; argv++; + } else if (!strcmp(argv[0], "--debug")) { + debug = 1; + argc--; argv++; +#endif /* DEBUG */ + } else if (!strncmp(argv[0], "--", 2)) { + fprintf(stderr, "ttcp: illegal option: %s\n", argv[0]); + do_Usage(); exit(1); + } else { + /* the arg was not a '--' arg */ + break; /* while (1) */ + } + } /* while (1) */ + + + /* ----------------------- main part ----------------------- */ + +#if defined(__NTVIS__) && !defined(UNDER_CE) + /* Set "stdin" to have binary mode: */ + if (_setmode(_fileno(stdin), _O_BINARY) == -1) + perror("%s: Error setting stdin to binary mode"); + /* Set "stdout" to have binary mode: */ + if (_setmode(_fileno(stdout), _O_BINARY) == -1) + perror("%s: Error setting stdout to binary mode"); +#endif /* __NTVIS__ */ + +if (log_cnt) open_log(); + +/* input error checking */ +if (burstn > nbuf) { + fprintf(stderr, "ttcp: buffers per burst must be less than or equal to " + "total number of buffers\n"); + exit(1); +} +if (bufmin < -1) { + fprintf(stderr, "ttcp: minimum buffer size specified with -R option must " + "be non-negative\n"); + exit(1); +} +if (buflen > 65535) { + fprintf(stderr, "ttcp: maximum buffer size specified with -l option must " + "be <= 65536\n"); + exit(1); +} +if (bufmin > buflen) { + fprintf(stderr, "ttcp: minimum buffer size specified with -R option must " + "be less than or equal to (maximum) buffer size specified with -l\n"); + exit(1); +} + +/* buffer allocation */ + + if (udp && buflen < MIN_UDP_LEN) + buflen = MIN_UDP_LEN; /* send more than the sentinel size */ + + if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL) + err("malloc"); + if (bufalign != 0) + buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign; + + fprintf(stderr,"ttcp%s: buflen=%d, nbuf=%d, align=%d/%d, port=%d\n", + trans?"-t":"-r",buflen, nbuf, bufalign, bufoffset, port); + if (log_cnt)fprintf(fplog," %6d %6d %6d %6d %4d", + buflen, nbuf, bufalign, bufoffset, port); + + /* preload the buffer for the transmit condition */ + pattern( buf, buflen ); + + /* seed the random number generator */ + if ((bufmin != -1) || (rndm != 0)) { +#if defined(__NTVIS__) + srand(seed); +#else /* ! __NTVIS__ */ + srandom(seed); +#endif /* __NTVIS__ */ + } + + if(trans) + {/* xmitr */ + if (argc == 0) { + fprintf(stderr, "ttcp: missing destination host arg\n"); + do_Usage(); exit(1); + } + + bzero((char *)&sinhim, sizeof(sinhim)); + host = argv[0]; + if (atoi(host) > 0 ) + {/* Numeric */ + sinhim.sin_family = AF_INET; + sinhim.sin_addr.s_addr = inet_addr(host); + } + else + {if ((addr=gethostbyname(host)) == NULL) sockets_err("bad hostname"); + sinhim.sin_family = addr->h_addrtype; + bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length); + sinhim.sin_addr.s_addr = addr_tmp; + } + sinhim.sin_port = htons(port); + sinme.sin_port = 0; /* free choice */ + } + else + {/* rcvr */ + sinme.sin_port = htons(port); + } +#if defined(__NTVIS__) + sinme.sin_family = AF_INET; +#endif + + fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0); + +#if defined(__NTVIS__) + if (fd == INVALID_SOCKET) sockets_err("socket"); +#else + if (fd < 0) sockets_err("socket"); +#endif + + if (verbose) { + char *label = trans?"ttcp-t":"ttcp-r"; +#if defined(UNDER_CE) + SYSTEMTIME SystemTime; + char time_str[30]; + + GetLocalTime(&SystemTime); + sprintf(time_str, "%s %s %d %02d:%02d:%02d %d\n", weekday[SystemTime.wDayOfWeek], month[SystemTime.wMonth - 1], + SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wYear); +#else + time_t now; + char *time_str; + + time(&now); + time_str = ctime(&now); +#endif + fprintf(stdout,"%s: start time %s", label, time_str); + fprintf(stdout,"%s: File-Descriptor 0x%x Opened\n", label, fd ); + } + +#if defined(__NTVIS__) + if (bind(fd, (struct sockaddr FAR *)&sinme, sizeof(sinme)) == SOCKET_ERROR) + sockets_err("bind"); +#else + if (bind(fd, SOCKADDR_CAST &sinme, sizeof(sinme)) < 0) + sockets_err("bind"); +#endif /* __NTVIS__ */ + + +#if defined(SO_SNDBUF) || defined(SO_RCVBUF) + if (sockbufsize) + { +#if defined(__lynx__) || defined(__sun__) || defined(__NTVIS__) + if (trans) + {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, + sizeof sockbufsize) < 0) + sockets_err("setsockopt: sndbuf"); + } + else + {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, + sizeof sockbufsize) < 0) + sockets_err("setsockopt: rcvbuf"); + } + +#else + if (trans) + + {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, + sizeof sockbufsize) < 0) + sockets_err("setsockopt: sndbuf"); + } + else + {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize, + sizeof sockbufsize) < 0) + sockets_err("setsockopt: rcvbuf"); + } +#endif /* __lynx__ __sun__ __NTVIS__ */ + } + else + {/* + ** Added by Daniel Davids to Know Socket-Buffer-Sizes + */ + sockbuflen = sizeof sockbufsndsize; +#if defined(__lynx__) || defined(__sun__) || defined(__NTVIS__) + getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsndsize, + &sockbuflen); + sockbuflen = sizeof sockbufrcvsize; + getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufrcvsize, + &sockbuflen); +#else + getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsndsize, &sockbuflen); + sockbuflen = sizeof sockbufrcvsize; + getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufrcvsize, &sockbuflen); +#endif /* __lynx__ __sun__ __NTVIS__ */ + sockbufsize = ( sockbufsndsize + sockbufrcvsize ) / 2; + + if ( sockbufsndsize != sockbufrcvsize ) + {fprintf(stderr, "sockbufsndsize=%d, ", sockbufsndsize ); + fprintf(stderr, "sockbufrcvsize=%d, ", sockbufrcvsize ); + } + } +#endif /* defined(SO_SNDBUF) || defined(SO_RCVBUF) */ + + if (sockbufsize) fprintf(stderr, "sockbufsize=%d, \n", sockbufsize); + + if (log_cnt) + {if (sockbufsize)fprintf(fplog," %6d",sockbufsize); + else fprintf(fplog," 0"); + } + +#if defined(__linux__) + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&pri, sizeof pri) < 0) + sockets_err("setsockopt: priority"); +#endif + + + if (trans) fprintf(stderr, "# %s sender -> %s #\n", udp?"udp":"tcp", host); + else fprintf(stderr, "# %s receiver #\n", udp?"udp":"tcp"); + + if (!udp) + { +#if !defined(__NTVIS__) + signal(SIGPIPE, sigpipe); +#endif /* !__NTVIS__ */ + + if (trans) + {/* We are the client if transmitting */ + if (options) + { +#if defined(BSD42) + if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0) +#else /* BSD43 */ + if( setsockopt(fd, SOL_SOCKET, options, (char *)&one, sizeof(one)) < 0) +#endif /* BDS42 */ + sockets_err("setsockopt"); + } +#ifdef TCP_NODELAY + if (nodelay) + {struct protoent *p; + p = getprotobyname("tcp"); +#if defined(__lynx__) || defined(__sun__) || defined(__NTVIS__) + if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, + (char *) &one, sizeof(one)) < 0) +#else + if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, + &one, sizeof(one)) < 0) +#endif /* __lynx__ __sun__ __NTVIS__ */ + sockets_err("setsockopt: nodelay"); + } +#endif /* TCP_NODELAY */ + if (connect(fd, SOCKADDR_CAST &sinhim, sizeof(sinhim) ) < 0) + sockets_err("connect"); + }/* if (trans) */ + else + {/* otherwise, we are the server and should listen for connections */ + +errno = 0; + +#if defined(sgi) || ( defined(__osf__) && !defined(_CFE) ) + if( listen(fd,1) <0 ) +#else + if( listen(fd,0) <0 ) /* allow a queue of 0 */ +#endif + sockets_err("listen"); + + if(options) { + int err; +#if defined(BSD42) + err = setsockopt(fd, SOL_SOCKET, options, 0, 0); +#elif defined(__lynx__) || defined(__sun__) || defined(__NTVIS__) + err = setsockopt(fd, SOL_SOCKET, options, (char *) &one, sizeof(one)); +#else + err = setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)); +#endif /* BSD42 */ + if (err < 0) + sockets_err("setsockopt"); + } + fromlen = sizeof(frominet); + domain = AF_INET; + if (timeout > 0) { + fd_set readfds, exceptfds; + struct timeval tv_timeout; + int n; + + tv_timeout.tv_sec = timeout/1000; + tv_timeout.tv_usec = (timeout%1000)*1000; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(fd, &readfds); + FD_SET(fd, &exceptfds); + + n = select( fd+1, &readfds, NULL, &exceptfds, &tv_timeout ); + if (n == 0 || n == SOCKET_ERROR) { + sockets_err("select listen"); + return 0; + } + } + if((fd=accept(fd, SOCKADDR_CAST &frominet, &fromlen) ) < 0) + sockets_err("accept"); + + if (getpeername(fd, SOCKADDR_CAST &peer, &peerlen) < 0) + sockets_err("getpeername"); + + fprintf(stderr,"ttcp-r: accept from %s\n",inet_ntoa(peer.sin_addr)); + + } /* otherwise we are ... */ + } + + prep_timer(); + errno = 0; + nbytes = 0.0; + numCalls = 0; + + { + register int cnt,multi; + char *pb; + int nb = 0; + unsigned long rbuflen = 0; + multi = nbuf; + + if (trans) { +#if !defined(BSD43) + if(udp) { + int err; + int nochecksum_opt = 0; + err = setsockopt(fd, IPPROTO_UDP, UDP_NOCHECKSUM, + (char *)&nochecksum_opt, sizeof(nochecksum_opt)); + if (err < 0) + sockets_err("setsockopt"); + } +#endif + + if(udp && !no_start) { + int start_count = 2; + char start_pkt[START_PKT_LEN]; + memset(start_pkt, 0, START_PKT_LEN); + memcpy(start_pkt, start_pattern, START_PATTERN_LEN); + + while (start_count-- > 0) { + (void)Nwrite( fd, start_pkt, START_PKT_LEN ); /* rcvr start */ + if (udpsleep) { + usleep(udpsleep); + /* clear errno (see man page for errno(3), definition of + EINTR. usleep() uses SIGCONT? ) */ + if (errno == EINTR) errno = 0; + } /* udpsleep */ + } + } + + /* initial seqence num for UDP */ + if (udp) buf[0] = 0; + k = burstn; + + if (sinkmode) { + while (multi-- > 0 && !no_data) { + + if (bufmin == -1) { + rbuflen = buflen; + } else { + /* set rbuflen to a random value evenly distributed in + [bufmin, buflen]. As long as buflen is < 2^16, we can + fit the calculation in 32 bits */ +#if defined(__NTVIS__) + rbuflen = (( (unsigned long)rand() * + ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin; +#else /* ! __NTVIS__ */ + rbuflen = (( ((unsigned long)random() >> 15) * + ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin; +#endif /* __NTVIS__ */ + } + + if (rndm) { + unsigned int i, j, l; + unsigned long data; + + if (udp) + l = 1; + else + l = 0; + + for (i = l; i < rbuflen; /* null */) { +#if defined(__NTVIS__) + data = (unsigned long)rand(); +#else /* ! __NTVIS__ */ + data = (unsigned long)random(); +#endif /* __NTVIS__ */ + /*fprintf(stderr, "%08x\n",data);*/ /* DEBUG */ + /* The NT rand() function returns only 16 useful bits! */ + for (j = 0; (j < 2/*4*/) && (i < rbuflen) ; j++) { + buf[i++] = (unsigned char)(data & 0xff); + data >>= 8; + } + } + } + + if ((cnt=Nwrite(fd,buf,rbuflen)) != (int)rbuflen) + sockets_err("error from the socket write"); + /* increment sequence num if UDP */ + if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF); + + if (debug) + fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n", + ++nb, cnt, nbuf ); + + nbytes += rbuflen; + + /* hashes */ + if (hash) { + fprintf(stderr,"#"); + } + + /* Check for the end of a burst */ + if (--k <= 0) { + k = burstn; + + /* sleep to avoid overrunning slower receivers - henry */ + if (udpsleep) { + usleep(udpsleep); + /* clear errno (see man page for errno(3), definition of + EINTR. usleep() uses SIGCONT? ) */ + if (errno == EINTR) errno = 0; + } /* udpsleep */ + } + } /* while */ + + } /* if (sinkmode) */ + else + { + + nbuf = 0; + + if (bufmin == -1) { + rbuflen = buflen; + } else { + /* set rbuflen to a random value evenly distributed in + [bufmin, buflen]. As long as buflen is < 2^16, we can + fit the calculation in 32 bits */ +#if defined(__NTVIS__) + rbuflen = (( (unsigned long)rand() * + ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin; +#else /* ! __NTVIS__ */ + rbuflen = (( ((unsigned long)random() >> 15) * + ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin; +#endif /* __NTVIS__ */ + } + + if (udp) + pb = &(buf[1]); + else + pb = &(buf[0]); + +#if !defined(__NTVIS__) /* else case specific to WINNT */ + while((cnt=read(0,pb,rbuflen)) > 0) +#else /* __NTVIS__ */ + while((cnt=(int)fread(pb,1,rbuflen,stdin)) > 0) +#endif /* __NTVIS__ */ + { + + if (udp) + multi = cnt+1; /* don't include seq. num. in count of data */ + else + multi = cnt; + if ((cnt=Nwrite(fd,buf,multi)) != (int)multi) + sockets_err("error from the socket write"); + /* increment seqence num if UDP */ + if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF); + nbuf++; + + if (debug) + fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n", + ++nb, cnt, nbuf ); + + nbytes += multi; + + /* hashes */ + if (hash) { + fprintf(stderr,"#"); + } + + /* Check for the end of a burst */ + if (--k <= 0) { + k = burstn; + + /* sleep to avoid overrunning slower receivers - henry */ + if (udpsleep) { + usleep(udpsleep); + /* clear errno (see man page for errno(3), definition of + EINTR. usleep() uses SIGCONT? ) */ + if (errno == EINTR) errno = 0; + } /* udpsleep */ + } + + if (bufmin == -1) { + rbuflen = buflen; + } else { + /* set rbuflen to a random value evenly distributed in + [bufmin, buflen]. As long as buflen is < 2^16, we can + fit the calculation in 32 bits */ +#if defined(__NTVIS__) + rbuflen = (( (unsigned long)rand() * + ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin; +#else /* ! __NTVIS__ */ + rbuflen = (( ((unsigned long)random() >> 15) * + ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin; +#endif /* __NTVIS__ */ + } + + } /* while */ + + } /* if (sinkmode) */ + + if (hash) { + fprintf(stderr,"\n"); + fflush(stderr); + } + +#if defined(UNDER_CE) + errno = WSAGetLastError(); +#endif + if (!errno) { + read_timer(); + if(udp && !no_end) { + int end_count = 4; + int data_count = nbuf; + char end_pkt[END_PKT_LEN]; + unsigned char* net_byte = &end_pkt[END_PATTERN_LEN]; + memset(end_pkt, 0, END_PKT_LEN); + memcpy(end_pkt, end_pattern, END_PATTERN_LEN); + net_byte[3] = data_count & 0xFF; data_count >>= 8; + net_byte[2] = data_count & 0xFF; data_count >>= 8; + net_byte[1] = data_count & 0xFF; data_count >>= 8; + net_byte[0] = data_count & 0xFF; + + while (end_count-- > 0) { + Nwrite( fd, end_pkt, END_PKT_LEN ); /* rcvr end */ + if (udpsleep && end_count>0) usleep(udpsleep); + } + } + result_summary(); + } + } /* trans */ + else + { + if (udp) { + udp_rcv_test(); + } + else + {/* not udp received transfer */ + while ((cnt=Nread(fd,buf,buflen)) > 0) + {if(debug)fprintf(stdout, + "ttcp%s: %5d | %d Bytes Read\n", + trans?"-t":"-r", ++nb, cnt ); + nbytes += cnt; + if (!sinkmode) { +#if !defined(__NTVIS__) /* else case specific to WINNT */ + if (write(1,buf,cnt) != cnt) err("write"); +#else /* __NTVIS__ */ + if ((int)fwrite(buf,1,cnt,stdout) != cnt) err("fwrite"); +#endif /* __NTVIS__ */ + } + } +#if defined(UNDER_CE) + errno = WSAGetLastError(); +#endif + if (!errno) { + read_timer(); + result_summary(); + } + } + } + } + + if(errno) err("IO"); + +#if defined(__NTVIS__) + closesocket ( fd ); +#else + close ( fd ); +#endif /* __NTVIS__ */ + + if (verbose) fprintf(stdout,"ttcp%s: File-Descriptor fd 0x%x Closed\n" , + trans?"-t":"-r", fd ); + + if (log_cnt) close_log(); + + fprintf(stderr,"ttcp done.\n"); + fflush(stdout); + + exit(0); +} +/*--------------------------------------------------------------------------*/ +void +udp_rcv_test(void) +{ + enum {START_WAIT, DATA_WAIT, DATA_RCV, END_TEST} rcv_state; + enum {START_PKT_TYPE, END_PKT_TYPE, DATA_PKT_TYPE} pkt_type; + int cnt; + int nbuffers = 0; + unsigned int start_pkt_cnt = 0; + unsigned int end_pkt_cnt = 0; + unsigned int data_pkt_cnt = 0; + unsigned int expected_pkt_cnt = 0; + unsigned char seq = 0; + unsigned char buf_seq; + + rcv_state = START_WAIT; + while (rcv_state != END_TEST && (cnt=Nread(fd,buf,buflen)) > 0) { + /* Determine the type of packet received */ + if (!memcmp(buf, start_pattern, START_PATTERN_LEN)) { + pkt_type = START_PKT_TYPE; + start_pkt_cnt++; + } else if (!memcmp(buf, end_pattern, END_PATTERN_LEN)) { + /* read the expected data packet count from the end packet */ + unsigned char* net_byte = buf; + net_byte += END_PATTERN_LEN; + expected_pkt_cnt = ((net_byte[0] << 24) + (net_byte[1] << 16) + + (net_byte[2] << 8) + net_byte[3]); + pkt_type = END_PKT_TYPE; + end_pkt_cnt++; + } else { + data_pkt_cnt++; + pkt_type = DATA_PKT_TYPE; + } + + if (rcv_state == START_WAIT) { + /* Wait until we see a vaild start packet */ + if (pkt_type == START_PKT_TYPE) { + prep_timer(); + rcv_state = DATA_WAIT; + } else if (pkt_type == DATA_PKT_TYPE) { + fprintf(stderr, "ERROR: Missed UDP start packet.\n"); + prep_timer(); + rcv_state = DATA_RCV; + } else if (pkt_type == END_PKT_TYPE) { + fprintf(stderr, "ERROR: Found UDP end packet before start packet or data.\n"); + rcv_state = END_TEST; + } + } else if (rcv_state == DATA_WAIT) { + /* Skip any extra start packets until we see data */ + if (pkt_type == START_PKT_TYPE) { + prep_timer(); + } else if (pkt_type == DATA_PKT_TYPE) { + rcv_state = DATA_RCV; + } else if (pkt_type == END_PKT_TYPE) { + fprintf(stderr, "ERROR: Found UDP end packet without receiving " + "any data packets.\n"); + rcv_state = END_TEST; + } + } else { /* DATA_RCV */ + /* Collect data packets until we see a vaild end packet */ + if (pkt_type == START_PKT_TYPE) { + /* We missed the end packets and now a new test is + * starting. Report the results of this test then start + * another. */ + read_timer(); + result_summary(); + fprintf(stderr, "ERROR: Found UDP start packet while receiving data.\n" + "ERROR: Expected more data packets or an end packet.\n"); + nbytes = 0.0; + nbuffers = 0; + numCalls = 0; + prep_timer(); + rcv_state = DATA_WAIT; + } else if (pkt_type == DATA_PKT_TYPE) { + /* loop in this state */ + } else if (pkt_type == END_PKT_TYPE) { + /* we used to print results here but now we do when the loop ends */ + rcv_state = END_TEST; + } + } + + /* tally data packets the same way from whatever state we are in */ + if (pkt_type == DATA_PKT_TYPE) { + if (debug) + fprintf(stderr, "ttcp-r: %5d | %d Bytes Read\n", ++nbuffers, cnt); + nbytes += cnt; + if (seq_info) { + /* check seqence num */ + buf_seq = (unsigned char)(buf[0]); + if (buf_seq != seq) { + fprintf(stderr, "ERROR: Out of sequence. " + "Buffer %u, seq %u, expected %u\n", + data_pkt_cnt, buf_seq, seq); + seq = buf_seq; + } + seq++; + } + if (!sinkmode) { +#if !defined(__NTVIS__) /* else case specific to WINNT */ + if (write(1,&(buf[1]),cnt-1) != cnt-1) err("write"); +#else /* __NTVIS__ */ + if ((int)fwrite(&(buf[1]),1,cnt-1,stdout) != cnt-1) err("fwrite"); +#endif /* __NTVIS__ */ + } + } + } /* end-while */ + + /* normal end of test */ + read_timer(); + result_summary(); + fprintf(stderr, "ttcp-r: packets %u data, %u start, %u end\n", + data_pkt_cnt, start_pkt_cnt, end_pkt_cnt); + if (expected_pkt_cnt != 0) { + int lost_cnt = expected_pkt_cnt - data_pkt_cnt; + + fprintf(stderr, "ttcp-r: %g%% (%u/%u) packet loss\n", + 100.0 * (double)lost_cnt/(double)expected_pkt_cnt, + lost_cnt, expected_pkt_cnt); + } +} + +/*--------------------------------------------------------------------------*/ +/* calc_cpu_time(): Time difference, in usecs, of the combined user and + * sys times of the given start and end usage info */ +double +calc_cpu_time( + struct rusage *r0, + struct rusage *r1 +) +{ + double time; + time_t ms; + struct timeval tdiff, tend, tstart; + + /* total user delta time + total system delta time */ + tvadd( &tend, &r1->ru_utime, &r1->ru_stime ); /* user + sys time @ end */ + tvadd( &tstart, &r0->ru_utime, &r0->ru_stime ); /* user + sys time @ start*/ + tvsub( &tdiff, &tend, &tstart ); + + /* useconds */ + time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec; + + /* debug mseconds */ + ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000; + if (ms != (time_t)(time/1000.0)) { + fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n", + (int)ms, time/1000.0); + } + + return time; +} + +/*--------------------------------------------------------------------------*/ +/* calc_real_time(): Time difference in usecs of the given times */ +double +calc_real_time( + struct timeval *t0, + struct timeval *t1 +) +{ + double time; + time_t ms; + struct timeval tdiff; + + tvsub(&tdiff, t1 ,t0); + + /* useconds */ + time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec; + + /* debug mseconds */ + ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000; + if (ms != (time_t)(time/1000.0)) { + fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n", + (int)ms, time/1000.0); + } + + return time; +} +/*--------------------------------------------------------------------------*/ +void +result_summary(void) +{ + char* label = trans ? "ttcp-t" : "ttcp-r"; + double cput = calc_cpu_time(&ru0, &ru1); + double realt = calc_real_time(&time0, &time1); + double t_min; + double bytes_per_sec; + + /* lower end boundary conditions */ + t_min = 10.0; /* 10 usec */ +#if defined(__NTVIS__) + t_min = 1000.0; /* 1 msec */ +#endif + if (cput <= t_min) { /* value in usec */ + cput = t_min; + fprintf(stderr,"%s: cpu time too short set at %.0f usec, NOT accurate result.\n", + label,t_min); + } + if (realt <= t_min) { /* value in usec */ + realt = t_min; + fprintf(stderr,"%s: real time too short, set at %.0f usec, NOT accurate result.\n", + label,t_min); + } + + bytes_per_sec = (nbytes/realt)*1e6; + + fprintf(stderr,"%s: %.0f bytes in %.06f real seconds = %s/sec +++\n", + label, nbytes, realt/1e6, outfmt(fmt, bytes_per_sec)); + + if (verbose) + fprintf(stderr,"%s: %.0f bytes in %.06f cpu seconds = %s/cpu sec\n", + label, nbytes,cput/1e6, outfmt(fmt, (nbytes/cput)*1e6)); + + fprintf(stderr,"%s: %ld I/O calls, %.3f msec(real)/call, %.3f msec(cpu)/call\n", + label, numCalls, + (numCalls>0)?(realt/(double)numCalls)/1000.0:0.0, + (numCalls>0)?(cput /(double)numCalls)/1000.0:0.0); + + fprintf(stderr,"%s: ", label); + prusage(&ru0, &ru1, &time0, &time1); + fprintf(stderr,"\n"); + + if (verbose) + printf("%s: buffer address %#x\n", label, (unsigned int)buf); + + if (fplog) { + struct timeval tdiff; + /* User time */ + tvsub(&tdiff, &ru1.ru_utime, &ru0.ru_utime); + fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec); + /* System time */ + tvsub(&tdiff, &ru1.ru_stime, &ru0.ru_stime); + fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec); + /* Percent of cput usage */ + fprintf(fplog," %.1f", 100.0 * (cput/realt)); + /* validity of real time mesurment */ + fprintf(fplog, (realt == t_min)?" 0":" 1"); + /* bytes, seconds, MBytes/sec, IO calls */ + fprintf(fplog," %10.0f %4.06f %4.3f %6ld", + nbytes, realt/1e6, bytes_per_sec/(1024.0*1024.0), numCalls); + } +} +/*--------------------------------------------------------------------------*/ +void +sockets_err(char* s) +{ +#if defined(__NTVIS__) + int err = WSAGetLastError(); + char* prefix = trans?"ttcp-t":"ttcp-r"; + fprintf(stderr,"%s: %s\n", prefix, s); + fprintf(stderr,"%s: errno=%d\n", prefix, err); + exit(1); +#else + err(s); +#endif /* __NTVIS__ */ +} + +/*--------------------------------------------------------------------------*/ +void +err(char *s) +{ + char* prefix = trans?"ttcp-t":"ttcp-r"; + fprintf(stderr,"%s: ", prefix); + perror(s); + fprintf(stderr,"%s: errno=%d\n", prefix, errno); + exit(1); +} +/*--------------------------------------------------------------------------*/ +void +mes(char *s) +{ + fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s); +} +/*--------------------------------------------------------------------------*/ +void +pattern( char *cp, int cnt ) +{ + register char c; + register int cnt1; + cnt1 = cnt; + c = 0; + while( cnt1-- > 0 ) { + while( !isprint((c&0x7F)) ) c++; + *cp++ = (c++&0x7F); + } +} +/*--------------------------------------------------------------------------*/ +char * +outfmt(char format, double b) +{ + static char obuf[50]; + double giga = 1024.0 * 1024.0 * 1024.0; + double mega = 1024.0 * 1024.0; + double kilo = 1024.0; + + if (format == 'A') { + if (b >= giga) + format = 'G'; + else if (b >= mega) + format = 'M'; + else if (b >= kilo) + format = 'K'; + else + format = 'B'; + } + + switch (format) { + case 'G': + sprintf(obuf, "%.3f GB", b / giga); + break; + case 'M': + sprintf(obuf, "%.3f MB", b / mega); + break; + case 'K': + sprintf(obuf, "%.3f KB", b / kilo); + break; + case 'B': + sprintf(obuf, "%4f B", b); + break; + case 'g': + sprintf(obuf, "%.3f Gbit", b * 8.0 / giga); + break; + case 'm': + sprintf(obuf, "%.3f Mbit", b * 8.0 / mega); + break; + case 'k': + sprintf(obuf, "%.3f Kbit", b * 8.0 / kilo); + break; + case 'b': + sprintf(obuf, "%4f b", b * 8.0); + break; + default: + sprintf(obuf, "default.........."); + } + return obuf; +} +/*--------------------------------------------------------------------------*/ +#if defined(SYSV) + +/*ARGSUSED*/ + +#if defined(__osf__) +/* getrusage defined in the system lib */ +#else +#if defined(__lynx__) +/* getrusage defined in the system lib */ +#else +#if defined(__sun__) +/* getrusage defined in the system lib */ +#else + +int +getrusage(ignored, ru) + int ignored; + register struct rusage *ru; +{ + + +#if defined(__NTVIS__) + HANDLE phd; + FILETIME CreateTime, ExitTime, KernelTime, UserTime; + SYSTEMTIME SysTime; +#if defined(UNDER_CE) + phd = GetCurrentThread(); + if( GetThreadTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime) + != TRUE) +#else + phd = GetCurrentProcess(); + if( GetProcessTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime) + != TRUE) +#endif + {ru->ru_stime.tv_sec = 0; + ru->ru_stime.tv_usec = 0; + ru->ru_utime.tv_sec = 0; + ru->ru_utime.tv_usec = 0; + } + else + { + (void) FileTimeToSystemTime(&KernelTime, &SysTime); + /* + * fprintf(stdout, + * "System sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds); + */ + ru->ru_stime.tv_sec = SysTime.wSecond; + ru->ru_stime.tv_usec = SysTime.wMilliseconds * 1000; + (void) FileTimeToSystemTime(&UserTime, &SysTime); + /* + * fprintf(stdout, + * " User sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds); + */ + ru->ru_utime.tv_sec = SysTime.wSecond; + ru->ru_utime.tv_usec = SysTime.wMilliseconds * 1000; + } + +#else /* __NTVIS__ */ + + struct tms buftime; + times(&buftime); + /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */ + /* info : in lynxOS HZ is called TICKSPERSEC (<conf.h>) */ + + ru->ru_stime.tv_sec = buftime.tms_stime / HZ; + ru->ru_stime.tv_usec = ((buftime.tms_stime % HZ) * 1000000) / HZ; + ru->ru_utime.tv_sec = buftime.tms_utime / HZ; + ru->ru_utime.tv_usec = ((buftime.tms_utime % HZ) * 1000000) / HZ; +#endif /* __NTVIS__ */ +return(0); + +} /* static getrusage */ + +#endif /* __sun__ */ +#endif /* __lynx__ */ +#endif /* __osf__ */ +#endif /* SYSV */ +/*--------------------------------------------------------------------------*/ +#if defined(SYSV) +#if defined(__hpux__) || defined(_AIX) || defined(__sun__) +/* gettimeofday defined in the system lib */ +#else +# if defined (__osf__) ||defined (__lynx__) +/* gettimeofday defined in the system lib */ +#else +/*ARGSUSED*/ +static +gettimeofday(tp, zp) +struct timeval *tp; +struct timezone *zp; +{ +#if defined(__NTVIS__) +#if defined(UNDER_CE) + SYSTEMTIME SystemTime; + + GetLocalTime(&SystemTime); + tp->tv_sec = SystemTime.wSecond; + tp->tv_usec = SystemTime.wMilliseconds * 1000; +#else + struct _timeb timeptr; + + _ftime(&timeptr); + tp->tv_sec = timeptr.time; + tp->tv_usec = timeptr.millitm * 1000; +#endif +#else /* all cases */ + tp->tv_sec = time(0); + tp->tv_usec = 0; +#endif /* __NTVIS__ */ +return(1); +} /* static gettimeofday */ + +#endif /*__osf__ || __lynx__ */ +#endif /* __hpux__ || _AIX || __sun__ || __osf__*/ +#endif /* SYSV */ +/*--------------------------------------------------------------------------*/ +/* + * P R E P _ T I M E R + */ +void +prep_timer(void) +{ + gettimeofday(&time0, (struct timezone *)0); + getrusage(RUSAGE_SELF, &ru0); +} +/*--------------------------------------------------------------------------*/ +/* + * R E A D _ T I M E R + * + */ +void +read_timer(void) +{ + getrusage(RUSAGE_SELF, &ru1); + gettimeofday(&time1, (struct timezone *)0); +} +/*--------------------------------------------------------------------------*/ +/* Print the process usage calculated from timers values extracted + * before and after the transfer execution. + */ +void +prusage( + struct rusage *r0, struct rusage *r1, + struct timeval *t0, struct timeval *t1 +) +{ + struct timeval tdiff; + int t, ms; + register char *cp; + double cput = calc_cpu_time(r0, r1); + double realt = calc_real_time(t0, t1); + + /* t == total user delta time + total system delta time */ + if (debug) + { + printf("timers : end startup\n"); + printf("user (sec) : %9ld %9ld\n",r1->ru_utime.tv_sec, + r0->ru_utime.tv_sec); + printf("user (usec): %9ld %9ld\n",r1->ru_utime.tv_usec, + r0->ru_utime.tv_usec); + printf("sys (sec) : %9ld %9ld\n",r1->ru_stime.tv_sec, + r0->ru_stime.tv_sec); + printf("sys (usec): %9ld %9ld\n",r1->ru_stime.tv_usec, + r0->ru_stime.tv_usec); + printf("time (sec) : %9ld %9ld\n",t1->tv_sec,t0->tv_sec); + printf("time (usec): %9ld %9ld\n",t1->tv_usec,t0->tv_usec); + } + /* for the AIX debug, most counters are outside a good range + printf(" r0 r1\n"); + printf("ru_ixrss %20ld %20ld \n", r0->ru_ixrss ,r1->ru_ixrss ); + printf("ru_idrss %20ld %20ld \n", r0->ru_idrss ,r1->ru_idrss ); + printf("ru_isrss %20ld %20ld \n", r0->ru_isrss ,r1->ru_isrss ); + printf("ru_minflt %20ld %20ld \n", r0->ru_minflt ,r1->ru_minflt ); + printf("ru_majflt %20ld %20ld \n", r0->ru_majflt ,r1->ru_majflt ); + printf("ru_nswap %20ld %20ld \n", r0->ru_nswap ,r1->ru_nswap ); + printf("ru_inblock %20ld %20ld \n", r0->ru_inblock ,r1->ru_inblock ); + printf("ru_oublock %20ld %20ld \n", r0->ru_oublock ,r1->ru_oublock ); + printf("ru_msgsnd %20ld %20ld \n", r0->ru_msgsnd ,r1->ru_msgsnd ); + printf("ru_msgrcv %20ld %20ld \n", r0->ru_msgrcv ,r1->ru_msgrcv ); + printf("ru_nsignals %20ld %20ld \n", r0->ru_nsignals ,r1->ru_nsignals); + printf("ru_nvcsw %20ld %20ld \n", r0->ru_nvcsw ,r1->ru_nvcsw ); + printf("ru_nivcsw %20ld %20ld \n", r0->ru_nivcsw ,r1->ru_nivcsw ); + */ + + /* cpu time in mseconds */ + t = (int)(cput / 1000.0); + + /* ms == value of the internal clock at the end of the xfer */ + /* also called real time. */ + /* real time in mseconds */ + ms = (int)(realt / 1000.0); + + /* The display is based on variables provided by the function getrusage + Info located in : /usr/include/sys/resource.h + */ +#if defined(SYSV) + +#if defined(_AIX) + /* with AIX cernsp most counters are wrong + * cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0"; + */ + cp = "%Uuser %Ssys %Ereal %P\0"; + +#else +#if defined(__osf__) + cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0"; +#else +#if defined(sgi) /* IRIX 3.3 will show 0 for %M,%F,%R,%C */ + cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw\0"; +#else +#if defined(__Lynx__) + cp = "%Uuser %Ssys %Ereal %P\0"; +#else + cp = "%Uuser %Ssys %Ereal %P\0"; /* all SYSV except those mentionned */ +#endif /*__lynx__ */ +#endif /* sgi */ +#endif /*__osf__ */ +#endif /* _AIX */ + +#else /* BSD system */ + cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0"; + +#endif /* SYSV */ + + for (; *cp; cp++) { + if (*cp != '%') { + putc(*cp, stderr); + /* *outp++ = *cp; */ + } else if (cp[1]) + switch(*++cp) { + case 'U': + tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime); + fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec); + break; + + case 'S': + tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime); + fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec); + break; + + case 'E': + psecs( ms / 1000); + break; + + case 'P': + fprintf(stderr,"%.1f%%", (cput*100.0 / (realt ? realt : 1.0)) ); + break; + +#if !defined(SYSV) || defined(__osf__) || defined(_AIX) + case 'W': + { + int i = r1->ru_nswap - r0->ru_nswap; + fprintf(stderr,"%d", i); + break; + } + + case 'X': + fprintf(stderr,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t); + break; + + case 'D': + fprintf(stderr,"%ld", t == 0 ? 0 : + (r1->ru_idrss+r1->ru_isrss - (r0->ru_idrss+r0->ru_isrss))/t); + break; + + case 'K': + fprintf(stderr,"%ld", t == 0 ? 0 : + ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) - + (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t); + break; + + case 'M': + fprintf(stderr,"%ld", r1->ru_maxrss/2); + break; + + case 'F': + fprintf(stderr,"%ld", r1->ru_majflt-r0->ru_majflt); + break; + + case 'R': + fprintf(stderr,"%ld", r1->ru_minflt-r0->ru_minflt); + break; + + case 'I': + fprintf(stderr,"%ld", r1->ru_inblock-r0->ru_inblock); + break; + + case 'O': + fprintf(stderr,"%ld", r1->ru_oublock-r0->ru_oublock); + break; + + case 'C': + fprintf(stderr,"%ld+%ld", + r1->ru_nvcsw-r0->ru_nvcsw, r1->ru_nivcsw-r0->ru_nivcsw); + break; +#endif /* !SYSV || __osf__ */ + default: + putc(*cp, stderr); + break; + } /* switch */ + } /* for */ +} +/*--------------------------------------------------------------------------*/ +/* add 2 times structure and move usec bigger than 1000000 to sec */ +void +tvadd(tsum, t0, t1) + struct timeval *tsum, *t0, *t1; +{ + tsum->tv_sec = t0->tv_sec + t1->tv_sec; + tsum->tv_usec = t0->tv_usec + t1->tv_usec; + if (tsum->tv_usec > 1000000) tsum->tv_sec++, tsum->tv_usec -= 1000000; +} +/*--------------------------------------------------------------------------*/ +/* substract 2 time structure (t1 > t0) */ +void +tvsub(tdiff, t1, t0) + struct timeval *tdiff, *t1, *t0; +{ + tdiff->tv_sec = t1->tv_sec - t0->tv_sec; + tdiff->tv_usec = t1->tv_usec - t0->tv_usec; + if (tdiff->tv_usec < 0) tdiff->tv_sec--, tdiff->tv_usec += 1000000; +} + +/*--------------------------------------------------------------------------*/ +void +psecs(int l) +{ + int i = (int)l/3600; + + if (i) { + /* hours:min:sec */ + fprintf(stderr,"%d:", i); + i = (int)l % 3600; + fprintf(stderr,"%.2d:%.2d", i/60, i%60); + } else { + /* min:sec */ + i = (int)l; + fprintf(stderr,"%d:%.2d", i/60, i%60); + } +} +/*--------------------------------------------------------------------------*/ +/* N R E A D */ + +int +Nread(SOCKET s, void* bufp, int count ) +{ +#if defined(__lynx__) || defined(__svr4__) || defined(_AIX) || defined(__NTVIS__) || defined(__FreeBSD__) + struct sockaddr from; +#else + struct sockaddr_in from; +#endif + int len = sizeof(from); + register int cnt; + + if (timeout > 0) { + fd_set readfds, exceptfds; + struct timeval tv_timeout; + int n; + + tv_timeout.tv_sec = timeout/1000; + tv_timeout.tv_usec = (timeout%1000)*1000; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(s, &readfds); + FD_SET(s, &exceptfds); + + n = select( s+1, &readfds, NULL, &exceptfds, &tv_timeout ); + if (n == SOCKET_ERROR) { + sockets_err("select read"); + } else if (n == 0) { + return (0); + } + + } + + if( udp ) + {cnt = recvfrom( s, bufp, count, 0, SOCKADDR_CAST &from, &len ); + numCalls++; + } + else + {if( b_flag ) cnt = mread( s, bufp, count ); /* fill bufp */ + else + { +#if defined(__NTVIS__) + cnt = recv( s, bufp, count, 0 ); +#else + cnt = read( s, bufp, count ); +#endif /* __NTVIS__ */ + numCalls++; + } + if (touchdata && cnt > 0) + {register int c = cnt, sum = 0; + register char *b = bufp; + while (c--) sum += *b++; + } + } + /* rchrch printf (" numcall %d read buffer %d bytes \n",numCalls,cnt); */ + return(cnt); +} +/*--------------------------------------------------------------------------*/ +/* N W R I T E */ + +int +Nwrite( int s, void* bufp, int count ) +{ + register int cnt; + if( udp ) + { + again: + cnt = sendto( s, bufp, count, 0, SOCKADDR_CAST &sinhim, + sizeof(sinhim) ); + + numCalls++; + +#if defined(__NTVIS__) + if( cnt<0 && WSAENOBUFS == WSAGetLastError()) +#else + if( cnt<0 && errno == ENOBUFS ) +#endif /* __NTVIS__ */ + + { delay(18000); errno = 0; goto again; } + } else /* if (udp) */ + { + +#if defined(__NTVIS__) + cnt = send( s, bufp, count, 0 ); + numCalls++; +#else + cnt = write( s, bufp, count ); + numCalls++; +#endif /* __NTVIS__ */ + } + return(cnt); +} +/*--------------------------------------------------------------------------*/ +void +delay(us) +int us; +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = (time_t)us; + +#if defined(__hpux__) + select(1, 0, 0, 0, &tv); +#else + select(1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); +#endif +} +/*--------------------------------------------------------------------------*/ +/* M R E A D + * + * This function performs the function of a read(II) but will + * call read(II) multiple times in order to get the requested + * number of characters. This can be necessary because + * network connections don't deliver data with the same + * grouping as it is written with. Written by Robert S. Miles, BRL. + */ +int +mread(int s, char* bufp, unsigned n) +{ + register unsigned count = 0; + register int nread; + + do + { +#if defined(__NTVIS__) + nread = recv(s, bufp, n-count, 0); +#else + nread = read(s, bufp, n-count); +#endif /* __NTVIS__ */ + numCalls++; + if(nread < 0) {perror("ttcp_mread"); return(-1); } + if(nread == 0) return((int)count); + count += (unsigned)nread; + bufp += nread; + }while(count < n); + return((int)count); +} + +/*--------------------------------------------------------------------------*/ +void +open_log() +{static long sysTicks; +#if defined(UNDER_CE) + SYSTEMTIME SystemTime; +#endif + sprintf(logfile,"%s_%s",logfile_head,trans?"t":"r"); + + fprintf(stderr,"open the log file >%s<\n",logfile); + if ((fplog = fopen(logfile,"r")) == NULL) + + {if ((fplog = fopen(logfile,"a+")) == NULL) + {fprintf(stderr,"Failure : creation of the file >%s< \n",logfile ); + exit(1); + } + else + {fprintf(fplog," creation date : "); + /* get date */ +#if defined(UNDER_CE) + GetLocalTime(&SystemTime); + sprintf(fplog,"%02d-%02d-%02d %02d:%02d\n", SystemTime.wDay, month[SystemTime.wMonth - 1], + SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute); +#else + time(&sysTicks); + tms = localtime(&sysTicks); + fprintf(fplog,"%02d-%02d-%02d %02d:%02d\n", + tms->tm_mday, tms->tm_mon, tms->tm_year,tms->tm_hour, tms->tm_min); +#endif + + /* An other version will produce : Mon Aug 4 16:32:16 1997 + * long lDxcomsTicks; char *pDateTime; + * time(&lDxcomsTicks); + * pDateTime = ctime(&lDxcomsTicks); *(pDateTime+24) = '\0'; + * fprintf(fplog," ttcp called : %s", pDateTime); + */ + fprintf(fplog,"format\n"); + fprintf(fplog,",buflen, nbuf(byte), bufalign(byte), bufoffset(byte)"); + fprintf(fplog,", port, sockbufsize(byte), UserTime(sec), SysTime(sec)\n"); + fprintf(fplog,", CPUusage(%%), Validity, nbytes(byte), realt(sec)"); + fprintf(fplog,", rate(MB/sec), I/O call, hours*3600+min*60+sec\n\n"); + /* day-month-year, hour:minute\n\n"); */ + } + } /* file already exist */ + else + {fclose (fplog); + if ((fplog = fopen(logfile,"a+")) == NULL) + {fprintf(stderr,"Failure : access of the file >%s< \n",logfile ); + exit(1); + } + } +} +/*--------------------------------------------------------------------------*/ +void +close_log() +{ +#if defined(UNDER_CE) + SYSTEMTIME SystemTime; + + GetLocalTime(&SystemTime); + fprintf(fplog," %d\n", SystemTime.wHour * 3600 + SystemTime.wMinute * 60 + SystemTime.wSecond); +#else + static long sysTicks; + time(&sysTicks); + tms = localtime(&sysTicks); + fprintf(fplog," %d\n",((tms->tm_hour)*3600 + (tms->tm_min)*60 + tms->tm_sec)); +#endif + fclose(fplog); + fflush(fplog); +} +/*--------------------------------------------------------------------------*/ +/* routine emulating UNIX function under NT */ +#if defined(__NTVIS__) + +/*---------------------------------------------------------------------------*/ +static void +error(char *pch) +{ + if (!opterr) { + return; // without printing + } + fprintf(stderr, "%s: %s: %c\n", + (NULL != progname) ? progname : "getopt", pch, optopt); +} +/*---------------------------------------------------------------------------*/ +int +getopt(int argc, char **argv, char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + register char *oli; /* option letter list index */ + + if (!*place) { + // update scanning pointer + if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) { + place = EMSG; + return -1; + } + // place now points to the first char past the initial '-' + if (place[0] == '-') { + // found "--" + // Was the word just a '--'? + if (place[1] == '\0') + ++optind; // yes, so consume the word + // otherwise, the '--' was the start of a longer word, + // so do not consume it. + place = EMSG; + return -1; + } + } + + /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' + || !(oli = strchr(ostr, optopt))) { + if (!*place) { + ++optind; + } + error("illegal option"); + return BADCH; + } + if (*++oli != ':') { + /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } else { + /* need an argument */ + if (*place) { + optarg = place; /* no white space */ + } else if (argc <= ++optind) { + /* no arg */ + place = EMSG; + error("option requires an argument"); + return BADCH; + } else { + optarg = argv[optind]; /* white space */ + } + place = EMSG; + ++optind; + } + return optopt; // return option letter +} + +void +usleep(unsigned int microseconds) +{ + Sleep(microseconds/1000); +} +#endif /* __NTVIS__ */ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +void +do_help() +{ +char More_help[] = +" Details about the reply: \n" +" Example: \n" +" ttcp-t: buflen=8192, nbuf=100, align=16384/0, port=5010\n" +" ttcp-t: File-Descriptor 0x4 Opened\n" +" # tcp sender -> <host> #\n" +" ttcp-t: 819200 bytes in 1.152557 real seconds = 694.109 KB/sec +++\n" +" ttcp-t: 100 I/O calls, 11.526 msec(real)/call, 0.213 msec(cpu)/call\n" +" ttcp-t: 0.001914user 0.019388sys 0:01real 1% 9i+58d 190maxrss 1+2pf 177+180csw\n" +" ttcp-t: buffer address 0x28000\n" +" ttcp-t: File-Descriptor fd 0x4 Closed\n" +" ttcp done.\n\n" +"cpu seconds == (sec) elapse ru_utime + elapse ru_stime.\n" +" ru_utime == The total amount of time running in user mode.\n" +" ru_stime == The total amount of time spent in the system.\n" +" executing on behalf of the process.\n" +"real seconds == elapse time calculated by the system timer (date).\n" +"I/O calls == I/O call to the driver.\n" +"msec/call == average elapse time (Real seconds) between each I/O.\n" +"calls/sec == invert of msec/call.\n" +"user == (sec.msec) elaspe ru_utime.\n" +"sys == (sec.msec) elapse ru_stime.\n" +"real == (min:sec) CPU seconds.\n" +"%% == Real seconds / CPU seconds.\n" +"(ru_ixrss)i+(ru_idrss)d\n" +" ru_ixrss == An integral value indicating the amount of memory \n" +" used by the text segment that was also shared among\n" +" other processes. This value is expressed in units of\n" +" kilobytes * seconds-of-execution and is calculated \n" +" by adding the number of shared memory pages in use \n" +" each time the internal system clock ticks, and then\n" +" averaging over one-second intervals.\n" +" ru_idrss == An integral value of the amount of unshared memory \n" +" in the data segment of a process (expressed in \n" +" units of kilobytes * seconds-of-execution).\n"; + +char More_help1[] = +" (ru_maxrss/2)maxrss.\n" +" ru_maxrss == The maximum size, in kilobytes, of the used\n" +" resident set size. \n" +" (ru_majflt)+(ru_minflt)pf : Page fault\n" +" ru_majflt == The number of page faults serviced that required\n" +" I/O activity.\n" +" ru_minflt == The number of page faults serviced without any\n" +" I/O activity. In this case, I/O activity is \n" +" avoided by reclaiming a page frame from the list \n" +" of pages awaiting reallocation. \n" +"(ru_nvcsw)+(ru_nivcsw)csw : context switch\n" +" ru_nvcsw == The number of times a context switch resulted \n" +" because a process voluntarily gave up the \n" +" processor before its time slice was completed. \n" +" This usually occurs while the process waits \n" +" for availability of a resource.\n" +" ru_nivcsw == The number of times a context switch resulted \n" +" because a higher priority process ran or because\n" +" the current process exceeded its time slice.\n\n"; + +char More_help2[] = +"log file format :\n" +" buflen, nbuf(byte), bufalign(byte), bufoffset(byte)\n" +" port, sockbufsize(byte), UserTime(sec), SysTime(sec), CPUusage(%)\n" +" nbytes(byte), realt(sec), rate(MB/sec), I/O call,\n" +" hours*3600+min*60+sec\n\n"; + + fprintf(stderr,More_help); + fprintf(stderr,More_help1); + fprintf(stderr,More_help2); +} +/*---------------------------------------------------------------------------*/ +void +do_Usage() +{ +char Usage[] = +" Usage: ttcp -t [-options] host [ < in ] ttcp -r [-options > out]\n" +"Example: ttcp -t -s -v -n100 host ttcp -r -s -v -n100\n" +"Common options:\n" +" -V prints version number and date of last modification\n" +" -L create and append all results to a file named ttcp_log\n" +" -h more help\n" +" -l ## length of bufs read from or written to network (default 8192,\n" +" max 65535)\n" +" -u use UDP instead of TCP\n" +" -p ## port number to send to or listen at (default 5001)\n" +#if defined(__linux__) +" -P ## link-layer priority (default 0)\n" +#endif +" -s (ttcp -t) : source a pattern to network\n" +" (ttcp -r) : sink (discard) all data from network\n" +" -A ## align the start of buffers to this modulus (default 16384)\n" +" -O ## start buffers at this offset from the modulus (default 0)\n" +" -v verbose: print more statistics\n" +" -d set SO_DEBUG socket option\n" +" -b ## set socket buffer size (if supported)\n" +" -f X format for rate: b,B = bits, bytes k,K = kilo{bits,bytes};\n" +" m,M = mega{bits,bytes}; g,G = giga{bits,bytes}\n" +" -w ## set timeout value (in milliseconds) to exit if no receive data or tcp connect\n" +"Options specific to (ttcp -t) :\n" +" -n ## number of source bufs written to network (default 2048)\n" +" -x use random data in tcp/udp frames (-I provides seed)\n" +" -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n" +" -H print hash marks to indicate progress, one per buffer\n" +" -I init/seed value for RNG when sending random size bufs (default 1)\n" +" -N ## number of source bufs per burst, i.e between sleeps (default 1)\n" +" -R ## send random size buffers with minimum size specified, max size\n" +" is value of -l option\n" +" -S ## millisecs between bursts (only used for udp, 10ms resolution)\n" +"Options specific to (ttcp -r) :\n" +" -B for -s, only output full blocks as specified by -l (for TAR)\n" +" -T \"touch\": access each byte as it's read\n" +" -i report information on out of order sequence numbers\n" +#if defined(DEBUG) +"Options for debug:\n" +" --nostart do not send UDP start packets\n" +" --noend do not send UDP end packets\n" +" --nodata do not send UDP data packets\n" +" --debug print extra debug outputs\n" +#endif /* DEBUG */ +; + + fprintf(stderr,Usage); +} + +/* Define automatic Emacs variables for consistent code formatting */ +/* Local Variables: */ +/* c-basic-offset:2 */ +/* indent-tabs-mode:nil */ +/* End: */ diff --git a/openwrt/package/ttcp/ttcp.control b/openwrt/package/ttcp/ttcp.control new file mode 100644 index 000000000..3633ef1df --- /dev/null +++ b/openwrt/package/ttcp/ttcp.control @@ -0,0 +1,6 @@ +Package: ttcp +Priority: optional +Section: net +Maintainer: Felix Fietkau <nbd@vd-s.ath.cx> +Source: buildroot internal +Description: A small utility to test TCP connection performance |