1723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*****************************************************************************/
2723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* "NetPIPE" -- Network Protocol Independent Performance Evaluator.          */
3723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* Copyright 1997, 1998 Iowa State University Research Foundation, Inc.      */
4723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*                                                                           */
5723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* This program is free software; you can redistribute it and/or modify      */
6723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* it under the terms of the GNU General Public License as published by      */
7723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* the Free Software Foundation.  You should have received a copy of the     */
8723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* 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.   */
10723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*                                                                           */
11723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*     * TCP.c              ---- TCP calls source                            */
12723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*     * TCP.h              ---- Include file for TCP calls and data structs */
13723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/* 2002/03/18 --- Modified for IPv6 - Robbie Williamson (robbiew@us.ibm.com) */
14723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew/*****************************************************************************/
15723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew#include    "netpipe.h"
16723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
17354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint Setup(ArgStruct * p)
18723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
19723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
20354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int tr, one = 1;	/* tr==1 if process is a transmitter */
21354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sr = 0;
22354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sockfd;
23354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sockaddr *lsin1;
24354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *host;
25354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *server_host;
26354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct addrinfo *addr;
27354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct addrinfo *server_addr;
28354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct addrinfo hints;
29354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct protoent *proto;
30354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
31354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&hints, 0, sizeof(hints));
32354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	hints.ai_family = AF_INET6;
33354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
34354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	host = p->host;		/* copy ptr to hostname */
35354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	server_host = p->server_host;	/* copy ptr to server */
36354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
37354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	tr = p->tr;		/* copy tr indicator */
38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sr = p->sr;
39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&p->prot.sin1, 0, sizeof(p->prot.sin1));
41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&p->prot.sin2, 0, sizeof(p->prot.sin2));
42354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
44354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: can't open stream socket! errno=%d\n", errno);
45354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(-4);
46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!(proto = getprotobyname("tcp"))) {
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: protocol 'tcp' unknown!\n");
50354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(555);
51354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Attempt to set TCP_NODELAY */
54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (setsockopt(sockfd, proto->p_proto, TCP_NODELAY, &one, sizeof(one)) <
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    0) {
56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: setsockopt: TCP_NODELAY failed! errno=%d\n",
57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       errno);
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(556);
59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* If requested, set the send and receive buffer sizes */
62354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->prot.sndbufsz > 0) {
63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("Send and Receive Buffers set to %d bytes\n",
64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       p->prot.sndbufsz);
65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt
66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    (sockfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz),
67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     sizeof(p->prot.sndbufsz)) < 0) {
68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
69354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("NetPIPE: setsockopt: SO_SNDBUF failed! errno=%d\n",
70354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     errno);
71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
73354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt
74354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    (sockfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz),
75354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		     sizeof(p->prot.rcvbufsz)) < 0) {
76354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("NetPIPE: setsockopt: SO_RCVBUF failed! errno=%d\n",
78354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     errno);
79354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
80354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
81354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
82354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
83354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (tr) {		/* if client i.e., Sender */
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (host) {
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			getaddrinfo(host, NULL, &hints, &addr);
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			memcpy(&p->prot.sin1, addr->ai_addr, addr->ai_addrlen);
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {
89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if ((getaddrinfo(host, NULL, &hints, &addr)) != 0) {
90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf("NetPIPE: invalid hostname '%s'\n",
91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       host);
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(-5);
93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->prot.sin1.sin6_port = htons(p->port);
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {		/* we are the receiver (server) */
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		memset(&p->prot.sin1, 0, sizeof(p->prot.sin1));
100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (sr == 0) {
101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			p->prot.sin1.sin6_addr = in6addr_any;
102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			p->prot.sin1.sin6_port = htons(p->port);
103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			lsin1 = (struct sockaddr *)&p->prot.sin1;
104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (bind
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (sockfd, (struct sockaddr *)lsin1,
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.sin1)) < 0) {
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("NetPIPE: server: bind on local address failed! errno=%d",
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     errno);
110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(-6);
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			getaddrinfo(server_host, NULL, NULL, &server_addr);
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			memcpy(&p->prot.sin1, server_addr->ai_addr,
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       server_addr->ai_addrlen);
116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if ((getaddrinfo(server_host, NULL, NULL, &server_addr))
117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    != 0) {
118354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf("NetPIPE: invalid hostname '%s'\n",
119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       host);
120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(-5);
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			memcpy(&p->prot.sin1, server_addr->ai_addr,
123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       server_addr->ai_addrlen);
124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			p->prot.sin1.sin6_port = htons(p->port);
125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			lsin1 = (struct sockaddr *)&p->prot.sin1;
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (bind
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (sockfd, (struct sockaddr *)lsin1,
128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.sin1)) < 0) {
129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("NetPIPE: server: bind on %s failed! errno=%d",
131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     server_host, errno);
132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(-6);
133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
134354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
136354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (tr)
138354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->commfd = sockfd;
139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	else
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->servicefd = sockfd;
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
14357c212c57d43b73993ce4af1224b26c810353516vapier
14457c212c57d43b73993ce4af1224b26c810353516vapier}
145723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int readFully(int fd, void *obuf, int len)
147723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesLeft = len;
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *buf = (char *)obuf;
150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead = 0;
151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 &&
153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       (bytesRead = read(fd, (void *)buf, bytesLeft)) > 0) {
154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesRead;
155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		buf += bytesRead;
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead <= 0)
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		return bytesRead;
159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return len;
160723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
161723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid Sync(ArgStruct * p)
163723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char s[] = "SyncMe";
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char response[7];
166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, s, strlen(s)) < 0 ||
168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    readFully(p->commfd, response, strlen(s)) < 0) {
169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		perror
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("NetPIPE: error writing or reading synchronization string");
171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(3);
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (strncmp(s, response, strlen(s))) {
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "NetPIPE: Synchronization string incorrect!\n");
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(3);
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
177723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
178723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid PrepareToReceive(ArgStruct * p)
180723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
181723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew	/*
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   The Berkeley sockets interface doesn't have a method to pre-post
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   a buffer for reception of data.
184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
185723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
186723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendData(ArgStruct * p)
188723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesWritten, bytesLeft;
190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *q;
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesLeft = p->bufflen;
193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesWritten = 0;
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	q = p->buff;
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 &&
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       (bytesWritten = write(p->commfd, q, bytesLeft)) > 0) {
197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesWritten;
198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		q += bytesWritten;
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesWritten == -1) {
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write: error encountered, errno=%d\n", errno);
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(401);
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
204723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
205723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvData(ArgStruct * p)
207723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesLeft;
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *q;
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesLeft = p->bufflen;
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = 0;
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	q = p->buff1;
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (bytesLeft > 0 && (bytesRead = read(p->commfd, q, bytesLeft)) > 0) {
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		bytesLeft -= bytesRead;
217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		q += bytesRead;
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesLeft > 0 && bytesRead == 0) {
220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    ("NetPIPE: \"end of file\" encountered on reading from socket\n");
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead == -1) {
223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read: error encountered, errno=%d\n", errno);
224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(401);
225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
226723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
227723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendTime(ArgStruct * p, double *t)
229723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int ltime, ntime;
231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/*
233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   Multiply the number of seconds by 1e6 to get time in microseconds
234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	   and convert value to an unsigned 32-bit integer.
235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ltime = (unsigned int)(*t * 1.e6);
237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
238354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Send time in network order */
239354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ntime = htonl(ltime);
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, (char *)&ntime, sizeof(unsigned int)) < 0) {
241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write failed in SendTime: errno=%d\n", errno);
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(301);
243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
244723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
245723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvTime(ArgStruct * p, double *t)
247723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int ltime, ntime;
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
251354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = readFully(p->commfd, (void *)&ntime, sizeof(unsigned int));
252354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead < 0) {
253354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read failed in RecvTime: errno=%d\n", errno);
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(302);
255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead != sizeof(unsigned int)) {
256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr,
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"NetPIPE: partial read in RecvTime of %d bytes\n",
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bytesRead);
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(303);
260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	ltime = ntohl(ntime);
262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Result is ltime (in microseconds) divided by 1.0e6 to get seconds */
264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	*t = (double)ltime / 1.0e6;
265723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
266723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid SendRepeat(ArgStruct * p, int rpt)
268723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int lrpt, nrpt;
270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lrpt = rpt;
272354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Send repeat count as an unsigned 32 bit integer in network order */
273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	nrpt = htonl(lrpt);
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p->commfd, (void *)&nrpt, sizeof(unsigned int)) < 0) {
275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: write failed in SendRepeat: errno=%d\n",
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       errno);
277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(304);
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
279723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
280723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid RecvRepeat(ArgStruct * p, int *rpt)
282723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned int lrpt, nrpt;
284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytesRead;
285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	bytesRead = readFully(p->commfd, (void *)&nrpt, sizeof(unsigned int));
287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (bytesRead < 0) {
288354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("NetPIPE: read failed in RecvRepeat: errno=%d\n", errno);
289354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(305);
290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else if (bytesRead != sizeof(unsigned int)) {
291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr,
292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			"NetPIPE: partial read in RecvRepeat of %d bytes\n",
293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bytesRead);
294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(306);
295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
296354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	lrpt = ntohl(nrpt);
297354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
298354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	*rpt = lrpt;
299723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
300723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
301354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint Establish(ArgStruct * p)
302723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
303354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	socklen_t clen;
304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int one = 1;
305354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct protoent *proto;
306354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	clen = sizeof(p->prot.sin2);
308354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->tr) {
309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (connect(p->commfd, (struct sockaddr *)&(p->prot.sin1),
310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    sizeof(p->prot.sin1)) < 0) {
311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("Client: Cannot Connect! errno=%d\n", errno);
312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-10);
313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* SERVER */
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		listen(p->servicefd, 5);
317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		p->commfd =
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    accept(p->servicefd, (struct sockaddr *)&(p->prot.sin2),
319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			   &clen);
320354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (p->commfd < 0) {
322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("Server: Accept Failed! errno=%d\n", errno);
323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-12);
324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/*
327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		   Attempt to set TCP_NODELAY. TCP_NODELAY may or may not be propagated
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		   to accepted sockets.
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		 */
330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!(proto = getprotobyname("tcp"))) {
331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("unknown protocol!\n");
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(555);
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (setsockopt(p->commfd, proto->p_proto, TCP_NODELAY,
336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       &one, sizeof(one)) < 0) {
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf("setsockopt: TCP_NODELAY failed! errno=%d\n",
338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       errno);
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(556);
340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* If requested, set the send and receive buffer sizes */
343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (p->prot.sndbufsz > 0) {
344354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			printf
345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Send and Receive Buffers on accepted socket set to %d bytes\n",
346354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     p->prot.sndbufsz);
347354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (setsockopt
348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (p->commfd, SOL_SOCKET, SO_SNDBUF,
349354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     &(p->prot.sndbufsz),
350354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.sndbufsz)) < 0) {
351354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
352354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("setsockopt: SO_SNDBUF failed! errno=%d\n",
353354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     errno);
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(556);
355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
356354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (setsockopt
357354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    (p->commfd, SOL_SOCKET, SO_RCVBUF,
358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     &(p->prot.rcvbufsz),
359354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     sizeof(p->prot.rcvbufsz)) < 0) {
360354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				printf
361354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("setsockopt: SO_RCVBUF failed! errno=%d\n",
362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				     errno);
363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(556);
364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
366354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
368723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew}
369723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew
370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint CleanUp(ArgStruct * p)
371723b3af0846cab5b1ffd0fe975965729a3eaf98brobbiew{
372354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *quit = "QUIT";
373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (p->tr) {
374354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		write(p->commfd, quit, 5);
375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		read(p->commfd, quit, 5);
376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->commfd);
377354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		read(p->commfd, quit, 5);
379354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		write(p->commfd, quit, 5);
380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->commfd);
381354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		close(p->servicefd);
382354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	return (0);
384ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
385