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