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