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