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

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