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