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