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