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