1/*
2 *        T T C P . C
3 *
4 * Test TCP connection.  Makes a connection on port 5001
5 * and transfers fabricated buffers or data copied from stdin.
6 *
7 * Usable on 4.2, 4.3, and 4.1a systems by defining one of
8 * BSD42 BSD43 (BSD41a)
9 * Machines using System V with BSD sockets should define SYSV.
10 *
11 * Modified for operation under 4.2BSD, 18 Dec 84
12 *       T.C. Slattery, USNA
13 * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
14 * Modified in 1989 at Silicon Graphics, Inc.
15 *        catch SIGPIPE to be able to print stats when receiver has died
16 *        for tcp, don't look for sentinel during reads to allow small transfers
17 *        increased default buffer size to 8K, nbuf to 2K to transfer 16MB
18 *        moved default port to 5001, beyond IPPORT_USERRESERVED
19 *        make sinkmode default because it is more popular,
20 *                -s now means don't sink/source
21 *        count number of read/write system calls to see effects of
22 *                blocking from full socket buffers
23 *        for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
24 *        buffer alignment options, -A and -O
25 *        print stats in a format that's a bit easier to use with grep & awk
26 *        for SYSV, mimic BSD routines to use most of the existing timing code
27 * Modified by Steve Miller of the University of Maryland, College Park
28 *        -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
29 * Modified Sept. 1989 at Silicon Graphics, Inc.
30 *        restored -s sense at request of tcs@brl
31 * Modified Oct. 1991 at Silicon Graphics, Inc.
32 *        use getopt(3) for option processing, add -f and -T options.
33 *        SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
34 *
35 * Modified --> Nov 1996 at CERN (Daniel DAVIDS)
36 *        printout of the Socket-Buffer-Sizes
37 *        configured for HP-UX 9000 OS
38 *        configured for Windows NT OS
39 * Modified Dec 1996 at CERN (Jacques ROCHEZ)
40 *        severe cleanup
41 *        addaptation to the gcc compiler (ANSI)
42 *        configured for Lynx OS
43 *        automatic format for the rate display (G/M/K/)bytes/sec
44 *        added log (L) and more help (h) options.
45 * Modified May 1997 at CERN (Jacques ROCHEZ)
46 *        removed the mes() function following err() function.
47 *        changed the default port to 5010
48 * Modified jul 1997 at CERN (Jacques ROCHEZ)
49 *        adapted the timing calculation in microseconds
50 *        addapted the code for Vsisual C++ under NT4.0
51 * Modified aug 1997 at CERN (Jacques ROCHEZ)
52 *        initialise to 0 the variables nbytes, numcalls
53 *        moved the buffer pre-load outside the measured timed area
54 * Distribution Status -
55 *        Public Domain.  Distribution Unlimited.
56 * Modified jun 1998 at Epigram
57 *        - print hash marks to indicate prograss on transmitting side
58 *        - sleep between bursts of buffers
59 *        - set number of buffers/burst
60 * Modified jul 1998 at Epigram
61 *        - send random size buffers
62 * Modified jan 1999 at Epigram (WES)
63 *        - added start and end patterns to UDP start and end packets
64 *        - added handling of missed start, end, or data packets for UDP tests
65 */
66#ifndef lint
67static char RCSid[] = "ttcp.c $- CERN Revision: 3.8 (dev level) -$";
68#endif
69
70static char VersDate[] = "Epigram 15-jul-98";
71
72/*                system dependent setting
73 *                ------------------------
74 * uname -a,gcc -v a.c are the tools used
75 *
76 * Platform/OS          #define         MACRO predefined
77 * -----------          -------   ---------------------------------------------------
78 * SunOS OS             BSD43     __unix__   __sun__   __sparc__
79 * SUN Solaris           SYSV     __unix__   __sun__   __sparc__   __svr4__
80 * SGI-IRIX  < 3.3 SYSV     set as #define sgi
81 * HP-UX 9000           SYSV      __unix__   __hpux__  __hp9k8__
82 * OSF/1 V3.2           SYSV      __unix__   __osf__   __alpha__
83 * OSF/1 V4.0           SYSV      __unix__   __osf__   __alpha__   _CFE
84 * LynxOS               SYSV      __unix__   __lynx__  __powerpc__
85 * Windows NT           SYSV                 __WINNT__ __i386__    __M_COFF__
86 * AIX                  SYSV      _AIX       _AIX32    _POWER      _IBMR2   _ARCH_PWR
87
88
89 * Micosoft Visual C++ compiler under WindowNT 4.0
90 * Windows NT                    _WINDOWS    WIN32
91
92 * Unix BSD 41a         BSD41a
93 *          42          BSD42
94 *          43          BSD43
95
96 * Machines using System V with BSD sockets should define SYSV.
97 *
98 *            Compiler commands
99 *            -----------------
100 * LynxOS : gcc -c ttcp.c -o ttcp.o | gcc -o ttcp -O ttcp.o -lnetinet -lc_p -lc
101 */
102
103/* -------------attempt to set an automatic UNIX  OS family detection -------*/
104
105#if defined(__hp9k8__) || defined(__osf__) || defined(__srv4__)
106#define SYSV
107#endif
108#if defined(__lynx__)
109#define SYSV
110#endif
111/* for solaris (__srv4__) the parameters SYSV is already set */
112
113/* version A.09.01  'key words' differs from A.09.05 A */
114#if defined(__hpux)
115#define __hpux__
116#endif
117
118#if defined(__sun__)&&!defined(__srv4__)
119#define BSD43                  /* changed by BSD42 if necessary */
120#endif
121
122#if defined(_WIN32)                /* Window NT 4.0 compiled with VisualC++ 4 */
123#define __NTVIS__
124#define SYSV
125#endif
126
127#if defined(__FreeBSD__)
128#define BSD43
129#endif
130
131#if defined(__linux__)
132#define BSD43
133#endif
134/*--------------------------------------------------------------------------*/
135
136#if !defined(UNDER_CE)
137#include <signal.h>
138#include <ctype.h>
139#include <errno.h>
140#include <sys/types.h>
141#endif
142
143#if defined(SYSV)
144
145#if defined(__osf__)
146#include <sys/socket.h>
147#include <netinet/in.h>
148#include <netinet/tcp.h>
149#include <arpa/inet.h>
150#include <netdb.h>
151#include <sys/time.h>           /* struct timeval */
152#include <sys/resource.h>       /* definition of struct rusage */
153
154#else  /* else of __osf__ */
155#if defined(__NTVIS__)
156#include <winsock2.h>
157#include <windows.h>            /* required for all Windows applications */
158#include <ws2tcpip.h>
159#include <memory.h>
160#include <time.h>
161#if !defined(UNDER_CE)
162#include <sys\timeb.h>
163#include <fcntl.h>
164#endif
165#include <stdlib.h>
166#include <io.h>
167struct rusage { struct timeval ru_utime, ru_stime; };
168#define RUSAGE_SELF 0
169#else  /* else of __NTVIS__ */
170#if defined(__lynx__)
171#include <socket.h>             /* located in  /usr/include/..... */
172#include <netinet/in.h>
173#include <netinet/tcp.h>
174#include <arpa/inet.h>
175#include <netdb.h>
176#include <time.h>
177#include <resource.h>           /* definition of struct rusage */
178#include <sys/times.h>
179#define RUSAGE_SELF 0
180#include <conf.h>               /* definition of TICKSPERSEC (HZ) */
181#include <sys/param.h>
182
183#else  /* else of __Lynx__  */
184#if defined(__svr4__)
185#include <sys/socket.h>
186#include <sys/uio.h>
187#include <netinet/in.h>
188#include <netinet/tcp.h>
189#include <arpa/inet.h>
190#include <netdb.h>
191#include <sys/time.h>           /* struct timeval */
192#include <sys/resource.h>       /* definition of struct rusage */
193#include <sys/times.h>
194#define RUSAGE_SELF 0
195#include <sys/param.h>
196
197#else  /* else of __svr4__    all SYSV cases except those mentionned before */
198#include <sys/socket.h>
199#include <netinet/in.h>
200#include <netinet/tcp.h>
201#include <arpa/inet.h>
202#include <netdb.h>
203#include <sys/time.h>           /* struct timeval */
204#include <sys/resource.h>       /* definition of struct rusage */
205#include <sys/times.h>
206#define RUSAGE_SELF 0
207#include <sys/param.h>
208
209#endif /* __svr4__  */
210#endif /* __lynx__  */
211#endif /* __NTVIS__ */
212#endif /* __osf__   */
213
214#else  /* else of SYSV      it is a BSD OS  */
215#include <stdlib.h>
216#include <string.h>
217#include <sys/socket.h>
218#include <netinet/in.h>
219#include <netinet/tcp.h>
220#include <arpa/inet.h>
221#include <netdb.h>
222#if defined(__linux__)
223#include <time.h>           /* struct timeval */
224#else
225#include <sys/time.h>           /* struct timeval */
226#endif
227#include <sys/resource.h>       /* definition of struct rusage */
228#include <unistd.h>		/* for usleep() - henry */
229#define SOCKET_ERROR	-1
230
231#endif /* SYSV */
232
233#if defined(__NTVIS__)
234
235#if defined(_DEBUG)     /* usual debug symbol for VC++ */
236#define DEBUG 1
237#endif
238
239void usleep(unsigned int microseconds);
240
241#define bcopy(a,b,n) memcpy((b), (a), (n))
242#define bzero(a,n) memset((a), 0, (n))
243
244#ifndef _GETOPT_
245#define _GETOPT_
246int getopt(int argc, char **argv, char *optstring);
247
248extern char *optarg;                // returned arg to go with this option
249extern int optind;                  // index to next argv element to process
250extern int opterr;                  // should error messages be printed?
251extern int optopt;                  //
252
253#define BADCH ('?')
254#endif // _GETOPT
255
256/* get option letter from argument vector  */
257int
258        opterr = 1,                  // should error messages be printed?
259        optind = 1,                  // index into parent argv vector
260        optopt;                      // character checked for validity
261char   *optarg;                      // argument associated with option
262
263#define EMSG        ""
264char *progname;                      // may also be defined elsewhere
265#endif /*__NTVIS__*/
266
267/* sockaddr_in ==  file server address structure
268 *
269 * Socket address, internet style.   declared in : /netinet/in.h
270 * struct sockaddr_in {short   sin_family;
271 *                     u_short sin_port;
272 *                     struct  in_addr sin_addr;
273 *                     char    sin_zero[8];
274 *                    };
275 *
276 * Structure used by kernel to store most addresses. declared in ./sys/socket.h
277 * struct sockaddr{u_short sa_family;       address family
278 *                 char    sa_data[14];     up to 14 bytes of direct address
279 *                };
280 * PS : sin stand for "socket internet number"
281 */
282
283#ifndef __NTVIS__
284#define FAR
285#endif
286
287/*
288#if     defined(__CONST_SOCKADDR_ARG)
289#define SOCKADDR_CAST   (__CONST_SOCKADDR_ARG)
290#elif  defined(__lynx__) || defined(__sun__) || defined(_AIX) || defined(__FreeBSD__) || defined(__NTVIS__)
291#define SOCKADDR_CAST   (struct sockaddr FAR *)
292#else
293#define SOCKADDR_CAST
294#endif
295*/
296#define SOCKADDR_CAST (void *)	// just shutup already...
297
298#if defined(__sun__)
299struct sockaddr_in sockaddr;   /* done in ./X11/Xdmcp.h */
300#endif
301
302struct sockaddr_in sinme;     /* is the socket struct. in the local host */
303struct sockaddr_in sinhim;    /* is the socket struc. in the remote host */
304
305#if defined(__lynx__) || defined(__svr4__) || defined(_AIX)
306struct sockaddr frominet;
307#else
308struct sockaddr_in frominet;
309#endif /* __lynx__ */
310
311int domain, fromlen;
312
313#if !defined(__NTVIS__)
314#define SOCKET int
315#endif /* __NTVIS__ */
316SOCKET fd;                             /* fd of network socket */
317
318#if !defined(__lynx__)
319extern int errno;
320#endif
321
322#include <stdio.h>
323
324FILE  *fplog = NULL;                   /* file pointer for the log file */
325char  logfile[100];                    /* file name for the log */
326static char logfile_head[] ="ttcp_log";   /* header  name for the log */
327int   buflen = 8 * 1024;               /* length of buffer */
328char  *buf;                            /* ptr to dynamic buffer */
329int   nbuf = 2 * 1024;                 /* number of buffers to send in sinkmode */
330
331#define START_PKT_LEN 4
332#define START_PATTERN_LEN 4
333#define END_PKT_LEN 8
334#define END_PATTERN_LEN 4
335#define MIN_UDP_LEN 5
336
337char start_pattern[START_PATTERN_LEN] = {1, 2, 3, 4};
338char end_pattern[END_PATTERN_LEN] = {2, 2, 2, 2};
339
340int   bufoffset = 0;                   /* align buffer to this */
341int   bufalign = 16*1024;              /* modulo this */
342
343int   udp = 0;                         /* 0 = tcp, !0 = udp */
344int   options = 0;                     /* socket options */
345int   one = 1;                         /* for 4.3 BSD style setsockopt() */
346short port = 5010;                     /* TCP port number */
347char *host;                            /* ptr to name of host */
348int  rndm = 0;                         /* 0="normal", !0=random data */
349int  trans;                            /* 0=receive, !0=transmit mode */
350int  timeout;                          /* read timeout in millisec */
351int  debug = 0;                        /* 0=No-Debug, 1=Debug-Set-On */
352int  sinkmode = 0;                     /* 0=normal I/O, !0=sink/source mode */
353int  verbose = 0;                      /* 0=print basic info, 1=print cpu rate,
354                                        * proc resource usage. */
355int  nodelay = 0;                      /* set TCP_NODELAY socket option */
356int  pri = 0;                          /* link layer priority */
357int  b_flag = 0;                       /* use mread() */
358int  log_cnt = 0;                      /* append result to a log */
359int  sockbufsize = 0;                  /* socket buffer size to use */
360char fmt = 'A';                        /* output format:
361                                        *  b = bits,     B = bytes,
362                                        *  k = kilobits, K = kilobytes,
363                                        *  m = megabits, M = megabytes,
364                                        *  g = gigabits, G = gigabytes,
365                                        *  A = automatic Xbytes (default) */
366int  touchdata = 0;                    /* access data after reading */
367int  seq_info = 0;                     /* report out of order seq nums */
368
369int hash = 0;                          /* print hash marks for each buffer */
370int udpsleep = 0;                      /* sleep in between udp buffers */
371int burstn = 1;                        /* number of buffers per burst */
372int bufmin = -1;                       /* minimum buffer size to use when
373                                          sending random-size buffers */
374unsigned int seed = 1;                 /* seed for random number generator
375                                          used for random buffer lengths */
376int no_start = 0;                      /* skip the start frames for UDP */
377int no_data = 0;                       /* skip all data frames for UDP */
378int no_end = 0;                        /* skip the end frames for UDP */
379
380double   nbytes;                       /* bytes on net */
381unsigned long numCalls;                /* # of I/O system calls */
382
383struct hostent *addr;
384extern int optind;
385extern char *optarg;
386
387#if defined(UNDER_CE)
388static int errno;
389static char *weekday[] ={"Sun", "Mon","Tues", "Wed", "Thurs", "Fri", "Sat"};
390static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "July", "Aug", "Sep", "Oct", "Nov", "Dec"};
391#define perror printf
392#endif
393
394/*--------------------------------------------------------------------------*/
395static struct timeval time0;    /* Time at which timing started */
396static struct timeval time1;
397static struct rusage ru0;       /* Resource utilization at the start */
398static struct rusage ru1;
399static struct tm *tms;        /* system time structure */
400
401
402/*-----------Prototype functions definitions -------------------------------*/
403/*--------------------------------------------------------------------------*/
404
405                                   /* ANSI input/output functions (stdio.h) */
406
407#if defined(__lynx__)
408int  getopt(int, char**, char*);
409int  gettimeofday(struct timeval *tp, struct timezone *tzp);
410
411#else
412#if defined(__svr4__)
413
414#else
415#if defined(_AIX)
416
417#else
418#if defined(__hpux__)
419#else
420#if defined(__NTVIS__)
421#else
422#if defined(BSD42) || defined(BSD43)
423#else
424
425int  printf( char*, ...);
426int  fprintf(FILE*,char*, ...);
427void perror(char*);
428int  getopt(int, char**, char*);
429int  gettimeofday(struct timeval *tp, struct timezone *tzp);
430#endif  /* BSD42 || BSD43 */
431#endif  /* __NTVIS__ */
432#endif  /* __hpux__ */
433#endif  /*  _AIX    */
434#endif  /* __svr4__ */
435#endif  /* __lynx__ */
436
437int main(int argc, char* argv[]);
438#if ( (!(defined(BSD42))) && (!(defined(BSD43))) && (!(defined(__NTVIS__))) )
439int  read(int, char*, int);
440int  write(int, char*, int);
441int  close(int);
442#endif /* !(BSD42) && !(BSD43) */
443int  fclose(FILE *stream);
444
445#if !defined(BSD43) && !defined(__NTVIS__)
446void bzero(char*,int);
447void bcopy(char*, char*, int);
448char strncpy(char *s1,char *s2,size_t n);
449int  atoi(char*);
450int  malloc(int);
451#endif
452
453
454                           /* ANSI socket functions prototype /sys/socket.h */
455#if defined(__lynx__)
456int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
457
458#else
459#if defined(__svr4__) && !defined(sparc)
460
461/*  informations in : /usr/include/sys/socket.h */
462int  socket(int, int, int);
463int  connect(int, struct sockaddr *, int);
464int  bind(int, struct sockaddr *, int);
465int  listen(int, int);
466int  accept(int, struct sockaddr *, int *);
467int  sendto(int, const char *, int, int, const struct sockaddr *, int);
468int  recvfrom(int, char *, int, int, struct sockaddr *, int *);
469int  getpeername(int, struct sockaddr *, int *);
470int  getsockopt(int, int, int, char *, int *);
471int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
472
473#else
474#if defined(_AIX)
475int  select(unsigned long, void *, void *, void *, struct timeval *);
476
477#else
478#if defined(__hpux__)
479int getrusage(int who,struct rusage *rusage);
480
481#else
482#if defined(__NTVIS__)
483
484#else
485#if defined(BSD42) || defined(BSD43)
486
487#else
488
489int  socket(int, int, int);
490int  connect(int s,struct sockaddr_in *name, int namelen);
491int  bind(int s,struct sockaddr *name,int namelen);
492int  listen(int, int);
493int  accept(int, struct sockaddr_in *, int *);
494int  sendto(int, char *, int, int, struct sockaddr_in *, int);
495int  recvfrom(int, char *, int, int, struct sockaddr_in *, int *);
496int  getpeername(int, struct sockaddr *, int *);
497int  setsockopt(int, int, int, char *, int);
498
499int  getsockopt(int, int, int, char*, int*);
500int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
501
502#endif /* BSD42 || BSD43 */
503#endif /* __hpux__ */
504#endif /*  _AIX    */
505#endif /* __svr4__ */
506#endif /* __lynx__ */
507#endif /* __NTVIS__ */
508
509/* ttcp prototype functions */
510void udp_rcv_test(void);
511double calc_cpu_time(struct rusage *r0, struct rusage *r1);
512double calc_real_time(struct timeval *t0, struct timeval *t1);
513int  getrusage(int who,struct rusage *rusage);
514void sockets_err(char*);
515void err(char *);
516void mes(char *);
517void pattern(char *, int);
518int  Nread(SOCKET, void *, int);
519int  Nwrite(int, void *, int);
520void delay(int);
521int  mread(int, char *,unsigned);
522char *outfmt(char format, double b);
523void prep_timer(void);
524void read_timer(void);
525void result_summary(void);
526void prusage(struct rusage*,  struct rusage*,
527             struct timeval*, struct timeval*);
528void tvadd(struct timeval *tsum, struct timeval *t0,struct timeval *t1);
529void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
530void psecs(int);
531void open_log(void);
532void close_log(void);
533void do_Usage(void);
534void do_help(void);
535
536/*--------------------------------------------------------------------------*/
537#if !defined(__NTVIS__)
538void
539sigpipe()
540{;
541}
542#endif
543/*--------------------------------------------------------------------------*/
544/*--------------------------------------------------------------------------*/
545int
546main(int argc, char **argv)
547{
548  unsigned long addr_tmp;
549  int c,k;
550  int sockbufsndsize,sockbufrcvsize;
551  int sockbuflen;
552  struct sockaddr_in peer;
553  int peerlen = sizeof(peer);
554
555#if defined(__NTVIS__)
556  extern char *optarg;
557  WSADATA WSAData;
558  WSAStartup(MAKEWORD(1,1), &WSAData);
559#endif /* __NTVIS__ */
560
561  if (argc < 2) { do_Usage(); exit(1); }
562
563  while (1) {
564    while ((c=getopt(argc, argv, "hidrstuvxHVBDTLb:f:l:n:p:A:O:S:N:P:R:I:w:")) != -1) {
565      switch (c) {
566        case 'w':
567           timeout = atoi(optarg);
568           break;
569        case 'I':
570           seed = atoi(optarg);
571           break;
572        case 'N':
573           burstn = atoi(optarg);
574           break;
575	case 'P':
576#if defined(__linux__)
577	   pri = atoi(optarg);
578	   break;
579#else
580	   fprintf(stderr, "ttcp: -P option not supported on this OS\n");
581	   exit(1);
582#endif
583	case 'R':
584	   bufmin = atoi(optarg);
585	   break;
586        case 'S':
587           udpsleep = atoi(optarg);
588           if (udpsleep < 0) udpsleep = 0;
589           /* convert msec arg to usec for usleep, minimum 10ms */
590           udpsleep = udpsleep * 1000;
591           break;
592        case 'H':
593           hash = 1;
594           break;
595        case 'V':
596           fprintf(stdout,"%s %s\n" , RCSid , VersDate );
597           exit(0);
598        case 'B':
599          b_flag = 1;
600          break;
601        case 'L':
602          log_cnt = 1;
603          break;
604        case 'h':
605          do_help();
606          exit(1);
607          break;
608        case 't':
609          trans = 1;
610          break;
611        case 'r':
612          trans = 0;
613          break;
614        case 'x':
615          rndm = 1;
616          break;
617        case 'd':
618          options |= SO_DEBUG;
619          break;
620        case 'D':
621#ifdef TCP_NODELAY
622        nodelay = 1;
623#else
624        fprintf(stderr,
625       "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
626#endif
627          break;
628        case 'n':
629          nbuf = atoi(optarg);
630          break;
631        case 'l':
632          buflen = atoi(optarg);
633          break;
634        case 's':
635          sinkmode = !sinkmode;
636          break;
637        case 'p':
638          port = atoi(optarg);
639          break;
640        case 'u':
641          udp = 1;
642          break;
643        case 'v':
644          verbose = 1;
645          break;
646        case 'A':
647          bufalign = atoi(optarg);
648          break;
649        case 'O':
650          bufoffset = atoi(optarg);
651          break;
652        case 'b':
653#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
654          sockbufsize = atoi(optarg);
655#else
656          fprintf(stderr,
657"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
658#endif
659          break;
660        case 'f':
661          fmt = *optarg;
662          break;
663        case 'T':
664          touchdata = 1;
665          break;
666        case 'i':
667          seq_info = 1;
668          break;
669
670      default:
671          {do_Usage(); exit(1);}
672       }/*switch */
673    }/* while getopt() */
674
675    argc -= optind;
676    argv += optind;
677    optind = 0;
678
679    /* check for '--' args */
680    if (argc == 0) {
681      /* no more args */
682      break; /* while (1) */
683#if defined(DEBUG)
684    } else if (!strcmp(argv[0], "--nostart")) {
685      no_start = 1;
686      argc--; argv++;
687    } else if (!strcmp(argv[0], "--nodata")) {
688      no_data = 1;
689      argc--; argv++;
690    } else if (!strcmp(argv[0], "--noend")) {
691      no_end = 1;
692      argc--; argv++;
693    } else if (!strcmp(argv[0], "--debug")) {
694      debug = 1;
695      argc--; argv++;
696#endif /* DEBUG */
697    } else if (!strncmp(argv[0], "--", 2)) {
698      fprintf(stderr, "ttcp: illegal option: %s\n", argv[0]);
699      do_Usage(); exit(1);
700    } else {
701      /* the arg was not a '--' arg */
702      break; /* while (1) */
703    }
704  } /* while (1) */
705
706
707 /* ----------------------- main part ----------------------- */
708
709#if defined(__NTVIS__) && !defined(UNDER_CE)
710  /* Set "stdin" to have binary mode: */
711  if (_setmode(_fileno(stdin), _O_BINARY) == -1)
712    perror("%s: Error setting stdin to binary mode");
713  /* Set "stdout" to have binary mode: */
714  if (_setmode(_fileno(stdout), _O_BINARY) == -1)
715    perror("%s: Error setting stdout to binary mode");
716#endif /* __NTVIS__ */
717
718if (log_cnt) open_log();
719
720/* input error checking */
721if (burstn > nbuf) {
722    fprintf(stderr, "ttcp: buffers per burst must be less than or equal to "
723        "total number of buffers\n");
724    exit(1);
725}
726if (bufmin < -1) {
727    fprintf(stderr, "ttcp: minimum buffer size specified with -R option must "
728        "be non-negative\n");
729    exit(1);
730}
731if (buflen > 65535) {
732    fprintf(stderr, "ttcp: maximum buffer size specified with -l option must "
733        "be <= 65536\n");
734    exit(1);
735}
736if (bufmin > buflen) {
737    fprintf(stderr, "ttcp: minimum buffer size specified with -R option must "
738        "be less than or equal to (maximum) buffer size specified with -l\n");
739    exit(1);
740}
741
742/* buffer allocation */
743
744 if (udp && buflen < MIN_UDP_LEN)
745   buflen = MIN_UDP_LEN;        /* send more than the sentinel size */
746
747 if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
748      err("malloc");
749 if (bufalign != 0)
750      buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign;
751
752 fprintf(stderr,"ttcp%s: buflen=%d, nbuf=%d, align=%d/%d, port=%d\n",
753            trans?"-t":"-r",buflen, nbuf, bufalign, bufoffset, port);
754 if (log_cnt)fprintf(fplog," %6d %6d %6d %6d %4d",
755                      buflen, nbuf, bufalign, bufoffset, port);
756
757 /* preload the buffer for the transmit condition */
758 pattern( buf, buflen );
759
760 /* seed the random number generator */
761 if ((bufmin != -1) || (rndm != 0)) {
762#if defined(__NTVIS__)
763   srand(seed);
764#else /* ! __NTVIS__ */
765   srandom(seed);
766#endif /* __NTVIS__ */
767 }
768
769 if(trans)
770   {/* xmitr */
771     if (argc == 0) {
772       fprintf(stderr, "ttcp: missing destination host arg\n");
773       do_Usage(); exit(1);
774     }
775
776     bzero((char *)&sinhim, sizeof(sinhim));
777     host = argv[0];
778     if (atoi(host) > 0 )
779       {/* Numeric */
780         sinhim.sin_family = AF_INET;
781         sinhim.sin_addr.s_addr = inet_addr(host);
782       }
783     else
784       {if ((addr=gethostbyname(host)) == NULL) sockets_err("bad hostname");
785        sinhim.sin_family = addr->h_addrtype;
786        bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length);
787        sinhim.sin_addr.s_addr = addr_tmp;
788       }
789     sinhim.sin_port = htons(port);
790     sinme.sin_port = 0;                /* free choice */
791   }
792 else
793   {/* rcvr */
794     sinme.sin_port =  htons(port);
795   }
796#if defined(__NTVIS__)
797 sinme.sin_family = AF_INET;
798#endif
799
800 fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0);
801
802#if defined(__NTVIS__)
803 if (fd == INVALID_SOCKET) sockets_err("socket");
804#else
805 if (fd < 0) sockets_err("socket");
806#endif
807
808 if (verbose) {
809	char *label = trans?"ttcp-t":"ttcp-r";
810#if defined(UNDER_CE)
811	SYSTEMTIME SystemTime;
812	char time_str[30];
813
814	GetLocalTime(&SystemTime);
815	sprintf(time_str, "%s %s %d %02d:%02d:%02d %d\n", weekday[SystemTime.wDayOfWeek], month[SystemTime.wMonth - 1],
816		SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wYear);
817#else
818   time_t now;
819   char *time_str;
820
821   time(&now);
822   time_str = ctime(&now);
823#endif
824   fprintf(stdout,"%s: start time %s", label, time_str);
825   fprintf(stdout,"%s: File-Descriptor 0x%x Opened\n", label, fd );
826 }
827
828	// reuse existing address (if restarting)
829	char reuse = 1;
830	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));
831
832#if defined(__NTVIS__)
833 if (bind(fd, (struct sockaddr FAR *)&sinme, sizeof(sinme)) == SOCKET_ERROR)
834   sockets_err("bind");
835#else
836 if (bind(fd, SOCKADDR_CAST &sinme, sizeof(sinme)) < 0)
837   sockets_err("bind");
838#endif /* __NTVIS__ */
839
840
841#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
842 if (sockbufsize)
843   {
844#if defined(__lynx__) || defined(__sun__)  || defined(__NTVIS__)
845     if (trans)
846       {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize,
847                       sizeof sockbufsize) < 0)
848        sockets_err("setsockopt: sndbuf");
849       }
850     else
851       {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize,
852                       sizeof sockbufsize) < 0)
853        sockets_err("setsockopt: rcvbuf");
854       }
855
856#else
857     if (trans)
858
859         {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
860                       sizeof sockbufsize) < 0)
861        sockets_err("setsockopt: sndbuf");
862       }
863     else
864       {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
865                       sizeof sockbufsize) < 0)
866        sockets_err("setsockopt: rcvbuf");
867       }
868#endif /* __lynx__ __sun__ __NTVIS__ */
869   }
870 else
871   {/*
872    ** Added by Daniel Davids to Know Socket-Buffer-Sizes
873    */
874     sockbuflen = sizeof sockbufsndsize;
875#if defined(__lynx__) || defined(__sun__) || defined(__NTVIS__)
876     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsndsize,
877                &sockbuflen);
878     sockbuflen = sizeof sockbufrcvsize;
879     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufrcvsize,
880                     &sockbuflen);
881#else
882     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsndsize, &sockbuflen);
883     sockbuflen = sizeof sockbufrcvsize;
884     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufrcvsize, &sockbuflen);
885#endif /* __lynx__ __sun__ __NTVIS__ */
886     sockbufsize = ( sockbufsndsize + sockbufrcvsize ) / 2;
887
888     if ( sockbufsndsize != sockbufrcvsize )
889       {fprintf(stderr, "sockbufsndsize=%d, ", sockbufsndsize );
890       fprintf(stderr, "sockbufrcvsize=%d, ", sockbufrcvsize );
891       }
892   }
893#endif /* defined(SO_SNDBUF) || defined(SO_RCVBUF) */
894
895 if (sockbufsize) fprintf(stderr, "sockbufsize=%d, \n", sockbufsize);
896
897 if (log_cnt)
898   {if (sockbufsize)fprintf(fplog," %6d",sockbufsize);
899    else fprintf(fplog," 0");
900   }
901
902#if defined(__linux__)
903 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&pri, sizeof pri) < 0)
904   sockets_err("setsockopt: priority");
905#endif
906
907
908 if (trans)  fprintf(stderr, "# %s sender -> %s #\n", udp?"udp":"tcp", host);
909 else        fprintf(stderr, "# %s receiver #\n", udp?"udp":"tcp");
910
911 if (!udp)
912   {
913#if !defined(__NTVIS__)
914     signal(SIGPIPE, sigpipe);
915#endif /* !__NTVIS__ */
916
917     if (trans)
918       {/* We are the client if transmitting */
919         if (options)
920           {
921#if defined(BSD42)
922            if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
923#else /* BSD43 */
924       if( setsockopt(fd, SOL_SOCKET, options, (char *)&one, sizeof(one)) < 0)
925#endif /* BDS42 */
926           sockets_err("setsockopt");
927           }
928#ifdef TCP_NODELAY
929         if (nodelay)
930           {struct protoent *p;
931            p = getprotobyname("tcp");
932#if defined(__lynx__)  || defined(__sun__)        || defined(__NTVIS__)
933                if( p && setsockopt(fd, p->p_proto, TCP_NODELAY,
934                                      (char *) &one, sizeof(one)) < 0)
935#else
936            if( p && setsockopt(fd, p->p_proto, TCP_NODELAY,
937                                      &one, sizeof(one)) < 0)
938#endif /* __lynx__  __sun__ __NTVIS__ */
939            sockets_err("setsockopt: nodelay");
940           }
941#endif /* TCP_NODELAY */
942         if (connect(fd, SOCKADDR_CAST &sinhim, sizeof(sinhim) ) < 0)
943         sockets_err("connect");
944       }/* if (trans) */
945     else
946       {/* otherwise, we are the server and should listen for connections */
947
948errno = 0;
949
950#if defined(sgi) || ( defined(__osf__) && !defined(_CFE) )
951        if( listen(fd,1) <0 )
952#else
953        if( listen(fd,0) <0 )   /* allow a queue of 0 */
954#endif
955        sockets_err("listen");
956
957        if(options) {
958          int err;
959#if defined(BSD42)
960          err = setsockopt(fd, SOL_SOCKET, options, 0, 0);
961#elif defined(__lynx__) || defined(__sun__) || defined(__NTVIS__)
962          err = setsockopt(fd, SOL_SOCKET, options, (char *) &one, sizeof(one));
963#else
964          err = setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one));
965#endif /* BSD42 */
966          if (err < 0)
967            sockets_err("setsockopt");
968        }
969        fromlen = sizeof(frominet);
970        domain = AF_INET;
971 if (timeout > 0) {
972   fd_set readfds, exceptfds;
973   struct timeval tv_timeout;
974   int n;
975
976   tv_timeout.tv_sec = timeout/1000;
977   tv_timeout.tv_usec = (timeout%1000)*1000;
978
979   FD_ZERO(&readfds);
980   FD_ZERO(&exceptfds);
981   FD_SET(fd, &readfds);
982   FD_SET(fd, &exceptfds);
983
984   n =  select( fd+1, &readfds, NULL, &exceptfds, &tv_timeout );
985   if (n == 0 || n == SOCKET_ERROR) {
986     sockets_err("select listen");
987     return 0;
988   }
989 }
990        if((fd=accept(fd, SOCKADDR_CAST &frominet, &fromlen) ) < 0)
991                sockets_err("accept");
992
993        if (getpeername(fd, SOCKADDR_CAST &peer, &peerlen) < 0)
994          sockets_err("getpeername");
995
996        fprintf(stderr,"ttcp-r: accept from %s\n",inet_ntoa(peer.sin_addr));
997
998       } /* otherwise we are ... */
999   }
1000
1001 prep_timer();
1002 errno = 0;
1003 nbytes = 0.0;
1004 numCalls = 0;
1005
1006 {
1007   register int cnt,multi;
1008   char *pb;
1009   int nb = 0;
1010   unsigned long rbuflen = 0;
1011   multi = nbuf;
1012
1013   if (trans) {
1014#if !defined(BSD43)
1015     if(udp) {
1016       int err;
1017       int nochecksum_opt = 0;
1018       err = setsockopt(fd, IPPROTO_UDP, UDP_NOCHECKSUM,
1019                        (char *)&nochecksum_opt, sizeof(nochecksum_opt));
1020       if (err < 0)
1021         sockets_err("setsockopt");
1022     }
1023#endif
1024
1025     if(udp && !no_start) {
1026       int start_count = 2;
1027       char start_pkt[START_PKT_LEN];
1028       memset(start_pkt, 0, START_PKT_LEN);
1029       memcpy(start_pkt, start_pattern, START_PATTERN_LEN);
1030
1031       while (start_count-- > 0) {
1032         (void)Nwrite( fd, start_pkt, START_PKT_LEN ); /* rcvr start */
1033         if (udpsleep) {
1034           usleep(udpsleep);
1035           /* clear errno (see man page for errno(3), definition of
1036              EINTR.  usleep() uses SIGCONT? ) */
1037           if (errno == EINTR) errno = 0;
1038         } /* udpsleep */
1039       }
1040     }
1041
1042     /* initial seqence num for UDP */
1043     if (udp) buf[0] = 0;
1044     k = burstn;
1045
1046     if (sinkmode) {
1047       while (multi-- > 0 && !no_data) {
1048
1049         if (bufmin == -1) {
1050           rbuflen = buflen;
1051         } else {
1052           /* set rbuflen to a random value evenly distributed in
1053              [bufmin, buflen].  As long as buflen is < 2^16, we can
1054              fit the calculation in 32 bits */
1055#if defined(__NTVIS__)
1056           rbuflen = (( (unsigned long)rand() *
1057                        ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
1058#else /* ! __NTVIS__ */
1059           rbuflen = (( ((unsigned long)random() >> 15) *
1060                        ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
1061#endif /* __NTVIS__ */
1062         }
1063
1064         if (rndm) {
1065           unsigned int i, j, l;
1066           unsigned long data;
1067
1068           if (udp)
1069             l = 1;
1070           else
1071             l = 0;
1072
1073           for (i = l; i < rbuflen; /* null */) {
1074#if defined(__NTVIS__)
1075             data = (unsigned long)rand();
1076#else /* ! __NTVIS__ */
1077             data = (unsigned long)random();
1078#endif /* __NTVIS__ */
1079             /*fprintf(stderr, "%08x\n",data);*/ /* DEBUG */
1080             /* The NT rand() function returns only 16 useful bits! */
1081             for (j = 0; (j < 2/*4*/) && (i < rbuflen) ; j++) {
1082               buf[i++] = (unsigned char)(data & 0xff);
1083               data >>= 8;
1084             }
1085           }
1086         }
1087
1088         if ((cnt=Nwrite(fd,buf,rbuflen)) != (int)rbuflen)
1089         sockets_err("error from the socket write");
1090         /* increment sequence num if UDP */
1091         if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF);
1092
1093         if (debug)
1094           fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n",
1095                   ++nb, cnt, nbuf );
1096
1097         nbytes += rbuflen;
1098
1099         /* hashes */
1100         if (hash) {
1101           fprintf(stderr,"#");
1102         }
1103
1104         /* Check for the end of a burst */
1105         if (--k <= 0) {
1106           k = burstn;
1107
1108           /* sleep to avoid overrunning slower receivers - henry */
1109           if (udpsleep) {
1110             usleep(udpsleep);
1111             /* clear errno (see man page for errno(3), definition of
1112              EINTR.  usleep() uses SIGCONT? ) */
1113             if (errno == EINTR) errno = 0;
1114           } /* udpsleep */
1115         }
1116       } /* while */
1117
1118     } /* if (sinkmode) */
1119     else
1120     {
1121
1122       nbuf = 0;
1123
1124       if (bufmin == -1) {
1125         rbuflen = buflen;
1126       } else {
1127         /* set rbuflen to a random value evenly distributed in
1128            [bufmin, buflen].  As long as buflen is < 2^16, we can
1129            fit the calculation in 32 bits */
1130#if defined(__NTVIS__)
1131         rbuflen = (( (unsigned long)rand() *
1132                      ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
1133#else /* ! __NTVIS__ */
1134         rbuflen = (( ((unsigned long)random() >> 15) *
1135                      ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
1136#endif /* __NTVIS__ */
1137       }
1138
1139       if (udp)
1140         pb = &(buf[1]);
1141       else
1142         pb = &(buf[0]);
1143
1144#if !defined(__NTVIS__)     /* else case specific to WINNT */
1145       while((cnt=read(0,pb,rbuflen)) > 0)
1146#else /* __NTVIS__ */
1147       while((cnt=(int)fread(pb,1,rbuflen,stdin)) > 0)
1148#endif /* __NTVIS__ */
1149        {
1150
1151         if (udp)
1152           multi = cnt+1; /* don't include seq. num. in count of data */
1153         else
1154           multi = cnt;
1155         if ((cnt=Nwrite(fd,buf,multi)) != (int)multi)
1156           sockets_err("error from the socket write");
1157         /* increment seqence num if UDP */
1158         if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF);
1159         nbuf++;
1160
1161         if (debug)
1162           fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n",
1163                   ++nb, cnt, nbuf );
1164
1165         nbytes += multi;
1166
1167         /* hashes */
1168         if (hash) {
1169           fprintf(stderr,"#");
1170         }
1171
1172         /* Check for the end of a burst */
1173         if (--k <= 0) {
1174           k = burstn;
1175
1176           /* sleep to avoid overrunning slower receivers - henry */
1177           if (udpsleep) {
1178             usleep(udpsleep);
1179             /* clear errno (see man page for errno(3), definition of
1180              EINTR.  usleep() uses SIGCONT? ) */
1181             if (errno == EINTR) errno = 0;
1182           } /* udpsleep */
1183         }
1184
1185         if (bufmin == -1) {
1186           rbuflen = buflen;
1187         } else {
1188           /* set rbuflen to a random value evenly distributed in
1189              [bufmin, buflen].  As long as buflen is < 2^16, we can
1190              fit the calculation in 32 bits */
1191#if defined(__NTVIS__)
1192           rbuflen = (( (unsigned long)rand() *
1193                        ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
1194#else /* ! __NTVIS__ */
1195           rbuflen = (( ((unsigned long)random() >> 15) *
1196                        ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
1197#endif /* __NTVIS__ */
1198         }
1199
1200       } /* while */
1201
1202     } /* if (sinkmode) */
1203
1204     if (hash) {
1205       fprintf(stderr,"\n");
1206       fflush(stderr);
1207     }
1208
1209#if defined(UNDER_CE)
1210	 errno = WSAGetLastError();
1211#endif
1212     if (!errno) {
1213       read_timer();
1214       if(udp && !no_end) {
1215         int end_count = 4;
1216         int data_count = nbuf;
1217         char end_pkt[END_PKT_LEN];
1218         unsigned char* net_byte = &end_pkt[END_PATTERN_LEN];
1219         memset(end_pkt, 0, END_PKT_LEN);
1220         memcpy(end_pkt, end_pattern, END_PATTERN_LEN);
1221         net_byte[3] = data_count & 0xFF; data_count >>= 8;
1222         net_byte[2] = data_count & 0xFF; data_count >>= 8;
1223         net_byte[1] = data_count & 0xFF; data_count >>= 8;
1224         net_byte[0] = data_count & 0xFF;
1225
1226         while (end_count-- > 0) {
1227           Nwrite( fd, end_pkt, END_PKT_LEN ); /* rcvr end */
1228           if (udpsleep && end_count>0) usleep(udpsleep);
1229         }
1230       }
1231       result_summary();
1232     }
1233   } /* trans */
1234   else
1235   {
1236       if (udp) {
1237         udp_rcv_test();
1238       }
1239       else
1240       {/* not udp received transfer */
1241         while ((cnt=Nread(fd,buf,buflen)) > 0)
1242           {if(debug)fprintf(stdout,
1243                            "ttcp%s: %5d | %d Bytes Read\n",
1244                            trans?"-t":"-r", ++nb, cnt );
1245           nbytes += cnt;
1246           if (!sinkmode) {
1247#if !defined(__NTVIS__)     /* else case specific to WINNT */
1248             if (write(1,buf,cnt) != cnt) err("write");
1249#else /* __NTVIS__ */
1250             if ((int)fwrite(buf,1,cnt,stdout) != cnt) err("fwrite");
1251#endif /* __NTVIS__ */
1252           }
1253         }
1254#if defined(UNDER_CE)
1255		 errno = WSAGetLastError();
1256#endif
1257         if (!errno) {
1258           read_timer();
1259           result_summary();
1260         }
1261       }
1262     }
1263   }
1264
1265 if(errno) err("IO");
1266
1267#if defined(__NTVIS__)
1268  closesocket ( fd );
1269#else
1270  close ( fd );
1271#endif /* __NTVIS__ */
1272
1273  if (verbose) fprintf(stdout,"ttcp%s: File-Descriptor  fd 0x%x Closed\n" ,
1274                       trans?"-t":"-r", fd );
1275
1276  if (log_cnt) close_log();
1277
1278  fprintf(stderr,"ttcp done.\n");
1279  fflush(stdout);
1280
1281  exit(0);
1282}
1283/*--------------------------------------------------------------------------*/
1284void
1285udp_rcv_test(void)
1286{
1287  enum {START_WAIT, DATA_WAIT, DATA_RCV, END_TEST} rcv_state;
1288  enum {START_PKT_TYPE, END_PKT_TYPE, DATA_PKT_TYPE} pkt_type;
1289  int cnt;
1290  int nbuffers = 0;
1291  unsigned int start_pkt_cnt = 0;
1292  unsigned int end_pkt_cnt = 0;
1293  unsigned int data_pkt_cnt = 0;
1294  unsigned int expected_pkt_cnt = 0;
1295  unsigned char seq = 0;
1296  unsigned char buf_seq;
1297
1298  rcv_state = START_WAIT;
1299  while (rcv_state != END_TEST && (cnt=Nread(fd,buf,buflen)) > 0) {
1300    /* Determine the type of packet received */
1301    if (!memcmp(buf, start_pattern, START_PATTERN_LEN)) {
1302      pkt_type = START_PKT_TYPE;
1303      start_pkt_cnt++;
1304    } else if (!memcmp(buf, end_pattern, END_PATTERN_LEN)) {
1305      /* read the expected data packet count from the end packet */
1306      unsigned char* net_byte = buf;
1307      net_byte += END_PATTERN_LEN;
1308      expected_pkt_cnt = ((net_byte[0] << 24) + (net_byte[1] << 16) +
1309                          (net_byte[2] << 8) + net_byte[3]);
1310      pkt_type = END_PKT_TYPE;
1311      end_pkt_cnt++;
1312    } else {
1313      data_pkt_cnt++;
1314      pkt_type = DATA_PKT_TYPE;
1315    }
1316
1317    if (rcv_state == START_WAIT) {
1318      /* Wait until we see a vaild start packet */
1319      if (pkt_type == START_PKT_TYPE) {
1320        prep_timer();
1321        rcv_state = DATA_WAIT;
1322      } else if (pkt_type == DATA_PKT_TYPE) {
1323        fprintf(stderr, "ERROR: Missed UDP start packet.\n");
1324        prep_timer();
1325        rcv_state = DATA_RCV;
1326      } else if (pkt_type == END_PKT_TYPE) {
1327        fprintf(stderr, "ERROR: Found UDP end packet before start packet or data.\n");
1328        rcv_state = END_TEST;
1329      }
1330    } else if (rcv_state == DATA_WAIT) {
1331      /* Skip any extra start packets until we see data */
1332      if (pkt_type == START_PKT_TYPE) {
1333        prep_timer();
1334      } else if (pkt_type == DATA_PKT_TYPE) {
1335        rcv_state = DATA_RCV;
1336      } else if (pkt_type == END_PKT_TYPE) {
1337        fprintf(stderr, "ERROR: Found UDP end packet without receiving "
1338                "any data packets.\n");
1339        rcv_state = END_TEST;
1340      }
1341    } else { /* DATA_RCV */
1342      /* Collect data packets until we see a vaild end packet */
1343      if (pkt_type == START_PKT_TYPE) {
1344        /* We missed the end packets and now a new test is
1345         * starting. Report the results of this test then start
1346         * another. */
1347        read_timer();
1348        result_summary();
1349        fprintf(stderr, "ERROR: Found UDP start packet while receiving data.\n"
1350                "ERROR: Expected more data packets or an end packet.\n");
1351        nbytes = 0.0;
1352        nbuffers = 0;
1353        numCalls = 0;
1354        prep_timer();
1355        rcv_state = DATA_WAIT;
1356      } else if (pkt_type == DATA_PKT_TYPE) {
1357        /* loop in this state */
1358      } else if (pkt_type == END_PKT_TYPE) {
1359        /* we used to print results here but now we do when the loop ends */
1360        rcv_state = END_TEST;
1361      }
1362    }
1363
1364    /* tally data packets the same way from whatever state we are in */
1365    if (pkt_type == DATA_PKT_TYPE) {
1366      if (debug)
1367        fprintf(stderr, "ttcp-r: %5d | %d Bytes Read\n", ++nbuffers, cnt);
1368      nbytes += cnt;
1369      if (seq_info) {
1370        /* check seqence num */
1371        buf_seq = (unsigned char)(buf[0]);
1372        if (buf_seq != seq) {
1373          fprintf(stderr, "ERROR: Out of sequence. "
1374                  "Buffer %u, seq %u, expected %u\n",
1375                  data_pkt_cnt, buf_seq, seq);
1376          seq = buf_seq;
1377        }
1378        seq++;
1379      }
1380      if (!sinkmode) {
1381#if !defined(__NTVIS__)     /* else case specific to WINNT */
1382        if (write(1,&(buf[1]),cnt-1) != cnt-1) err("write");
1383#else /* __NTVIS__ */
1384        if ((int)fwrite(&(buf[1]),1,cnt-1,stdout) != cnt-1) err("fwrite");
1385#endif /* __NTVIS__ */
1386      }
1387    }
1388  } /* end-while */
1389
1390  /* normal end of test */
1391  read_timer();
1392  result_summary();
1393  fprintf(stderr, "ttcp-r: packets %u data, %u start, %u end\n",
1394          data_pkt_cnt, start_pkt_cnt, end_pkt_cnt);
1395  if (expected_pkt_cnt != 0) {
1396    int lost_cnt = expected_pkt_cnt - data_pkt_cnt;
1397
1398    fprintf(stderr, "ttcp-r: %g%% (%u/%u) packet loss\n",
1399            100.0 * (double)lost_cnt/(double)expected_pkt_cnt,
1400            lost_cnt, expected_pkt_cnt);
1401  }
1402}
1403
1404/*--------------------------------------------------------------------------*/
1405/* calc_cpu_time(): Time difference, in usecs, of the combined user and
1406 * sys times of the given start and end usage info */
1407double
1408calc_cpu_time(
1409  struct rusage *r0,
1410  struct rusage *r1
1411)
1412{
1413  double time;
1414  time_t ms;
1415  struct timeval tdiff, tend, tstart;
1416
1417  /* total user delta time + total system delta time */
1418  tvadd( &tend, &r1->ru_utime, &r1->ru_stime );   /* user + sys time  @ end */
1419  tvadd( &tstart, &r0->ru_utime, &r0->ru_stime ); /* user + sys time  @ start*/
1420  tvsub( &tdiff, &tend, &tstart );
1421
1422  /* useconds */
1423  time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec;
1424
1425  /* debug mseconds */
1426  ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000;
1427  if (ms != (time_t)(time/1000.0)) {
1428    fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n",
1429            (int)ms, time/1000.0);
1430  }
1431
1432  return time;
1433}
1434
1435/*--------------------------------------------------------------------------*/
1436/* calc_real_time(): Time difference in usecs of the given times */
1437double
1438calc_real_time(
1439  struct timeval *t0,
1440  struct timeval *t1
1441)
1442{
1443  double time;
1444  time_t ms;
1445  struct timeval tdiff;
1446
1447  tvsub(&tdiff, t1 ,t0);
1448
1449  /* useconds */
1450  time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec;
1451
1452  /* debug mseconds */
1453  ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000;
1454  if (ms != (time_t)(time/1000.0)) {
1455    fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n",
1456            (int)ms, time/1000.0);
1457  }
1458
1459  return time;
1460}
1461/*--------------------------------------------------------------------------*/
1462void
1463result_summary(void)
1464{
1465  char* label = trans ? "ttcp-t" : "ttcp-r";
1466  double cput = calc_cpu_time(&ru0, &ru1);
1467  double realt = calc_real_time(&time0, &time1);
1468  double t_min;
1469  double bytes_per_sec;
1470
1471  /* lower end boundary conditions */
1472  t_min = 10.0;                 /* 10 usec */
1473#if  defined(__NTVIS__)
1474  t_min = 1000.0;               /* 1 msec */
1475#endif
1476  if (cput <= t_min) {          /* value in usec */
1477    cput = t_min;
1478    fprintf(stderr,"%s: cpu time too short set at %.0f usec, NOT accurate result.\n",
1479            label,t_min);
1480  }
1481  if (realt <= t_min) {         /* value in usec */
1482    realt = t_min;
1483    fprintf(stderr,"%s: real time too short, set at %.0f usec, NOT accurate result.\n",
1484            label,t_min);
1485  }
1486
1487  bytes_per_sec = (nbytes/realt)*1e6;
1488
1489  fprintf(stderr,"%s: %.0f bytes in %.06f real seconds = %s/sec +++\n",
1490          label, nbytes, realt/1e6, outfmt(fmt, bytes_per_sec));
1491
1492  if (verbose)
1493    fprintf(stderr,"%s: %.0f bytes in %.06f cpu  seconds = %s/cpu sec\n",
1494            label, nbytes,cput/1e6, outfmt(fmt, (nbytes/cput)*1e6));
1495
1496  fprintf(stderr,"%s: %ld I/O calls, %.3f msec(real)/call, %.3f msec(cpu)/call\n",
1497          label, numCalls,
1498          (numCalls>0)?(realt/(double)numCalls)/1000.0:0.0,
1499          (numCalls>0)?(cput /(double)numCalls)/1000.0:0.0);
1500
1501  fprintf(stderr,"%s: ", label);
1502  prusage(&ru0, &ru1, &time0, &time1);
1503  fprintf(stderr,"\n");
1504
1505  if (verbose)
1506    printf("%s: buffer address %#x\n", label, (unsigned int)buf);
1507
1508  if (fplog) {
1509    struct timeval tdiff;
1510    /* User time */
1511    tvsub(&tdiff, &ru1.ru_utime, &ru0.ru_utime);
1512    fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
1513    /* System time */
1514    tvsub(&tdiff, &ru1.ru_stime, &ru0.ru_stime);
1515    fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
1516    /* Percent of cput usage */
1517    fprintf(fplog," %.1f", 100.0 * (cput/realt));
1518    /* validity of real time mesurment */
1519    fprintf(fplog, (realt == t_min)?" 0":" 1");
1520    /* bytes, seconds, MBytes/sec, IO calls */
1521    fprintf(fplog," %10.0f %4.06f %4.3f %6ld",
1522            nbytes, realt/1e6, bytes_per_sec/(1024.0*1024.0), numCalls);
1523  }
1524}
1525/*--------------------------------------------------------------------------*/
1526void
1527sockets_err(char* s)
1528{
1529#if defined(__NTVIS__)
1530  int err = WSAGetLastError();
1531  char* prefix = trans?"ttcp-t":"ttcp-r";
1532  fprintf(stderr,"%s: %s\n", prefix, s);
1533  fprintf(stderr,"%s: errno=%d\n", prefix, err);
1534  exit(1);
1535#else
1536  err(s);
1537#endif /* __NTVIS__ */
1538}
1539
1540/*--------------------------------------------------------------------------*/
1541void
1542err(char *s)
1543{
1544  char* prefix = trans?"ttcp-t":"ttcp-r";
1545  fprintf(stderr,"%s: ", prefix);
1546  perror(s);
1547  fprintf(stderr,"%s: errno=%d\n", prefix, errno);
1548  exit(1);
1549}
1550/*--------------------------------------------------------------------------*/
1551void
1552mes(char *s)
1553{
1554        fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
1555}
1556/*--------------------------------------------------------------------------*/
1557void
1558pattern( char *cp, int cnt )
1559{
1560        register char c;
1561        register int cnt1;
1562        cnt1 = cnt;
1563        c = 0;
1564        while( cnt1-- > 0 )  {
1565                while( !isprint((c&0x7F)) )  c++;
1566                *cp++ = (c++&0x7F);
1567        }
1568}
1569/*--------------------------------------------------------------------------*/
1570char *
1571outfmt(char format, double b)
1572{
1573  static char obuf[50];
1574  double giga = 1024.0 * 1024.0 * 1024.0;
1575  double mega = 1024.0 * 1024.0;
1576  double kilo = 1024.0;
1577
1578  if (format == 'A') {
1579    if (b >= giga)
1580      format = 'G';
1581    else if (b >= mega)
1582      format = 'M';
1583    else if (b >= kilo)
1584      format = 'K';
1585    else
1586      format = 'B';
1587  }
1588
1589  switch (format) {
1590  case 'G':
1591    sprintf(obuf, "%.3f GB", b / giga);
1592    break;
1593  case 'M':
1594    sprintf(obuf, "%.3f MB", b / mega);
1595    break;
1596  case 'K':
1597    sprintf(obuf, "%.3f KB", b / kilo);
1598    break;
1599  case 'B':
1600    sprintf(obuf, "%4f B", b);
1601    break;
1602  case 'g':
1603    sprintf(obuf, "%.3f Gbit", b * 8.0 / giga);
1604    break;
1605  case 'm':
1606    sprintf(obuf, "%.3f Mbit", b * 8.0 / mega);
1607    break;
1608  case 'k':
1609    sprintf(obuf, "%.3f Kbit", b * 8.0 / kilo);
1610    break;
1611  case 'b':
1612    sprintf(obuf, "%4f b", b * 8.0);
1613    break;
1614  default:
1615    sprintf(obuf, "default..........");
1616  }
1617  return obuf;
1618}
1619/*--------------------------------------------------------------------------*/
1620#if defined(SYSV)
1621
1622/*ARGSUSED*/
1623
1624#if defined(__osf__)
1625/* getrusage defined in the system lib */
1626#else
1627#if defined(__lynx__)
1628/* getrusage defined in the system lib */
1629#else
1630#if defined(__sun__)
1631/* getrusage defined in the system lib */
1632#else
1633
1634int
1635getrusage(ignored, ru)
1636     int ignored;
1637     register struct rusage *ru;
1638{
1639
1640
1641#if defined(__NTVIS__)
1642  HANDLE phd;
1643  FILETIME CreateTime, ExitTime, KernelTime, UserTime;
1644  SYSTEMTIME SysTime;
1645#if defined(UNDER_CE)
1646  phd = GetCurrentThread();
1647  if( GetThreadTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime)
1648      != TRUE)
1649#else
1650  phd = GetCurrentProcess();
1651  if( GetProcessTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime)
1652      != TRUE)
1653#endif
1654    {ru->ru_stime.tv_sec  = 0;
1655    ru->ru_stime.tv_usec = 0;
1656    ru->ru_utime.tv_sec  = 0;
1657    ru->ru_utime.tv_usec = 0;
1658    }
1659  else
1660   {
1661     (void) FileTimeToSystemTime(&KernelTime, &SysTime);
1662     /*
1663      * fprintf(stdout,
1664      * "System sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds);
1665      */
1666     ru->ru_stime.tv_sec  = SysTime.wSecond;
1667     ru->ru_stime.tv_usec = SysTime.wMilliseconds * 1000;
1668     (void) FileTimeToSystemTime(&UserTime, &SysTime);
1669     /*
1670      *  fprintf(stdout,
1671      *  "   User sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds);
1672      */
1673     ru->ru_utime.tv_sec  = SysTime.wSecond;
1674     ru->ru_utime.tv_usec = SysTime.wMilliseconds * 1000;
1675    }
1676
1677#else   /* __NTVIS__ */
1678
1679  struct tms buftime;
1680  times(&buftime);
1681  /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
1682  /* info : in lynxOS HZ is called TICKSPERSEC (<conf.h>) */
1683
1684    ru->ru_stime.tv_sec  = buftime.tms_stime / HZ;
1685    ru->ru_stime.tv_usec = ((buftime.tms_stime % HZ) * 1000000) / HZ;
1686    ru->ru_utime.tv_sec  = buftime.tms_utime / HZ;
1687    ru->ru_utime.tv_usec = ((buftime.tms_utime % HZ) * 1000000) / HZ;
1688#endif /* __NTVIS__ */
1689return(0);
1690
1691} /* static getrusage */
1692
1693#endif /* __sun__ */
1694#endif /* __lynx__ */
1695#endif /* __osf__ */
1696#endif /* SYSV */
1697/*--------------------------------------------------------------------------*/
1698#if defined(SYSV)
1699#if defined(__hpux__) || defined(_AIX) || defined(__sun__)
1700/* gettimeofday defined in the system lib */
1701#else
1702# if defined (__osf__) ||defined (__lynx__)
1703/* gettimeofday defined in the system lib */
1704#else
1705/*ARGSUSED*/
1706static
1707gettimeofday(tp, zp)
1708struct timeval *tp;
1709struct timezone *zp;
1710{
1711#if defined(__NTVIS__)
1712#if defined(UNDER_CE)
1713	SYSTEMTIME SystemTime;
1714
1715	GetLocalTime(&SystemTime);
1716	tp->tv_sec = SystemTime.wSecond;
1717	tp->tv_usec = SystemTime.wMilliseconds * 1000;
1718#else
1719  struct _timeb timeptr;
1720
1721  _ftime(&timeptr);
1722  tp->tv_sec = timeptr.time;
1723  tp->tv_usec = timeptr.millitm * 1000;
1724#endif
1725#else /* all cases */
1726  tp->tv_sec = time(0);
1727  tp->tv_usec = 0;
1728#endif /* __NTVIS__ */
1729return(1);
1730} /* static gettimeofday */
1731
1732#endif /*__osf__ || __lynx__ */
1733#endif /* __hpux__ || _AIX || __sun__ || __osf__*/
1734#endif /* SYSV */
1735/*--------------------------------------------------------------------------*/
1736/*
1737 *                        P R E P _ T I M E R
1738 */
1739void
1740prep_timer(void)
1741{
1742  gettimeofday(&time0, (struct timezone *)0);
1743  getrusage(RUSAGE_SELF, &ru0);
1744}
1745/*--------------------------------------------------------------------------*/
1746/*
1747 *                        R E A D _ T I M E R
1748 *
1749 */
1750void
1751read_timer(void)
1752{
1753  getrusage(RUSAGE_SELF, &ru1);
1754  gettimeofday(&time1, (struct timezone *)0);
1755}
1756/*--------------------------------------------------------------------------*/
1757/*         Print the process usage calculated from timers values extracted
1758 *         before and after the transfer execution.
1759 */
1760void
1761prusage(
1762  struct rusage *r0, struct rusage *r1,
1763  struct timeval *t0, struct timeval *t1
1764)
1765{
1766  struct timeval tdiff;
1767  int t, ms;
1768  register char *cp;
1769  double cput = calc_cpu_time(r0, r1);
1770  double realt = calc_real_time(t0, t1);
1771
1772  /* t == total user delta time + total system delta time */
1773  if (debug)
1774  {
1775    printf("timers     : end          startup\n");
1776    printf("user (sec) : %9ld  %9ld\n",r1->ru_utime.tv_sec,
1777           r0->ru_utime.tv_sec);
1778    printf("user (usec): %9ld  %9ld\n",r1->ru_utime.tv_usec,
1779           r0->ru_utime.tv_usec);
1780    printf("sys  (sec) : %9ld  %9ld\n",r1->ru_stime.tv_sec,
1781           r0->ru_stime.tv_sec);
1782    printf("sys  (usec): %9ld  %9ld\n",r1->ru_stime.tv_usec,
1783           r0->ru_stime.tv_usec);
1784    printf("time (sec) : %9ld  %9ld\n",t1->tv_sec,t0->tv_sec);
1785    printf("time (usec): %9ld  %9ld\n",t1->tv_usec,t0->tv_usec);
1786  }
1787  /* for the AIX debug, most counters are outside a good range
1788    printf("                               r0                   r1\n");
1789    printf("ru_ixrss    %20ld %20ld \n", r0->ru_ixrss  ,r1->ru_ixrss  );
1790    printf("ru_idrss    %20ld %20ld \n", r0->ru_idrss  ,r1->ru_idrss  );
1791    printf("ru_isrss    %20ld %20ld \n", r0->ru_isrss ,r1->ru_isrss );
1792    printf("ru_minflt   %20ld %20ld \n", r0->ru_minflt  ,r1->ru_minflt  );
1793    printf("ru_majflt   %20ld %20ld \n", r0->ru_majflt  ,r1->ru_majflt  );
1794    printf("ru_nswap    %20ld %20ld \n", r0->ru_nswap  ,r1->ru_nswap  );
1795    printf("ru_inblock  %20ld %20ld \n", r0->ru_inblock  ,r1->ru_inblock );
1796    printf("ru_oublock  %20ld %20ld \n", r0->ru_oublock  ,r1->ru_oublock  );
1797    printf("ru_msgsnd   %20ld %20ld \n", r0->ru_msgsnd  ,r1->ru_msgsnd  );
1798    printf("ru_msgrcv   %20ld %20ld \n", r0->ru_msgrcv  ,r1->ru_msgrcv   );
1799    printf("ru_nsignals %20ld %20ld \n", r0->ru_nsignals  ,r1->ru_nsignals);
1800    printf("ru_nvcsw    %20ld %20ld \n", r0->ru_nvcsw   ,r1->ru_nvcsw   );
1801    printf("ru_nivcsw   %20ld %20ld \n", r0->ru_nivcsw  ,r1->ru_nivcsw  );
1802  */
1803
1804  /* cpu time in mseconds */
1805  t = (int)(cput / 1000.0);
1806
1807  /* ms == value of the internal clock at the end of the xfer   */
1808  /*                             also called real time.         */
1809  /* real time in mseconds */
1810  ms = (int)(realt / 1000.0);
1811
1812  /* The display is based on variables provided by the function getrusage
1813     Info located in : /usr/include/sys/resource.h
1814  */
1815#if defined(SYSV)
1816
1817#if defined(_AIX)
1818  /* with AIX cernsp most counters are wrong
1819   * cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0";
1820   */
1821  cp = "%Uuser %Ssys %Ereal %P\0";
1822
1823#else
1824#if defined(__osf__)
1825  cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0";
1826#else
1827#if defined(sgi)                        /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
1828  cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw\0";
1829#else
1830#if defined(__Lynx__)
1831  cp = "%Uuser %Ssys %Ereal %P\0";
1832#else
1833  cp = "%Uuser %Ssys %Ereal %P\0";    /* all SYSV except those mentionned */
1834#endif /*__lynx__ */
1835#endif /* sgi     */
1836#endif /*__osf__  */
1837#endif /* _AIX    */
1838
1839#else  /* BSD system */
1840  cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0";
1841
1842#endif /* SYSV    */
1843
1844  for (; *cp; cp++) {
1845    if (*cp != '%') {
1846      putc(*cp, stderr);
1847      /*  *outp++ = *cp; */
1848    } else if (cp[1])
1849      switch(*++cp) {
1850      case 'U':
1851        tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
1852        fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
1853        break;
1854
1855      case 'S':
1856        tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
1857        fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
1858        break;
1859
1860      case 'E':
1861        psecs( ms / 1000);
1862        break;
1863
1864      case 'P':
1865        fprintf(stderr,"%.1f%%", (cput*100.0 / (realt ? realt : 1.0)) );
1866        break;
1867
1868#if !defined(SYSV) || defined(__osf__) || defined(_AIX)
1869      case 'W':
1870        {
1871          int i = r1->ru_nswap - r0->ru_nswap;
1872          fprintf(stderr,"%d", i);
1873          break;
1874        }
1875
1876      case 'X':
1877        fprintf(stderr,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
1878        break;
1879
1880      case 'D':
1881        fprintf(stderr,"%ld", t == 0 ? 0 :
1882                (r1->ru_idrss+r1->ru_isrss - (r0->ru_idrss+r0->ru_isrss))/t);
1883        break;
1884
1885      case 'K':
1886        fprintf(stderr,"%ld", t == 0 ? 0 :
1887                ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
1888                 (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
1889        break;
1890
1891      case 'M':
1892        fprintf(stderr,"%ld", r1->ru_maxrss/2);
1893        break;
1894
1895      case 'F':
1896        fprintf(stderr,"%ld", r1->ru_majflt-r0->ru_majflt);
1897        break;
1898
1899      case 'R':
1900        fprintf(stderr,"%ld", r1->ru_minflt-r0->ru_minflt);
1901        break;
1902
1903      case 'I':
1904        fprintf(stderr,"%ld", r1->ru_inblock-r0->ru_inblock);
1905        break;
1906
1907      case 'O':
1908        fprintf(stderr,"%ld", r1->ru_oublock-r0->ru_oublock);
1909        break;
1910
1911      case 'C':
1912        fprintf(stderr,"%ld+%ld",
1913                r1->ru_nvcsw-r0->ru_nvcsw, r1->ru_nivcsw-r0->ru_nivcsw);
1914        break;
1915#endif /* !SYSV || __osf__ */
1916      default:
1917        putc(*cp, stderr);
1918        break;
1919      } /* switch */
1920  } /* for */
1921}
1922/*--------------------------------------------------------------------------*/
1923/* add 2 times structure and move usec bigger than 1000000 to sec */
1924void
1925tvadd(tsum, t0, t1)
1926     struct timeval *tsum, *t0, *t1;
1927{
1928  tsum->tv_sec = t0->tv_sec + t1->tv_sec;
1929  tsum->tv_usec = t0->tv_usec + t1->tv_usec;
1930  if (tsum->tv_usec > 1000000) tsum->tv_sec++, tsum->tv_usec -= 1000000;
1931}
1932/*--------------------------------------------------------------------------*/
1933/* substract 2 time structure (t1 > t0) */
1934void
1935tvsub(tdiff, t1, t0)
1936     struct timeval *tdiff, *t1, *t0;
1937{
1938  tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1939  tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1940  if (tdiff->tv_usec < 0)  tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1941}
1942
1943/*--------------------------------------------------------------------------*/
1944void
1945psecs(int l)
1946{
1947  int i = (int)l/3600;
1948
1949  if (i) {
1950    /* hours:min:sec */
1951    fprintf(stderr,"%d:", i);
1952    i = (int)l % 3600;
1953    fprintf(stderr,"%.2d:%.2d", i/60, i%60);
1954  } else {
1955    /* min:sec */
1956    i = (int)l;
1957    fprintf(stderr,"%d:%.2d", i/60, i%60);
1958  }
1959}
1960/*--------------------------------------------------------------------------*/
1961/*                        N R E A D                                           */
1962
1963int
1964Nread(SOCKET s, void* bufp, int count )
1965{
1966#if defined(__lynx__) || defined(__svr4__) || defined(_AIX) || defined(__NTVIS__) || defined(__FreeBSD__)
1967  struct sockaddr from;
1968#else
1969  struct sockaddr_in from;
1970#endif
1971  int len = sizeof(from);
1972  register int cnt;
1973
1974  if (timeout > 0) {
1975    fd_set readfds, exceptfds;
1976    struct timeval tv_timeout;
1977    int n;
1978
1979    tv_timeout.tv_sec = timeout/1000;
1980    tv_timeout.tv_usec = (timeout%1000)*1000;
1981
1982    FD_ZERO(&readfds);
1983    FD_ZERO(&exceptfds);
1984    FD_SET(s, &readfds);
1985    FD_SET(s, &exceptfds);
1986
1987    n =  select( s+1, &readfds, NULL, &exceptfds, &tv_timeout );
1988    if (n == SOCKET_ERROR) {
1989      sockets_err("select read");
1990    } else if (n == 0) {
1991      return (0);
1992    }
1993
1994  }
1995
1996  if( udp )
1997    {cnt = recvfrom( s, bufp, count, 0, SOCKADDR_CAST &from, &len );
1998    numCalls++;
1999    }
2000  else
2001    {if( b_flag )  cnt = mread( s, bufp, count );        /* fill bufp */
2002    else
2003      {
2004#if defined(__NTVIS__)
2005        cnt = recv( s, bufp, count, 0 );
2006#else
2007        cnt = read( s, bufp, count );
2008#endif /* __NTVIS__ */
2009        numCalls++;
2010      }
2011    if (touchdata && cnt > 0)
2012      {register int c = cnt, sum = 0;
2013       register char *b = bufp;
2014       while (c--) sum += *b++;
2015      }
2016    }
2017  /* rchrch   printf (" numcall %d read buffer %d bytes \n",numCalls,cnt); */
2018  return(cnt);
2019}
2020/*--------------------------------------------------------------------------*/
2021/*                        N W R I T E                                         */
2022
2023int
2024Nwrite( int s, void* bufp, int count )
2025{
2026  register int cnt;
2027  if( udp )
2028    {
2029    again:
2030      cnt = sendto( s, bufp, count, 0, SOCKADDR_CAST &sinhim,
2031                                                sizeof(sinhim) );
2032
2033      numCalls++;
2034
2035#if defined(__NTVIS__)
2036      if( cnt<0 && WSAENOBUFS == WSAGetLastError())
2037#else
2038      if( cnt<0 && errno == ENOBUFS )
2039#endif /* __NTVIS__ */
2040
2041        { delay(18000); errno = 0; goto again; }
2042    }  else /* if (udp) */
2043    {
2044
2045#if defined(__NTVIS__)
2046      cnt = send( s, bufp, count, 0 );
2047      numCalls++;
2048#else
2049      cnt = write( s, bufp, count );
2050      numCalls++;
2051#endif /* __NTVIS__ */
2052    }
2053  return(cnt);
2054}
2055/*--------------------------------------------------------------------------*/
2056void
2057delay(us)
2058int us;
2059{
2060  struct timeval tv;
2061
2062  tv.tv_sec = 0;
2063  tv.tv_usec = (time_t)us;
2064
2065#if defined(__hpux__)
2066  select(1, 0, 0, 0, &tv);
2067#else
2068  select(1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
2069#endif
2070}
2071/*--------------------------------------------------------------------------*/
2072/*                        M R E A D
2073 *
2074 * This function performs the function of a read(II) but will
2075 * call read(II) multiple times in order to get the requested
2076 * number of characters.  This can be necessary because
2077 * network connections don't deliver data with the same
2078 * grouping as it is written with.  Written by Robert S. Miles, BRL.
2079 */
2080int
2081mread(int s, char* bufp, unsigned n)
2082{
2083  register unsigned        count = 0;
2084  register int                nread;
2085
2086  do
2087    {
2088#if defined(__NTVIS__)
2089     nread = recv(s, bufp, n-count, 0);
2090#else
2091     nread = read(s, bufp, n-count);
2092#endif /* __NTVIS__ */
2093     numCalls++;
2094     if(nread < 0)  {perror("ttcp_mread"); return(-1); }
2095     if(nread == 0)  return((int)count);
2096     count += (unsigned)nread;
2097     bufp += nread;
2098    }while(count < n);
2099  return((int)count);
2100}
2101
2102/*--------------------------------------------------------------------------*/
2103void
2104open_log()
2105{static long sysTicks;
2106#if defined(UNDER_CE)
2107	SYSTEMTIME SystemTime;
2108#endif
2109 sprintf(logfile,"%s_%s",logfile_head,trans?"t":"r");
2110
2111 fprintf(stderr,"open the log file >%s<\n",logfile);
2112 if ((fplog = fopen(logfile,"r")) == NULL)
2113
2114   {if ((fplog = fopen(logfile,"a+")) == NULL)
2115     {fprintf(stderr,"Failure : creation of the file >%s< \n",logfile );
2116      exit(1);
2117     }
2118    else
2119     {fprintf(fplog," creation date : ");
2120      /* get date */
2121#if defined(UNDER_CE)
2122	GetLocalTime(&SystemTime);
2123	sprintf(fplog,"%02d-%02d-%02d %02d:%02d\n", SystemTime.wDay, month[SystemTime.wMonth - 1],
2124		SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute);
2125#else
2126      time(&sysTicks);
2127      tms = localtime(&sysTicks);
2128      fprintf(fplog,"%02d-%02d-%02d %02d:%02d\n",
2129              tms->tm_mday, tms->tm_mon, tms->tm_year,tms->tm_hour, tms->tm_min);
2130#endif
2131
2132      /* An other version will produce : Mon Aug  4 16:32:16 1997
2133       * long  lDxcomsTicks;  char *pDateTime;
2134       * time(&lDxcomsTicks);
2135       * pDateTime = ctime(&lDxcomsTicks);  *(pDateTime+24) = '\0';
2136       * fprintf(fplog," ttcp called : %s", pDateTime);
2137       */
2138      fprintf(fplog,"format\n");
2139      fprintf(fplog,",buflen, nbuf(byte), bufalign(byte), bufoffset(byte)");
2140      fprintf(fplog,",  port, sockbufsize(byte), UserTime(sec), SysTime(sec)\n");
2141      fprintf(fplog,",  CPUusage(%%), Validity, nbytes(byte), realt(sec)");
2142      fprintf(fplog,",  rate(MB/sec), I/O call, hours*3600+min*60+sec\n\n");
2143      /* day-month-year, hour:minute\n\n");  */
2144    }
2145  } /* file already exist */
2146   else
2147   {fclose (fplog);
2148     if ((fplog = fopen(logfile,"a+")) == NULL)
2149       {fprintf(stderr,"Failure : access of the file >%s< \n",logfile );
2150        exit(1);
2151           }
2152   }
2153}
2154/*--------------------------------------------------------------------------*/
2155void
2156close_log()
2157{
2158#if defined(UNDER_CE)
2159	SYSTEMTIME SystemTime;
2160
2161	GetLocalTime(&SystemTime);
2162	fprintf(fplog," %d\n", SystemTime.wHour * 3600 + SystemTime.wMinute * 60 + SystemTime.wSecond);
2163#else
2164 static long sysTicks;
2165 time(&sysTicks);
2166 tms = localtime(&sysTicks);
2167 fprintf(fplog," %d\n",((tms->tm_hour)*3600 + (tms->tm_min)*60 + tms->tm_sec));
2168#endif
2169 fclose(fplog);
2170 fflush(fplog);
2171}
2172/*--------------------------------------------------------------------------*/
2173/* routine emulating UNIX function under NT */
2174#if defined(__NTVIS__)
2175
2176/*---------------------------------------------------------------------------*/
2177static void
2178error(char *pch)
2179{
2180        if (!opterr) {
2181                return;                // without printing
2182        }
2183        fprintf(stderr, "%s: %s: %c\n",
2184                (NULL != progname) ? progname : "getopt", pch, optopt);
2185}
2186/*---------------------------------------------------------------------------*/
2187int
2188getopt(int argc, char **argv, char *ostr)
2189{
2190  static char *place = EMSG;    /* option letter processing */
2191  register char *oli;           /* option letter list index */
2192
2193  if (!*place) {
2194    // update scanning pointer
2195    if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) {
2196      place = EMSG;
2197      return -1;
2198    }
2199    // place now points to the first char past the initial '-'
2200    if (place[0] == '-') {
2201      // found "--"
2202      // Was the word just a '--'?
2203      if (place[1] == '\0')
2204        ++optind; // yes, so consume the word
2205      // otherwise, the '--' was the start of a longer word,
2206      // so do not consume it.
2207      place = EMSG;
2208      return -1;
2209    }
2210  }
2211
2212  /* option letter okay? */
2213  if ((optopt = (int)*place++) == (int)':'
2214      || !(oli = strchr(ostr, optopt))) {
2215    if (!*place) {
2216      ++optind;
2217    }
2218    error("illegal option");
2219    return BADCH;
2220  }
2221  if (*++oli != ':') {
2222    /* don't need argument */
2223    optarg = NULL;
2224    if (!*place)
2225      ++optind;
2226  } else {
2227    /* need an argument */
2228    if (*place) {
2229      optarg = place;                /* no white space */
2230    } else  if (argc <= ++optind) {
2231      /* no arg */
2232      place = EMSG;
2233      error("option requires an argument");
2234      return BADCH;
2235    } else {
2236      optarg = argv[optind];                /* white space */
2237    }
2238    place = EMSG;
2239    ++optind;
2240  }
2241  return optopt;                        // return option letter
2242}
2243
2244void
2245usleep(unsigned int microseconds)
2246{
2247  Sleep(microseconds/1000);
2248}
2249#endif /* __NTVIS__ */
2250/*--------------------------------------------------------------------------*/
2251/*--------------------------------------------------------------------------*/
2252void
2253do_help()
2254{
2255char More_help[] =
2256" Details about the reply: \n"
2257"   Example: \n"
2258"   ttcp-t: buflen=8192, nbuf=100, align=16384/0, port=5010\n"
2259"   ttcp-t: File-Descriptor 0x4 Opened\n"
2260"   # tcp sender -> <host> #\n"
2261"   ttcp-t: 819200 bytes in 1.152557 real seconds = 694.109 KB/sec +++\n"
2262"   ttcp-t: 100 I/O calls, 11.526 msec(real)/call, 0.213 msec(cpu)/call\n"
2263"   ttcp-t: 0.001914user 0.019388sys 0:01real 1% 9i+58d 190maxrss 1+2pf 177+180csw\n"
2264"   ttcp-t: buffer address 0x28000\n"
2265"   ttcp-t: File-Descriptor  fd 0x4 Closed\n"
2266"   ttcp done.\n\n"
2267"cpu seconds  ==  (sec) elapse ru_utime + elapse ru_stime.\n"
2268"                 ru_utime == The total amount of time running in user mode.\n"
2269"                 ru_stime == The total amount of time spent in the system.\n"
2270"                             executing on behalf of the process.\n"
2271"real seconds ==  elapse time calculated by the system timer (date).\n"
2272"I/O calls    ==  I/O call to the driver.\n"
2273"msec/call    ==  average elapse time (Real seconds) between each I/O.\n"
2274"calls/sec    ==  invert of msec/call.\n"
2275"user         ==  (sec.msec) elaspe ru_utime.\n"
2276"sys          ==  (sec.msec) elapse ru_stime.\n"
2277"real         ==  (min:sec)  CPU seconds.\n"
2278"%%           ==  Real seconds / CPU seconds.\n"
2279"(ru_ixrss)i+(ru_idrss)d\n"
2280"             ru_ixrss  == An integral value indicating the amount of memory \n"
2281"                          used by the text segment that was also shared among\n"
2282"                          other processes. This value is expressed in units of\n"
2283"                          kilobytes * seconds-of-execution and is calculated \n"
2284"                          by adding the number of shared memory pages in use \n"
2285"                          each time the internal system clock ticks, and then\n"
2286"                          averaging over one-second intervals.\n"
2287"             ru_idrss  == An integral value of the amount of unshared memory \n"
2288"                          in the data segment of a process (expressed in \n"
2289"                          units of kilobytes * seconds-of-execution).\n";
2290
2291char More_help1[] =
2292"  (ru_maxrss/2)maxrss.\n"
2293"             ru_maxrss == The maximum size, in kilobytes, of the used\n"
2294"                          resident set size. \n"
2295"  (ru_majflt)+(ru_minflt)pf : Page fault\n"
2296"             ru_majflt == The number of page faults serviced that required\n"
2297"                          I/O activity.\n"
2298"             ru_minflt == The number of page faults serviced without any\n"
2299"                          I/O activity. In this case, I/O activity is \n"
2300"                          avoided by reclaiming a page frame from the list \n"
2301"                          of pages awaiting reallocation. \n"
2302"(ru_nvcsw)+(ru_nivcsw)csw : context switch\n"
2303"             ru_nvcsw  == The number of times a context switch resulted \n"
2304"                          because a process voluntarily gave up the \n"
2305"                          processor before its time slice was completed. \n"
2306"                          This usually occurs while the process waits \n"
2307"                          for availability of a resource.\n"
2308"             ru_nivcsw == The number of times a context switch resulted \n"
2309"                          because a higher priority process ran or because\n"
2310"                          the current process exceeded its time slice.\n\n";
2311
2312char More_help2[] =
2313"log file format :\n"
2314"         buflen, nbuf(byte), bufalign(byte), bufoffset(byte)\n"
2315"         port, sockbufsize(byte), UserTime(sec), SysTime(sec), CPUusage(%)\n"
2316"         nbytes(byte), realt(sec), rate(MB/sec), I/O call,\n"
2317"                 hours*3600+min*60+sec\n\n";
2318
2319  fprintf(stderr,More_help);
2320  fprintf(stderr,More_help1);
2321  fprintf(stderr,More_help2);
2322}
2323/*---------------------------------------------------------------------------*/
2324void
2325do_Usage()
2326{
2327char Usage[] =
2328"  Usage: ttcp -t [-options] host [ < in ]    ttcp -r [-options > out]\n"
2329"Example: ttcp -t -s -v -n100 host            ttcp -r -s -v -n100\n"
2330"Common options:\n"
2331"    -V      prints version number and date of last modification\n"
2332"    -L      create and append all results to a file named ttcp_log\n"
2333"    -h      more help\n"
2334"    -l ##   length of bufs read from or written to network (default 8192,\n"
2335"            max 65535)\n"
2336"    -u      use UDP instead of TCP\n"
2337"    -p ##   port number to send to or listen at (default 5001)\n"
2338#if defined(__linux__)
2339"    -P ##   link-layer priority (default 0)\n"
2340#endif
2341"    -s      (ttcp -t) : source a pattern to network\n"
2342"            (ttcp -r) : sink (discard) all data from network\n"
2343"    -A ##   align the start of buffers to this modulus (default 16384)\n"
2344"    -O ##   start buffers at this offset from the modulus (default 0)\n"
2345"    -v      verbose: print more statistics\n"
2346"    -d      set SO_DEBUG socket option\n"
2347"    -b ##   set socket buffer size (if supported)\n"
2348"    -f X    format for rate: b,B = bits, bytes k,K = kilo{bits,bytes};\n"
2349"                             m,M = mega{bits,bytes}; g,G = giga{bits,bytes}\n"
2350"    -w ##   set timeout value (in milliseconds) to exit if no receive data or tcp connect\n"
2351"Options specific to (ttcp -t) :\n"
2352"    -n ##   number of source bufs written to network (default 2048)\n"
2353"    -x      use random data in tcp/udp frames (-I provides seed)\n"
2354"    -D      don't buffer TCP writes (sets TCP_NODELAY socket option)\n"
2355"    -H      print hash marks to indicate progress, one per buffer\n"
2356"    -I      init/seed value for RNG when sending random size bufs (default 1)\n"
2357"    -N ##   number of source bufs per burst, i.e between sleeps (default 1)\n"
2358"    -R ##   send random size buffers with minimum size specified, max size\n"
2359"            is value of -l option\n"
2360"    -S ##   millisecs between bursts (only used for udp, 10ms resolution)\n"
2361"Options specific to (ttcp -r) :\n"
2362"    -B      for -s, only output full blocks as specified by -l (for TAR)\n"
2363"    -T      \"touch\": access each byte as it's read\n"
2364"    -i      report information on out of order sequence numbers\n"
2365#if defined(DEBUG)
2366"Options for debug:\n"
2367"    --nostart do not send UDP start packets\n"
2368"    --noend   do not send UDP end packets\n"
2369"    --nodata  do not send UDP data packets\n"
2370"    --debug   print extra debug outputs\n"
2371#endif /* DEBUG */
2372;
2373
2374  fprintf(stderr,Usage);
2375}
2376
2377/* Define automatic Emacs variables for consistent code formatting */
2378/* Local Variables:     */
2379/* c-basic-offset:2     */
2380/* indent-tabs-mode:nil */
2381/* End:                 */
2382