source: freewrt/package/ttcp/ttcp.c@ 428f140

freewrt_1_0 freewrt_2_0
Last change on this file since 428f140 was 475ad56, checked in by Waldemar Brodkorb <wbx@…>, 20 years ago

add OpenWrt trunk revision 3830.

git-svn-id: svn://www.freewrt.org/trunk/freewrt@1 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 72.8 KB
Line 
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
67static char RCSid[] = "ttcp.c $- CERN Revision: 3.8 (dev level) -$";
68#endif
69
70static char VersDate[] = "Epigram 15-jul-98";
71
72/* system dependent setting
73 * ------------------------
74 * uname -a,gcc -v a.c are the tools used
75 *
76 * Platform/OS #define MACRO predefined
77 * ----------- ------- ---------------------------------------------------
78 * SunOS OS BSD43 __unix__ __sun__ __sparc__
79 * SUN Solaris SYSV __unix__ __sun__ __sparc__ __svr4__
80 * SGI-IRIX < 3.3 SYSV set as #define sgi
81 * HP-UX 9000 SYSV __unix__ __hpux__ __hp9k8__
82 * OSF/1 V3.2 SYSV __unix__ __osf__ __alpha__
83 * OSF/1 V4.0 SYSV __unix__ __osf__ __alpha__ _CFE
84 * LynxOS SYSV __unix__ __lynx__ __powerpc__
85 * Windows NT SYSV __WINNT__ __i386__ __M_COFF__
86 * AIX SYSV _AIX _AIX32 _POWER _IBMR2 _ARCH_PWR
87
88
89 * Micosoft Visual C++ compiler under WindowNT 4.0
90 * Windows NT _WINDOWS WIN32
91
92 * Unix BSD 41a BSD41a
93 * 42 BSD42
94 * 43 BSD43
95
96 * Machines using System V with BSD sockets should define SYSV.
97 *
98 * Compiler commands
99 * -----------------
100 * LynxOS : gcc -c ttcp.c -o ttcp.o | gcc -o ttcp -O ttcp.o -lnetinet -lc_p -lc
101 */
102
103/* -------------attempt to set an automatic UNIX OS family detection -------*/
104
105#if defined(__hp9k8__) || defined(__osf__) || defined(__srv4__)
106#define SYSV
107#endif
108#if defined(__lynx__)
109#define SYSV
110#endif
111/* for solaris (__srv4__) the parameters SYSV is already set */
112
113/* version A.09.01 'key words' differs from A.09.05 A */
114#if defined(__hpux)
115#define __hpux__
116#endif
117
118#if defined(__sun__)&&!defined(__srv4__)
119#define BSD43 /* changed by BSD42 if necessary */
120#endif
121
122#if defined(_WIN32) /* Window NT 4.0 compiled with VisualC++ 4 */
123#define __NTVIS__
124#define SYSV
125#endif
126
127#if defined(__FreeBSD__)
128#define BSD43
129#endif
130
131#if defined(__linux__)
132#define BSD43
133#endif
134/*--------------------------------------------------------------------------*/
135
136#if !defined(UNDER_CE)
137#include <signal.h>
138#include <ctype.h>
139#include <errno.h>
140#include <sys/types.h>
141#endif
142
143#if defined(SYSV)
144
145#if defined(__osf__)
146#include <sys/socket.h>
147#include <netinet/in.h>
148#include <netinet/tcp.h>
149#include <arpa/inet.h>
150#include <netdb.h>
151#include <sys/time.h> /* struct timeval */
152#include <sys/resource.h> /* definition of struct rusage */
153
154#else /* else of __osf__ */
155#if defined(__NTVIS__)
156#include <winsock2.h>
157#include <windows.h> /* required for all Windows applications */
158#include <ws2tcpip.h>
159#include <memory.h>
160#include <time.h>
161#if !defined(UNDER_CE)
162#include <sys\timeb.h>
163#include <fcntl.h>
164#endif
165#include <stdlib.h>
166#include <io.h>
167struct rusage { struct timeval ru_utime, ru_stime; };
168#define RUSAGE_SELF 0
169#else /* else of __NTVIS__ */
170#if defined(__lynx__)
171#include <socket.h> /* located in /usr/include/..... */
172#include <netinet/in.h>
173#include <netinet/tcp.h>
174#include <arpa/inet.h>
175#include <netdb.h>
176#include <time.h>
177#include <resource.h> /* definition of struct rusage */
178#include <sys/times.h>
179#define RUSAGE_SELF 0
180#include <conf.h> /* definition of TICKSPERSEC (HZ) */
181#include <sys/param.h>
182
183#else /* else of __Lynx__ */
184#if defined(__svr4__)
185#include <sys/socket.h>
186#include <sys/uio.h>
187#include <netinet/in.h>
188#include <netinet/tcp.h>
189#include <arpa/inet.h>
190#include <netdb.h>
191#include <sys/time.h> /* struct timeval */
192#include <sys/resource.h> /* definition of struct rusage */
193#include <sys/times.h>
194#define RUSAGE_SELF 0
195#include <sys/param.h>
196
197#else /* else of __svr4__ all SYSV cases except those mentionned before */
198#include <sys/socket.h>
199#include <netinet/in.h>
200#include <netinet/tcp.h>
201#include <arpa/inet.h>
202#include <netdb.h>
203#include <sys/time.h> /* struct timeval */
204#include <sys/resource.h> /* definition of struct rusage */
205#include <sys/times.h>
206#define RUSAGE_SELF 0
207#include <sys/param.h>
208
209#endif /* __svr4__ */
210#endif /* __lynx__ */
211#endif /* __NTVIS__ */
212#endif /* __osf__ */
213
214#else /* else of SYSV it is a BSD OS */
215#include <stdlib.h>
216#include <string.h>
217#include <sys/socket.h>
218#include <netinet/in.h>
219#include <netinet/tcp.h>
220#include <arpa/inet.h>
221#include <netdb.h>
222#if defined(__linux__)
223#include <time.h> /* struct timeval */
224#else
225#include <sys/time.h> /* struct timeval */
226#endif
227#include <sys/resource.h> /* definition of struct rusage */
228#include <unistd.h> /* for usleep() - henry */
229#define SOCKET_ERROR -1
230
231#endif /* SYSV */
232
233#if defined(__NTVIS__)
234
235#if defined(_DEBUG) /* usual debug symbol for VC++ */
236#define DEBUG 1
237#endif
238
239void usleep(unsigned int microseconds);
240
241#define bcopy(a,b,n) memcpy((b), (a), (n))
242#define bzero(a,n) memset((a), 0, (n))
243
244#ifndef _GETOPT_
245#define _GETOPT_
246int getopt(int argc, char **argv, char *optstring);
247
248extern char *optarg; // returned arg to go with this option
249extern int optind; // index to next argv element to process
250extern int opterr; // should error messages be printed?
251extern int optopt; //
252
253#define BADCH ('?')
254#endif // _GETOPT
255
256/* get option letter from argument vector */
257int
258 opterr = 1, // should error messages be printed?
259 optind = 1, // index into parent argv vector
260 optopt; // character checked for validity
261char *optarg; // argument associated with option
262
263#define EMSG ""
264char *progname; // may also be defined elsewhere
265#endif /*__NTVIS__*/
266
267/* sockaddr_in == file server address structure
268 *
269 * Socket address, internet style. declared in : /netinet/in.h
270 * struct sockaddr_in {short sin_family;
271 * u_short sin_port;
272 * struct in_addr sin_addr;
273 * char sin_zero[8];
274 * };
275 *
276 * Structure used by kernel to store most addresses. declared in ./sys/socket.h
277 * struct sockaddr{u_short sa_family; address family
278 * char sa_data[14]; up to 14 bytes of direct address
279 * };
280 * PS : sin stand for "socket internet number"
281 */
282
283#ifndef __NTVIS__
284#define FAR
285#endif
286
287#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__)
296struct sockaddr_in sockaddr; /* done in ./X11/Xdmcp.h */
297#endif
298
299struct sockaddr_in sinme; /* is the socket struct. in the local host */
300struct sockaddr_in sinhim; /* is the socket struc. in the remote host */
301
302#if defined(__lynx__) || defined(__svr4__) || defined(_AIX)
303struct sockaddr frominet;
304#else
305struct sockaddr_in frominet;
306#endif /* __lynx__ */
307
308int domain, fromlen;
309
310#if !defined(__NTVIS__)
311#define SOCKET int
312#endif /* __NTVIS__ */
313SOCKET fd; /* fd of network socket */
314
315#if !defined(__lynx__)
316extern int errno;
317#endif
318
319#include <stdio.h>
320
321FILE *fplog = NULL; /* file pointer for the log file */
322char logfile[100]; /* file name for the log */
323static char logfile_head[] ="ttcp_log"; /* header name for the log */
324int buflen = 8 * 1024; /* length of buffer */
325char *buf; /* ptr to dynamic buffer */
326int 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
334char start_pattern[START_PATTERN_LEN] = {1, 2, 3, 4};
335char end_pattern[END_PATTERN_LEN] = {2, 2, 2, 2};
336
337int bufoffset = 0; /* align buffer to this */
338int bufalign = 16*1024; /* modulo this */
339
340int udp = 0; /* 0 = tcp, !0 = udp */
341int options = 0; /* socket options */
342int one = 1; /* for 4.3 BSD style setsockopt() */
343short port = 5010; /* TCP port number */
344char *host; /* ptr to name of host */
345int rndm = 0; /* 0="normal", !0=random data */
346int trans; /* 0=receive, !0=transmit mode */
347int timeout; /* read timeout in millisec */
348int debug = 0; /* 0=No-Debug, 1=Debug-Set-On */
349int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */
350int verbose = 0; /* 0=print basic info, 1=print cpu rate,
351 * proc resource usage. */
352int nodelay = 0; /* set TCP_NODELAY socket option */
353int pri = 0; /* link layer priority */
354int b_flag = 0; /* use mread() */
355int log_cnt = 0; /* append result to a log */
356int sockbufsize = 0; /* socket buffer size to use */
357char 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) */
363int touchdata = 0; /* access data after reading */
364int seq_info = 0; /* report out of order seq nums */
365
366int hash = 0; /* print hash marks for each buffer */
367int udpsleep = 0; /* sleep in between udp buffers */
368int burstn = 1; /* number of buffers per burst */
369int bufmin = -1; /* minimum buffer size to use when
370 sending random-size buffers */
371unsigned int seed = 1; /* seed for random number generator
372 used for random buffer lengths */
373int no_start = 0; /* skip the start frames for UDP */
374int no_data = 0; /* skip all data frames for UDP */
375int no_end = 0; /* skip the end frames for UDP */
376
377double nbytes; /* bytes on net */
378unsigned long numCalls; /* # of I/O system calls */
379
380struct hostent *addr;
381extern int optind;
382extern char *optarg;
383
384#if defined(UNDER_CE)
385static int errno;
386static char *weekday[] ={"Sun", "Mon","Tues", "Wed", "Thurs", "Fri", "Sat"};
387static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "July", "Aug", "Sep", "Oct", "Nov", "Dec"};
388#define perror printf
389#endif
390
391/*--------------------------------------------------------------------------*/
392static struct timeval time0; /* Time at which timing started */
393static struct timeval time1;
394static struct rusage ru0; /* Resource utilization at the start */
395static struct rusage ru1;
396static 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__)
405int getopt(int, char**, char*);
406int 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
422int printf( char*, ...);
423int fprintf(FILE*,char*, ...);
424void perror(char*);
425int getopt(int, char**, char*);
426int 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
434int main(int argc, char* argv[]);
435#if ( (!(defined(BSD42))) && (!(defined(BSD43))) && (!(defined(__NTVIS__))) )
436int read(int, char*, int);
437int write(int, char*, int);
438int close(int);
439#endif /* !(BSD42) && !(BSD43) */
440int fclose(FILE *stream);
441
442#if !defined(BSD43) && !defined(__NTVIS__)
443void bzero(char*,int);
444void bcopy(char*, char*, int);
445char strncpy(char *s1,char *s2,size_t n);
446int atoi(char*);
447int malloc(int);
448#endif
449
450
451 /* ANSI socket functions prototype /sys/socket.h */
452#if defined(__lynx__)
453int 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 */
459int socket(int, int, int);
460int connect(int, struct sockaddr *, int);
461int bind(int, struct sockaddr *, int);
462int listen(int, int);
463int accept(int, struct sockaddr *, int *);
464int sendto(int, const char *, int, int, const struct sockaddr *, int);
465int recvfrom(int, char *, int, int, struct sockaddr *, int *);
466int getpeername(int, struct sockaddr *, int *);
467int getsockopt(int, int, int, char *, int *);
468int select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
469
470#else
471#if defined(_AIX)
472int select(unsigned long, void *, void *, void *, struct timeval *);
473
474#else
475#if defined(__hpux__)
476int 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
486int socket(int, int, int);
487int connect(int s,struct sockaddr_in *name, int namelen);
488int bind(int s,struct sockaddr *name,int namelen);
489int listen(int, int);
490int accept(int, struct sockaddr_in *, int *);
491int sendto(int, char *, int, int, struct sockaddr_in *, int);
492int recvfrom(int, char *, int, int, struct sockaddr_in *, int *);
493int getpeername(int, struct sockaddr *, int *);
494int setsockopt(int, int, int, char *, int);
495
496int getsockopt(int, int, int, char*, int*);
497int 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 */
507void udp_rcv_test(void);
508double calc_cpu_time(struct rusage *r0, struct rusage *r1);
509double calc_real_time(struct timeval *t0, struct timeval *t1);
510int getrusage(int who,struct rusage *rusage);
511void sockets_err(char*);
512void err(char *);
513void mes(char *);
514void pattern(char *, int);
515int Nread(SOCKET, void *, int);
516int Nwrite(int, void *, int);
517void delay(int);
518int mread(int, char *,unsigned);
519char *outfmt(char format, double b);
520void prep_timer(void);
521void read_timer(void);
522void result_summary(void);
523void prusage(struct rusage*, struct rusage*,
524 struct timeval*, struct timeval*);
525void tvadd(struct timeval *tsum, struct timeval *t0,struct timeval *t1);
526void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
527void psecs(int);
528void open_log(void);
529void close_log(void);
530void do_Usage(void);
531void do_help(void);
532
533/*--------------------------------------------------------------------------*/
534#if !defined(__NTVIS__)
535void
536sigpipe()
537{;
538}
539#endif
540/*--------------------------------------------------------------------------*/
541/*--------------------------------------------------------------------------*/
542int
543main(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
715if (log_cnt) open_log();
716
717/* input error checking */
718if (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}
723if (bufmin < -1) {
724 fprintf(stderr, "ttcp: minimum buffer size specified with -R option must "
725 "be non-negative\n");
726 exit(1);
727}
728if (buflen > 65535) {
729 fprintf(stderr, "ttcp: maximum buffer size specified with -l option must "
730 "be <= 65536\n");
731 exit(1);
732}
733if (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
941errno = 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/*--------------------------------------------------------------------------*/
1277void
1278udp_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 */
1400double
1401calc_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 */
1430double
1431calc_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/*--------------------------------------------------------------------------*/
1455void
1456result_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/*--------------------------------------------------------------------------*/
1519void
1520sockets_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/*--------------------------------------------------------------------------*/
1534void
1535err(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/*--------------------------------------------------------------------------*/
1544void
1545mes(char *s)
1546{
1547 fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
1548}
1549/*--------------------------------------------------------------------------*/
1550void
1551pattern( 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/*--------------------------------------------------------------------------*/
1563char *
1564outfmt(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
1627int
1628getrusage(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__ */
1682return(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*/
1699static
1700gettimeofday(tp, zp)
1701struct timeval *tp;
1702struct 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__ */
1722return(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 */
1732void
1733prep_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 */
1743void
1744read_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 */
1753void
1754prusage(
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 */
1917void
1918tvadd(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) */
1927void
1928tvsub(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/*--------------------------------------------------------------------------*/
1937void
1938psecs(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
1956int
1957Nread(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
2016int
2017Nwrite( 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/*--------------------------------------------------------------------------*/
2049void
2050delay(us)
2051int 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 */
2073int
2074mread(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/*--------------------------------------------------------------------------*/
2096void
2097open_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/*--------------------------------------------------------------------------*/
2148void
2149close_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/*---------------------------------------------------------------------------*/
2170static void
2171error(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/*---------------------------------------------------------------------------*/
2180int
2181getopt(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
2237void
2238usleep(unsigned int microseconds)
2239{
2240 Sleep(microseconds/1000);
2241}
2242#endif /* __NTVIS__ */
2243/*--------------------------------------------------------------------------*/
2244/*--------------------------------------------------------------------------*/
2245void
2246do_help()
2247{
2248char 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
2284char 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
2305char 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/*---------------------------------------------------------------------------*/
2317void
2318do_Usage()
2319{
2320char 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: */
Note: See TracBrowser for help on using the repository browser.