Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

NetworkStream.hpp

Go to the documentation of this file.
00001 /*==========================================================================
00002  * Copyright (c) 2004 University of Massachusetts.  All Rights Reserved.
00003  *
00004  * Use of the Lemur Toolkit for Language Modeling and Information Retrieval
00005  * is subject to the terms of the software license set forth in the LICENSE
00006  * file included with this software, and also available at
00007  * http://www.lemurproject.org/license.html
00008  *
00009  *==========================================================================
00010  */
00011 
00012 
00013 //
00014 // NetworkStream
00015 //
00016 // 23 March 2004 -- tds
00017 //
00018 
00019 #ifndef INDRI_NETWORKSTREAM_HPP
00020 #define INDRI_NETWORKSTREAM_HPP
00021 
00022 #if defined(__APPLE__) || defined(__SVR4) || defined(WIN32)
00023 #define MSG_NOSIGNAL 0
00024 #endif
00025 
00026 #include "lemur-platform.h"
00027 #include "lemur-compat.hpp"
00028 #include "indri/indri-platform.h"
00029 #include <string>
00030 
00031 namespace indri
00032 {
00033   namespace net
00034   {
00035     
00036     class NetworkStream {
00037     private:
00038       socket_t _socket;
00039 
00040       struct sockaddr_in _getSockaddr( const char* name, unsigned int port ) {
00041         long address = 0;
00042 
00043 #ifndef WIN32
00044         if( name && isdigit(name[0]) ) {
00045 #else
00046         if( name && name[0] >= 0 && isdigit(name[0]) ) {
00047 #endif
00048           address = inet_addr(name);
00049         } else {
00050           hostent* host = gethostbyname(name);
00051       
00052           if( host && host->h_length ) {
00053             address = *( (long*) host->h_addr );
00054           }
00055         }
00056 
00057         struct sockaddr_in sa;
00058 
00059         sa.sin_addr.s_addr = address;
00060         sa.sin_port = htons(port);
00061         sa.sin_family = AF_INET;
00062         memset(&sa.sin_zero, 0, sizeof sa.sin_zero );
00063 
00064         return sa;
00065       }
00066 
00067     public:
00068       NetworkStream() : _socket(-1) {}
00069       NetworkStream( socket_t s ) : _socket(s) {}
00070       ~NetworkStream() {
00071         close();
00072       }
00073 
00074       std::string peer() {
00075         struct sockaddr_in sa;
00076         socklen_t addrlen = sizeof sa;
00077         std::string result;
00078 
00079         int error = ::getpeername( _socket, (struct sockaddr*) &sa, &addrlen );
00080 
00081         if( !error ) {
00082           hostent* he = ::gethostbyaddr( (const char*) &sa.sin_addr, sizeof sa.sin_addr.s_addr, AF_INET );
00083 
00084           if( he && he->h_length ) {
00085             return he->h_name;
00086           }
00087         }
00088 
00089         return "unknown";
00090       }
00091 
00092       bool connect( const std::string& name, unsigned int port ) {
00093         return connect(name.c_str(), port);
00094       }
00095 
00096       bool connect( const char* name, unsigned int port ) {
00097         lemur_compat::initializeNetwork();
00098 
00099         _socket = ::socket( AF_INET, SOCK_STREAM, 0 );
00100 #ifdef __APPLE__
00101         int set = 1;
00102         setsockopt(_socket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
00103 #endif
00104         struct sockaddr_in sa = _getSockaddr( name, port );
00105         int result = ::connect( _socket, (const sockaddr*) &sa, sizeof sa );
00106 
00107         if( result ) {
00108           close();
00109         }
00110 
00111         return !result;
00112       }
00113 
00114       void close() {
00115         lemur_compat::closesocket( _socket );
00116         _socket = -1;
00117       }
00118 
00119       int write( const void* buffer, size_t length ) {
00120 //        return ::send( _socket, (const char*) buffer, int(length), 0 );
00121         if (_socket == -1) return 0;
00122         int result = ::send( _socket, (const char*) buffer, int(length), MSG_NOSIGNAL );
00123         if (result < 0) close();
00124         return result;
00125       }
00126 
00127       int read( void* buffer, size_t length ) {
00128         return ::recv( _socket, (char*) buffer, int(length), 0 );
00129       }
00130 
00131       int blockingRead( void* buffer, size_t length ) {
00132         size_t bytesRead = 0;
00133         size_t chunkRead = 0;
00134         int result;
00135     
00136         while( bytesRead < length ) {
00137           // only try to read 100K at a time.
00138           chunkRead = lemur_compat::min<size_t>((size_t)1024*100, (length - bytesRead));
00139           result = read( (char*)buffer + bytesRead, chunkRead );
00140 
00141           if( result <= 0 ) {
00142             close();
00143             return int(bytesRead);
00144           }
00145 
00146           bytesRead += result;
00147         }
00148 
00149         return int(bytesRead);
00150       }
00151 
00152       int blockingWrite( const void* buffer, unsigned int length ) {
00153         size_t bytesWritten = 0;
00154 
00155         while( bytesWritten < (int) length ) {
00156           // only try to write 100K at a time.
00157           size_t chunkWrite = std::min((size_t)1024*100, (length - bytesWritten));
00158           int result = write( (const char*)buffer + bytesWritten, chunkWrite );
00159 
00160           if( result <= 0 ) {
00161             close();
00162             return int(bytesWritten);
00163           }
00164 
00165           bytesWritten += result;
00166         }
00167 
00168         return int(bytesWritten);
00169       }
00170 
00171       bool alive() {
00172         return _socket != -1;
00173       }
00174     };
00175   }
00176 }
00177 
00178 #endif // INDRI_NETWORKSTREAM_HPP

Generated on Tue Jun 15 11:02:54 2010 for Lemur by doxygen 1.3.4