• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   */
10 /*                                                                           */
11 /*     * TCP.c              ---- TCP calls source                            */
12 /*     * TCP.h              ---- Include file for TCP calls and data structs */
13 /* 2002/03/18 --- Modified for IPv6 - Robbie Williamson (robbiew@us.ibm.com) */
14 /*****************************************************************************/
15 #include    "netpipe.h"
16 
Setup(ArgStruct * p)17 int Setup(ArgStruct * p)
18 {
19 
20 	int tr, one = 1;	/* tr==1 if process is a transmitter */
21 	int sr = 0;
22 	int sockfd;
23 	struct sockaddr *lsin1;
24 	char *host;
25 	char *server_host;
26 	struct addrinfo *addr;
27 	struct addrinfo *server_addr;
28 	struct addrinfo hints;
29 	struct protoent *proto;
30 
31 	memset(&hints, 0, sizeof(hints));
32 	hints.ai_family = AF_INET6;
33 
34 	host = p->host;		/* copy ptr to hostname */
35 	server_host = p->server_host;	/* copy ptr to server */
36 
37 	tr = p->tr;		/* copy tr indicator */
38 	sr = p->sr;
39 
40 	memset(&p->prot.sin1, 0, sizeof(p->prot.sin1));
41 	memset(&p->prot.sin2, 0, sizeof(p->prot.sin2));
42 
43 	if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
44 		printf("NetPIPE: can't open stream socket! errno=%d\n", errno);
45 		exit(-4);
46 	}
47 
48 	if (!(proto = getprotobyname("tcp"))) {
49 		printf("NetPIPE: protocol 'tcp' unknown!\n");
50 		exit(555);
51 	}
52 
53 	/* Attempt to set TCP_NODELAY */
54 	if (setsockopt(sockfd, proto->p_proto, TCP_NODELAY, &one, sizeof(one)) <
55 	    0) {
56 		printf("NetPIPE: setsockopt: TCP_NODELAY failed! errno=%d\n",
57 		       errno);
58 		exit(556);
59 	}
60 
61 	/* If requested, set the send and receive buffer sizes */
62 	if (p->prot.sndbufsz > 0) {
63 		printf("Send and Receive Buffers set to %d bytes\n",
64 		       p->prot.sndbufsz);
65 		if (setsockopt
66 		    (sockfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz),
67 		     sizeof(p->prot.sndbufsz)) < 0) {
68 			printf
69 			    ("NetPIPE: setsockopt: SO_SNDBUF failed! errno=%d\n",
70 			     errno);
71 			exit(556);
72 		}
73 		if (setsockopt
74 		    (sockfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz),
75 		     sizeof(p->prot.rcvbufsz)) < 0) {
76 			printf
77 			    ("NetPIPE: setsockopt: SO_RCVBUF failed! errno=%d\n",
78 			     errno);
79 			exit(556);
80 		}
81 	}
82 
83 	if (tr) {		/* if client i.e., Sender */
84 
85 		if (host) {
86 			getaddrinfo(host, NULL, &hints, &addr);
87 			memcpy(&p->prot.sin1, addr->ai_addr, addr->ai_addrlen);
88 		} else {
89 			if ((getaddrinfo(host, NULL, &hints, &addr)) != 0) {
90 				printf("NetPIPE: invalid hostname '%s'\n",
91 				       host);
92 				exit(-5);
93 			}
94 		}
95 		p->prot.sin1.sin6_port = htons(p->port);
96 
97 	} else {		/* we are the receiver (server) */
98 
99 		memset(&p->prot.sin1, 0, sizeof(p->prot.sin1));
100 		if (sr == 0) {
101 			p->prot.sin1.sin6_addr = in6addr_any;
102 			p->prot.sin1.sin6_port = htons(p->port);
103 			lsin1 = (struct sockaddr *)&p->prot.sin1;
104 			if (bind
105 			    (sockfd, (struct sockaddr *)lsin1,
106 			     sizeof(p->prot.sin1)) < 0) {
107 				printf
108 				    ("NetPIPE: server: bind on local address failed! errno=%d",
109 				     errno);
110 				exit(-6);
111 			}
112 		} else {
113 			getaddrinfo(server_host, NULL, NULL, &server_addr);
114 			memcpy(&p->prot.sin1, server_addr->ai_addr,
115 			       server_addr->ai_addrlen);
116 			if ((getaddrinfo(server_host, NULL, NULL, &server_addr))
117 			    != 0) {
118 				printf("NetPIPE: invalid hostname '%s'\n",
119 				       host);
120 				exit(-5);
121 			}
122 			memcpy(&p->prot.sin1, server_addr->ai_addr,
123 			       server_addr->ai_addrlen);
124 			p->prot.sin1.sin6_port = htons(p->port);
125 			lsin1 = (struct sockaddr *)&p->prot.sin1;
126 			if (bind
127 			    (sockfd, (struct sockaddr *)lsin1,
128 			     sizeof(p->prot.sin1)) < 0) {
129 				printf
130 				    ("NetPIPE: server: bind on %s failed! errno=%d",
131 				     server_host, errno);
132 				exit(-6);
133 			}
134 		}
135 	}
136 
137 	if (tr)
138 		p->commfd = sockfd;
139 	else
140 		p->servicefd = sockfd;
141 
142 	return (0);
143 
144 }
145 
readFully(int fd,void * obuf,int len)146 static int readFully(int fd, void *obuf, int len)
147 {
148 	int bytesLeft = len;
149 	char *buf = (char *)obuf;
150 	int bytesRead = 0;
151 
152 	while (bytesLeft > 0 &&
153 	       (bytesRead = read(fd, (void *)buf, bytesLeft)) > 0) {
154 		bytesLeft -= bytesRead;
155 		buf += bytesRead;
156 	}
157 	if (bytesRead <= 0)
158 		return bytesRead;
159 	return len;
160 }
161 
Sync(ArgStruct * p)162 void Sync(ArgStruct * p)
163 {
164 	char s[] = "SyncMe";
165 	char response[7];
166 
167 	if (write(p->commfd, s, strlen(s)) < 0 ||
168 	    readFully(p->commfd, response, strlen(s)) < 0) {
169 		perror
170 		    ("NetPIPE: error writing or reading synchronization string");
171 		exit(3);
172 	}
173 	if (strncmp(s, response, strlen(s))) {
174 		fprintf(stderr, "NetPIPE: Synchronization string incorrect!\n");
175 		exit(3);
176 	}
177 }
178 
PrepareToReceive(ArgStruct * p)179 void PrepareToReceive(ArgStruct * p)
180 {
181 	/*
182 	   The Berkeley sockets interface doesn't have a method to pre-post
183 	   a buffer for reception of data.
184 	 */
185 }
186 
SendData(ArgStruct * p)187 void SendData(ArgStruct * p)
188 {
189 	int bytesWritten, bytesLeft;
190 	char *q;
191 
192 	bytesLeft = p->bufflen;
193 	bytesWritten = 0;
194 	q = p->buff;
195 	while (bytesLeft > 0 &&
196 	       (bytesWritten = write(p->commfd, q, bytesLeft)) > 0) {
197 		bytesLeft -= bytesWritten;
198 		q += bytesWritten;
199 	}
200 	if (bytesWritten == -1) {
201 		printf("NetPIPE: write: error encountered, errno=%d\n", errno);
202 		exit(401);
203 	}
204 }
205 
RecvData(ArgStruct * p)206 void RecvData(ArgStruct * p)
207 {
208 	int bytesLeft;
209 	int bytesRead;
210 	char *q;
211 
212 	bytesLeft = p->bufflen;
213 	bytesRead = 0;
214 	q = p->buff1;
215 	while (bytesLeft > 0 && (bytesRead = read(p->commfd, q, bytesLeft)) > 0) {
216 		bytesLeft -= bytesRead;
217 		q += bytesRead;
218 	}
219 	if (bytesLeft > 0 && bytesRead == 0) {
220 		printf
221 		    ("NetPIPE: \"end of file\" encountered on reading from socket\n");
222 	} else if (bytesRead == -1) {
223 		printf("NetPIPE: read: error encountered, errno=%d\n", errno);
224 		exit(401);
225 	}
226 }
227 
SendTime(ArgStruct * p,double * t)228 void SendTime(ArgStruct * p, double *t)
229 {
230 	unsigned int ltime, ntime;
231 
232 	/*
233 	   Multiply the number of seconds by 1e6 to get time in microseconds
234 	   and convert value to an unsigned 32-bit integer.
235 	 */
236 	ltime = (unsigned int)(*t * 1.e6);
237 
238 	/* Send time in network order */
239 	ntime = htonl(ltime);
240 	if (write(p->commfd, (char *)&ntime, sizeof(unsigned int)) < 0) {
241 		printf("NetPIPE: write failed in SendTime: errno=%d\n", errno);
242 		exit(301);
243 	}
244 }
245 
RecvTime(ArgStruct * p,double * t)246 void RecvTime(ArgStruct * p, double *t)
247 {
248 	unsigned int ltime, ntime;
249 	int bytesRead;
250 
251 	bytesRead = readFully(p->commfd, (void *)&ntime, sizeof(unsigned int));
252 	if (bytesRead < 0) {
253 		printf("NetPIPE: read failed in RecvTime: errno=%d\n", errno);
254 		exit(302);
255 	} else if (bytesRead != sizeof(unsigned int)) {
256 		fprintf(stderr,
257 			"NetPIPE: partial read in RecvTime of %d bytes\n",
258 			bytesRead);
259 		exit(303);
260 	}
261 	ltime = ntohl(ntime);
262 
263 	/* Result is ltime (in microseconds) divided by 1.0e6 to get seconds */
264 	*t = (double)ltime / 1.0e6;
265 }
266 
SendRepeat(ArgStruct * p,int rpt)267 void SendRepeat(ArgStruct * p, int rpt)
268 {
269 	unsigned int lrpt, nrpt;
270 
271 	lrpt = rpt;
272 	/* Send repeat count as an unsigned 32 bit integer in network order */
273 	nrpt = htonl(lrpt);
274 	if (write(p->commfd, (void *)&nrpt, sizeof(unsigned int)) < 0) {
275 		printf("NetPIPE: write failed in SendRepeat: errno=%d\n",
276 		       errno);
277 		exit(304);
278 	}
279 }
280 
RecvRepeat(ArgStruct * p,int * rpt)281 void RecvRepeat(ArgStruct * p, int *rpt)
282 {
283 	unsigned int lrpt, nrpt;
284 	int bytesRead;
285 
286 	bytesRead = readFully(p->commfd, (void *)&nrpt, sizeof(unsigned int));
287 	if (bytesRead < 0) {
288 		printf("NetPIPE: read failed in RecvRepeat: errno=%d\n", errno);
289 		exit(305);
290 	} else if (bytesRead != sizeof(unsigned int)) {
291 		fprintf(stderr,
292 			"NetPIPE: partial read in RecvRepeat of %d bytes\n",
293 			bytesRead);
294 		exit(306);
295 	}
296 	lrpt = ntohl(nrpt);
297 
298 	*rpt = lrpt;
299 }
300 
Establish(ArgStruct * p)301 int Establish(ArgStruct * p)
302 {
303 	socklen_t clen;
304 	int one = 1;
305 	struct protoent *proto;
306 
307 	clen = sizeof(p->prot.sin2);
308 	if (p->tr) {
309 		if (connect(p->commfd, (struct sockaddr *)&(p->prot.sin1),
310 			    sizeof(p->prot.sin1)) < 0) {
311 			printf("Client: Cannot Connect! errno=%d\n", errno);
312 			exit(-10);
313 		}
314 	} else {
315 		/* SERVER */
316 		listen(p->servicefd, 5);
317 		p->commfd =
318 		    accept(p->servicefd, (struct sockaddr *)&(p->prot.sin2),
319 			   &clen);
320 
321 		if (p->commfd < 0) {
322 			printf("Server: Accept Failed! errno=%d\n", errno);
323 			exit(-12);
324 		}
325 
326 		/*
327 		   Attempt to set TCP_NODELAY. TCP_NODELAY may or may not be propagated
328 		   to accepted sockets.
329 		 */
330 		if (!(proto = getprotobyname("tcp"))) {
331 			printf("unknown protocol!\n");
332 			exit(555);
333 		}
334 
335 		if (setsockopt(p->commfd, proto->p_proto, TCP_NODELAY,
336 			       &one, sizeof(one)) < 0) {
337 			printf("setsockopt: TCP_NODELAY failed! errno=%d\n",
338 			       errno);
339 			exit(556);
340 		}
341 
342 		/* If requested, set the send and receive buffer sizes */
343 		if (p->prot.sndbufsz > 0) {
344 			printf
345 			    ("Send and Receive Buffers on accepted socket set to %d bytes\n",
346 			     p->prot.sndbufsz);
347 			if (setsockopt
348 			    (p->commfd, SOL_SOCKET, SO_SNDBUF,
349 			     &(p->prot.sndbufsz),
350 			     sizeof(p->prot.sndbufsz)) < 0) {
351 				printf
352 				    ("setsockopt: SO_SNDBUF failed! errno=%d\n",
353 				     errno);
354 				exit(556);
355 			}
356 			if (setsockopt
357 			    (p->commfd, SOL_SOCKET, SO_RCVBUF,
358 			     &(p->prot.rcvbufsz),
359 			     sizeof(p->prot.rcvbufsz)) < 0) {
360 				printf
361 				    ("setsockopt: SO_RCVBUF failed! errno=%d\n",
362 				     errno);
363 				exit(556);
364 			}
365 		}
366 	}
367 	return (0);
368 }
369 
CleanUp(ArgStruct * p)370 int CleanUp(ArgStruct * p)
371 {
372 	char *quit = "QUIT";
373 	if (p->tr) {
374 		write(p->commfd, quit, 5);
375 		read(p->commfd, quit, 5);
376 		close(p->commfd);
377 	} else {
378 		read(p->commfd, quit, 5);
379 		write(p->commfd, quit, 5);
380 		close(p->commfd);
381 		close(p->servicefd);
382 	}
383 	return (0);
384 }
385