Port ttcp to -ng
[openwrt/svn-archive/archive.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: */