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
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/ServerSocketImpl.hpp"
00041 #include "blocxx/Format.hpp"
00042 #include "blocxx/ByteSwap.hpp"
00043 #include "blocxx/FileSystem.hpp"
00044 #include "blocxx/File.hpp"
00045 #include "blocxx/Thread.hpp"
00046 #include "blocxx/SocketUtils.hpp"
00047 #include "blocxx/System.hpp"
00048 #include "blocxx/TimeoutTimer.hpp"
00049
00050 extern "C"
00051 {
00052 #if !defined(BLOCXX_WIN32)
00053 #include <sys/types.h>
00054 #include <sys/stat.h>
00055 #include <sys/socket.h>
00056 #include <sys/time.h>
00057 #include <netinet/in.h>
00058 #include <arpa/inet.h>
00059 #include <netdb.h>
00060 #include <unistd.h>
00061 #include <fcntl.h>
00062
00063 #define INVALID_SOCKET -1
00064 #endif
00065 }
00066
00067 #include <cerrno>
00068
00069 namespace BLOCXX_NAMESPACE
00070 {
00072 ServerSocketImpl::ServerSocketImpl(SSLServerCtxRef sslCtx)
00073 : m_sockfd(INVALID_SOCKET)
00074 , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00075 , m_isActive(false)
00076 , m_sslCtx(sslCtx)
00077 #if defined(BLOCXX_WIN32)
00078 , m_event(NULL)
00079 , m_shuttingDown(false)
00080 {
00081 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00082 BLOCXX_ASSERT(m_event != NULL);
00083 }
00084 #else
00085 , m_udsFile()
00086 {
00087 }
00088 #endif
00089
00091 ServerSocketImpl::ServerSocketImpl(SocketFlags::ESSLFlag isSSL)
00092 : m_sockfd(INVALID_SOCKET)
00093 , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00094 , m_isActive(false)
00095 , m_isSSL(isSSL)
00096 #if defined(BLOCXX_WIN32)
00097 , m_event(NULL)
00098 , m_shuttingDown(false)
00099 {
00100 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00101 BLOCXX_ASSERT(m_event != NULL);
00102 }
00103 #else
00104 , m_udsFile()
00105 {
00106 }
00107 #endif
00108
00110 ServerSocketImpl::~ServerSocketImpl()
00111 {
00112 try
00113 {
00114 close();
00115 }
00116 catch (...)
00117 {
00118
00119 }
00120 #if defined(BLOCXX_WIN32)
00121 ::CloseHandle(m_event);
00122 #endif
00123 }
00124
00126 Select_t
00127 ServerSocketImpl::getSelectObj() const
00128 {
00129 #if defined(BLOCXX_WIN32)
00130 Select_t st;
00131 st.event = m_event;
00132 st.sockfd = m_sockfd;
00133 st.isSocket = true;
00134 st.networkevents = FD_ACCEPT;
00135 return st;
00136 #else
00137 return m_sockfd;
00138 #endif
00139 }
00140
00142 void
00143 ServerSocketImpl::doListen(UInt16 port, SocketFlags::ESSLFlag isSSL,
00144 int queueSize, const String& listenAddr,
00145 SocketFlags::EReuseAddrFlag reuseAddr)
00146 {
00147 m_isSSL = isSSL;
00148 doListen(port, queueSize,listenAddr, reuseAddr);
00149 }
00150
00151 #if defined(BLOCXX_WIN32)
00152
00153 void
00154 ServerSocketImpl::doListen(UInt16 port,
00155 int queueSize, const String& listenAddr,
00156 SocketFlags::EReuseAddrFlag reuseAddr)
00157 {
00158 SocketHandle_t sock_ipv6 = INVALID_SOCKET;
00159 m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00160 close();
00161
00162 #ifdef BLOCXX_HAVE_IPV6
00163
00164
00165 sock_ipv6 = ::socket(AF_INET6, SOCK_STREAM, 0);
00166 if (sock_ipv6 == INVALID_SOCKET)
00167 {
00168 switch(errno)
00169 {
00170 case EPROTONOSUPPORT:
00171 case EAFNOSUPPORT:
00172 case EPFNOSUPPORT:
00173 case EINVAL:
00174 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
00175 break;
00176 default:
00177 break;
00178 }
00179 }
00180 else
00181 {
00182 m_sockfd = sock_ipv6;
00183 }
00184 #else
00185 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
00186 #endif
00187 if (m_sockfd == INVALID_SOCKET)
00188 {
00189 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00190 System::lastErrorMsg(true)).c_str());
00191 }
00192
00193 unsigned long cmdArg = 1;
00194 if (::ioctlsocket(m_sockfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00195 {
00196 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00197 System::lastErrorMsg(true)).c_str());
00198 }
00199
00200 if (reuseAddr)
00201 {
00202 DWORD reuse = 1;
00203 ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
00204 (const char*)&reuse, sizeof(reuse));
00205 }
00206
00207 if ( sock_ipv6 == INVALID_SOCKET )
00208 {
00209
00210 ServerSocketImpl::doListenIPv4( port, queueSize, listenAddr);
00211 }
00212 #ifdef BLOCXX_HAVE_IPV6
00213 else
00214 {
00215
00216 ServerSocketImpl::doListenIPv6( port, queueSize, listenAddr, reuseAddr);
00217 }
00218 #endif
00219 }
00221 void
00222 ServerSocketImpl::doListenIPv4(UInt16 port, int queueSize, const String& listenAddr )
00223 {
00224
00225 InetSocketAddress_t inetAddr;
00226 memset(&inetAddr, 0, sizeof(inetAddr));
00227 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_family = AF_INET;
00228 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_port = hton16(port);
00229 if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00230 {
00231 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_addr.s_addr = hton32(INADDR_ANY);
00232 }
00233 else
00234 {
00235 SocketAddress addr = SocketAddress::getByName(listenAddr);
00236 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_addr.s_addr =
00237 reinterpret_cast<const sockaddr_in*>(addr.getInetAddress())->sin_addr.s_addr;
00238 }
00239 if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00240 {
00241 close();
00242 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00243 System::lastErrorMsg(true)).c_str());
00244 }
00245 if (::listen(m_sockfd, queueSize) == -1)
00246 {
00247 close();
00248 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00249 System::lastErrorMsg(true)).c_str());
00250 }
00251 fillAddrParms();
00252 m_isActive = true;
00253 }
00255 #ifdef BLOCXX_HAVE_IPV6
00256 void
00257 ServerSocketImpl::doListenIPv6(UInt16 port, int queueSize, const String& listenAddr)
00258 {
00259
00260 InetSocketAddress_t inetAddr;
00261 memset(&inetAddr, 0, sizeof(inetAddr));
00262 reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_family = AF_INET6;
00263 reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_port = hton16(port);
00264 if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00265 {
00266
00267 memcpy(reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_addr.s6_addr, &in6addr_any, sizeof(struct in6_addr));
00268 }
00269 else
00270 {
00271
00272 if(!inet_pton(AF_INET6, listenAddr.c_str(), (void*)&reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_addr))
00273 {
00274 addrinfo *addrinfos;
00275 addrinfo hints;
00276 memset(&hints, 0, sizeof(hints));
00277 hints.ai_socktype = SOCK_STREAM;
00278 hints.ai_family = AF_INET6;
00279 if(getaddrinfo(listenAddr.c_str(), NULL, &hints, &addrinfos))
00280 {
00281 close();
00282 BLOCXX_THROW(SocketException, Format("ServerSocketImpl:: doListen(): getaddrinfo() %1",
00283 System::lastErrorMsg(true)).c_str());
00284 }
00285 memcpy(reinterpret_cast<sockaddr_in6*>(&inetAddr), addrinfos->ai_addr, addrinfos->ai_addrlen);
00286 freeaddrinfo(addrinfos);
00287 }
00288 }
00289 if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00290 {
00291 close();
00292 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00293 System::lastErrorMsg(true)).c_str());
00294 }
00295 if (::listen(m_sockfd, queueSize) == -1)
00296 {
00297 close();
00298 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00299 System::lastErrorMsg(true)).c_str());
00300 }
00301 fillAddrParms();
00302 m_isActive = true;
00303 }
00304 #endif // BLOCXX_HAVE_IPV6
00305
00306 namespace
00307 {
00308
00309 int
00310 waitForAcceptIO(SocketHandle_t fd, HANDLE eventArg, const Timeout& timeOutSecs,
00311 long networkEvents)
00312 {
00313 TimeoutTimer timer(timeOutSecs);
00314
00315 if (networkEvents != -1L)
00316 {
00317 if(::WSAEventSelect(fd, eventArg, networkEvents) != 0)
00318 {
00319 BLOCXX_THROW(SocketException,
00320 Format("WSAEventSelect failed in waitForAcceptIO: %1",
00321 System::lastErrorMsg(true)).c_str());
00322 }
00323 }
00324
00325 int cc;
00326 switch(::WaitForSingleObject(eventArg, timer.asDWORDMs()))
00327 {
00328 case WAIT_OBJECT_0:
00329 ::ResetEvent(eventArg);
00330 cc = 0;
00331 break;
00332 case WAIT_TIMEOUT:
00333 cc = ETIMEDOUT;
00334 break;
00335 default:
00336 cc = -1;
00337 break;
00338 }
00339
00340 return cc;
00341 }
00342
00343 }
00344
00346 Socket
00347 ServerSocketImpl::accept(const Timeout& timeoutSecs)
00348 {
00349 BLOCXX_ASSERT(m_localAddress.getType() == SocketAddress::INET);
00350
00351 if (!m_isActive)
00352 {
00353 BLOCXX_THROW(SocketException, "ServerSocketImpl::accept: NONE");
00354 }
00355
00356
00357 if(::WSAEventSelect(m_sockfd, m_event, FD_ACCEPT) != 0)
00358 {
00359 BLOCXX_THROW(SocketException,
00360 Format("WSAEventSelect failed in accept: %1",
00361 System::lastErrorMsg(true)).c_str());
00362 }
00363
00364 SOCKET clntfd;
00365 socklen_t clntlen;
00366 InetSocketAddress_t clntInetAddr;
00367 HANDLE events[2];
00368 int cc;
00369
00370 while (true)
00371 {
00372 clntlen = sizeof(clntInetAddr);
00373 clntfd = ::accept(m_sockfd,
00374 reinterpret_cast<struct sockaddr*>(&clntInetAddr), &clntlen);
00375 if (clntfd != INVALID_SOCKET)
00376 {
00377
00378 break;
00379 }
00380
00381 if (::WSAGetLastError() != WSAEWOULDBLOCK)
00382 {
00383 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00384 System::lastErrorMsg(true)).c_str());
00385 }
00386
00387
00388 cc = waitForAcceptIO(m_sockfd, m_event, timeoutSecs, FD_ACCEPT);
00389 if(m_shuttingDown)
00390 {
00391 cc = -2;
00392 }
00393
00394 switch (cc)
00395 {
00396 case -1:
00397 BLOCXX_THROW(SocketException, "Error while waiting for network events");
00398 case -2:
00399 BLOCXX_THROW(SocketException, "Shutdown event was signaled");
00400 case ETIMEDOUT:
00401 BLOCXX_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00402 }
00403 }
00404
00405
00406 if(::WSAEventSelect(clntfd, NULL, 0) != 0)
00407 {
00408 BLOCXX_THROW(SocketException,
00409 Format("WSAEventSelect failed in accept: %1",
00410 System::lastErrorMsg(true)).c_str());
00411 }
00412
00413
00414 unsigned long cmdArg = 0;
00415 if (::ioctlsocket(clntfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00416 {
00417 BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00418 System::lastErrorMsg(true)).c_str());
00419 }
00420
00421 if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00422 {
00423 return Socket(clntfd, m_localAddress.getType(), m_isSSL);
00424 }
00425
00426 return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00427 }
00428 #else
00429
00430 void
00431 ServerSocketImpl::doListen(UInt16 port,
00432 int queueSize, const String& listenAddr,
00433 SocketFlags::EReuseAddrFlag reuseAddr)
00434 {
00435 SocketHandle_t sock_ipv6 = INVALID_SOCKET;
00436 m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00437 close();
00438
00439 #ifdef BLOCXX_HAVE_IPV6
00440
00441
00442 sock_ipv6 = ::socket(AF_INET6, SOCK_STREAM, 0);
00443 if (sock_ipv6 == INVALID_SOCKET)
00444 {
00445 switch(errno)
00446 {
00447 case EPROTONOSUPPORT:
00448 case EAFNOSUPPORT:
00449 case EPFNOSUPPORT:
00450 case EINVAL:
00451
00452 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
00453 break;
00454 default:
00455 break;
00456 }
00457 }
00458 else
00459 {
00460 m_sockfd = sock_ipv6;
00461 #ifdef IPV6_V6ONLY
00462 int ipv6_proto = IPPROTO_IPV6;
00463 #ifdef SOL_IP
00464 ipv6_proto = SOL_IP;
00465 #endif
00466 int ipv6_only=0;
00467 ::setsockopt(m_sockfd, ipv6_proto, IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only));
00468 #endif
00469 }
00470 #else
00471 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
00472 #endif
00473 if (m_sockfd == INVALID_SOCKET)
00474 {
00475 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00476 }
00477
00478 if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00479 {
00480 close();
00481 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00482 "close-on-exec flag on listen socket");
00483 }
00484
00485
00486 int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00487 ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00488
00489
00490
00491
00492
00493
00494
00495
00496 if (reuseAddr)
00497 {
00498 int reuse = 1;
00499 #if defined(BLOCXX_NCR)
00500 ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));
00501 #else
00502 ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00503 #endif
00504 }
00505 if ( sock_ipv6 == INVALID_SOCKET)
00506 {
00507
00508 ServerSocketImpl::doListenIPv4( port, queueSize, listenAddr );
00509 }
00510 #ifdef BLOCXX_HAVE_IPV6
00511 else
00512 {
00513 ServerSocketImpl::doListenIPv6( port, queueSize, listenAddr );
00514 }
00515 #endif
00516 }
00517
00519 void
00520 ServerSocketImpl::doListenIPv4(UInt16 port, int queueSize, const String& listenAddr )
00521 {
00522
00523 InetSocketAddress_t inetAddr;
00524 memset(&inetAddr, 0, sizeof(inetAddr));
00525 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_family = AF_INET;
00526 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_port = hton16(port);
00527 if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00528 {
00529 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_addr.s_addr = hton32(INADDR_ANY);
00530 }
00531 else
00532 {
00533 SocketAddress addr = SocketAddress::getByName(listenAddr);
00534 reinterpret_cast<sockaddr_in*>(&inetAddr)->sin_addr.s_addr =
00535 reinterpret_cast<const sockaddr_in*>(addr.getInetAddress())->sin_addr.s_addr;
00536 }
00537 if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00538 {
00539 close();
00540 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind");
00541 }
00542 if (::listen(m_sockfd, queueSize) == -1)
00543 {
00544 close();
00545 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen");
00546 }
00547 fillAddrParms();
00548 m_isActive = true;
00549 }
00550
00551 #ifdef BLOCXX_HAVE_IPV6
00552
00553 void
00554 ServerSocketImpl::doListenIPv6(UInt16 port, int queueSize, const String& listenAddr)
00555 {
00556
00557 InetSocketAddress_t inetAddr;
00558 memset(&inetAddr, 0, sizeof(inetAddr));
00559 reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_family = AF_INET6;
00560 reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_port = hton16(port);
00561 if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00562 {
00563
00564 memcpy(reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_addr.s6_addr, &in6addr_any, sizeof(struct in6_addr));
00565 }
00566 else
00567 {
00568
00569 if(!inet_pton(AF_INET6, listenAddr.c_str(), (void*)&reinterpret_cast<sockaddr_in6*>(&inetAddr)->sin6_addr))
00570 {
00571 addrinfo *addrinfos;
00572 addrinfo hints;
00573 memset(&hints, 0, sizeof(hints));
00574 hints.ai_socktype = SOCK_STREAM;
00575 hints.ai_family = AF_INET6;
00576 if(getaddrinfo(listenAddr.c_str(), NULL, &hints, &addrinfos))
00577 {
00578 close();
00579 BLOCXX_THROW_ERRNO_MSG(SocketException,"ServerSocketImpl::doListen(): getaddrinfo()");
00580 }
00581 memcpy(reinterpret_cast<sockaddr_in6*>(&inetAddr), addrinfos->ai_addr, addrinfos->ai_addrlen);
00582 freeaddrinfo(addrinfos);
00583 }
00584 }
00585 if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00586 {
00587 close();
00588 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind");
00589 }
00590 if (::listen(m_sockfd, queueSize) == -1)
00591 {
00592 close();
00593 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen");
00594 }
00595 fillAddrParms();
00596 m_isActive = true;
00597 }
00598 #endif
00599
00600 void
00601 ServerSocketImpl::doListenUDS(const String& filename, int queueSize, bool reuseAddr)
00602 {
00603 m_localAddress = SocketAddress::getUDS(filename);
00604 close();
00605 m_sockfd = ::socket(PF_UNIX,SOCK_STREAM, 0);
00606 if (m_sockfd == INVALID_SOCKET)
00607 {
00608 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00609 }
00610
00611 if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00612 {
00613 close();
00614 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00615 "close-on-exec flag on listen socket");
00616 }
00617
00618
00619
00620 int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00621 ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00622
00623 if (reuseAddr)
00624 {
00625
00626
00627 int reuse = 1;
00628 #if defined(BLOCXX_NCR)
00629 ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse));
00630 #else
00631 ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00632 #endif
00633 }
00634 String lockfilename = filename + ".lock";
00635 m_udsFile = FileSystem::openOrCreateFile(lockfilename);
00636 if (!m_udsFile)
00637 {
00638 BLOCXX_THROW_ERRNO_MSG(SocketException,
00639 Format("ServerSocketImpl::doListen(): Unable to open or create Unix Domain Socket lock: %1",
00640 lockfilename).c_str());
00641 }
00642
00643 if (m_udsFile.tryLock() == -1)
00644 {
00645 BLOCXX_THROW_ERRNO_MSG(SocketException,
00646 Format("ServerSocketImpl::doListen(): Unable to lock Unix Domain Socket: %1",
00647 filename).c_str());
00648 }
00649
00650
00651 if (FileSystem::exists(filename))
00652 {
00653 if (!FileSystem::removeFile(filename.c_str()))
00654 {
00655 BLOCXX_THROW_ERRNO_MSG(SocketException,
00656 Format("ServerSocketImpl::doListen(): Unable to unlink Unix Domain Socket: %1",
00657 filename).c_str());
00658 }
00659 }
00660
00661 #if defined(BLOCXX_NCR)
00662 if (::bind(m_sockfd, const_cast<SocketAddress_t *>(m_localAddress.getNativeForm()), m_localAddress.getNativeFormSize()) == -1)
00663 #else
00664 if (::bind(m_sockfd, m_localAddress.getNativeForm(), m_localAddress.getNativeFormSize()) == -1)
00665 #endif
00666 {
00667 close();
00668 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind()");
00669 }
00670
00671
00672 if (::chmod(filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == -1)
00673 {
00674 close();
00675 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): chmod()");
00676 }
00677 if (::listen(m_sockfd, queueSize) == -1)
00678 {
00679 close();
00680 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen()");
00681 }
00682 fillAddrParms();
00683 m_isActive = true;
00684 }
00686
00687
00688
00689
00690
00691
00692
00694 Socket
00695 ServerSocketImpl::accept(const Timeout& timeout)
00696 {
00697 if (!m_isActive)
00698 {
00699 BLOCXX_THROW(SocketException, "ServerSocketImpl::accept(): m_isActive == false");
00700 }
00701 int rc = 0;
00702 if ((rc = SocketUtils::waitForIO(m_sockfd, timeout, SocketFlags::E_WAIT_FOR_INPUT)) == 0)
00703 {
00704 int clntfd;
00705 socklen_t clntlen;
00706 InetSocketAddress_t clntInetAddr;
00707 struct sockaddr_un clntUnixAddr;
00708 struct sockaddr* pSA(0);
00709 if (m_localAddress.getType() == SocketAddress::INET)
00710 {
00711 pSA = reinterpret_cast<struct sockaddr*>(&clntInetAddr);
00712 clntlen = sizeof(clntInetAddr);
00713 }
00714 else if (m_localAddress.getType() == SocketAddress::UDS)
00715 {
00716 pSA = reinterpret_cast<struct sockaddr*>(&clntUnixAddr);
00717 clntlen = sizeof(clntUnixAddr);
00718 }
00719 else
00720 {
00721 BLOCXX_ASSERT(0);
00722 }
00723
00724 clntfd = ::accept(m_sockfd, pSA, &clntlen);
00725 if (clntfd < 0)
00726 {
00727
00728
00729 if (errno == EWOULDBLOCK
00730 || errno == ECONNABORTED
00731 #ifdef EPROTO
00732 || errno == EPROTO
00733 #endif
00734 )
00735 {
00736 BLOCXX_THROW(SocketException, "Client aborted TCP connection "
00737 "between select() and accept()");
00738 }
00739
00740 if (errno == EINTR)
00741 {
00742 Thread::testCancel();
00743 }
00744 BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::accept(): accept()");
00745 }
00746
00747
00748 int fdflags = ::fcntl(clntfd, F_GETFL, 0);
00749
00750
00751 if ((fdflags & O_NONBLOCK) == O_NONBLOCK)
00752 {
00753 ::fcntl(clntfd, F_SETFL, fdflags ^ O_NONBLOCK);
00754 }
00755
00756
00757 if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00758 {
00759 return Socket(clntfd, m_localAddress.getType(), m_isSSL);
00760 }
00761 return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00762 }
00763 else if (rc == ETIMEDOUT)
00764 {
00765
00766 BLOCXX_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00767 }
00768 else
00769 {
00770 BLOCXX_THROW_ERRNO_MSG(SocketException,"Timed out waiting for a connection");
00771 }
00772 }
00773 #endif
00774
00776 void
00777 ServerSocketImpl::close()
00778 {
00779 if (m_isActive)
00780 {
00781 #if defined(BLOCXX_WIN32)
00782 ::closesocket(m_sockfd);
00783 m_sockfd = INVALID_SOCKET;
00784 #else
00785 ::close(m_sockfd);
00786 if (m_localAddress.getType() == SocketAddress::UDS)
00787 {
00788 String filename = m_localAddress.toString();
00789 if (!FileSystem::removeFile(filename.c_str()))
00790 {
00791 BLOCXX_THROW_ERRNO_MSG(SocketException,
00792 Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket: %1",
00793 filename).c_str());
00794 }
00795 if (m_udsFile)
00796 {
00797 String lockfilename = filename + ".lock";
00798 if (m_udsFile.unlock() == -1)
00799 {
00800 BLOCXX_THROW_ERRNO_MSG(SocketException,
00801 Format("ServerSocketImpl::close(): Failed to unlock Unix Domain Socket: %1",
00802 lockfilename).c_str());
00803 }
00804 m_udsFile.close();
00805 if (!FileSystem::removeFile(lockfilename.c_str()))
00806 {
00807 BLOCXX_THROW_ERRNO_MSG(SocketException,
00808 Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket lock: %1",
00809 lockfilename).c_str());
00810 }
00811 }
00812 }
00813 #endif
00814 m_isActive = false;
00815 }
00816 }
00818 void
00819 ServerSocketImpl::fillAddrParms()
00820 {
00821 socklen_t len;
00822 if (m_localAddress.getType() == SocketAddress::INET)
00823 {
00824
00825 struct sockaddr *p_addr;
00826 InetSocketAddress_t ss;
00827 memset(&ss, 0, sizeof(ss));
00828 len = sizeof(ss);
00829 p_addr = reinterpret_cast<struct sockaddr*>(&ss);
00830 if (getsockname(m_sockfd, p_addr, &len) == -1)
00831 {
00832 BLOCXX_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00833 }
00834 m_localAddress.assignFromNativeForm(&ss, len);
00835 }
00836 #if !defined(BLOCXX_WIN32)
00837 else if (m_localAddress.getType() == SocketAddress::UDS)
00838 {
00839 struct sockaddr_un addr;
00840 memset(&addr, 0, sizeof(addr));
00841 len = sizeof(addr);
00842 if (getsockname(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr), &len) == -1)
00843 {
00844 BLOCXX_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00845 }
00846 m_localAddress.assignFromNativeForm(&addr, len);
00847 }
00848 #endif
00849 else
00850 {
00851 BLOCXX_ASSERT(0);
00852 }
00853 }
00854
00855 }
00856