00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035
00036 #ifdef HAVE_STRING_H
00037 #include <string.h>
00038 #else
00039 #error need string.h
00040 #endif
00041
00042 #ifdef HAVE_SYS_TYPES_H
00043 #include <sys/types.h>
00044 #else
00045 #error need sys/types.h
00046 #endif
00047
00048 #ifdef HAVE_ERRNO_H
00049 #include <errno.h>
00050 #else
00051 #error need errno.h
00052 #endif
00053
00054 #ifdef HAVE_SYS_SOCKET_H
00055 #include <sys/socket.h>
00056 #else
00057 #error need sys/socket.h
00058 #endif
00059
00060 #ifdef HAVE_NETINET_IN_H
00061 #include <netinet/in.h>
00062 #else
00063 #error need netinet/in.h
00064 #endif
00065
00066 #ifdef HAVE_NETDB_H
00067 #include <netdb.h>
00068 #else
00069 #error need netdb.h
00070 #endif
00071
00072 #ifdef HAVE_UNISTD_H
00073 #include <unistd.h>
00074 #else
00075 #error need unistd.h
00076 #endif
00077
00078 #ifdef HAVE_SYS_TIME_H
00079 #include <sys/time.h>
00080 #else
00081 #error need sys/time.h
00082 #endif
00083
00084
00085 #include "Util.h"
00086 #include "Exception.h"
00087 #include "TcpSocket.h"
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static const char fileid[] = "$Id: TcpSocket.cpp,v 1.11 2006/05/19 12:39:19 darkeye Exp $";
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 void
00110 TcpSocket :: init ( const char * host,
00111 unsigned short port ) throw ( Exception )
00112 {
00113 this->host = Util::strDup( host);
00114 this->port = port;
00115 this->sockfd = 0;
00116 }
00117
00118
00119
00120
00121
00122 void
00123 TcpSocket :: strip ( void) throw ( Exception )
00124 {
00125 if ( isOpen() ) {
00126 close();
00127 }
00128
00129 delete[] host;
00130 }
00131
00132
00133
00134
00135
00136 TcpSocket :: TcpSocket ( const TcpSocket & ss ) throw ( Exception )
00137 : Source( ss), Sink( ss )
00138 {
00139 int fd;
00140
00141 init( ss.host, ss.port);
00142
00143 if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) {
00144 strip();
00145 throw Exception( __FILE__, __LINE__, "dup failure");
00146 }
00147
00148 sockfd = fd;
00149 }
00150
00151
00152
00153
00154
00155 TcpSocket &
00156 TcpSocket :: operator= ( const TcpSocket & ss ) throw ( Exception )
00157 {
00158 if ( this != &ss ) {
00159 int fd;
00160
00161
00162 strip();
00163
00164
00165
00166 Sink::operator=( ss );
00167 Source::operator=( ss );
00168
00169 init( ss.host, ss.port);
00170
00171 if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) {
00172 strip();
00173 throw Exception( __FILE__, __LINE__, "dup failure");
00174 }
00175
00176 sockfd = fd;
00177 }
00178
00179 return *this;
00180 }
00181
00182
00183
00184
00185
00186 bool
00187 TcpSocket :: open ( void ) throw ( Exception )
00188 {
00189 #ifdef HAVE_ADDRINFO
00190 struct addrinfo hints
00191 struct addrinfo * ptr;
00192 struct sockaddr_storage addr;
00193 char portstr[6];
00194 #else
00195 struct sockaddr_in addr;
00196 struct hostent * pHostEntry;
00197 #endif
00198
00199 if ( isOpen() ) {
00200 return false;
00201 }
00202
00203 #ifdef HAVE_ADDRINFO
00204 memset(&hints, 0, sizeof(hints));
00205 hints.ai_socktype = SOCK_STREAM;
00206 hints.ai_family = AF_ANY;
00207 snprintf(portstr, sizeof(portstr), "%d", port);
00208
00209 if (getaddrinfo(host , portstr, &hints, &ptr)) {
00210 throw Exception( __FILE__, __LINE__, "getaddrinfo error", errno);
00211 }
00212 memcpy ( addr, ptr->ai_addr, ptr->ai_addrlen);
00213 freeaddrinfo(ptr);
00214 #else
00215 if ( !(pHostEntry = gethostbyname( host)) ) {
00216 throw Exception( __FILE__, __LINE__, "gethostbyname error", errno);
00217 }
00218
00219 if ( (sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
00220 throw Exception( __FILE__, __LINE__, "socket error", errno);
00221 }
00222
00223 memset( &addr, 0, sizeof(addr));
00224 addr.sin_family = AF_INET;
00225 addr.sin_port = htons(port);
00226 addr.sin_addr.s_addr = *((long*) pHostEntry->h_addr_list[0]);
00227 #endif
00228 if ( connect( sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1 ) {
00229 ::close( sockfd);
00230 sockfd = 0;
00231 throw Exception( __FILE__, __LINE__, "connect error", errno);
00232 }
00233
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241 bool
00242 TcpSocket :: canRead ( unsigned int sec,
00243 unsigned int usec ) throw ( Exception )
00244 {
00245 fd_set fdset;
00246 struct timeval tv;
00247 int ret;
00248
00249 if ( !isOpen() ) {
00250 return false;
00251 }
00252
00253 FD_ZERO( &fdset);
00254 FD_SET( sockfd, &fdset);
00255 tv.tv_sec = sec;
00256 tv.tv_usec = usec;
00257
00258 ret = select( sockfd + 1, &fdset, NULL, NULL, &tv);
00259
00260 if ( ret == -1 ) {
00261 throw Exception( __FILE__, __LINE__, "select error");
00262 }
00263
00264 return ret > 0;
00265 }
00266
00267
00268
00269
00270
00271 unsigned int
00272 TcpSocket :: read ( void * buf,
00273 unsigned int len ) throw ( Exception )
00274 {
00275 int ret;
00276
00277 if ( !isOpen() ) {
00278 return 0;
00279 }
00280
00281 ret = recv( sockfd, buf, len, 0);
00282
00283 if ( ret == -1 ) {
00284 switch (errno) {
00285 case ECONNRESET:
00286
00287 close();
00288 open();
00289 break;
00290
00291 default:
00292 throw Exception( __FILE__, __LINE__, "recv error", errno);
00293 }
00294 }
00295
00296 return ret;
00297 }
00298
00299
00300
00301
00302
00303 bool
00304 TcpSocket :: canWrite ( unsigned int sec,
00305 unsigned int usec ) throw ( Exception )
00306 {
00307 fd_set fdset;
00308 struct timeval tv;
00309 int ret;
00310
00311 if ( !isOpen() ) {
00312 return false;
00313 }
00314
00315 FD_ZERO( &fdset);
00316 FD_SET( sockfd, &fdset);
00317 tv.tv_sec = sec;
00318 tv.tv_usec = usec;
00319
00320 ret = select( sockfd + 1, NULL, &fdset, NULL, &tv);
00321
00322 if ( ret == -1 ) {
00323 throw Exception( __FILE__, __LINE__, "select error");
00324 }
00325
00326 return ret > 0;
00327 }
00328
00329
00330
00331
00332
00333 unsigned int
00334 TcpSocket :: write ( const void * buf,
00335 unsigned int len ) throw ( Exception )
00336 {
00337 int ret;
00338
00339 if ( !isOpen() ) {
00340 return 0;
00341 }
00342
00343 #ifdef HAVE_MSG_NOSIGNAL
00344 ret = send( sockfd, buf, len, MSG_NOSIGNAL);
00345 #else
00346 ret = send( sockfd, buf, len, 0);
00347 #endif
00348
00349 if ( ret == -1 ) {
00350 if ( errno == EAGAIN ) {
00351 ret = 0;
00352 } else {
00353 throw Exception( __FILE__, __LINE__, "send error", errno);
00354 }
00355 }
00356
00357 return ret;
00358 }
00359
00360
00361
00362
00363
00364 void
00365 TcpSocket :: close ( void ) throw ( Exception )
00366 {
00367 if ( !isOpen() ) {
00368 return;
00369 }
00370
00371 flush();
00372 ::close( sockfd);
00373 sockfd = 0;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418