~ubuntu-branches/ubuntu/trusty/netpipe/trusty

« back to all changes in this revision

Viewing changes to src/tcp6.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2010-01-06 19:07:32 UTC
  • mfrom: (4.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20100106190732-fg9urgk31weolrcs
Tags: 3.7.1-1
* New upstream release
* Bug fix: "debian/watch fails to report upstream's version", thanks
  to Raphael Geissert (Closes: #450010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************/
 
2
/* "NetPIPE" -- Network Protocol Independent Performance Evaluator.          */
 
3
/* Copyright 1997, 1998 Iowa State University Research Foundation, Inc.      */
 
4
/*                                                                           */
 
5
/* This program is free software; you can redistribute it and/or modify      */
 
6
/* it under the terms of the GNU General Public License as published by      */
 
7
/* the Free Software Foundation.  You should have received a copy of the     */
 
8
/* GNU General Public License along with this program; if not, write to the  */
 
9
/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
 
10
/*                                                                           */
 
11
/* TCP6 extension Copyright 2004 George V. Neville-Neil and Neville-Neil     */
 
12
/* Consulting                                                                */
 
13
/*                                                                           */
 
14
/*     * tcp6.c         ---- TCP over IPv6 calls source                      */
 
15
/*     * tcp.h          ---- Include file for TCP6 calls and data structs    */
 
16
/*****************************************************************************/
 
17
#include    "netpipe.h"
 
18
 
 
19
#if defined (MPLITE)
 
20
#include "mplite.h"
 
21
#endif
 
22
 
 
23
 
 
24
int doing_reset = 0;
 
25
 
 
26
void Init(ArgStruct *p, int* pargc, char*** pargv)
 
27
{
 
28
    p->reset_conn = 0; /* Default to not resetting connection */
 
29
    p->prot.sndbufsz = p->prot.rcvbufsz = 0;
 
30
    /* The transmitter will be set using the -h host flag. */
 
31
    p->tr = 0;
 
32
    p->rcv = 1;
 
33
}
 
34
 
 
35
void Setup(ArgStruct *p)
 
36
{
 
37
    int one = 1;
 
38
    int sockfd = -1;
 
39
    /* ptr to sockaddr_in in ArgStruct */
 
40
    struct sockaddr_in6 *lsin1, *lsin2;      
 
41
    
 
42
    char *host;
 
43
    struct hostent *hp;
 
44
    struct protoent *proto;
 
45
    int send_size, recv_size, sizeofint = sizeof(int);
 
46
        
 
47
    host = p->host;                           /* copy ptr to hostname */ 
 
48
        
 
49
    lsin1 = &(p->prot.sin1);
 
50
    lsin2 = &(p->prot.sin2);
 
51
        
 
52
    bzero((char *) lsin1, sizeof(*lsin1));
 
53
    bzero((char *) lsin2, sizeof(*lsin2));
 
54
 
 
55
    if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0){
 
56
        printf("NetPIPE: can't open stream socket! errno=%d\n", errno);
 
57
        exit(-4);
 
58
    }
 
59
 
 
60
    if(!(proto = getprotobyname("tcp"))){
 
61
        printf("NetPIPE: protocol 'tcp' unknown!\n");
 
62
        exit(555);
 
63
    }
 
64
 
 
65
    /* Attempt to set TCP_NODELAY */
 
66
 
 
67
    if(setsockopt(sockfd, proto->p_proto, TCP_NODELAY, &one, sizeof(one)) < 0)
 
68
    {
 
69
        printf("NetPIPE: setsockopt: TCP_NODELAY failed! errno=%d\n", errno);
 
70
        exit(556);
 
71
    }
 
72
 
 
73
    /* If requested, set the send and receive buffer sizes */
 
74
 
 
75
    if(p->prot.sndbufsz > 0)
 
76
    {
 
77
        if(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz), 
 
78
                      sizeof(p->prot.sndbufsz)) < 0)
 
79
        {
 
80
            printf("NetPIPE: setsockopt: SO_SNDBUF failed! errno=%d\n", errno);
 
81
            printf("You may have asked for a buffer larger than the system can handle\n");
 
82
            exit(556);
 
83
        }
 
84
        if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz), 
 
85
                      sizeof(p->prot.rcvbufsz)) < 0)
 
86
        {
 
87
            printf("NetPIPE: setsockopt: SO_RCVBUF failed! errno=%d\n", errno);
 
88
            printf("You may have asked for a buffer larger than the system can handle\n");
 
89
            exit(556);
 
90
        }
 
91
    }
 
92
    getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
 
93
               (char *) &send_size, (void *) &sizeofint);
 
