source: network-demos/ttcp/ttcp_orig/ttcp.c @ 544f5a5

network-demos-4-7-branch network-demos-4-7-3
Last change on this file since 544f5a5 was ce34271, checked in by Joel Sherrill <joel.sherrill@…>, on 02/10/99 at 19:57:04

Added debug print when test can't get a buffer. This is probably a fatal
error in the stack but it would be nice to get a message from the
test just in case.

  • Property mode set to 100644
File size: 18.8 KB
Line 
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 * Distribution Status -
36 *      Public Domain.  Distribution Unlimited.
37 *
38 *  $Id$
39 */
40
41#ifndef lint
42static char RCSid[] = "ttcp.c $Revision$";
43#endif
44
45#define BSD43
46/* #define BSD42 */
47/* #define BSD41a */
48/* #define SYSV */      /* required on SGI IRIX releases before 3.3 */
49
50#include <stdio.h>
51#include <signal.h>
52#include <ctype.h>
53#include <errno.h>
54#include <sys/types.h>
55#include <sys/socket.h>
56#include <netinet/in.h>
57#include <netinet/tcp.h>
58#include <arpa/inet.h>
59#include <netdb.h>
60#include <sys/time.h>           /* struct timeval */
61
62#if defined(SYSV)
63#include <sys/times.h>
64#include <sys/param.h>
65struct rusage {
66    struct timeval ru_utime, ru_stime;
67};
68#define RUSAGE_SELF 0
69#else
70#include <sys/resource.h>
71#endif
72
73struct sockaddr_in sinme;
74struct sockaddr_in sinhim;
75struct sockaddr_in frominet;
76
77int domain, fromlen;
78int fd;                         /* fd of network socket */
79
80int buflen = 8 * 1024;          /* length of buffer */
81char *buf;                      /* ptr to dynamic buffer */
82int nbuf = 2 * 1024;            /* number of buffers to send in sinkmode */
83
84int bufoffset = 0;              /* align buffer to this */
85int bufalign = 16*1024;         /* modulo this */
86
87int udp = 0;                    /* 0 = tcp, !0 = udp */
88int options = 0;                /* socket options */
89int one = 1;                    /* for 4.3 BSD style setsockopt() */
90short port = 5001;              /* TCP port number */
91char *host;                     /* ptr to name of host */
92int trans;                      /* 0=receive, !0=transmit mode */
93int sinkmode = 0;               /* 0=normal I/O, !0=sink/source mode */
94int verbose = 0;                /* 0=print basic info, 1=print cpu rate, proc
95                                 * resource usage. */
96int nodelay = 0;                /* set TCP_NODELAY socket option */
97int b_flag = 0;                 /* use mread() */
98int sockbufsize = 0;            /* socket buffer size to use */
99char fmt = 'K';                 /* output format: k = kilobits, K = kilobytes,
100                                 *  m = megabits, M = megabytes,
101                                 *  g = gigabits, G = gigabytes */
102int touchdata = 0;              /* access data after reading */
103
104struct hostent *addr;
105extern int errno;
106extern int optind;
107extern char *optarg;
108
109char Usage[] = "\
110Usage: ttcp -t [-options] host [ < in ]\n\
111       ttcp -r [-options > out]\n\
112Common options:\n\
113        -l ##   length of bufs read from or written to network (default 8192)\n\
114        -u      use UDP instead of TCP\n\
115        -p ##   port number to send to or listen at (default 5001)\n\
116        -s      -t: source a pattern to network\n\
117                -r: sink (discard) all data from network\n\
118        -A      align the start of buffers to this modulus (default 16384)\n\
119        -O      start buffers at this offset from the modulus (default 0)\n\
120        -v      verbose: print more statistics\n\
121        -d      set SO_DEBUG socket option\n\
122        -b ##   set socket buffer size (if supported)\n\
123        -f X    format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
124Options specific to -t:\n\
125        -n##    number of source bufs written to network (default 2048)\n\
126        -D      don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
127Options specific to -r:\n\
128        -B      for -s, only output full blocks as specified by -l (for TAR)\n\
129        -T      \"touch\": access each byte as it's read\n\
130";     
131
132char stats[128];
133double nbytes;                  /* bytes on net */
134unsigned long numCalls;         /* # of I/O system calls */
135double cput, realt;             /* user, real time (seconds) */
136
137void err();
138void mes();
139int pattern();
140void prep_timer();
141double read_timer();
142int Nread();
143int Nwrite();
144void delay();
145int mread();
146char *outfmt();
147
148void
149sigpipe()
150{
151}
152
153main(argc,argv)
154int argc;
155char **argv;
156{
157        unsigned long addr_tmp;
158        int c;
159
160        if (argc < 2) goto usage;
161
162        while ((c = getopt(argc, argv, "drstuvBDTb:f:l:n:p:A:O:")) != -1) {
163                switch (c) {
164
165                case 'B':
166                        b_flag = 1;
167                        break;
168                case 't':
169                        trans = 1;
170                        break;
171                case 'r':
172                        trans = 0;
173                        break;
174                case 'd':
175                        options |= SO_DEBUG;
176                        break;
177                case 'D':
178#ifdef TCP_NODELAY
179                        nodelay = 1;
180#else
181                        fprintf(stderr,
182        "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
183#endif
184                        break;
185                case 'n':
186                        nbuf = atoi(optarg);
187                        break;
188                case 'l':
189                        buflen = atoi(optarg);
190                        break;
191                case 's':
192                        sinkmode = !sinkmode;
193                        break;
194                case 'p':
195                        port = atoi(optarg);
196                        break;
197                case 'u':
198                        udp = 1;
199                        break;
200                case 'v':
201                        verbose = 1;
202                        break;
203                case 'A':
204                        bufalign = atoi(optarg);
205                        break;
206                case 'O':
207                        bufoffset = atoi(optarg);
208                        break;
209                case 'b':
210#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
211                        sockbufsize = atoi(optarg);
212#else
213                        fprintf(stderr,
214"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
215#endif
216                        break;
217                case 'f':
218                        fmt = *optarg;
219                        break;
220                case 'T':
221                        touchdata = 1;
222                        break;
223
224                default:
225                        goto usage;
226                }
227        }
228        if(trans)  {
229                /* xmitr */
230                if (optind == argc)
231                        goto usage;
232                bzero((char *)&sinhim, sizeof(sinhim));
233                host = argv[optind];
234                if (atoi(host) > 0 )  {
235                        /* Numeric */
236                        sinhim.sin_family = AF_INET;
237#if defined(cray)
238                        addr_tmp = inet_addr(host);
239                        sinhim.sin_addr = addr_tmp;
240#else
241                        sinhim.sin_addr.s_addr = inet_addr(host);
242#endif
243                } else {
244                        if ((addr=gethostbyname(host)) == NULL)
245                                err("bad hostname");
246                        sinhim.sin_family = addr->h_addrtype;
247                        bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length);
248#if defined(cray)
249                        sinhim.sin_addr = addr_tmp;
250#else
251                        sinhim.sin_addr.s_addr = addr_tmp;
252#endif /* cray */
253                }
254                sinhim.sin_port = htons(port);
255                sinme.sin_port = 0;             /* free choice */
256        } else {
257                /* rcvr */
258                sinme.sin_port =  htons(port);
259        }
260
261
262        if (udp && buflen < 5) {
263            buflen = 5;         /* send more than the sentinel size */
264        }
265
266        if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
267                err("malloc");
268        if (bufalign != 0)
269                buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign;
270
271        if (trans) {
272            fprintf(stdout,
273            "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
274                buflen, nbuf, bufalign, bufoffset, port);
275            if (sockbufsize)
276                fprintf(stdout, ", sockbufsize=%d", sockbufsize);
277            fprintf(stdout, "  %s  -> %s\n", udp?"udp":"tcp", host);
278        } else {
279            fprintf(stdout,
280            "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
281                buflen, nbuf, bufalign, bufoffset, port);
282            if (sockbufsize)
283                fprintf(stdout, ", sockbufsize=%d", sockbufsize);
284            fprintf(stdout, "  %s\n", udp?"udp":"tcp");
285        }
286
287        if ((fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0)) < 0)
288                err("socket");
289        mes("socket");
290
291        if (bind(fd, &sinme, sizeof(sinme)) < 0)
292                err("bind");
293
294#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
295        if (sockbufsize) {
296            if (trans) {
297                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
298                    sizeof sockbufsize) < 0)
299                        err("setsockopt: sndbuf");
300                mes("sndbuf");
301            } else {
302                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
303                    sizeof sockbufsize) < 0)
304                        err("setsockopt: rcvbuf");
305                mes("rcvbuf");
306            }
307        }
308#endif
309
310        if (!udp)  {
311            signal(SIGPIPE, sigpipe);
312            if (trans) {
313                /* We are the client if transmitting */
314                if (options)  {
315#if defined(BSD42)
316                        if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
317#else /* BSD43 */
318                        if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
319#endif
320                                err("setsockopt");
321                }
322#ifdef TCP_NODELAY
323                if (nodelay) {
324                        struct protoent *p;
325                        p = getprotobyname("tcp");
326                        if( p && setsockopt(fd, p->p_proto, TCP_NODELAY,
327                            &one, sizeof(one)) < 0)
328                                err("setsockopt: nodelay");
329                        mes("nodelay");
330                }
331#endif
332                if(connect(fd, &sinhim, sizeof(sinhim) ) < 0)
333                        err("connect");
334                mes("connect");
335            } else {
336                /* otherwise, we are the server and
337                 * should listen for the connections
338                 */
339#if defined(ultrix) || defined(sgi)
340                listen(fd,1);   /* workaround for alleged u4.2 bug */
341#else
342                listen(fd,0);   /* allow a queue of 0 */
343#endif
344                if(options)  {
345#if defined(BSD42)
346                        if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
347#else /* BSD43 */
348                        if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
349#endif
350                                err("setsockopt");
351                }
352                fromlen = sizeof(frominet);
353                domain = AF_INET;
354                if((fd=accept(fd, &frominet, &fromlen) ) < 0)
355                        err("accept");
356                { struct sockaddr_in peer;
357                  int peerlen = sizeof(peer);
358                  if (getpeername(fd, (struct sockaddr_in *) &peer,
359                                &peerlen) < 0) {
360                        err("getpeername");
361                  }
362                  fprintf(stderr,"ttcp-r: accept from %s\n",
363                        inet_ntoa(peer.sin_addr));
364                }
365            }
366        }
367        prep_timer();
368        errno = 0;
369        if (sinkmode) {     
370                register int cnt;
371                if (trans)  {
372                        pattern( buf, buflen );
373                        if(udp)  (void)Nwrite( fd, buf, 4 ); /* rcvr start */
374                        while (nbuf-- && Nwrite(fd,buf,buflen) == buflen)
375                                nbytes += buflen;
376                        if(udp)  (void)Nwrite( fd, buf, 4 ); /* rcvr end */
377                } else {
378                        if (udp) {
379                            while ((cnt=Nread(fd,buf,buflen)) > 0)  {
380                                    static int going = 0;
381                                    if( cnt <= 4 )  {
382                                            if( going )
383                                                    break;      /* "EOF" */
384                                            going = 1;
385                                            prep_timer();
386                                    } else {
387                                            nbytes += cnt;
388                                    }
389                            }
390                        } else {
391                            while ((cnt=Nread(fd,buf,buflen)) > 0)  {
392                                    nbytes += cnt;
393                            }
394                        }
395                }
396        } else {
397                register int cnt;
398                if (trans)  {
399                        while((cnt=read(0,buf,buflen)) > 0 &&
400                            Nwrite(fd,buf,cnt) == cnt)
401                                nbytes += cnt;
402                }  else  {
403                        while((cnt=Nread(fd,buf,buflen)) > 0 &&
404                            write(1,buf,cnt) == cnt)
405                                nbytes += cnt;
406                }
407        }
408        if(errno) err("IO");
409        (void)read_timer(stats,sizeof(stats));
410        if(udp&&trans)  {
411                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
412                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
413                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
414                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
415        }
416        if( cput <= 0.0 )  cput = 0.001;
417        if( realt <= 0.0 )  realt = 0.001;
418        fprintf(stdout,
419                "ttcp%s: %.0f bytes in %.2f real seconds = %s/sec +++\n",
420                trans?"-t":"-r",
421                nbytes, realt, outfmt(nbytes/realt));
422        if (verbose) {
423            fprintf(stdout,
424                "ttcp%s: %.0f bytes in %.2f CPU seconds = %s/cpu sec\n",
425                trans?"-t":"-r",
426                nbytes, cput, outfmt(nbytes/cput));
427        }
428        fprintf(stdout,
429                "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
430                trans?"-t":"-r",
431                numCalls,
432                1024.0 * realt/((double)numCalls),
433                ((double)numCalls)/realt);
434        fprintf(stdout,"ttcp%s: %s\n", trans?"-t":"-r", stats);
435        if (verbose) {
436            fprintf(stdout,
437                "ttcp%s: buffer address %#x\n",
438                trans?"-t":"-r",
439                buf);
440        }
441        exit(0);
442
443usage:
444        fprintf(stderr,Usage);
445        exit(1);
446}
447
448void
449err(s)
450char *s;
451{
452        fprintf(stderr,"ttcp%s: ", trans?"-t":"-r");
453        perror(s);
454        fprintf(stderr,"errno=%d\n",errno);
455        exit(1);
456}
457
458void
459mes(s)
460char *s;
461{
462        fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
463}
464
465pattern( cp, cnt )
466register char *cp;
467register int cnt;
468{
469        register char c;
470        c = 0;
471        while( cnt-- > 0 )  {
472                while( !isprint((c&0x7F)) )  c++;
473                *cp++ = (c++&0x7F);
474        }
475}
476
477char *
478outfmt(b)
479double b;
480{
481    static char obuf[50];
482    switch (fmt) {
483        case 'G':
484            sprintf(obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
485            break;
486        default:
487        case 'K':
488            sprintf(obuf, "%.2f KB", b / 1024.0);
489            break;
490        case 'M':
491            sprintf(obuf, "%.2f MB", b / 1024.0 / 1024.0);
492            break;
493        case 'g':
494            sprintf(obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
495            break;
496        case 'k':
497            sprintf(obuf, "%.2f Kbit", b * 8.0 / 1024.0);
498            break;
499        case 'm':
500            sprintf(obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
501            break;
502    }
503    return obuf;
504}
505
506static struct   timeval time0;  /* Time at which timing started */
507static struct   rusage ru0;     /* Resource utilization at the start */
508
509static void prusage();
510static void tvadd();
511static void tvsub();
512static void psecs();
513
514#if defined(SYSV)
515/*ARGSUSED*/
516static
517getrusage(ignored, ru)
518    int ignored;
519    register struct rusage *ru;
520{
521    struct tms buf;
522
523    times(&buf);
524
525    /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
526    ru->ru_stime.tv_sec  = buf.tms_stime / HZ;
527    ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
528    ru->ru_utime.tv_sec  = buf.tms_utime / HZ;
529    ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
530}
531
532/*ARGSUSED*/
533static
534gettimeofday(tp, zp)
535    struct timeval *tp;
536    struct timezone *zp;
537{
538    tp->tv_sec = time(0);
539    tp->tv_usec = 0;
540}
541#endif /* SYSV */
542
543/*
544 *                      P R E P _ T I M E R
545 */
546void
547prep_timer()
548{
549        gettimeofday(&time0, (struct timezone *)0);
550        getrusage(RUSAGE_SELF, &ru0);
551}
552
553/*
554 *                      R E A D _ T I M E R
555 *
556 */
557double
558read_timer(str,len)
559char *str;
560{
561        struct timeval timedol;
562        struct rusage ru1;
563        struct timeval td;
564        struct timeval tend, tstart;
565        char line[132];
566
567        getrusage(RUSAGE_SELF, &ru1);
568        gettimeofday(&timedol, (struct timezone *)0);
569        prusage(&ru0, &ru1, &timedol, &time0, line);
570        (void)strncpy( str, line, len );
571
572        /* Get real time */
573        tvsub( &td, &timedol, &time0 );
574        realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
575
576        /* Get CPU time (user+sys) */
577        tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
578        tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
579        tvsub( &td, &tend, &tstart );
580        cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
581        if( cput < 0.00001 )  cput = 0.00001;
582        return( cput );
583}
584
585static void
586prusage(r0, r1, e, b, outp)
587        register struct rusage *r0, *r1;
588        struct timeval *e, *b;
589        char *outp;
590{
591        struct timeval tdiff;
592        register time_t t;
593        register char *cp;
594        register int i;
595        int ms;
596
597        t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
598            (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
599            (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
600            (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
601        ms =  (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
602
603#define END(x)  {while(*x) x++;}
604#if defined(SYSV)
605        cp = "%Uuser %Ssys %Ereal %P";
606#else
607#if defined(sgi)                /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
608        cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
609#else
610        cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
611#endif
612#endif
613        for (; *cp; cp++)  {
614                if (*cp != '%')
615                        *outp++ = *cp;
616                else if (cp[1]) switch(*++cp) {
617
618                case 'U':
619                        tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
620                        sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
621                        END(outp);
622                        break;
623
624                case 'S':
625                        tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
626                        sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
627                        END(outp);
628                        break;
629
630                case 'E':
631                        psecs(ms / 100, outp);
632                        END(outp);
633                        break;
634
635                case 'P':
636                        sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1))));
637                        END(outp);
638                        break;
639
640#if !defined(SYSV)
641                case 'W':
642                        i = r1->ru_nswap - r0->ru_nswap;
643                        sprintf(outp,"%d", i);
644                        END(outp);
645                        break;
646
647                case 'X':
648                        sprintf(outp,"%d", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
649                        END(outp);
650                        break;
651
652                case 'D':
653                        sprintf(outp,"%d", t == 0 ? 0 :
654                            (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
655                        END(outp);
656                        break;
657
658                case 'K':
659                        sprintf(outp,"%d", t == 0 ? 0 :
660                            ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
661                            (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
662                        END(outp);
663                        break;
664
665                case 'M':
666                        sprintf(outp,"%d", r1->ru_maxrss/2);
667                        END(outp);
668                        break;
669
670                case 'F':
671                        sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt);
672                        END(outp);
673                        break;
674
675                case 'R':
676                        sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt);
677                        END(outp);
678                        break;
679
680                case 'I':
681                        sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock);
682                        END(outp);
683                        break;
684
685                case 'O':
686                        sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock);
687                        END(outp);
688                        break;
689                case 'C':
690                        sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw,
691                                r1->ru_nivcsw-r0->ru_nivcsw );
692                        END(outp);
693                        break;
694#endif /* !SYSV */
695                }
696        }
697        *outp = '\0';
698}
699
700static void
701tvadd(tsum, t0, t1)
702        struct timeval *tsum, *t0, *t1;
703{
704
705        tsum->tv_sec = t0->tv_sec + t1->tv_sec;
706        tsum->tv_usec = t0->tv_usec + t1->tv_usec;
707        if (tsum->tv_usec > 1000000)
708                tsum->tv_sec++, tsum->tv_usec -= 1000000;
709}
710
711static void
712tvsub(tdiff, t1, t0)
713        struct timeval *tdiff, *t1, *t0;
714{
715
716        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
717        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
718        if (tdiff->tv_usec < 0)
719                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
720}
721
722static void
723psecs(l,cp)
724long l;
725register char *cp;
726{
727        register int i;
728
729        i = l / 3600;
730        if (i) {
731                sprintf(cp,"%d:", i);
732                END(cp);
733                i = l % 3600;
734                sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10);
735                END(cp);
736        } else {
737                i = l;
738                sprintf(cp,"%d", i / 60);
739                END(cp);
740        }
741        i %= 60;
742        *cp++ = ':';
743        sprintf(cp,"%d%d", i / 10, i % 10);
744}
745
746/*
747 *                      N R E A D
748 */
749Nread( fd, buf, count )
750int fd;
751void *buf;
752int count;
753{
754        struct sockaddr_in from;
755        int len = sizeof(from);
756        register int cnt;
757        if( udp )  {
758                cnt = recvfrom( fd, buf, count, 0, &from, &len );
759                numCalls++;
760        } else {
761                if( b_flag )
762                        cnt = mread( fd, buf, count );  /* fill buf */
763                else {
764                        cnt = read( fd, buf, count );
765                        numCalls++;
766                }
767                if (touchdata && cnt > 0) {
768                        register int c = cnt, sum;
769                        register char *b = buf;
770                        while (c--)
771                                sum += *b++;
772                }
773        }
774        return(cnt);
775}
776
777/*
778 *                      N W R I T E
779 */
780Nwrite( fd, buf, count )
781int fd;
782void *buf;
783int count;
784{
785        register int cnt;
786        if( udp )  {
787again:
788                cnt = sendto( fd, buf, count, 0, &sinhim, sizeof(sinhim) );
789                numCalls++;
790                if( cnt<0 && errno == ENOBUFS )  {
791                        printf("ttcp: out of buffers -- delaying\n"); /*JRS*/
792                        delay(18000);
793                        errno = 0;
794                        goto again;
795                }
796        } else {
797                cnt = write( fd, buf, count );
798                numCalls++;
799        }
800        return(cnt);
801}
802
803void
804delay(us)
805{
806        struct timeval tv;
807
808        tv.tv_sec = 0;
809        tv.tv_usec = us;
810        (void)select( 1, (char *)0, (char *)0, (char *)0, &tv );
811}
812
813/*
814 *                      M R E A D
815 *
816 * This function performs the function of a read(II) but will
817 * call read(II) multiple times in order to get the requested
818 * number of characters.  This can be necessary because
819 * network connections don't deliver data with the same
820 * grouping as it is written with.  Written by Robert S. Miles, BRL.
821 */
822int
823mread(fd, bufp, n)
824int fd;
825register char   *bufp;
826unsigned        n;
827{
828        register unsigned       count = 0;
829        register int            nread;
830
831        do {
832                nread = read(fd, bufp, n-count);
833                numCalls++;
834                if(nread < 0)  {
835                        perror("ttcp_mread");
836                        return(-1);
837                }
838                if(nread == 0)
839                        return((int)count);
840                count += (unsigned)nread;
841                bufp += nread;
842         } while(count < n);
843
844        return((int)count);
845}
Note: See TracBrowser for help on using the repository browser.