#include "NET_Client.h" #include #include #include #define DEFAULT_PROTO 0 /*************************************************************************** N E T _ C L I E N T : : N E T _ C L I E N T ***************************************************************************/ NET_Client::NET_Client(bool is_pure) { socketStartup(); clientlen= sizeof(clientsocket); //remote_host=NULL; strcpy(remotehostname,""); clientfd=-1; id= -1; strcpy(clientName,""); pure=is_pure; // not pure by default, send clientname and packet length } /*************************************************************************** N E T _ C L I E N T : : ~ N E T _ C L I E N T ***************************************************************************/ NET_Client::~NET_Client() { // cout << "Deconstructing NET_Client: " << clientName << endl; if (clientfd>=0) close(clientfd); socketCleanup(); } /*************************************************************************** N E T _ C L I E N T : : S E T C L I E N T N A M E ***************************************************************************/ void NET_Client::setClientName(char *name) { strcpy(clientName,name); } /*************************************************************************** N E T _ C L I E N T : : C O N N E C T ***************************************************************************/ int NET_Client::connect(char *host, int port) { int serverinetaddr; struct hostent *remote_host; // Close previous connections if (clientfd>0) { close(clientfd); clientfd= -1; } // Establish new connection remote_host = gethostbyname(host); if (!remote_host) { printf("Couldn't look up host.\n"); exit(1); } serverinetaddr = ((struct in_addr*)remote_host->h_addr)->s_addr; memset((char *) &clientsocket, 0, sizeof(clientsocket)); clientsocket.sin_family = AF_INET; clientsocket.sin_addr.s_addr = serverinetaddr; clientsocket.sin_port = htons(port); clientfd = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTO); int opt=1; setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY,(char *)&opt,sizeof(int)); int result = ::connect(clientfd, (struct sockaddr *)&clientsocket, sizeof(clientsocket)); if (result == -1) close (clientfd); else { // Write the name of this client in first packet on connection if (!pure) writeNetMsg(clientName,strlen(clientName)+1); } return result; } // Returns a complete packet, no partial data // -1=no packet ready or error, // 0=eof, // num=length of packet read // size tells the maximum packet size for buf. /*************************************************************************** N E T _ C L I E N T : : R E A D N E T M S G ***************************************************************************/ int NET_Client::readNetMsg(void *buf, int size) { // Save orig blocking state #ifdef sgi int blockingarg=fcntl(clientfd, F_GETFL); #else int isblocking=getblocking(); #endif int nleft, nread; char *ptr= (char *)buf; int nbytes; // Read how many bytes in the packet if (!pure) nread = global_read(clientfd,&nbytes,4); // Convert net to host byte ordering nbytes=ntohl(nbytes); // return on error, no data ready, or eof if (nread<=0) return nread; // Set blocking to receive this packet blocking(); // Now get the whoel packet nleft=nbytes; while (nleft>0) { nread = global_read(clientfd,ptr,nleft); if (nread <0) return nread; // error else if (nread==0) //eof break; nleft -= nread; ptr+= nread; } // Set blocking how it started #ifdef sgi fcntl(clientfd,F_SETFL, blockingarg ); #else setblocking(isblocking); #endif return (nbytes-nleft); } // writes a whole packet out to the net, with header packet length // so readNetMsg can grab the whole thing at once. /*************************************************************************** N E T _ C L I E N T : : W R I T E N E T M S G ***************************************************************************/ int NET_Client::writeNetMsg(void *buf, int size) { char *ptr=(char *)buf; // Check for empty packet and eliminate or pipe breaks if (size==0 || buf==NULL) return 0; // Convert size into network order int netsize = htonl(size); // Write out the length of the packet int tmp=4; if (!pure) global_write(clientfd,&netsize,tmp); // Write the rest of the packet int nleft,nwritten; nleft=size; while (nleft>0) { nwritten= global_write(clientfd,ptr,nleft); if (nwritten <=0) return (nwritten); nleft -=nwritten; ptr += nwritten; } return (size-nleft); } /*************************************************************************** N E T _ C L I E N T : : R E A D ***************************************************************************/ int NET_Client::read(void *buf, int size) { return global_read (clientfd,buf,size); } /*************************************************************************** N E T _ C L I E N T : : W R I T E ***************************************************************************/ int NET_Client::write (void *buf, int size) { return global_write(clientfd,buf,size); } /*************************************************************************** N E T _ C L I E N T : : S E T B L O C K I N G ***************************************************************************/ void NET_Client::setblocking(int isblocking) { #ifdef WIN32 unsigned long arg= !isblocking; #else /*unix */ int arg= !isblocking; #endif ioctl(clientfd,FIONBIO,&arg); } /*************************************************************************** N E T _ C L I E N T : : G E T B L O C K I N G ***************************************************************************/ // this whole function is suspect. I think getblocking is bogus int NET_Client::getblocking() { #ifdef sgi int flags=fcntl(clientfd, F_GETFL); int val=!(flags & FNONBLK); printf ("Blocking val: %d\n",val); return val; #else //return WSAIsBlocking(); //!!!! this doesn't work!!! return 1; #endif } /*************************************************************************** N E T _ C L I E N T : : N O N B L O C K I N G ***************************************************************************/ void NET_Client::nonblocking() { setblocking(0); } /*************************************************************************** N E T _ C L I E N T : : B L O C K I N G ***************************************************************************/ void NET_Client::blocking() { setblocking(1); } /*************************************************************************** * N E T _ C L I E N T : : R E M O T E H O S T N A M E ***************************************************************************/ char *NET_Client::remoteHostname() { return remotehostname; /* if (remote_host==NULL) return NULL; else return remote_host->h_name; */ }