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.10 2005/04/11 19:34:23 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 memcpy ( addr, ptr->ai_addr, ptr->ai_addrlen);
00212 freeaddrinfo(ptr);
00213 #else
00214 if ( !(pHostEntry = gethostbyname( host)) ) {
00215 throw Exception( __FILE__, __LINE__, "gethostbyname error", errno);
00216 }
00217
00218 if ( (sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
00219 throw Exception( __FILE__, __LINE__, "socket error", errno);
00220 }
00221
00222 memset( &addr, 0, sizeof(addr));
00223 addr.sin_family = AF_INET;
00224 addr.sin_port = htons(port);
00225 addr.sin_addr.s_addr = *((long*) pHostEntry->h_addr_list[0]);
00226 #endif
00227 if ( connect( sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1 ) {
00228 ::close( sockfd);
00229 sockfd = 0;
00230 throw Exception( __FILE__, __LINE__, "connect error", errno);
00231 }
00232
00233 return true;
00234 }
00235
00236
00237
00238
00239
00240 bool
00241 TcpSocket :: canRead ( unsigned int sec,
00242 unsigned int usec ) throw ( Exception )
00243 {
00244 fd_set fdset;
00245 struct timeval tv;
00246 int ret;
00247
00248 if ( !isOpen() ) {
00249 return false;
00250 }
00251
00252 FD_ZERO( &fdset);
00253 FD_SET( sockfd, &fdset);
00254 tv.tv_sec = sec;
00255 tv.tv_usec = usec;
00256
00257 ret = select( sockfd + 1, &fdset, NULL, NULL, &tv);
00258
00259 if ( ret == -1 ) {
00260 throw Exception( __FILE__, __LINE__, "select error");
00261 }
00262
00263 return ret > 0;
00264 }
00265
00266
00267
00268
00269
00270 unsigned int
00271 TcpSocket :: read ( void * buf,
00272 unsigned int len ) throw ( Exception )
00273 {
00274 int ret;
00275
00276 if ( !isOpen() ) {
00277 return 0;
00278 }
00279
00280 ret = recv( sockfd, buf, len, 0);
00281
00282 if ( ret == -1 ) {
00283 throw Exception( __FILE__, __LINE__, "recv error", errno);
00284 }
00285
00286 return ret;
00287 }
00288
00289
00290
00291
00292
00293 bool
00294 TcpSocket :: canWrite ( unsigned int sec,
00295 unsigned int usec ) throw ( Exception )
00296 {
00297 fd_set fdset;
00298 struct timeval tv;
00299 int ret;
00300
00301 if ( !isOpen() ) {
00302 return false;
00303 }
00304
00305 FD_ZERO( &fdset);
00306 FD_SET( sockfd, &fdset);
00307 tv.tv_sec = sec;
00308 tv.tv_usec = usec;
00309
00310 ret = select( sockfd + 1, NULL, &fdset, NULL, &tv);
00311
00312 if ( ret == -1 ) {
00313 throw Exception( __FILE__, __LINE__, "select error");
00314 }
00315
00316 return ret > 0;
00317 }
00318
00319
00320
00321
00322
00323 unsigned int
00324 TcpSocket :: write ( const void * buf,
00325 unsigned int len ) throw ( Exception )
00326 {
00327 int ret;
00328
00329 if ( !isOpen() ) {
00330 return 0;
00331 }
00332
00333 #ifdef HAVE_MSG_NOSIGNAL
00334 ret = send( sockfd, buf, len, MSG_NOSIGNAL);
00335 #else
00336 ret = send( sockfd, buf, len, 0);
00337 #endif
00338
00339 if ( ret == -1 ) {
00340 if ( errno == EAGAIN ) {
00341 ret = 0;
00342 } else {
00343 throw Exception( __FILE__, __LINE__, "send error", errno);
00344 }
00345 }
00346
00347 return ret;
00348 }
00349
00350
00351
00352
00353
00354 void
00355 TcpSocket :: close ( void ) throw ( Exception )
00356 {
00357 if ( !isOpen() ) {
00358 return;
00359 }
00360
00361 flush();
00362 ::close( sockfd);
00363 sockfd = 0;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
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