Listing 3: TCP class hierarchy: selected method implementation
// Make sure that a system call went well // If a system call (say, fcntl()) fails // it returns -1 and sets the errno #define do_well(FX) (void)( (FX) < 0 ? (perror("System error"), \ _error("Failed system call " #FX " at line %d of ´%s'.\n", \ __LINE__, __FILE__),0) : 1) // Obtains the IP address of the specified // host. The host name may be specified // either in the dot notation, or as a // host "name". // Name resolution is performed in the // latter case. IPaddress::IPaddress(const char * host_name) { // First check to see if the host // name is specified in the IP address // dot notation if( (address = inet_addr(host_name)) != (unsigned long)(-1) ) return; struct hostent *host_ptr = ::gethostbyname(host_name); if( host_ptr == 0 ) _error("Host name '%s' cannot be resolved",host_name); if( host_ptr->h_addrtype != AF_INET ) _error("'%s' isn't an Internet site, or so the DNS says",host_name); address = *(unsigned long *)(host_ptr->h_addr); } // Read from the socket returning the // size of the block read StreamSocket::ReadResult StreamSocket::read(void * buffer, const unsigned int len) { assert( status == Good ); assert( len != 0 ); ReadResult result = { ::read(socket_handle,buffer,len), Good }; if( result.len == 0 ) return result.status = (status = Eof), result; if( result.len == (unsigned)(-1L) ) if( errno == EWOULDBLOCK ) return result.len = 0, result.status = Nodata, result; else { perror("reading from the socket"); return result.len = 0, result.status = (status = Failure), result; } return result; } // Set blocking/non-blocking I/O // If the blocking i/o is set, reading // on socket blocks the process until // the packet arrives. If i/o is non-blocking, // read() returns -1 with errno=EWOULDBLOCK // if there is nothing to read void StreamSocket::set_blocking_io(const BOOL onoff) { int arg = fcntl(socket_handle,F_GETFL,0); do_well( arg ); do_well( fcntl(socket_handle,F_SETFL,onoff ? arg & ~FNDELAY : arg | FNDELAY) ); } // Enable/disable SIGIO upon arriving of a // new packet void StreamSocket::enable_sigio(const BOOL onoff) { int arg = fcntl(socket_handle,F_GETFL,0); do_well( arg ); do_well( fcntl(socket_handle,F_SETFL,onoff ? arg | FASYNC : arg & ~FASYNC) ); if( onoff ) // Tell which process should get SIGIO do_well( fcntl(socket_handle,F_SETOWN,getpid()) ); } //End of File