94
    getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
 
95
               (char *) &recv_size, (void *) &sizeofint);
 
96
 
 
97
    if(!doing_reset) {
 
98
        fprintf(stderr,"Send and receive buffers are %d and %d bytes\n",
 
99
                send_size, recv_size);
 
100
        fprintf(stderr, "(A bug in Linux doubles the requested buffer sizes)\n");
 
101
    }
 
102
 
 
103
    if( p->tr ) {                             /* Primary transmitter */
 
104
 
 
105
        lsin1->sin6_family = AF_INET6;
 
106
 
 
107
        /* First attempt to convert the string to an IPv6 */
 
108
        /* address. */
 
109
        /* If the user supplied a real host name this will fail and */
 
110
        /* we'll then do a name lookup. */
 
111
 
 
112
        if (inet_pton(AF_INET6, host, &lsin1->sin6_addr) == 0)
 
113
        {
 
114
            if ((hp = gethostbyname2(host, AF_INET6)) == NULL)
 
115
            {
 
116
                printf("NetPIPE: invalid hostname '%s'\n", host);
 
117
                exit(-5);
 
118
            }
 
119
 
 
120
            if (hp->h_addrtype != AF_INET6) 
 
121
            {
 
122
                printf("NetPIPE: invalid hostname '%s'\n", host);
 
123
                exit(-5);
 
124
            }
 
125
            bcopy(hp->h_addr, (char*) &(lsin1->sin6_addr), 
 
126
                  hp->h_length);
 
127
        }
 
128
 
 
129
        lsin1->sin6_port = htons(p->port);
 
130
        
 
131
        p->commfd = sockfd;
 
132
        
 
133
    } else if( p->rcv ) {                     /* we are the receiver */
 
134
        bzero((char *) lsin1, sizeof(*lsin1));
 
135
        lsin1->sin6_family  = AF_INET6;
 
136
        lsin1->sin6_len     = sizeof(*lsin1);
 
137
        lsin1->sin6_port    = htons(p->port);
 
138
        /* Setting this to all 0 is the "ANY" address. */
 
139
        bzero(&lsin1->sin6_addr, sizeof(lsin1->sin6_addr));
 
140
   
 
141
        if (bind(sockfd, (struct sockaddr *) lsin1, sizeof(*lsin1)) < 0){
 
142
            printf("NetPIPE: server: bind on local address failed! errno=%d", errno);
 
143
            exit(-6);
 
144
        }
 
145
 
 
146
        p->servicefd = sockfd;
 
147
    }
 
148
    p->upper = send_size + recv_size;
 
149
 
 
150
    establish(p);                               /* Establish connections */
 
151
 
 
152
}   
 
153
 
 
154
static int
 
155
readFully(int fd, void *obuf, int len)
 
156
{
 
157
    int bytesLeft = len;
 
158
    char *buf = (char *) obuf;
 
159
    int bytesRead = 0;
 
160
 
 
161
    while (bytesLeft > 0 &&
 
162
           (bytesRead = read(fd, (void *) buf, bytesLeft)) > 0)
 
163
    {
 
164
        bytesLeft -= bytesRead;
 
165
        buf += bytesRead;
 
166
    }
 
167
    if (bytesRead <= 0) return bytesRead;
 
168
    return len;
 
169
}
 
170
 
 
171
void Sync(ArgStruct *p)
 
172
{
 
173
    char s[] = "SyncMe", response[] = "      ";
 
174
 
 
175
    if (write(p->commfd, s, strlen(s)) < 0 ||           /* Write to nbor */
 
176
        readFully(p->commfd, response, strlen(s)) < 0)  /* Read from nbor */
 
177
    {
 
178
        perror("NetPIPE: error writing or reading synchronization string");
 
179
        exit(3);
 
180
    }
 
181
    if (strncmp(s, response, strlen(s)))
 
182
    {
 
183
        fprintf(stderr, "NetPIPE: Synchronization string incorrect! |%s|\n", response);
 
184
        exit(3);
 
185
    }
 
186
}
 
187
 
 
188
void PrepareToReceive(ArgStruct *p)
 
189
{
 
190
    /*
 
191
      The Berkeley sockets interface doesn't have a method to pre-post
 
192
      a buffer for reception of data.
 
193
    */
 
194
}
 
195
 
 
196
void SendData(ArgStruct *p)
 
