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