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