1b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*****************************************************************************/
2b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* "NetPIPE" -- Network Protocol Independent Performance Evaluator.          */
3b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* Copyright 1997, 1998 Iowa State University Research Foundation, Inc.      */
4b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*                                                                           */
5b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* This program is free software; you can redistribute it and/or modify      */
6b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* it under the terms of the GNU General Public License as published by      */
7b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* the Free Software Foundation.  You should have received a copy of the     */
8b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/* GNU General Public License along with this program; if not, write to the  */
94548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao/* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   */
10b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*                                                                           */
11b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*     * TCP.c              ---- TCP calls source                            */
12b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*     * TCP.h              ---- Include file for TCP calls and data structs */
13b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew/*****************************************************************************/
14b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew#include    "netpipe.h"
15b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
16354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint Setup(ArgStruct * p)
17b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
18354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int tr, one = 1;	/* tr==1 if process is a transmitter */
19354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sockfd;
20354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sockaddr_in *lsin1, *lsin2;	/* ptr to sockaddr_in in ArgStruct */
21354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *host;
22354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct hostent *addr;
23354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct protoent *proto;
24354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
25354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	host = p->host;		/* copy ptr to hostname */
26354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	tr = p->tr;		/* copy tr indicator */
27354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
28354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lsin1 = &(p->prot.sin1);
29354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lsin2 = &(p->prot.sin2);
30354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
31354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset((char *)lsin1, 0x00, sizeof(*lsin1));
32354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset((char *)lsin2, 0x00, sizeof(*lsin2));
33354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
34354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
35354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: can't open stream socket! errno=%d\n", errno);
36354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(-4);
37354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!(proto = getprotobyname("tcp"))) {
40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: protocol 'tcp' unknown!\n");
41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(555);
42354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
44354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Attempt to set TCP_NODELAY */
45354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (setsockopt(sockfd, proto->p_proto, TCP_NODELAY, &one, sizeof(one)) <
46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    0) {
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: setsockopt: TCP_NODELAY failed! errno=%d\n",
48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       errno);
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(556);
50354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
51354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* If requested, set the send and receive buffer sizes */
53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->prot.sndbufsz > 0) {
54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("Send and Receive Buffers set to %d bytes\n",
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       p->prot.sndbufsz);
56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt
57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    (sockfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz),
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     sizeof(p->prot.sndbufsz)) < 0) {
59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("NetPIPE: setsockopt: SO_SNDBUF failed! errno=%d\n",
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     errno);
62354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt
65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    (sockfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz),
66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     sizeof(p->prot.rcvbufsz)) < 0) {
67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("NetPIPE: setsockopt: SO_RCVBUF failed! errno=%d\n",
69354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     errno);
70354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
73354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
74354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (tr) {		/* if client i.e., Sender */
75354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
76354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (atoi(host) > 0) {	/* Numerical IP address */
77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			lsin1->sin_family = AF_INET;
78354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			lsin1->sin_addr.s_addr = inet_addr(host);
79354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
80354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {
81354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
82354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if ((addr = gethostbyname(host)) == NULL) {
83354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf("NetPIPE: invalid hostname '%s'\n",
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       host);
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(-5);
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			lsin1->sin_family = addr->h_addrtype;
89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			memcpy((char *)&(lsin1->sin_addr.s_addr), addr->h_addr,
90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       addr->h_length);
91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		lsin1->sin_port = htons(p->port);
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {		/* we are the receiver (server) */
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		memset((char *)lsin1, 0x00, sizeof(*lsin1));
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		lsin1->sin_family = AF_INET;
99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		lsin1->sin_addr.s_addr = htonl(INADDR_ANY);
100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		lsin1->sin_port = htons(p->port);
101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (bind(sockfd, (struct sockaddr *)lsin1, sizeof(*lsin1)) < 0) {
103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("NetPIPE: server: bind on local address failed! errno=%d",
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     errno);
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-6);
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (tr)
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->commfd = sockfd;
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	else
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->servicefd = sockfd;
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
11757c212c57d43b73993ce4af1224b26c810353516vapier}
118b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int readFully(int fd, void *obuf, int len)
120b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesLeft = len;
122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *buf = (char *)obuf;
123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead = 0;
124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 &&
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       (bytesRead = read(fd, (void *)buf, bytesLeft)) > 0) {
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesRead;
128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		buf += bytesRead;
129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead <= 0)
131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		return bytesRead;
132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return len;
133b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
134b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid Sync(ArgStruct * p)
136b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char s[] = "SyncMe";
138354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char response[7];
139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, s, strlen(s)) < 0 ||
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    readFully(p->commfd, response, strlen(s)) < 0) {
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		perror
143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("NetPIPE: error writing or reading synchronization string");
144354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(3);
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (strncmp(s, response, strlen(s))) {
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "NetPIPE: Synchronization string incorrect!\n");
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(3);
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
150b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
151b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid PrepareToReceive(ArgStruct * p)
153b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
154b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew	/*
155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   The Berkeley sockets interface doesn't have a method to pre-post
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   a buffer for reception of data.
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
158b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
159b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendData(ArgStruct * p)
161b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesWritten, bytesLeft;
163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *q;
164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesLeft = p->bufflen;
166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesWritten = 0;
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	q = p->buff;
168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 &&
169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       (bytesWritten = write(p->commfd, q, bytesLeft)) > 0) {
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesWritten;
171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		q += bytesWritten;
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesWritten == -1) {
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write: error encountered, errno=%d\n", errno);
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(401);
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
177b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
178b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvData(ArgStruct * p)
180b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesLeft;
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *q;
184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesLeft = p->bufflen;
186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = 0;
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	q = p->buff1;
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 && (bytesRead = read(p->commfd, q, bytesLeft)) > 0) {
189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesRead;
190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		q += bytesRead;
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesLeft > 0 && bytesRead == 0) {
193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("NetPIPE: \"end of file\" encountered on reading from socket\n");
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead == -1) {
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read: error encountered, errno=%d\n", errno);
197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(401);
198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
199b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
200b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendTime(ArgStruct * p, double *t)
202b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int ltime, ntime;
204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/*
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   Multiply the number of seconds by 1e6 to get time in microseconds
207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   and convert value to an unsigned 32-bit integer.
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ltime = (unsigned int)(*t * 1.e6);
210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Send time in network order */
212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ntime = htonl(ltime);
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, (char *)&ntime, sizeof(unsigned int)) < 0) {
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write failed in SendTime: errno=%d\n", errno);
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(301);
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
217b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
218b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvTime(ArgStruct * p, double *t)
220b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int ltime, ntime;
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = readFully(p->commfd, (void *)&ntime, sizeof(unsigned int));
225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead < 0) {
226354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read failed in RecvTime: errno=%d\n", errno);
227354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(302);
228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead != sizeof(unsigned int)) {
229354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr,
230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"NetPIPE: partial read in RecvTime of %d bytes\n",
231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bytesRead);
232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(303);
233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ltime = ntohl(ntime);
235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Result is ltime (in microseconds) divided by 1.0e6 to get seconds */
237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	*t = (double)ltime / 1.0e6;
238b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
239b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendRepeat(ArgStruct * p, int rpt)
241b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int lrpt, nrpt;
243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
244354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lrpt = rpt;
245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Send repeat count as an unsigned 32 bit integer in network order */
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	nrpt = htonl(lrpt);
247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, (void *)&nrpt, sizeof(unsigned int)) < 0) {
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write failed in SendRepeat: errno=%d\n",
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       errno);
250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(304);
251354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
252b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
253b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvRepeat(ArgStruct * p, int *rpt)
255b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int lrpt, nrpt;
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = readFully(p->commfd, (void *)&nrpt, sizeof(unsigned int));
260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead < 0) {
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read failed in RecvRepeat: errno=%d\n", errno);
262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(305);
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead != sizeof(unsigned int)) {
264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr,
265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"NetPIPE: partial read in RecvRepeat of %d bytes\n",
266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bytesRead);
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(306);
268354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lrpt = ntohl(nrpt);
270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	*rpt = lrpt;
272b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
273b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint Establish(ArgStruct * p)
275b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	socklen_t clen;
277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int one = 1;
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct protoent *proto;
279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	clen = sizeof(p->prot.sin2);
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->tr) {
282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (connect(p->commfd, (struct sockaddr *)&(p->prot.sin1),
283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    sizeof(p->prot.sin1)) < 0) {
284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("Client: Cannot Connect! errno=%d\n", errno);
285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-10);
286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
288354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* SERVER */
289354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		listen(p->servicefd, 5);
290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->commfd =
291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    accept(p->servicefd, (struct sockaddr *)&(p->prot.sin2),
292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			   &clen);
293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (p->commfd < 0) {
295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("Server: Accept Failed! errno=%d\n", errno);
296354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-12);
297354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
298354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
299354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/*
300354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		   Attempt to set TCP_NODELAY. TCP_NODELAY may or may not be propagated
301354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		   to accepted sockets.
302354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		 */
303354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!(proto = getprotobyname("tcp"))) {
304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("unknown protocol!\n");
305354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(555);
306354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
308354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt(p->commfd, proto->p_proto, TCP_NODELAY,
309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       &one, sizeof(one)) < 0) {
310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("setsockopt: TCP_NODELAY failed! errno=%d\n",
311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       errno);
312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* If requested, set the send and receive buffer sizes */
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (p->prot.sndbufsz > 0) {
317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Send and Receive Buffers on accepted socket set to %d bytes\n",
319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     p->prot.sndbufsz);
320354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (setsockopt
321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (p->commfd, SOL_SOCKET, SO_SNDBUF,
322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     &(p->prot.sndbufsz),
323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.sndbufsz)) < 0) {
324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("setsockopt: SO_SNDBUF failed! errno=%d\n",
326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     errno);
327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(556);
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (setsockopt
330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (p->commfd, SOL_SOCKET, SO_RCVBUF,
331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     &(p->prot.rcvbufsz),
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.rcvbufsz)) < 0) {
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("setsockopt: SO_RCVBUF failed! errno=%d\n",
335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     errno);
336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(556);
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
341b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew}
342b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew
343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint CleanUp(ArgStruct * p)
344b1cd5fc471d12f7c4bda56c6da5d63287e42bfferobbiew{
345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *quit = "QUIT";
346354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->tr) {
347354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		write(p->commfd, quit, 5);
348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		read(p->commfd, quit, 5);
349354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->commfd);
350354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
351354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		read(p->commfd, quit, 5);
352354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		write(p->commfd, quit, 5);
353354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->commfd);
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->servicefd);
355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
356354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
357ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
358