Log In
New Account
  
 
Home My Page Project Tree Code Snippets Project Openings NUTSS
 
 
Summary Tracker Lists CVS Files
 

CVS | Administration

Annotation of libnutss/examples/nutssttcp.c, revision 1.1

1.1     ! saikat      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 Jul 2001 by Pekka Savola <pekkas@netcore.fi>
        !            36:     implement full IPv6 support (server uses ipv6 mapped addresses for ipv4)
        !            37:     fix a few warnings (from *BSD)
        !            38:     fix loads of more warnings
        !            39:     use snprintf with a few fixed-sized buffers, fix format strings
        !            40:  *
        !            41:  * Modified Oct 2001 by Jaakko Kyrö <jkyro@cs.helsinki.fi>
        !            42:  *      Added -I option to specify network interface
        !            43:  *
        !            44:  * Modified Oct 2002 by Pekka Savola <pekkas@netcore.fi>
        !            45:  *      fix port selection for >2^15
        !            46:     clean out _cray, sysv etc. cruft, always build with IPv6
        !            47:  *      major cleanups, should be a bit more readable now
        !            48:  *
        !            49:  * Modified Oct 2002 by Stig Venaas <venaas@uninett.no>
        !            50:  *      added multicast support
        !            51:  *      added -w option to specify microsecond delay between each write
        !            52:  *      further cleanups
        !            53:  *
        !            54:  * Modified Oct 2002 by Pekka Savola <pekkas@netcore.fi>
        !            55:  *      made one variable 'static' to fix compilation on Solaris from <sleinen@switch.ch>
        !            56:  *
        !            57:  * Modified Aug 2004 by Stig Venaas <venaas@uninett.no>
        !            58:  *      Binding to group address when receiving multicast
        !            59:  *      Added SO_REUSEADDR so multiple processes can listen to same port
        !            60:  *
        !            61:  * Modified Jan. 2005 by Vladimir Mencl at Charles University, Prague
        !            62:  *      include stdlib,h (define malloc, required for IA64)
        !            63:  *      clean compile on Linux (IA64, i686), FreeBSD
        !            64:  *
        !            65:  * Distribution Status -
        !            66:  *      Public Domain.  Distribution Unlimited.
        !            67:  */
        !            68: #ifndef lint
        !            69: static char RCSid[] = "ttcp.c $Revision: 1.1 $";
        !            70: /* avoid warning: `RCSid' defined but not used */
        !            71: static char * useRCSid = ( RCSid + ( (char *)&useRCSid - (char *)&useRCSid ) );
        !            72: #endif
        !            73:
        !            74: #include <sys/types.h>
        !            75: #include <sys/socket.h>
        !            76: /* struct timeval */
        !            77: #include <sys/resource.h>
        !            78: #include <net/if.h>
        !            79: #include <netinet/in.h>
        !            80: #include <netinet/tcp.h>
        !            81: #include <arpa/inet.h>
        !            82:
        !            83: #include <ctype.h>
        !            84: #include <errno.h>
        !            85: #include <netdb.h>
        !            86: #include <signal.h>
        !            87: #include <stdio.h>
        !            88: #include <stdlib.h>
        !            89: #include <string.h>
        !            90: #include <unistd.h>
        !            91:
        !            92: struct sockaddr_storage frominet;
        !            93: struct addrinfo hints, *res, *res0;
        !            94: struct ipv6_mreq mreq6;
        !            95: struct ip_mreq mreq;
        !            96:
        !            97: size_t fromlen;
        !            98:     /* fd of network socket */
        !            99:
        !           100:        /* length of buffer */
        !           101:   /* ptr to dynamic buffer */
        !           102:  /* number of buffers to send in sinkmode */
        !           103:
        !           104:    /* align buffer to this */
        !           105:       /* modulo this */
        !           106:
        !           107: /* 0 = tcp, !0 = udp */
        !           108:      /* socket options */
        !           109: int one = 1;                    /* for 4.3 BSD style setsockopt() */
        !           110:  /* TCP/UDP port number */
        !           111:  /* ptr to name of host */
        !           112:   /* 0=receive, !0=transmit mode */
        !           113:     /* 0=normal I/O, !0=sink/source mode */
        !           114:      /* 0=print basic info, 1=print cpu rate, proc
        !           115:     * resource usage. */
        !           116:      /* set TCP_NODELAY socket option */
        !           117:      /* use mread() */
        !           118:  /* socket buffer size to use */
        !           119:      /* output format: k = kilobits, K = kilobytes,
        !           120:     *  m = megabits, M = megabytes,
        !           121:     *  g = gigabits, G = gigabytes */
        !           122:    /* access data after reading */
        !           123: /* usecs to wait between each write */
        !           124:  /* Address family to be determined */
        !           125:
        !           126: extern int errno;
        !           127: extern int optind;
        !           128: extern char *optarg;
        !           129:
        !           130: char Usage[] = "\
        !           131: Usage: ttcp -t [-options] host [ < in ]\n\
        !           132:        ttcp -r [-options] [multicast-group][ > out]\n\
        !           133: Common options:\n\
        !           134:    use IPv4\n\
        !           135:    use IPv6\n\
        !           136: length of bufs read from or written to network (default 8192)\n\
        !           137:    use UDP instead of TCP\n\
        !           138: port number to send to or listen at (default 5001)\n\
        !           139:    -t: source a pattern to network\n\
        !           140:      -r: sink (discard) all data from network\n\
        !           141: align the start of buffers to this modulus (default 16384)\n\
        !           142: start buffers at this offset from the modulus (default 0)\n\
        !           143:    verbose: print more statistics\n\
        !           144:    set SO_DEBUG socket option\n\
        !           145: set socket buffer size (if supported)\n\
        !           146:  format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
        !           147: Options specific to -t:\n\
        !           148: number of source bufs written to network (default 2048)\n\
        !           149:    don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
        !           150: number of microseconds to wait between each write\n\
        !           151: Options specific to -r:\n\
        !           152:    for -s, only output full blocks as specified by -l (for TAR)\n\
        !           153:    \"touch\": access each byte as it's read\n\
        !           154:         -I if   Specify the network interface (e.g. eth0) to use\n\
        !           155: ";
        !           156:
        !           157: char stats[128];
        !           158:       /* bytes on net */
        !           159:       /* # of I/O system calls */
        !           160:   /* user, real time (seconds) */
        !           161:
        !           162: void err();
        !           163: void mes();
        !           164: void pattern();
        !           165: void prep_timer();
        !           166: double read_timer();
        !           167: int Nread();
        !           168: int Nwrite();
        !           169: void delay();
        !           170: int mread();
        !           171: char *outfmt();
        !           172:
        !           173: void
        !           174: sigpipe()
        !           175: {
        !           176: }
        !           177:
        !           178: int
        !           179: main(int argc, char **argv)
        !           180: {
        !           181:       char *device = NULL;
        !           182: /* Address family if multicast, else 0 */
        !           183:       int c;
        !           184:
        !           185:       if (argc < 2) goto usage;
        !           186:
        !           187:       while ((c = getopt(argc, argv, "46drstuvBDTb:f:l:n:p:w:A:O:I:")) != -1) {
        !           188:      switch (c) {
        !           189:      case '4':
        !           190:     af = AF_INET;
        !           191:     break;
        !           192:      case '6':
        !           193:     af = AF_INET6;
        !           194:     break;
        !           195:      case 'I':
        !           196:     device = optarg;
        !           197:     break;
        !           198:      case 'B':
        !           199:     b_flag = 1;
        !           200:     break;
        !           201:      case 't':
        !           202:     trans = 1;
        !           203:     break;
        !           204:      case 'r':
        !           205:     trans = 0;
        !           206:     break;
        !           207:      case 'd':
        !           208:     options |= SO_DEBUG;
        !           209:     break;
        !           210:      case 'D':
        !           211: #ifdef TCP_NODELAY
        !           212:     nodelay = 1;
        !           213: #else
        !           214:     fprintf(stderr,
        !           215:       "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
        !           216: #endif
        !           217:     break;
        !           218:      case 'n':
        !           219:     nbuf = atoi(optarg);
        !           220:     break;
        !           221:      case 'l':
        !           222:     buflen = atoi(optarg);
        !           223:     break;
        !           224:      case 's':
        !           225:     sinkmode = !sinkmode;
        !           226:     break;
        !           227:      case 'p':
        !           228:     port = optarg;
        !           229:     break;
        !           230:      case 'u':
        !           231:     udp = 1;
        !           232:     break;
        !           233:      case 'v':
        !           234:     verbose = 1;
        !           235:     break;
        !           236:      case 'w':
        !           237:     wait = strtol(optarg, (char **)NULL, 10);
        !           238:     break;
        !           239:      case 'A':
        !           240:     bufalign = atoi(optarg);
        !           241:     break;
        !           242:      case 'O':
        !           243:     bufoffset = atoi(optarg);
        !           244:     break;
        !           245:      case 'b':
        !           246: #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
        !           247:     sockbufsize = atoi(optarg);
        !           248: #else
        !           249:     fprintf(stderr,
        !           250: "ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
        !           251: #endif
        !           252:     break;
        !           253:      case 'f':
        !           254:     fmt = *optarg;
        !           255:     break;
        !           256:      case 'T':
        !           257:     touchdata = 1;
        !           258:     break;
        !           259:      default:
        !           260:     goto usage;
        !           261:      }
        !           262:       }
        !           263:
        !           264:       memset(&hints, 0, sizeof(hints));
        !           265:       hints.ai_family = af;
        !           266:       hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
        !           267:
        !           268:       if (trans) {
        !           269:      /* xmitr */
        !           270:      if (optind == argc)
        !           271:     goto usage;
        !           272:      host = argv[optind];
        !           273:      if (getaddrinfo(host, port, &hints, &res) != 0) {
        !           274:     fprintf(stderr, "can't resolve %s port %s\n", host, port);
        !           275:     exit(1);
        !           276:      }
        !           277:
        !           278:      if (udp) {
        !           279:     /* Check if multicast address */
        !           280:     if (res->ai_family == AF_INET6) {
        !           281:                                if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)
        !           282:                                                            res->ai_addr)->sin6_addr)) {
        !           283:                                        maf = AF_INET6;
        !           284:                                }
        !           285:     } else if (res->ai_family == AF_INET) {
        !           286:                                if (IN_MULTICAST(ntohl(((struct sockaddr_in *)
        !           287:                                                  res->ai_addr)->sin_addr.s_addr))) {
        !           288:                                        maf = AF_INET;
        !           289:                                }
        !           290:     }
        !           291:      }
        !           292:       } else {
        !           293:      /* rcvr */
        !           294:      if (udp && optind < argc) {
        !           295:     if (inet_pton(AF_INET, argv[optind], &mreq.imr_multiaddr) <= 0) {
        !           296:                                if (inet_pton(AF_INET6, argv[optind], &mreq6.ipv6mr_multiaddr) <= 0) {
        !           297:                                        fprintf(stderr, "%s is not a multicast address\n", argv[optind]);
        !           298:                                        exit(1);
        !           299:                                }
        !           300:                                /* IPv6 */
        !           301:                                if (!IN6_IS_ADDR_MULTICAST(&mreq6.ipv6mr_multiaddr)) {
        !           302:                                        fprintf(stderr, "%s is not a multicast address\n", argv[optind]);
        !           303:                                        exit(1);
        !           304:                                }
        !           305:                                hints.ai_family = AF_INET6;
        !           306:                                maf = AF_INET6;
        !           307:                                mreq6.ipv6mr_interface = 0;
        !           308:     } else {
        !           309:                                /* IPv4 */
        !           310:                                if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
        !           311:                                        fprintf(stderr, "%s is not a multicast address\n", argv[optind]);
        !           312:                                        exit(1);
        !           313:                                }
        !           314:                                hints.ai_family = AF_INET;
        !           315:                                maf = AF_INET;
        !           316:                                mreq.imr_interface.s_addr = INADDR_ANY;
        !           317:     }
        !           318:     host = argv[optind];
        !           319:     hints.ai_flags = AI_NUMERICHOST;
        !           320:      } else {
        !           321:     host = NULL;
        !           322:     hints.ai_flags = AI_PASSIVE;
        !           323:      }
        !           324:      if (getaddrinfo(host, port, &hints, &res0) != 0) {
        !           325:     fprintf(stderr, "can't resolve %s\n", port);
        !           326:     exit(1);
        !           327:      }
        !           328:
        !           329:      /* if libc supports ipv6 but kernel doesn't: get the first one */
        !           330:      /* XXX: uses ipv6 mapped addresses as generic methods aren't there yet */
        !           331:      for (res = res0; res; res = res->ai_next) {
        !           332:     if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) > 0)
        !           333:    break;
        !           334:      }
        !           335:       }
        !           336:
        !           337:       if (udp && buflen < 5) {
        !           338:      /* send more than the sentinel size */
        !           339:       }
        !           340:
        !           341:       if ((buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
        !           342:      err("malloc");
        !           343:       if (bufalign != 0)
        !           344:      buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign;
        !           345:
        !           346:       if (trans) {
        !           347:      fprintf(stderr, "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%s",
        !           348:     buflen, nbuf, bufalign, bufoffset, port);
        !           349:      if (sockbufsize)
        !           350:    fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           351:      fprintf(stderr, "  %s  -> %s\n", udp ? "udp" : "tcp", host);
        !           352:       } else {
        !           353:      fprintf(stderr, "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%s",
        !           354:    buflen, nbuf, bufalign, bufoffset, port);
        !           355:     if (sockbufsize)
        !           356:     fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           357:      fprintf(stderr, "  %s\n", udp ? "udp" : "tcp");
        !           358:       }
        !           359:
        !           360:       if (!fd) {
        !           361:      if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
        !           362:     err("socket");
        !           363:       }
        !           364:
        !           365:       if (device) {
        !           366:      if (maf == AF_INET) {
        !           367:     /* Not supported, using struct ip_mreq we need to find IP
        !           368:      * address of interface, at least linux has ip_mreqn which
        !           369:      * uses interface index
        !           370:      */
        !           371:      } else if (maf == AF_INET6) {
        !           372:     if ((mreq6.ipv6mr_interface = if_nametoindex(device)) == 0) {
        !           373:    err("unknown device");
        !           374:     }
        !           375:      } else {
        !           376:     struct ifreq ifr;
        !           377:     memset(&ifr, 0, sizeof(ifr));
        !           378:     strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
        !           379:     ifr.ifr_name[IFNAMSIZ-1] = '\0';
        !           380: #ifdef SO_BINDTODEVICE
        !           381:     if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr,sizeof(ifr)) == -1) {
        !           382:    err("bind-to-device");
        !           383:     }
        !           384: #else
        !           385:     fprintf(stderr, "ttcp: warning: setting device not supported!\n");
        !           386: #endif
        !           387:      }
        !           388:       }
        !           389:       mes("socket");
        !           390:
        !           391:       if (maf == AF_INET) {
        !           392:      if (trans) {
        !           393:     /* set hop limit, default 1. Should perhaps be an option */
        !           394:     int ttl=30;
        !           395:     setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
        !           396:      } else {
        !           397:     /* join the group */
        !           398:     setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
        !           399:      }
        !           400:       } else if (maf == AF_INET6) {
        !           401:      if (trans) {
        !           402:     /* set hop limit, default 1. Should perhaps be an option */
        !           403:     int hops=30;
        !           404:     setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(hops));
        !           405:      } else {
        !           406:     /* join the group */
        !           407:     setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6));
        !           408:      }
        !           409:       }
        !           410:
        !           411:       if (!trans) {
        !           412: #ifdef SO_REUSEADDR
        !           413:      if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
        !           414:     err("reuseaddr");
        !           415: #endif
        !           416:      if (bind(fd, (struct sockaddr *)res->ai_addr, res->ai_addrlen) < 0)
        !           417:     err("bind");
        !           418:       }
        !           419:
        !           420: #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
        !           421:       if (sockbufsize) {
        !           422:           if (trans) {
        !           423:      if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
        !           424:          sizeof sockbufsize) < 0)
        !           425:     err("setsockopt: sndbuf");
        !           426:      mes("sndbuf");
        !           427:           } else {
        !           428:      if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
        !           429:          sizeof sockbufsize) < 0)
        !           430:     err("setsockopt: rcvbuf");
        !           431:      mes("rcvbuf");
        !           432:           }
        !           433:       }
        !           434: #endif
        !           435:
        !           436:       if (!udp)  {
        !           437:           signal(SIGPIPE, sigpipe);
        !           438:           if (trans) {
        !           439:      /* We are the client if transmitting */
        !           440:      if (options)  {
        !           441:     if (setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
        !           442:    err("setsockopt");
        !           443:      }
        !           444: #ifdef TCP_NODELAY
        !           445:      if (nodelay) {
        !           446:     struct protoent *p;
        !           447:     p = getprotobyname("tcp");
        !           448:     if (p && setsockopt(fd, p->p_proto, TCP_NODELAY,
        !           449:         &one, sizeof(one)) < 0)
        !           450:    err("setsockopt: nodelay");
        !           451:     mes("nodelay");
        !           452:      }
        !           453: #endif
        !           454:      if (connect(fd, (struct sockaddr *)res->ai_addr, res->ai_addrlen) < 0)
        !           455:     err("connect");
        !           456:      mes("connect");
        !           457:           } else {
        !           458:      /* otherwise, we are the server and
        !           459:                * should listen for the connections
        !           460:                */
        !           461:      listen(fd, 0);   /* allow a queue of 0 */
        !           462:      if (options) {
        !           463:     if (setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
        !           464:    err("setsockopt");
        !           465:      }
        !           466:      fromlen = sizeof(frominet);
        !           467:
        !           468:      if ((fd = accept(fd, (struct sockaddr*)&frominet, &fromlen)) < 0)
        !           469:     err("accept");
        !           470:      {
        !           471:        struct sockaddr_storage peer;
        !           472:        char addr_buf[NI_MAXHOST];
        !           473:        size_t peerlen = sizeof(peer);
        !           474:
        !           475:        if (getpeername(fd, (struct sockaddr*) &peer, &peerlen) < 0)
        !           476:     err("getpeername");
        !           477:        if (getnameinfo((struct sockaddr *) &peer, res->ai_addrlen, addr_buf,
        !           478:  sizeof(addr_buf), NULL, 0, NI_NUMERICHOST))
        !           479:   err("getnameinfo");
        !           480:        fprintf(stderr,"ttcp-r: accept from %s\n", addr_buf);
        !           481:      }
        !           482:           }
        !           483:       }
        !           484:       prep_timer();
        !           485:       errno = 0;
        !           486:       if (sinkmode) {
        !           487:      register int cnt;
        !           488:      if (trans) {
        !           489:     pattern(buf, buflen);
        !           490:     if (udp)
        !           491:    (void)Nwrite(fd, buf, 4); /* rcvr start */
        !           492:     while (nbuf-- && Nwrite(fd, buf, buflen) == buflen)
        !           493:    nbytes += buflen;
        !           494:     if (udp)
        !           495:    (void)Nwrite(fd, buf, 4); /* rcvr end */
        !           496:      } else {
        !           497:     if (udp) {
        !           498:         while ((cnt = Nread(fd, buf, buflen)) > 0)  {
        !           499:        static int going = 0;
        !           500:        if (cnt <= 4) {
        !           501:       if (going)
        !           502:       /* "EOF" */
        !           503:       going = 1;
        !           504:       prep_timer();
        !           505:        } else
        !           506:       nbytes += cnt;
        !           507:         }
        !           508:     } else {
        !           509:         while ((cnt = Nread(fd, buf, buflen)) > 0)  {
        !           510:        nbytes += cnt;
        !           511:         }
        !           512:     }
        !           513:      }
        !           514:       } else {
        !           515:      register int cnt;
        !           516:      if (trans) {
        !           517:     while ((cnt = read(0, buf, buflen)) > 0 &&
        !           518:         Nwrite(fd, buf, cnt) == cnt)
        !           519:    nbytes += cnt;
        !           520:      } else {
        !           521:     while ((cnt = Nread(fd, buf, buflen)) > 0 &&
        !           522:         write(1, buf, cnt) == cnt)
        !           523:    nbytes += cnt;
        !           524:      }
        !           525:       }
        !           526:       if (errno)
        !           527:      err("IO");
        !           528:       (void)read_timer(stats, sizeof(stats));
        !           529:       if (udp && trans)  {
        !           530:      (void)Nwrite(fd, buf, 4); /* rcvr end */
        !           531:      (void)Nwrite(fd, buf, 4); /* rcvr end */
        !           532:      (void)Nwrite(fd, buf, 4); /* rcvr end */
        !           533:      (void)Nwrite(fd, buf, 4); /* rcvr end */
        !           534:       }
        !           535:       if (cput <= 0.0)
        !           536:      cput = 0.001;
        !           537:       if (realt <= 0.0)
        !           538:      realt = 0.001;
        !           539:       fprintf(stderr,
        !           540:      "ttcp%s: %.0f bytes in %.2f real seconds = %s/sec +++\n",
        !           541:      trans ? "-t" : "-r",
        !           542:      nbytes, realt, outfmt(nbytes/realt));
        !           543:       if (verbose) {
        !           544:           fprintf(stderr,
        !           545:      "ttcp%s: %.0f bytes in %.2f CPU seconds = %s/cpu sec\n",
        !           546:      trans ? "-t" : "-r",
        !           547:      nbytes, cput, outfmt(nbytes/cput));
        !           548:       }
        !           549:       fprintf(stderr,
        !           550:      "ttcp%s: %ld I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
        !           551:      trans ? "-t" : "-r",
        !           552:      numCalls,
        !           553:      1024.0 * realt/((double)numCalls),
        !           554:      ((double)numCalls)/realt);
        !           555:       fprintf(stderr, "ttcp%s: %s\n", trans ? "-t" : "-r", stats);
        !           556:       if (verbose) {
        !           557:           fprintf(stderr,
        !           558:      "ttcp%s: buffer address %p\n",
        !           559:      trans ? "-t" : "-r",
        !           560:      buf);
        !           561:       }
        !           562:       exit(0);
        !           563:
        !           564: usage:
        !           565:       fprintf(stderr, "%s", Usage);
        !           566:       exit(1);
        !           567: }
        !           568:
        !           569: void
        !           570: err(char *s)
        !           571: {
        !           572:       fprintf(stderr, "ttcp%s: ", trans ? "-t" : "-r");
        !           573:       perror(s);
        !           574:       fprintf(stderr, "errno=%d\n", errno);
        !           575:       exit(1);
        !           576: }
        !           577:
        !           578: void
        !           579: mes(char *s)
        !           580: {
        !           581:       fprintf(stderr, "ttcp%s: %s\n", trans ? "-t" : "-r", s);
        !           582: }
        !           583:
        !           584: void
        !           585: pattern(register char *cp, register int cnt)
        !           586: {
        !           587:       register char c;
        !           588:       c = 0;
        !           589:       while (cnt-- > 0) {
        !           590:      while (!isprint((c&0x7F))) c++;
        !           591:      *cp++ = (c++&0x7F);
        !           592:       }
        !           593: }
        !           594:
        !           595: char *
        !           596: outfmt(double b)
        !           597: {
        !           598:     static char obuf[50];
        !           599:     switch (fmt) {
        !           600:       case 'G':
        !           601:           snprintf(obuf, sizeof(obuf), "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
        !           602:           break;
        !           603:       default:
        !           604:       case 'K':
        !           605:           snprintf(obuf, sizeof(obuf), "%.2f KB", b / 1024.0);
        !           606:           break;
        !           607:       case 'M':
        !           608:           snprintf(obuf, sizeof(obuf), "%.2f MB", b / 1024.0 / 1024.0);
        !           609:           break;
        !           610:       case 'g':
        !           611:           snprintf(obuf, sizeof(obuf), "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
        !           612:           break;
        !           613:       case 'k':
        !           614:           snprintf(obuf, sizeof(obuf), "%.2f Kbit", b * 8.0 / 1024.0);
        !           615:           break;
        !           616:       case 'm':
        !           617:           snprintf(obuf, sizeof(obuf), "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
        !           618:           break;
        !           619:     }
        !           620:     return obuf;
        !           621: }
        !           622:
        !           623:   /* Time at which timing started */
        !           624:      /* Resource utilization at the start */
        !           625:
        !           626: static void prusage();
        !           627: static void tvadd();
        !           628: static void tvsub();
        !           629: static void psecs();
        !           630:
        !           631: /*
        !           632:   P R E P _ T I M E R
        !           633:  */
        !           634: void
        !           635: prep_timer()
        !           636: {
        !           637:       gettimeofday(&time0, (struct timezone *)0);
        !           638:       getrusage(RUSAGE_SELF, &ru0);
        !           639: }
        !           640:
        !           641: /*
        !           642:   R E A D _ T I M E R
        !           643:  *
        !           644:  */
        !           645: double
        !           646: read_timer(char *str, int len)
        !           647: {
        !           648:       struct timeval timedol;
        !           649:       struct rusage ru1;
        !           650:       struct timeval td;
        !           651:       struct timeval tend, tstart;
        !           652:       char line[132];
        !           653:
        !           654:       getrusage(RUSAGE_SELF, &ru1);
        !           655:       gettimeofday(&timedol, (struct timezone *)0);
        !           656:       prusage(&ru0, &ru1, &timedol, &time0, line);
        !           657:       /* XXX: buffer overflow if len > sizeof(line) */
        !           658:       (void)strncpy(str, line, len);
        !           659:
        !           660:       /* Get real time */
        !           661:       tvsub(&td, &timedol, &time0);
        !           662:       realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
        !           663:
        !           664:       /* Get CPU time (user+sys) */
        !           665:       tvadd(&tend, &ru1.ru_utime, &ru1.ru_stime);
        !           666:       tvadd(&tstart, &ru0.ru_utime, &ru0.ru_stime);
        !           667:       tvsub(&td, &tend, &tstart);
        !           668:       cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
        !           669:       if (cput < 0.00001)
        !           670:      cput = 0.00001;
        !           671:       return(cput);
        !           672: }
        !           673:
        !           674: static void
        !           675: prusage(register struct rusage *r0, register struct rusage *r1,
        !           676:       struct timeval *e, struct timeval *b, char *outp)
        !           677: {
        !           678:       struct timeval tdiff;
        !           679:       register time_t t;
        !           680:       register char *cp;
        !           681:       register int i;
        !           682:       int ms;
        !           683:
        !           684:       t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
        !           685:           (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
        !           686:           (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
        !           687:           (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
        !           688:       ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
        !           689:
        !           690: {while(*x) x++;}
        !           691:       cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
        !           692:       for (; *cp; cp++) {
        !           693:      if (*cp != '%')
        !           694:     *outp++ = *cp;
        !           695:      else if (cp[1]) switch(*++cp) {
        !           696:
        !           697:      case 'U':
        !           698:     tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
        !           699:     sprintf(outp, "%ld.%01ld", (long)tdiff.tv_sec, ((long)tdiff.tv_usec)/100000);
        !           700:     END(outp);
        !           701:     break;
        !           702:
        !           703:      case 'S':
        !           704:     tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
        !           705:    sprintf(outp, "%ld.%01ld", (long)tdiff.tv_sec, ((long)tdiff.tv_usec)/100000);
        !           706:     END(outp);
        !           707:     break;
        !           708:
        !           709:      case 'E':
        !           710:     psecs(ms / 100, outp);
        !           711:     END(outp);
        !           712:     break;
        !           713:
        !           714:      case 'P':
        !           715:     sprintf(outp, "%d%%", (int) (t*100 / ((ms ? ms : 1))));
        !           716:     END(outp);
        !           717:     break;
        !           718:
        !           719:      case 'W':
        !           720:     i = r1->ru_nswap - r0->ru_nswap;
        !           721:     sprintf(outp, "%ld", i);
        !           722:     END(outp);
        !           723:     break;
        !           724:
        !           725:      case 'X':
        !           726:     sprintf(outp, "%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
        !           727:     END(outp);
        !           728:     break;
        !           729:
        !           730:      case 'D':
        !           731:     sprintf(outp, "%ld", t == 0 ? 0 :
        !           732:         (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
        !           733:     END(outp);
        !           734:     break;
        !           735:
        !           736:      case 'K':
        !           737:     sprintf(outp, "%ld", t == 0 ? 0 :
        !           738:         ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
        !           739:         (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
        !           740:     END(outp);
        !           741:     break;
        !           742:
        !           743:      case 'M':
        !           744:     sprintf(outp, "%ld", r1->ru_maxrss/2);
        !           745:     END(outp);
        !           746:     break;
        !           747:
        !           748:      case 'F':
        !           749:     sprintf(outp, "%ld", r1->ru_majflt-r0->ru_majflt);
        !           750:     END(outp);
        !           751:     break;
        !           752:
        !           753:      case 'R':
        !           754:     sprintf(outp, "%ld", r1->ru_minflt-r0->ru_minflt);
        !           755:     END(outp);
        !           756:     break;
        !           757:
        !           758:      case 'I':
        !           759:     sprintf(outp, "%ld", r1->ru_inblock-r0->ru_inblock);
        !           760:     END(outp);
        !           761:     break;
        !           762:
        !           763:      case 'O':
        !           764:     sprintf(outp, "%ld", r1->ru_oublock-r0->ru_oublock);
        !           765:     END(outp);
        !           766:     break;
        !           767:      case 'C':
        !           768:     sprintf(outp, "%ld+%ld", r1->ru_nvcsw-r0->ru_nvcsw,
        !           769:    r1->ru_nivcsw-r0->ru_nivcsw );
        !           770:     END(outp);
        !           771:     break;
        !           772:      }
        !           773:       }
        !           774:       *outp = '\0';
        !           775: }
        !           776:
        !           777: static void
        !           778: tvadd(struct timeval *tsum, struct timeval *t0, struct timeval *t1)
        !           779: {
        !           780:       tsum->tv_sec = t0->tv_sec + t1->tv_sec;
        !           781:       tsum->tv_usec = t0->tv_usec + t1->tv_usec;
        !           782:       if (tsum->tv_usec > 1000000)
        !           783:      tsum->tv_sec++, tsum->tv_usec -= 1000000;
        !           784: }
        !           785:
        !           786: static void
        !           787: tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
        !           788: {
        !           789:       tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
        !           790:       tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
        !           791:       if (tdiff->tv_usec < 0)
        !           792:      tdiff->tv_sec--, tdiff->tv_usec += 1000000;
        !           793: }
        !           794:
        !           795: static void
        !           796: psecs(long l, register char *cp)
        !           797: {
        !           798:       register int i;
        !           799:
        !           800:       i = l / 3600;
        !           801:       if (i) {
        !           802:      sprintf(cp, "%d:", i);
        !           803:      END(cp);
        !           804:      i = l % 3600;
        !           805:      sprintf(cp, "%d%d", (i/60) / 10, (i/60) % 10);
        !           806:      END(cp);
        !           807:       } else {
        !           808:      i = l;
        !           809:      sprintf(cp, "%d", i / 60);
        !           810:      END(cp);
        !           811:       }
        !           812:       i %= 60;
        !           813:       *cp++ = ':';
        !           814:       sprintf(cp, "%d%d", i / 10, i % 10);
        !           815: }
        !           816:
        !           817: /*
        !           818:   N R E A D
        !           819:  */
        !           820: int
        !           821: Nread(int fd, void *buf, int count)
        !           822: {
        !           823:       struct sockaddr_in from;
        !           824:       size_t len = sizeof(from);
        !           825:       register int cnt;
        !           826:       if (udp) {
        !           827:      cnt = recvfrom(fd, buf, count, 0, (struct sockaddr *)&from, &len);
        !           828:      numCalls++;
        !           829:       } else {
        !           830:      if (b_flag)
        !           831:        /* fill buf */
        !           832:      else {
        !           833:     cnt = read(fd, buf, count);
        !           834:     numCalls++;
        !           835:      }
        !           836:      if (touchdata && cnt > 0) {
        !           837:     register int c = cnt, sum = 0;
        !           838:     register char *b = buf;
        !           839:     while (c--)
        !           840:    sum += *b++;
        !           841:      }
        !           842:       }
        !           843:       return(cnt);
        !           844: }
        !           845:
        !           846: /*
        !           847:   N W R I T E
        !           848:  */
        !           849: int
        !           850: Nwrite(int fd, void *buf, int count)
        !           851: {
        !           852:       register int cnt;
        !           853:       if (udp) {
        !           854: again:
        !           855:      cnt = sendto(fd, buf, count, 0, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
        !           856:      numCalls++;
        !           857:      if (cnt<0 && errno == ENOBUFS)  {
        !           858:     delay(18000);
        !           859:     errno = 0;
        !           860:     goto again;
        !           861:      }
        !           862:       } else {
        !           863:      cnt = write(fd, buf, count);
        !           864:      numCalls++;
        !           865:       }
        !           866:       if (wait)
        !           867:      delay(wait);
        !           868:       return(cnt);
        !           869: }
        !           870:
        !           871: void
        !           872: delay(int us)
        !           873: {
        !           874:       struct timeval tv;
        !           875:
        !           876:       tv.tv_sec = 0;
        !           877:       tv.tv_usec = us;
        !           878:       (void)select(1, NULL, NULL, NULL, &tv);
        !           879: }
        !           880:
        !           881: /*
        !           882:   M R E A D
        !           883:  *
        !           884:  * This function performs the function of a read(II) but will
        !           885:  * call read(II) multiple times in order to get the requested
        !           886:  * number of characters.  This can be necessary because
        !           887:  * network connections don't deliver data with the same
        !           888:  * grouping as it is written with.  Written by Robert S. Miles, BRL.
        !           889:  */
        !           890: int
        !           891: mread(int fd, register char *bufp, unsigned int n)
        !           892: {
        !           893:     count = 0;
        !           894: nread;
        !           895:
        !           896:       do {
        !           897:      nread = read(fd, bufp, n-count);
        !           898:      numCalls++;
        !           899:      if(nread < 0)  {
        !           900:     perror("ttcp_mread");
        !           901:     return(-1);
        !           902:      }
        !           903:      if(nread == 0)
        !           904:     return((int)count);
        !           905:      count += (unsigned)nread;
        !           906:      bufp += nread;
        !           907:        } while(count < n);
        !           908:
        !           909:       return((int)count);
        !           910: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
 

GForge.cis.cornell.edu is brought to you by

Cornell Computing and Information Science


Powered By GForge Collaborative Development Environment