197
{
 
198
    int bytesWritten, bytesLeft;
 
199
    char *q;
 
200
 
 
201
    bytesLeft = p->bufflen;
 
202
    bytesWritten = 0;
 
203
    q = p->s_ptr;
 
204
    while (bytesLeft > 0 &&
 
205
           (bytesWritten = write(p->commfd, q, bytesLeft)) > 0)
 
206
    {
 
207
        bytesLeft -= bytesWritten;
 
208
        q += bytesWritten;
 
209
    }
 
210
    if (bytesWritten == -1)
 
211
    {
 
212
        printf("NetPIPE: write: error encountered, errno=%d\n", errno);
 
213
        exit(401);
 
214
    }
 
215
}
 
216
 
 
217
void RecvData(ArgStruct *p)
 
218
{
 
219
    int bytesLeft;
 
220
    int bytesRead;
 
221
    char *q;
 
222
 
 
223
    bytesLeft = p->bufflen;
 
224
    bytesRead = 0;
 
225
    q = p->r_ptr;
 
226
    while (bytesLeft > 0 &&
 
227
           (bytesRead = read(p->commfd, q, bytesLeft)) > 0)
 
228
    {
 
229
        bytesLeft -= bytesRead;
 
230
        q += bytesRead;
 
231
    }
 
232
    if (bytesLeft > 0 && bytesRead == 0)
 
233
    {
 
234
        printf("NetPIPE: \"end of file\" encountered on reading from socket\n");
 
235
    }
 
236
    else if (bytesRead == -1)
 
237
    {
 
238
        printf("NetPIPE: read: error encountered, errno=%d\n", errno);
 
239
        exit(401);
 
240
    }
 
241
}
 
242
 
 
243
/* uint32_t is used to insure that the integer size is the same even in tests 
 
244
 * between 64-bit and 32-bit architectures. */
 
245
 
 
246
void SendTime(ArgStruct *p, double *t)
 
247
{
 
248
    uint32_t ltime, ntime;
 
249
 
 
250
    /*
 
251
      Multiply the number of seconds by 1e8 to get time in 0.01 microseconds
 
252
      and convert value to an unsigned 32-bit integer.
 
253
    */
 
254
    ltime = (uint32_t)(*t * 1.e8);
 
255
 
 
256
    /* Send time in network order */
 
257
    ntime = htonl(ltime);
 
258
    if (write(p->commfd, (char *)&ntime, sizeof(uint32_t)) < 0)
 
259
    {
 
260
        printf("NetPIPE: write failed in SendTime: errno=%d\n", errno);
 
261
        exit(301);
 
262
    }
 
263
}
 
264
 
 
265
void RecvTime(ArgStruct *p, double *t)
 
266
{
 
267
    uint32_t ltime, ntime;
 
268
    int bytesRead;
 
269
 
 
270
    bytesRead = readFully(p->commfd, (void *)&ntime, sizeof(uint32_t));
 
271
    if (bytesRead < 0)
 
272
    {
 
273
        printf("NetPIPE: read failed in RecvTime: errno=%d\n", errno);
 
274
        exit(302);
 
275
    }
 
276
    else if (bytesRead != sizeof(uint32_t))
 
277
    {
 
278
        fprintf(stderr, "NetPIPE: partial read in RecvTime of %d bytes\n",
 
279
                bytesRead);
 
280
        exit(303);
 
281
    }
 
282
    ltime = ntohl(ntime);
 
283
 
 
284
    /* Result is ltime (in microseconds) divided by 1.0e8 to get seconds */
 
285
 
 
286
    *t = (double)ltime / 1.0e8;
 
287
}
 
288
 
 
289
void SendRepeat(ArgStruct *p, int rpt)
 
290
{
 
291
    uint32_t lrpt, nrpt;
 
292
 
 
293
    lrpt = rpt;
 
294
    /* Send repeat count as a long in network order */
 
295
    nrpt = htonl(lrpt);
 
296
    if (write(p->commfd, (void *) &nrpt, sizeof(uint32_t)) < 0)
 
297
    {
 
298
        printf("NetPIPE: write failed in SendRepeat: errno=%d\n", errno);
 
299
        exit(304);
 
300
    }
 
301
}
 
302
 
 
303
void RecvRepeat(ArgStruct *p, int *rpt)
 
304
{
 
305
    uint32_t lrpt, nrpt;
 
306
    int bytesRead;
 
307
 
 
308
    bytesRead = readFully(p->commfd, (void *)&nrpt, sizeof(uint32_t));
 
309
    if (bytesRead < 0)
 
310
    {
 
311
        printf("NetPIPE: read failed in RecvRepeat: errno=%d\n", errno);
 
312
        exit(305);
 
313
    }
 
314
    else if (bytesRead != sizeof(uint32_t))
 
315
    {
 
316
        fprintf(stderr, "NetPIPE: partial read in RecvRepeat of %d bytes\n",
 
317
                bytesRead);
 
318
        exit(306);
 
319
    }
 
320
    lrpt = ntohl(nrpt);
 
321
 
 
322
    *rpt = lrpt;
 
323
}
 
