00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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