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