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

« back to all changes in this revision

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