324
 
 
325
void establish(ArgStruct *p)
 
326
{
 
327
    int one = 1;
 
328
    socklen_t clen;
 
329
    struct protoent *proto;
 
330
 
 
331
    clen = (socklen_t) sizeof(p->prot.sin2);
 
332
 
 
333
    if( p->tr ){
 
334
 
 
335
        while( connect(p->commfd, (struct sockaddr *) &(p->prot.sin1),
 
336
                       sizeof(p->prot.sin1)) < 0 ) {
 
337
 
 
338
            /* If we are doing a reset and we get a connection refused from
 
339
             * the connect() call, assume that the other node has not yet
 
340
             * gotten to its corresponding accept() call and keep trying until
 
341
             * we have success.
 
342
             */
 
343
            if(!doing_reset || errno != ECONNREFUSED) {
 
344
                printf("Client: Cannot Connect! errno=%d\n",errno);
 
345
                exit(-10);
 
346
            } 
 
347
        
 
348
        }
 
349
 
 
350
    } else if( p->rcv ) {
 
351
 
 
352
        /* SERVER */
 
353
        listen(p->servicefd, 5);
 
354
        p->commfd = accept(p->servicefd, (struct sockaddr *) &(p->prot.sin2), &clen);
 
355
 
 
356
        if(p->commfd < 0){
 
357
            printf("Server: Accept Failed! errno=%d\n",errno);
 
358
            exit(-12);
 
359
        }
 
360
 
 
361
        /*
 
362
          Attempt to set TCP_NODELAY. TCP_NODELAY may or may not be propagated
 
363
          to accepted sockets.
 
364
        */
 
365
        if(!(proto = getprotobyname("tcp"))){
 
366
            printf("unknown protocol!\n");
 
367
            exit(555);
 
368
        }
 
369
 
 
370
        if(setsockopt(p->commfd, proto->p_proto, TCP_NODELAY,
 
371
                      &one, sizeof(one)) < 0)
 
372
        {
 
373
            printf("setsockopt: TCP_NODELAY failed! errno=%d\n", errno);
 
374
            exit(556);
 
375
        }
 
376
 
 
377
        /* If requested, set the send and receive buffer sizes */
 
378
        if(p->prot.sndbufsz > 0)
 
379
        {
 
380
/*      printf("Send and Receive Buffers on accepted socket set to %d bytes\n",*/
 
381
/*           p->prot.sndbufsz);*/
 
382
            if(setsockopt(p->commfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz), 
 
383
                          sizeof(p->prot.sndbufsz)) < 0)
 
384
            {
 
385
                printf("setsockopt: SO_SNDBUF failed! errno=%d\n", errno);
 
386
                exit(556);
 
387
            }
 
388
            if(setsockopt(p->commfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz), 
 
389
                          sizeof(p->prot.rcvbufsz)) < 0)
 
390
            {
 
391
                printf("setsockopt: SO_RCVBUF failed! errno=%d\n", errno);
 
392
                exit(556);
 
393
            }
 
394
        }
 
395
    }
 
396
}
 
397
 
 
398
void CleanUp(ArgStruct *p)
 
399
{
 
400
    char *quit="QUIT";
 
401
 
 
402
    if (p->tr) {
 
403
 
 
404
        write(p->commfd,quit, 5);
 
405
        read(p->commfd, quit, 5);
 
406
        close(p->commfd);
 
407
 
 
408
    } else if( p->rcv ) {
 
409
 
 
410
        read(p->commfd,quit, 5);
 
411
        write(p->commfd,quit,5);
 
412
        close(p->commfd);
 
413
        close(p->servicefd);
 
414
 
 
415
    }
 
416
}
 
417
 
 
418
 
 
419
void Reset(ArgStruct *p)
 
420
{
 
421
  
 
422
    /* Reset sockets */
 
423
 
 
424
    if(p->reset_conn) {
 
425
 
 
426
        doing_reset = 1;
 
427
 
 
428
        /* Close the sockets */
 
429
 
 
430
        CleanUp(p);
 
431
 
 
432
        /* Now open and connect new sockets */
 
433
 
 
434
        Setup(p);
 
435
 
 
436
    }
 
437
 
 
438
}
 
439
 
 
440
void AfterAlignmentInit(ArgStruct *p)
 
441
{
 
442
 
 
443
}
 
444