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 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 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 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 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 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 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 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 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 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 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 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 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