Home | History | Annotate | Download | only in netpipe-2.4
      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