00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00033 #include <s3fc/s3_socket_tcp.h>
00034 #include <s3fc/s3_thread_base.h>
00035 #include <s3fc/s3_macros.h>
00036 #include <sstream>
00037 #ifndef _WIN32
00038 #include <sys/time.h>
00039 #endif
00040
00041 s3_socket_tcp::s3_socket_tcp(int newsock, bool new_set_reuseaddr)
00042 throw(s3_generic_exception) :
00043 set_reuseaddr(new_set_reuseaddr), my_errno(0), my_h_errno(0)
00044 {
00045 if(newsock == INVALID_SOCKET)
00046 {
00047 if ( !initialize() )
00048 {
00049 throw s3_generic_exception("s3_socket_tcp::s3_socket_tcp()",
00050 "Could not initialize socket");
00051 }
00052 }
00053 else
00054 {
00055 sock = newsock;
00056 }
00057 }
00058
00059 s3_socket_tcp::s3_socket_tcp(const s3_socket_tcp& template_sock)
00060 throw(s3_generic_exception) :
00061 set_reuseaddr(template_sock.set_reuseaddr), my_errno(0), my_h_errno(0)
00062 {
00063 if ( !initialize() )
00064 {
00065 throw s3_generic_exception("s3_socket_tcp::s3_socket_tcp()",
00066 "Could not initialize socket");
00067 }
00068 }
00069
00070 s3_socket_tcp::~s3_socket_tcp()
00071 {
00072 close(false);
00073 }
00074
00075 bool s3_socket_tcp::initialize()
00076 {
00077 set_errnos();
00078 if( (sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == 1)
00079 {
00080 S3FC_DBG2_("s3_socket_tcp::initialize()", "::socket() failed");
00081 sock = INVALID_SOCKET;
00082 set_errnos(errno);
00083 return false;
00084 }
00085 S3FC_DBG2_("s3_socket_tcp::initialize()", "::socket() ok");
00086
00087
00088 int optval = 1;
00089 if( set_reuseaddr )
00090 {
00091 if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval,
00092 sizeof(int)) != 0 )
00093 {
00094 set_errnos(errno);
00095 return false;
00096 }
00097 }
00098 return true;
00099 }
00100
00101 void s3_socket_tcp::set_errnos(int new_errno, int new_h_errno)
00102 {
00103 my_errno = new_errno;
00104 my_h_errno = new_h_errno;
00105 }
00106
00107 void s3_socket_tcp::change_socket(int newsock)
00108 {
00109 close(false);
00110 sock = newsock;
00111 }
00112
00113 bool s3_socket_tcp::bind(in_addr_t addr, in_port_t port)
00114 {
00115 S3FC_DBG_("s3_socket_tcp::bind(addr,port="<< port << ")");
00116 set_errnos();
00117 sockaddr_in my_addr;
00118 my_addr.sin_family = AF_INET;
00119 my_addr.sin_addr.s_addr = htonl(addr);
00120 my_addr.sin_port = htons(port);
00121 if ( ::bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) != 0 )
00122 {
00123 S3FC_DBG2_("s3_socket_tcp::bind()", "::bind() failed");
00124 set_errnos(errno);
00125 return false;
00126 }
00127 S3FC_DBG2_("s3_socket_tcp::bind()", "::bind() ok");
00128 return true;
00129 }
00130
00131 bool s3_socket_tcp::listen(int backlog)
00132 {
00133 S3FC_DBG_( "s3_socket_tcp::listen(backlog=" << backlog << ")");
00134 set_errnos();
00135 if( ::listen(sock, backlog) != 0 )
00136 {
00137 S3FC_DBG2_("s3_socket_tcp::listen()", "::listen() failed");
00138 set_errnos(errno);
00139 return false;
00140 }
00141 S3FC_DBG2_("s3_socket_tcp::listen()", "::listen() ok");
00142 return true;
00143 }
00144
00145 bool s3_socket_tcp::accept(s3_socket_tcp& newsock, sockaddr_in* clientname)
00146 {
00147 S3FC_DBG_("s3_socket_tcp::accept()");
00148 set_errnos();
00149 int accepted_socket;
00150 #ifdef _WIN32
00151 int size;
00152 #else
00153 socklen_t size;
00154 #endif
00155 size = clientname != 0 ? sizeof(*clientname) : 0;
00156 if( (accepted_socket =
00157 ::accept(sock, (struct sockaddr*)&clientname, &size)) == -1)
00158 {
00159 S3FC_DBG2_( "s3_socket_tcp::accept()", "::accept() failed" );
00160 set_errnos(errno);
00161 return false;
00162 }
00163 S3FC_DBG2_("s3_socket_tcp::accept()", "::accept() ok");
00164 newsock.change_socket(accepted_socket);
00165 return true;
00166 }
00167
00168 bool s3_socket_tcp::connect(const std::string& IP_address, in_port_t port)
00169 {
00170 S3FC_DBG_( "s3_socket_tcp::connect(IP_address=" << IP_address
00171 << ",port=" << port << ")" );
00172
00173 set_errnos();
00174 hostent *he = gethostbyname(IP_address.c_str());
00175 if (he == 0)
00176 {
00177 S3FC_DBG2_("s3_socket_tcp::connect()", "gethostbyname failed");
00178 if ( h_errno >= 0 )
00179 {
00180 set_errnos(-1, h_errno);
00181 }
00182 else
00183 {
00184 set_errnos(errno, 0);
00185 }
00186 return false;
00187 }
00188
00189 sockaddr_in addr;
00190 memset(&addr, 0, sizeof(addr));
00191 memcpy(&addr.sin_addr, he->h_addr, he->h_length);
00192 addr.sin_port = htons(port);
00193 addr.sin_family = he->h_addrtype;
00194
00195 if ( ::connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0 )
00196 {
00197 S3FC_DBG2_("s3_socket_tcp::connect()", "::connect() failed");
00198 set_errnos(errno);
00199 return false;
00200 }
00201 S3FC_DBG2_("s3_socket_tcp::connect()", "::connect() ok");
00202 return true;
00203 }
00204
00205 bool s3_socket_tcp::close(bool reinit) throw(s3_generic_exception)
00206 {
00207 S3FC_DBG_("s3_socket_tcp::close()");
00208
00209 set_errnos();
00210 int ret = 0;
00211 if ( is_valid() )
00212 {
00213 S3FC_DBG2_("s3_socket_tcp::close()", "closing socket");
00214 #ifdef _WIN32
00215 ret = closesocket(sock);
00216 #else
00217 ret = ::close(sock);
00218 #endif
00219 }
00220 sock = INVALID_SOCKET;
00221 if ( ret != 0 )
00222 {
00223 S3FC_DBG2_("s3_socket_tcp::close()", "::close() failed");
00224 set_errnos(errno);
00225 return false;
00226 }
00227 S3FC_DBG2_("s3_socket_tcp::close()", "::close() ok");
00228 if ( reinit && !initialize() )
00229 {
00230 throw s3_generic_exception("s3_socket_tcp::close()",
00231 "Could not reinitialize socket");
00232 }
00233 return true;
00234 }
00235
00236 std::string s3_socket_tcp::get_error() const
00237 {
00238 S3FC_DBG2_( "s3_socket_tcp::get_error()", "my_errno = " << my_errno
00239 << ", " << "my_h_errno = " << my_h_errno );
00240
00241 std::string error_string;
00242 if ( my_errno >= 0 )
00243 {
00244 #ifdef _WIN32
00245 std::stringstream ss;
00246 ss << "WSAGetLastError: " << my_errno;
00247 error_string = ss.str();
00248 #else
00249 error_string = strerror(my_errno);
00250 #endif
00251 }
00252 else if ( my_h_errno > 0 )
00253 {
00254 #ifdef _WIN32
00255 std::stringstream ss;
00256 ss << "WSAGetLastError: (h) " << my_h_errno;
00257 error_string = ss.str();
00258 #else
00259 error_string = hstrerror(my_h_errno);
00260 #endif
00261 }
00262 else if ( my_errno == -1 )
00263 {
00264 error_string = "Connection closed";
00265 }
00266 else if ( my_errno == -2 )
00267 {
00268 error_string = "Termination semaphore posted";
00269 }
00270 else
00271 {
00272 error_string = "Unknown error";
00273 }
00274
00275 S3FC_DBG_("error_string = " << error_string);
00276
00277 return error_string;
00278 }
00279
00280 bool s3_socket_tcp::read(void *data, int size, s3_semaphore *term)
00281 {
00282 S3FC_DBG2_("s3_socket_tcp::read()", "socket = " << sock);
00283
00284 set_errnos();
00285 int rem_size = size;
00286 int e = 0;
00287
00288 char *buf = reinterpret_cast<char*>(data);
00289 do
00290 {
00291
00292 s3_thread_base::test_cancel();
00293
00294
00295 if (term != 0 && term->try_wait())
00296 {
00297 set_errnos(-2);
00298 return false;
00299 }
00300
00301 switch (select_rd(1) )
00302 {
00303 case -1 : return false;
00304 case 0 : continue;
00305 case 1 : break;
00306 default: throw s3_generic_exception("s3_socket_tcp::read()",
00307 "select_rd() returned an invalid value");
00308 }
00309
00310 errno = 0;
00311 #ifdef _WIN32
00312 int ret = recv(sock, buf, rem_size, 0);
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 if ( ( ret == 0 ) || ( ret == SOCKET_ERROR ) )
00324 {
00325 if ( ret == SOCKET_ERROR )
00326 {
00327
00328 e = WSAGetLastError();
00329 if (e == WSAEWOULDBLOCK)
00330 {
00331
00332
00333
00334
00335
00336 continue;
00337 }
00338 else if (e == WSAENOTCONN)
00339 {
00340
00341
00342 set_errnos(-1);
00343 }
00344 else
00345 {
00346 set_errnos(e);
00347 }
00348 }
00349 else
00350 {
00351 set_errnos(-1);
00352 }
00353 return false;
00354 }
00355 #else
00356 int ret = recv(sock, buf, rem_size, MSG_DONTWAIT);
00357 e = errno;
00358
00359 if (e == EAGAIN)
00360 {
00361 continue;
00362 }
00363 else if ( (ret <= 0 ) || (e != 0) )
00364 {
00365
00366
00367 if (e == 0)
00368 {
00369 set_errnos(-1);
00370 }
00371 else
00372 {
00373 set_errnos(e);
00374 }
00375 return false;
00376 }
00377 #endif
00378
00379
00380 rem_size -= ret;
00381 buf = buf + ret;
00382
00383
00384 }
00385 while (rem_size > 0);
00386
00387 return true;
00388 }
00389
00390 bool s3_socket_tcp::write(void *data, int size, int max_packet,
00391 s3_semaphore *term)
00392 {
00393 S3FC_DBG_("s3_socket_tcp::write() called");
00394
00395 set_errnos();
00396 int rem_size = size;
00397 int packet_size = size;
00398 int e = 0;
00399
00400 char *buf = (char *) data;
00401
00402 if (max_packet > size )
00403 {
00404 packet_size = max_packet;
00405 }
00406
00407 do
00408 {
00409 s3_thread_base::test_cancel();
00410
00411
00412 if (term != 0 && term->try_wait())
00413 {
00414 set_errnos(-2);
00415 return false;
00416 }
00417
00418 switch (select_wr(1) )
00419 {
00420 case -1 : return false;
00421 case 0 : continue;
00422 case 1 : break;
00423 default: throw s3_generic_exception("s3_socket_tcp::write()",
00424 "select_wr() returned an invalid value");
00425 }
00426
00427 errno = 0;
00428 #ifdef _WIN32
00429 int ret = send(sock, buf, packet_size, 0);
00430 if (ret == SOCKET_ERROR) e = WSAGetLastError();
00431
00432 if (e == WSAEWOULDBLOCK)
00433 {
00434 continue;
00435 }
00436 else if (ret == SOCKET_ERROR)
00437 {
00438 set_errnos(e);
00439 return false;
00440 }
00441 #else
00442 int ret = send(sock, buf, packet_size, MSG_DONTWAIT | MSG_NOSIGNAL);
00443 e = errno;
00444 if ( e == EAGAIN)
00445 {
00446 continue;
00447 }
00448 else if ( (ret < 0 ) || (e != 0) )
00449 {
00450
00451 set_errnos(e);
00452 return false;
00453 }
00454 #endif
00455
00456
00457 rem_size = rem_size - ret;
00458 buf = buf + ret;
00459 if (rem_size < packet_size) packet_size = rem_size;
00460
00461
00462 }
00463 while (rem_size > 0);
00464
00465 return true;
00466 }
00467
00468 int s3_socket_tcp::select_rd(int delay)
00469 {
00470 fd_set fds, fde;
00471 timeval tv;
00472
00473 tv.tv_sec = delay;
00474 tv.tv_usec = 0;
00475
00476 FD_ZERO(&fds);
00477 FD_ZERO(&fde);
00478 FD_SET(sock, &fds);
00479 FD_SET(sock, &fde);
00480 errno = 0;
00481 int ret = select(sock+1, &fds, 0, &fde, &tv);
00482 if ( ( ret == -1 ) || FD_ISSET(sock, &fde) )
00483 {
00484 set_errnos(errno);
00485 return -1;
00486 }
00487 if (ret == 0 )
00488 {
00489 return 0;
00490 }
00491 if ( FD_ISSET(sock, &fds) )
00492 {
00493 return 1;
00494 }
00495
00496 return -2;
00497 }
00498
00499 int s3_socket_tcp::select_wr(int delay)
00500 {
00501 fd_set fds, fde;
00502 timeval tv;
00503
00504 tv.tv_sec = delay;
00505 tv.tv_usec = 0;
00506
00507 FD_ZERO(&fds);
00508 FD_ZERO(&fde);
00509 FD_SET(sock, &fds);
00510 FD_SET(sock, &fde);
00511 errno = 0;
00512 int ret = select(sock+1, 0, &fds, &fde, &tv);
00513 if ( ( ret == -1 ) || FD_ISSET(sock, &fde) )
00514 {
00515 set_errnos(errno);
00516 return -1;
00517 }
00518 if (ret == 0 )
00519 {
00520 return 0;
00521 }
00522 if ( FD_ISSET(sock, &fds) )
00523 {
00524 return 1;
00525 }
00526
00527 return -2;
00528
00529 }
00530