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
00033
00034
00035 #define ULXR_REUSE_SOCKET
00036
00037 #ifndef ULXR_OMIT_TCP_STUFF
00038
00039 #define ULXR_NEED_EXPORTS
00040 #include <ulxmlrpcpp/ulxmlrpcpp.h>
00041
00042 #include <cerrno>
00043
00044 #ifdef __SUN__
00045 #include <sys/systeminfo.h>
00046 #endif
00047
00048 #ifdef __unix__
00049 #include <sys/socket.h>
00050 #include <netinet/tcp.h>
00051
00052 #if defined(ULXR_USE_EPOLL) && defined(HAVE_SYS_EPOLL_H)
00053 #include <sys/epoll.h>
00054 #endif
00055
00056 #endif
00057
00058
00059
00060 #include <ulxmlrpcpp/ulxr_tcpip_connection.h>
00061 #include <ulxmlrpcpp/ulxr_htmlform_handler.h>
00062 #include <ulxmlrpcpp/ulxr_except.h>
00063
00064 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00065 #include <ulxmlrpcpp/ulxr_mutex.h>
00066 #endif
00067
00068
00069 namespace ulxr {
00070
00071
00072 ULXR_API_IMPL0 TcpIpConnection::ServerSocketData::ServerSocketData(int s_no)
00073 : count(1)
00074 , socket_no(s_no)
00075 {
00076 }
00077
00078
00079 ULXR_API_IMPL0 TcpIpConnection::ServerSocketData::~ServerSocketData()
00080 {
00081 close();
00082 }
00083
00084
00085 ULXR_API_IMPL(int) TcpIpConnection::ServerSocketData::getSocket() const
00086 {
00087 return socket_no;
00088 }
00089
00090
00091 ULXR_API_IMPL(void) TcpIpConnection::ServerSocketData::incRef()
00092 {
00093 ++count;
00094 }
00095
00096
00097 ULXR_API_IMPL(int) TcpIpConnection::ServerSocketData::decRef()
00098 {
00099 if (count > 0)
00100 --count;
00101 return count;
00102 }
00103
00104
00105 ULXR_API_IMPL(bool) TcpIpConnection::ServerSocketData::isOpen()
00106 {
00107 return socket_no != -1;
00108 }
00109
00110
00111 ULXR_API_IMPL(void) TcpIpConnection::ServerSocketData::close()
00112 {
00113 ULXR_TRACE(ULXR_PCHAR("close"));
00114 #ifndef __unix__
00115 ::closesocket(socket_no);
00116 #else
00117 int ret;
00118 do
00119 ret = ::close(socket_no);
00120 while(ret < 0 && (errno == EINTR || errno == EAGAIN));
00121
00122 if(ret < 0)
00123 throw ConnectionException(TransportError,
00124 ULXR_PCHAR("close() failed for TcpIpConnection::ServerSocketData"), 500);
00125 #endif
00126 socket_no = -1;
00127 }
00128
00129
00130 ULXR_API_IMPL(void) TcpIpConnection::ServerSocketData::shutdown(int in_mode)
00131 {
00132 ULXR_TRACE(ULXR_PCHAR("shutdown") << in_mode);
00133 int ret;
00134 do
00135 ret = ::shutdown(socket_no, in_mode);
00136 while(ret < 0 && (errno == EINTR || errno == EAGAIN));
00137
00138 if(ret < 0)
00139 throw ConnectionException(TransportError,
00140 ULXR_PCHAR("shutdown() failed for TcpIpConnection::ServerSocketData"), 500);
00141 }
00142
00143
00145
00146
00147 struct TcpIpConnection::PImpl
00148 {
00149 CppString serverdomain;
00150 unsigned port;
00151 ServerSocketData *server_data;
00152
00153 CppString host_name;
00154 struct sockaddr_in hostdata;
00155 socklen_t hostdata_len;
00156
00157 CppString remote_name;
00158 struct sockaddr_in remotedata;
00159 socklen_t remotedata_len;
00160 };
00161
00162
00163 ULXR_API_IMPL0 TcpIpConnection::TcpIpConnection(const TcpIpConnection &conn)
00164 : Connection(conn)
00165 , pimpl(new PImpl)
00166 {
00167 *pimpl = *conn.pimpl;
00168 }
00169
00170
00171 ULXR_API_IMPL0 TcpIpConnection::TcpIpConnection(bool I_am_server, long adr, unsigned prt)
00172 : Connection()
00173 , pimpl(new PImpl)
00174 {
00175 ULXR_TRACE(ULXR_PCHAR("TcpIpConnection(bool, long, uint)") << adr << ULXR_PCHAR(" ") << pimpl->port);
00176 init(prt);
00177
00178 pimpl->hostdata.sin_addr.s_addr = htonl(adr);
00179
00180 if (I_am_server)
00181 {
00182 pimpl->server_data = new ServerSocketData(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
00183 if (getServerHandle() < 0)
00184 throw ConnectionException(SystemError,
00185 ulxr_i18n(ULXR_PCHAR("Could not create socket: "))
00186 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00187
00188 #ifdef ULXR_REUSE_SOCKET
00189 int sockOpt = 1;
00190 if (::setsockopt(getServerHandle(), SOL_SOCKET, SO_REUSEADDR,
00191 (const char*)&sockOpt, sizeof(sockOpt)) < 0)
00192 throw ConnectionException(SystemError,
00193 ulxr_i18n(ULXR_PCHAR("Could not set reuse flag for socket: "))
00194 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00195 #endif
00196
00197 int iOptVal = getTimeout() * 1000;
00198 int iOptLen = sizeof(int);
00199 ::setsockopt(getServerHandle(), SOL_SOCKET, SO_RCVTIMEO, (char*)&iOptVal, iOptLen);
00200 ::setsockopt(getServerHandle(), SOL_SOCKET, SO_SNDTIMEO, (char*)&iOptVal, iOptLen);
00201
00202 if((::bind(getServerHandle(), (sockaddr*) &pimpl->hostdata, sizeof(pimpl->hostdata))) < 0)
00203 throw ConnectionException(SystemError,
00204 ulxr_i18n(ULXR_PCHAR("Could not bind adress: "))
00205 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00206
00207 ::listen(getServerHandle(), 5);
00208 }
00209 }
00210
00211
00212 ULXR_API_IMPL0
00213 TcpIpConnection::TcpIpConnection(bool I_am_server, const CppString &dom, unsigned prt)
00214 : Connection()
00215 , pimpl(new PImpl)
00216 {
00217 ULXR_TRACE(ULXR_PCHAR("TcpIpConnection(bool, string, uint)") << dom << ULXR_PCHAR(" ") << pimpl->port);
00218 init(prt);
00219
00220 pimpl->remote_name = dom;
00221
00222 struct hostent *hp = getHostAdress(dom);
00223 if (hp == 0)
00224 throw ConnectionException(SystemError,
00225 ulxr_i18n(ULXR_PCHAR("Host adress not found: ")) + pimpl->serverdomain, 500);
00226 memcpy(&(pimpl->hostdata.sin_addr), hp->h_addr_list[0], hp->h_length);
00227
00228 if (I_am_server)
00229 {
00230 pimpl->server_data = new ServerSocketData(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
00231 if (getServerHandle() < 0)
00232 throw ConnectionException(SystemError,
00233 ulxr_i18n(ULXR_PCHAR("Could not create socket: "))
00234 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00235 #ifdef ULXR_REUSE_SOCKET
00236 int sockOpt = 1;
00237 if (::setsockopt(getServerHandle(), SOL_SOCKET, SO_REUSEADDR,
00238 (const char*)&sockOpt, sizeof(sockOpt)) < 0)
00239 throw ConnectionException(SystemError,
00240 ulxr_i18n(ULXR_PCHAR("Could not set reuse flag for socket: "))
00241 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00242 #endif
00243
00244 int iOptVal = getTimeout() * 1000;
00245 int iOptLen = sizeof(int);
00246 ::setsockopt(getServerHandle(), SOL_SOCKET, SO_RCVTIMEO, (char*)&iOptVal, iOptLen);
00247 ::setsockopt(getServerHandle(), SOL_SOCKET, SO_SNDTIMEO, (char*)&iOptVal, iOptLen);
00248
00249 if((::bind(getServerHandle(), (sockaddr*) &pimpl->hostdata, sizeof(pimpl->hostdata))) < 0)
00250 throw ConnectionException(SystemError,
00251 ulxr_i18n(ULXR_PCHAR("Could not bind adress: "))
00252 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00253
00254 listen(getServerHandle(), 5);
00255 }
00256 }
00257
00258
00259 ULXR_API_IMPL(TcpIpConnection *) TcpIpConnection::makeClone()
00260 {
00261 return new TcpIpConnection(*this);
00262 }
00263
00264
00265 ULXR_API_IMPL(Connection *) TcpIpConnection::detach()
00266 {
00267 ULXR_TRACE(ULXR_PCHAR("detach"));
00268 TcpIpConnection *clone = makeClone();;
00269 clone->pimpl->server_data = 0;
00270
00271 clone->setServerData(getServerData());
00272 if (getServerData() != 0)
00273 getServerData()->incRef();
00274
00275 ULXR_TRACE(ULXR_PCHAR("detach getHandle() ") << getHandle());
00276 ULXR_TRACE(ULXR_PCHAR("detach clone->getHandle() ") << clone->getHandle());
00277 cut();
00278 ULXR_TRACE(ULXR_PCHAR("detach getHandle() ") << getHandle());
00279 ULXR_TRACE(ULXR_PCHAR("detach clone->getHandle() ") << clone->getHandle());
00280
00281 ULXR_TRACE(ULXR_PCHAR("/detach"));
00282 return clone;
00283 }
00284
00285
00286 ULXR_API_IMPL(void) TcpIpConnection::setProxy(long adr, unsigned port)
00287 {
00288 ULXR_TRACE(ULXR_PCHAR("setProxy ") << adr << ULXR_PCHAR(" ") << port);
00289 pimpl->hostdata.sin_addr.s_addr = htonl(adr);
00290 pimpl->hostdata.sin_port = htons(port);
00291 }
00292
00293
00294 ULXR_API_IMPL(void) TcpIpConnection::setProxy(const CppString &dom, unsigned port)
00295 {
00296 ULXR_TRACE(ULXR_PCHAR("setProxy ") << dom << ULXR_PCHAR(" ") << port);
00297 struct hostent *hp = getHostAdress(dom);
00298 if (hp == 0)
00299 throw ConnectionException(SystemError,
00300 ulxr_i18n(ULXR_PCHAR("Host adress for proxy not found: ")) + dom, 500);
00301 memcpy(&(pimpl->hostdata.sin_addr), hp->h_addr_list[0], hp->h_length);
00302 pimpl->hostdata.sin_port = htons(port);
00303 }
00304
00305
00306 ULXR_API_IMPL(void) TcpIpConnection::init(unsigned prt)
00307 {
00308 ULXR_TRACE(ULXR_PCHAR("init"));
00309 #if defined(__WIN32__) && !defined (ULXR_NO_WSA_STARTUP)
00310 WORD wVersionRequested;
00311 WSADATA wsaData;
00312 wVersionRequested = MAKEWORD( 2, 0 );
00313
00314 if (WSAStartup( wVersionRequested, &wsaData) != 0)
00315 throw ConnectionException(SystemError,
00316 ulxr_i18n(ULXR_PCHAR("Could not initialize Windows sockets: "))
00317 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00318 #endif
00319
00320 pimpl->server_data = 0;
00321 setTcpNoDelay(false);
00322 pimpl->serverdomain = ULXR_PCHAR("");
00323 pimpl->remote_name = ULXR_PCHAR("");
00324 setTimeout(10);
00325 pimpl->port = prt;
00326 pimpl->hostdata_len = sizeof(pimpl->hostdata);
00327 pimpl->remotedata_len = sizeof(pimpl->remotedata);
00328 memset(&pimpl->hostdata, 0, sizeof(pimpl->hostdata));
00329 memset(&pimpl->remotedata, 0, sizeof(pimpl->remotedata));
00330 pimpl->hostdata.sin_port = htons(pimpl->port);
00331 pimpl->hostdata.sin_family = AF_INET;
00332
00333 char buffer [1000];
00334 int ret = gethostname(buffer, sizeof(buffer)-1);
00335 if (ret != 0)
00336 throw ConnectionException(SystemError,
00337 ulxr_i18n(ULXR_PCHAR("Could not get host name: "))
00338 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00339
00340 pimpl->host_name = ULXR_GET_STRING(buffer);
00341
00342 #if defined(__SUN__)
00343
00344 long status = sysinfo(SI_SRPC_DOMAIN ,buffer, sizeof(buffer)-1);
00345 if (status == -1)
00346 throw ConnectionException(SystemError,
00347 ulxr_i18n(ULXR_PCHAR("Could not get domain name: "))
00348 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00349
00350 if (buffer[0] != 0)
00351 {
00352 pimpl->host_name += ULXR_PCHAR(".");
00353 pimpl->host_name += ULXR_GET_STRING(buffer);
00354 }
00355
00356 #elif defined(__unix__) || defined(__CYGWIN__)
00357
00358 ret = getdomainname(buffer, sizeof(buffer)-1);
00359 if (ret != 0)
00360 throw ConnectionException(SystemError,
00361 ulxr_i18n(ULXR_PCHAR("Could not get domain name: "))
00362 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00363
00364 if (buffer[0] != 0)
00365 {
00366 pimpl->host_name += ULXR_PCHAR(".");
00367 pimpl->host_name += ULXR_GET_STRING(buffer);
00368 }
00369
00370 #elif _WIN32
00371
00372 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00373 Mutex::Locker lock(gethostbynameMutex);
00374 #endif
00375
00376 struct hostent *hostEntPtr = gethostbyname(getLatin1(pimpl->host_name).c_str());
00377 if (!hostEntPtr)
00378 throw ConnectionException(SystemError,
00379 ulxr_i18n(ULXR_PCHAR("Could not get host+domain name: "))
00380 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00381 pimpl->host_name = ULXR_GET_STRING(hostEntPtr->h_name);
00382
00383 #else
00384 # pragma message ("don't know how to determine the domain name")
00385 #endif
00386 }
00387
00388
00389 ULXR_API_IMPL(void) TcpIpConnection::asciiToInAddr(const char *address, struct in_addr &saddr)
00390 {
00391 memset (&saddr, 0, sizeof(in_addr));
00392 struct hostent *host;
00393
00394
00395 saddr.s_addr = inet_addr(address);
00396 if ((int)saddr.s_addr == -1)
00397 throw ConnectionException(SystemError,
00398 ulxr_i18n(ULXR_PCHAR("Could not perform inet_addr(): "))
00399 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00400
00401 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00402 Mutex::Locker lock(gethostbynameMutex);
00403 #endif
00404
00405 host = gethostbyname(address);
00406 if (host == 0)
00407 throw ConnectionException(SystemError,
00408 ulxr_i18n(ULXR_PCHAR("Could not perform gethostname(): "))
00409 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00410
00411 memmove((void*)&saddr, host->h_addr_list, sizeof(in_addr));
00412 }
00413
00414
00415 ULXR_API_IMPL(struct hostent *)
00416 TcpIpConnection::getHostAdress(const CppString &dom)
00417 {
00418 unsigned start = 0;
00419 if (dom.substr(start, 5) == ULXR_PCHAR("http:"))
00420 start += 5;
00421
00422 if (dom.substr(start, 2) == ULXR_PCHAR("//"))
00423 start += 2;
00424
00425 std::size_t slash = dom.find (ULXR_PCHAR("/"), start);
00426 if (slash != CppString::npos)
00427 pimpl->serverdomain = dom.substr(start, slash-1);
00428 else
00429 pimpl->serverdomain = dom;
00430
00431 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00432 Mutex::Locker lock(gethostbynameMutex);
00433 #endif
00434
00435 return gethostbyname(getLatin1(pimpl->serverdomain).c_str() );
00436 }
00437
00438
00439 ULXR_API_IMPL0 TcpIpConnection::~TcpIpConnection()
00440 {
00441 ULXR_TRACE(ULXR_PCHAR("~TcpIpConnection"));
00442 try
00443 {
00444 decrementServerRef();
00445 }
00446 catch(...)
00447 {
00448
00449 }
00450 delete pimpl;
00451 pimpl = 0;
00452 }
00453
00454
00455 void TcpIpConnection::decrementServerRef(bool in_shutdown)
00456 {
00457 ULXR_TRACE(ULXR_PCHAR("decrementServerRef"));
00458
00459 if (pimpl->server_data != 0 && pimpl->server_data->decRef() <= 0)
00460 {
00461 ULXR_TRACE(ULXR_PCHAR("delete serverdata ") << std::hex << (void*)pimpl->server_data << std::dec);
00462
00463 if(in_shutdown)
00464 {
00465 ULXR_TRACE(ULXR_PCHAR("shutdown server_data"));
00466 if (pimpl->server_data->isOpen())
00467 #ifdef __WIN32__
00468 pimpl->server_data->shutdown(SD_BOTH);
00469 #else
00470 pimpl->server_data->shutdown(SHUT_RD);
00471 #endif
00472 }
00473
00474 delete pimpl->server_data;
00475 pimpl->server_data = 0;
00476 }
00477 }
00478
00479
00480 ULXR_API_IMPL(bool) TcpIpConnection::isServerMode() const
00481 {
00482 return pimpl->server_data != 0;
00483 }
00484
00485
00486 ULXR_API_IMPL(void) TcpIpConnection::open()
00487 {
00488 ULXR_TRACE(ULXR_PCHAR("open"));
00489 if (isOpen() )
00490 throw RuntimeException(ApplicationError,
00491 ulxr_i18n(ULXR_PCHAR("Attempt to open an already open connection")));
00492
00493 if (pimpl->server_data != 0)
00494 throw ConnectionException(SystemError,
00495 ulxr_i18n(ULXR_PCHAR("Connection is NOT prepared for client mode")), 500);
00496
00497
00498 setHandle(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
00499 if (getHandle() < 0)
00500 throw ConnectionException(SystemError,
00501 ulxr_i18n(ULXR_PCHAR("Could not create socket: "))
00502 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00503
00504 int iOptVal = getTimeout() * 1000;
00505 int iOptLen = sizeof(int);
00506 ::setsockopt(getHandle(), SOL_SOCKET, SO_RCVTIMEO, (char*)&iOptVal, iOptLen);
00507 ::setsockopt(getHandle(), SOL_SOCKET, SO_SNDTIMEO, (char*)&iOptVal, iOptLen);
00508 doTcpNoDelay();
00509
00510 if(connect(getHandle(), (struct sockaddr *)&pimpl->hostdata, sizeof(pimpl->hostdata)) < 0)
00511 throw ConnectionException(SystemError,
00512 ulxr_i18n(ULXR_PCHAR("Could not connect: "))
00513 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00514
00515 ULXR_TRACE(ULXR_PCHAR("/open.peername"));
00516 #ifdef ULXR_ENABLE_GET_PEERNAME
00517 pimpl->remotedata_len = sizeof(pimpl->remotedata);
00518 if(getpeername(getHandle(),
00519 (struct sockaddr *)&pimpl->remotedata,
00520 &pimpl->remotedata_len)<0)
00521 throw ConnectionException(SystemError,
00522 ulxr_i18n(ULXR_PCHAR("Could not get peer data: "))
00523 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00524 #ifdef __BORLANDC__
00525 pimpl->remote_name = ULXR_PCHAR("<remote-host>");
00526 host = 0;
00527 host;
00528 #else
00529 else
00530 {
00531 ULXR_TRACE(ULXR_PCHAR("/open.hostby ") << ULXR_GET_STRING(inet_ntoa(pimpl->remotedata.sin_addr))
00532 << ULXR_PCHAR(":") << HtmlFormHandler::makeNumber(ntohs(pimpl->remotedata.sin_port)));
00533
00534 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00535 Mutex::Locker lock(gethostbyaddrMutex);
00536 #endif
00537
00538 struct hostent *host = 0;
00539 #ifdef ULXR_ENABLE_DNS_LOOKUP
00540 host = gethostbyaddr((char*)&pimpl->remotedata.sin_addr,
00541 sizeof(pimpl->remotedata.sin_addr),
00542 AF_INET);
00543 #endif
00544
00545 if (0 == host)
00546 {
00547 pimpl->remote_name = ULXR_GET_STRING(inet_ntoa(pimpl->remotedata.sin_addr))
00548 + ULXR_GET_STRING(":") + HtmlFormHandler::makeNumber(ntohs(pimpl->remotedata.sin_port));
00549 ULXR_TRACE(ULXR_PCHAR("/open.hostby.if") << pimpl->remote_name);
00550 }
00551 else
00552 {
00553 pimpl->remote_name = ULXR_GET_STRING(host->h_name);
00554 ULXR_TRACE(ULXR_PCHAR("/open.hostby.else ") << pimpl->remote_name);
00555 }
00556 }
00557 #endif
00558
00559 #else // ULXR_ENABLE_GET_PEERNAME
00560 pimpl->remote_name = ULXR_GET_STRING("");
00561 #endif
00562
00563 ULXR_TRACE(ULXR_PCHAR("/open"));
00564 }
00565
00566
00567 ULXR_API_IMPL(bool) TcpIpConnection::accept(int in_timeout)
00568 {
00569 ULXR_TRACE(ULXR_PCHAR("accept"));
00570 if (isOpen() )
00571 throw RuntimeException(ApplicationError,
00572 ulxr_i18n(ULXR_PCHAR("Attempt to accept an already open connection")));
00573
00574
00575
00576 if (pimpl->server_data == 0)
00577 throw ConnectionException(SystemError,
00578 ulxr_i18n(ULXR_PCHAR("Connection is NOT prepared for server mode")), 500);
00579
00580 pimpl->remotedata_len = sizeof(pimpl->remotedata);
00581
00582 if (in_timeout != 0)
00583 {
00584
00585 #if defined(ULXR_USE_EPOLL) && defined(HAVE_SYS_EPOLL_H)
00586
00587 #ifdef __GNUC__
00588
00589 #endif
00590
00591 ULXR_TRACE(ULXR_PCHAR("waiting for epoll_*()"));
00592
00593 int epollfd;
00594
00595 struct epoll_event ev_accept;
00596 memset(&ev_accept,0,sizeof(struct epoll_event));
00597
00598
00599 if((epollfd = ::epoll_create(1)) != -1)
00600 {
00601
00602 ev_accept.events = EPOLLIN;
00603 ev_accept.data.ptr = NULL;
00604
00605 int ctlresult;
00606 if((ctlresult = ::epoll_ctl(epollfd, EPOLL_CTL_ADD, getServerData()->getSocket(), &ev_accept)) == 0)
00607 {
00608
00609 struct epoll_event ev[1];
00610 memset(&ev[0],0,sizeof(struct epoll_event));
00611
00612 int toval;
00613 if (in_timeout != 0)
00614 toval = in_timeout*1000;
00615 else
00616 toval = -1;
00617
00618 int waitresult;
00619 if((waitresult = epoll_wait(epollfd,ev,1, toval)) == -1)
00620 {
00621 ::close(epollfd);
00622 throw ConnectionException(SystemError, ulxr_i18n(ULXR_PCHAR("Could not wait for the connection (epoll_wait() error):")), 500);
00623 }
00624
00625 else
00626 {
00627 ::close(epollfd);
00628 if(waitresult == 0)
00629 {
00630 return false;
00631 }
00632
00633 else
00634 {
00635 if(waitresult == 1)
00636 {
00637
00638
00639 }
00640
00641 else
00642 {
00643
00644 throw ConnectionException(SystemError,ulxr_i18n(ULXR_PCHAR("Problem while attempting to accept by epoll.")), 500);
00645 }
00646 }
00647 }
00648
00649 }
00650
00651 else
00652 {
00653 ::close(epollfd);
00654 throw ConnectionException(SystemError,ulxr_i18n(ULXR_PCHAR("Could not perform epoll_ctl() call: ")), 500);
00655 }
00656 }
00657
00658 else
00659 {
00660 ::close(epollfd);
00661 throw ConnectionException(SystemError,ulxr_i18n(ULXR_PCHAR("Could not perform epoll_create() call: ")), 500);
00662 }
00663
00664 #else
00665
00666 #ifdef __GNUC__
00667
00668 #endif
00669
00670 ULXR_TRACE(ULXR_PCHAR("waiting for select()"));
00671
00672 fd_set oReadSockSet;
00673 FD_ZERO( &oReadSockSet );
00674 FD_SET( getServerData()->getSocket(), &oReadSockSet );
00675
00676 struct timeval tv;
00677 struct timeval *ptv = 0;
00678 tv.tv_sec = in_timeout;
00679 tv.tv_usec = 0;
00680 if (in_timeout != 0)
00681 ptv = &tv;
00682
00683 int ret = 0;
00684
00685 if((ret = select(FD_SETSIZE, &oReadSockSet, NULL, NULL, ptv)) < 0)
00686 throw ConnectionException(SystemError,
00687 ulxr_i18n(ULXR_PCHAR("Could not wait for the connection (select() error):"))
00688 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00689
00690
00691 if(!ret)
00692 {
00693 ULXR_TRACE(ULXR_PCHAR("accept returns false"));
00694 return false;
00695 }
00696
00697 #endif // ULXR_USE_EPOLL
00698
00699 }
00700
00701 ULXR_TRACE(ULXR_PCHAR("waiting for connection"));
00702 do
00703 setHandle(::accept(getServerHandle(),
00704 (sockaddr*) &pimpl->remotedata, &pimpl->remotedata_len ));
00705 while(getHandle() < 0 && (errno == EINTR || errno == EAGAIN));
00706
00707 if(getHandle() < 0)
00708 throw ConnectionException(SystemError,
00709 ulxr_i18n(ULXR_PCHAR("Could not accept a connection: "))
00710 + ULXR_GET_STRING(getErrorString(getLastError())), 500);
00711
00712 doTcpNoDelay();
00713
00714 #ifdef ULXR_ENABLE_GET_PEERNAME
00715 struct hostent *host = 0;
00716
00717 #ifndef ULXR_OMIT_REENTRANT_PROTECTOR
00718 Mutex::Locker lock(gethostbyaddrMutex);
00719 #endif
00720
00721 #ifdef ULXR_ENABLE_DNS_LOOKUP
00722 host = gethostbyaddr((char*)&pimpl->remotedata.sin_addr,
00723 sizeof(pimpl->remotedata.sin_addr),
00724 AF_INET);
00725 #endif
00726
00727 if (0 == host)
00728 pimpl->remote_name = ULXR_GET_STRING(inet_ntoa(pimpl->remotedata.sin_addr))
00729 + ULXR_GET_STRING(":") + HtmlFormHandler::makeNumber(ntohs(pimpl->remotedata.sin_port));
00730 else
00731 pimpl->remote_name = ULXR_GET_STRING(host->h_name);
00732 #else
00733 pimpl->remote_name = ULXR_PCHAR("");
00734 #endif
00735
00736 ULXR_TRACE(ULXR_PCHAR("/accept"));
00737 return true;
00738 }
00739
00740
00741 ULXR_API_IMPL(unsigned) TcpIpConnection::getPort()
00742 {
00743 if(pimpl->port == 0)
00744 {
00745 struct sockaddr_in saddr_in;
00746 socklen_t size = sizeof(struct sockaddr_in);
00747
00748 int err = getsockname(getServerHandle(), (struct sockaddr*) &saddr_in, &size);
00749 if(!err)
00750 pimpl->port = ntohs(saddr_in.sin_port);
00751 }
00752
00753 return pimpl->port;
00754 }
00755
00756
00757 ULXR_API_IMPL(CppString) TcpIpConnection::getHostName() const
00758 {
00759 return pimpl->host_name;
00760 }
00761
00762
00763 ULXR_API_IMPL(CppString) TcpIpConnection::getServerDomain() const
00764 {
00765 return pimpl->serverdomain;
00766 }
00767
00768
00769 ULXR_API_IMPL(CppString) TcpIpConnection::getPeerName() const
00770 {
00771 return pimpl->remote_name;
00772 }
00773
00774
00775 ULXR_API_IMPL(void) TcpIpConnection::setServerData (ServerSocketData *in_server_data)
00776 {
00777 ULXR_TRACE(ULXR_PCHAR("setServerData ") << std::hex << (void*)in_server_data
00778 << ULXR_PCHAR(" ") << (void*)pimpl->server_data << std::dec);
00779
00780
00781 if(pimpl->server_data != 0)
00782 decrementServerRef();
00783
00784 pimpl->server_data = in_server_data;
00785 }
00786
00787
00788 ULXR_API_IMPL(int) TcpIpConnection::getServerHandle ()
00789 {
00790 if (pimpl->server_data != 0)
00791 return pimpl->server_data->getSocket();
00792
00793 return -1;
00794 }
00795
00796
00797 ULXR_API_IMPL(TcpIpConnection::ServerSocketData *) TcpIpConnection::getServerData () const
00798 {
00799 ULXR_TRACE(ULXR_PCHAR("getServerData ") << std::hex << (void*)pimpl->server_data << std::dec);
00800 return pimpl->server_data;
00801 }
00802
00803
00804 ULXR_API_IMPL(void) TcpIpConnection::shutdown(int in_mode)
00805 {
00806 int handle = getServerHandle ();
00807 if (handle < 0)
00808 handle = getHandle();
00809
00810 ULXR_TRACE(ULXR_PCHAR("shutdown for ") << handle);
00811
00812 int ret;
00813 do
00814 ret = ::shutdown(handle, in_mode);
00815 while(ret < 0 && (errno == EINTR || errno == EAGAIN));
00816
00817 if(ret < 0)
00818 throw ConnectionException(TransportError,
00819 ULXR_PCHAR("Shutdown failed: ")+getErrorString(getLastError()), 500);
00820
00821 ULXR_TRACE(ULXR_PCHAR("shutdown succeeded"));
00822 }
00823
00824
00825 ULXR_API_IMPL(void) TcpIpConnection::close()
00826 {
00827 ULXR_TRACE(ULXR_PCHAR("close"));
00828 #ifdef ULXR_ENABLE_GET_PEERNAME
00829
00830 #endif
00831 Connection::close();
00832 }
00833
00834
00835 ULXR_API_IMPL(int) TcpIpConnection::abortOnClose(int bOn)
00836 {
00837 linger sock_linger_struct = {1, 0};
00838 sock_linger_struct.l_onoff = bOn;
00839
00840 #ifdef __WIN32__
00841 return setsockopt(getServerHandle(), SOL_SOCKET, SO_LINGER,
00842 (const char*)&sock_linger_struct, sizeof(linger));
00843 #else
00844 return setsockopt(getServerHandle(), SOL_SOCKET, SO_LINGER,
00845 &sock_linger_struct, sizeof(linger));
00846 #endif
00847 }
00848
00849
00850 ULXR_API_IMPL(void) TcpIpConnection::setTcpNoDelay(bool bOn)
00851 {
00852 noDelayOpt = 0;
00853 if (bOn)
00854 noDelayOpt = 1;
00855 doTcpNoDelay();
00856 }
00857
00858
00859 ULXR_API_IMPL(int) TcpIpConnection::doTcpNoDelay()
00860 {
00861 int sock;
00862 if (getServerData() != 0)
00863 sock = getServerData()->getSocket();
00864 else
00865 sock = getHandle();
00866
00867 int ret = -1;
00868 if (sock > 0)
00869 #ifdef __WIN32__
00870 ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
00871 (const char*)&noDelayOpt, sizeof(noDelayOpt));
00872 #else
00873 ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
00874 &noDelayOpt, sizeof(noDelayOpt));
00875 #endif
00876
00877 ULXR_TRACE(ULXR_PCHAR("/doTcpNoDelay:") << noDelayOpt
00878 << ULXR_PCHAR(" ret: ") << ret
00879 << ULXR_PCHAR(" sock: ") << sock);
00880 return ret;
00881 }
00882
00883
00884 ULXR_API_IMPL(CppString) TcpIpConnection::getInterfaceName()
00885 {
00886 return ULXR_PCHAR("tcpip");
00887 }
00888
00889
00890 ULXR_API_IMPL(int) TcpIpConnection::getLastError()
00891 {
00892 #ifdef __WIN32__
00893 return(WSAGetLastError());
00894 #else
00895 return(errno);
00896 #endif
00897 }
00898
00899
00900 }
00901
00902
00903 #endif // ULXR_OMIT_TCP_STUFF