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 
00036 #include "OW_config.h"
00037 #include "OW_ServerSocketImpl.hpp"
00038 #include "OW_Format.hpp"
00039 #include "OW_ByteSwap.hpp"
00040 #include "OW_FileSystem.hpp"
00041 #include "OW_File.hpp"
00042 #include "OW_Thread.hpp"
00043 #include "OW_SocketUtils.hpp"
00044 #include "OW_System.hpp"
00045 
00046 extern "C"
00047 {
00048 #if !defined(OW_WIN32)
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051 #include <sys/socket.h>
00052 #include <sys/time.h>
00053 #include <netinet/in.h>
00054 #include <arpa/inet.h>
00055 #include <netdb.h>
00056 #include <unistd.h>
00057 #include <fcntl.h>
00058 #endif
00059 }
00060 
00061 #include <cerrno>
00062 
00063 namespace OW_NAMESPACE
00064 {
00066 ServerSocketImpl::ServerSocketImpl(SSLServerCtxRef sslCtx)
00067    : m_sockfd(-1)
00068    , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00069    , m_isActive(false)
00070    , m_sslCtx(sslCtx)
00071 #if defined(OW_WIN32)
00072    , m_event(NULL)
00073    , m_shuttingDown(false)
00074 {
00075    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00076    OW_ASSERT(m_event != NULL);
00077 }
00078 #else
00079    , m_udsFile()
00080 {
00081 }
00082 #endif
00083 
00085 ServerSocketImpl::ServerSocketImpl(SocketFlags::ESSLFlag isSSL)
00086    : m_sockfd(-1)
00087    , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00088    , m_isActive(false)
00089    , m_isSSL(isSSL)
00090 #if defined(OW_WIN32)
00091    , m_event(NULL)
00092    , m_shuttingDown(false)
00093 {
00094    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00095    OW_ASSERT(m_event != NULL);
00096 }
00097 #else
00098    , m_udsFile()
00099 {
00100 }
00101 #endif
00102 
00104 ServerSocketImpl::~ServerSocketImpl()
00105 {
00106    try
00107    {
00108       close();
00109    }
00110    catch (...)
00111    {
00112       
00113    }
00114 #if defined(OW_WIN32)
00115    ::CloseHandle(m_event);
00116 #endif
00117 }
00118 
00120 Select_t
00121 ServerSocketImpl::getSelectObj() const
00122 {
00123 #if defined(OW_WIN32)
00124    Select_t st;
00125    st.event = m_event;
00126    st.sockfd = m_sockfd;
00127    st.networkevents = FD_ACCEPT;
00128    return st;
00129 #else
00130    return m_sockfd;
00131 #endif
00132 }
00133 
00135 void
00136 ServerSocketImpl::doListen(UInt16 port, SocketFlags::ESSLFlag isSSL,
00137    int queueSize, const String& listenAddr,
00138    SocketFlags::EReuseAddrFlag reuseAddr)
00139 {
00140    m_isSSL = isSSL;
00141    doListen(port, queueSize,listenAddr, reuseAddr);
00142 }
00143 
00144 #if defined(OW_WIN32)
00145 
00146 void
00147 ServerSocketImpl::doListen(UInt16 port,
00148    int queueSize, const String& listenAddr,
00149    SocketFlags::EReuseAddrFlag reuseAddr)
00150 {
00151    m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00152    close();
00153    if ((m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
00154    {
00155       OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00156          System::lastErrorMsg(true)).c_str());
00157    }
00158 
00159    
00160    unsigned long cmdArg = 1;
00161    if (::ioctlsocket(m_sockfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00162    {
00163       OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00164          System::lastErrorMsg(true)).c_str());
00165    }
00166 
00167    if (reuseAddr)
00168    {
00169       DWORD reuse = 1;
00170       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
00171          (const char*)&reuse, sizeof(reuse));
00172    }
00173       
00174    InetSocketAddress_t inetAddr;
00175    inetAddr.sin_family = AF_INET;
00176    if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00177    {
00178       inetAddr.sin_addr.s_addr = hton32(INADDR_ANY);
00179    }
00180    else
00181    {
00182       SocketAddress addr = SocketAddress::getByName(listenAddr);
00183       inetAddr.sin_addr.s_addr = addr.getInetAddress()->sin_addr.s_addr;
00184    }
00185    inetAddr.sin_port = hton16(port);
00186    if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00187    {
00188       close();
00189       OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00190          System::lastErrorMsg(true)).c_str());
00191    }
00192    if (::listen(m_sockfd, queueSize) == -1)
00193    {
00194       close();
00195       OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00196          System::lastErrorMsg(true)).c_str());
00197    }
00198    fillAddrParms();
00199    m_isActive = true;
00200 }
00201 
00202 namespace
00203 {
00204 
00205 int
00206 waitForAcceptIO(SocketHandle_t fd, HANDLE eventArg, int timeOutSecs,
00207    long networkEvents)
00208 {
00209    DWORD timeout = (timeOutSecs != -1)
00210       ? static_cast<DWORD>(timeOutSecs * 1000)
00211       : INFINITE;
00212 
00213    if (networkEvents != -1L)
00214    {
00215       if(::WSAEventSelect(fd, eventArg, networkEvents) != 0)
00216       {
00217          OW_THROW(SocketException,
00218             Format("WSAEventSelect failed in waitForAcceptIO: %1",
00219             System::lastErrorMsg(true)).c_str());
00220       }
00221    }
00222 
00223    int cc;
00224    switch(::WaitForSingleObject(eventArg, timeout))
00225    {
00226       case WAIT_OBJECT_0:
00227          ::ResetEvent(eventArg);
00228          cc = 0;
00229          break;
00230       case WAIT_TIMEOUT:
00231          cc = ETIMEDOUT;
00232          break;
00233       default:
00234          cc = -1;
00235          break;
00236    }
00237 
00238    return cc;
00239 }
00240 
00241 }
00242 
00244 Socket
00245 ServerSocketImpl::accept(int timeoutSecs)
00246 {
00247    OW_ASSERT(m_localAddress.getType() == SocketAddress::INET);
00248 
00249    if (!m_isActive)
00250    {
00251       OW_THROW(SocketException, "ServerSocketImpl::accept: NONE");
00252    }
00253 
00254    
00255    if(::WSAEventSelect(m_sockfd, m_event, FD_ACCEPT) != 0)
00256    {
00257       OW_THROW(SocketException,
00258          Format("WSAEventSelect failed in accept: %1",
00259          System::lastErrorMsg(true)).c_str());
00260    }
00261 
00262    SOCKET clntfd;
00263    socklen_t clntlen;
00264    struct sockaddr_in clntInetAddr;
00265    HANDLE events[2];
00266    int cc;
00267 
00268    while (true)
00269    {
00270       clntlen = sizeof(clntInetAddr);
00271       clntfd = ::accept(m_sockfd,
00272          reinterpret_cast<struct sockaddr*>(&clntInetAddr), &clntlen);
00273       if (clntfd != INVALID_SOCKET)
00274       {
00275          
00276          break;
00277       }
00278 
00279       if (::WSAGetLastError() != WSAEWOULDBLOCK)
00280       {
00281          OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00282             System::lastErrorMsg(true)).c_str());
00283       }
00284 
00285       
00286       cc = waitForAcceptIO(m_sockfd, m_event, timeoutSecs, FD_ACCEPT);
00287       if(m_shuttingDown)
00288       {
00289          cc = -2;
00290       }
00291 
00292       switch (cc)
00293       {
00294          case -1:
00295             OW_THROW(SocketException, "Error while waiting for network events");
00296          case -2:
00297             OW_THROW(SocketException, "Shutdown event was signaled");
00298          case ETIMEDOUT:
00299             OW_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00300       }
00301    }
00302 
00303    
00304    if(::WSAEventSelect(clntfd, NULL, 0) != 0)
00305    {
00306       OW_THROW(SocketException,
00307          Format("WSAEventSelect failed in accept: %1",
00308          System::lastErrorMsg(true)).c_str());
00309    }
00310 
00311    
00312    unsigned long cmdArg = 0;
00313    if (::ioctlsocket(clntfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00314    {
00315       OW_THROW(SocketException, Format("ServerSocketImpl: %1",
00316          System::lastErrorMsg(true)).c_str());
00317    }
00318 
00319    if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00320    {
00321       return Socket(clntfd, m_localAddress.getType(), m_isSSL);
00322    }
00323 
00324    return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00325 }
00326 #else
00327 
00328 void
00329 ServerSocketImpl::doListen(UInt16 port,
00330    int queueSize, const String& listenAddr,
00331    SocketFlags::EReuseAddrFlag reuseAddr)
00332 {
00333    m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00334    close();
00335    if ((m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
00336    {
00337       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00338    }
00339    
00340    if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00341    {
00342       close();
00343       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00344          "close-on-exec flag on listen socket");
00345    }
00346    
00347    
00348    int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00349    ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00350    
00351    
00352    
00353    
00354    
00355    
00356    
00357    
00358    if (reuseAddr)
00359    {
00360       int reuse = 1;
00361       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00362    }
00363       
00364    InetSocketAddress_t inetAddr;
00365    inetAddr.sin_family = AF_INET;
00366    if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00367    {
00368       inetAddr.sin_addr.s_addr = hton32(INADDR_ANY);
00369    }
00370    else
00371    {
00372       SocketAddress addr = SocketAddress::getByName(listenAddr);
00373       inetAddr.sin_addr.s_addr = addr.getInetAddress()->sin_addr.s_addr;
00374    }
00375    inetAddr.sin_port = hton16(port);
00376    if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00377    {
00378       close();
00379       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind");
00380    }
00381    if (::listen(m_sockfd, queueSize) == -1)
00382    {
00383       close();
00384       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen");
00385    }
00386    fillAddrParms();
00387    m_isActive = true;
00388 }
00389 
00391 void
00392 ServerSocketImpl::doListen(const String& filename, int queueSize, bool reuseAddr)
00393 {
00394    m_localAddress = SocketAddress::getUDS(filename);
00395    close();
00396    if ((m_sockfd = ::socket(PF_UNIX,SOCK_STREAM, 0)) == -1)
00397    {
00398       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00399    }
00400    
00401    if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00402    {
00403       close();
00404       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00405          "close-on-exec flag on listen socket");
00406    }
00407 
00408    
00409    
00410    int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00411    ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00412    
00413    if (reuseAddr)
00414    {
00415       
00416       
00417       int reuse = 1;
00418       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00419    }
00420    String lockfilename = filename + ".lock";
00421    m_udsFile = FileSystem::openOrCreateFile(lockfilename);
00422    if (!m_udsFile)
00423    {
00424       OW_THROW_ERRNO_MSG(SocketException,
00425          Format("ServerSocketImpl::doListen(): Unable to open or create Unix Domain Socket lock: %1",
00426             lockfilename).c_str());
00427    }
00428    
00429    if (m_udsFile.tryLock() == -1)
00430    {
00431       OW_THROW_ERRNO_MSG(SocketException,
00432          Format("ServerSocketImpl::doListen(): Unable to lock Unix Domain Socket: %1",
00433             filename).c_str());
00434    }
00435    
00436    
00437    if (FileSystem::exists(filename))
00438    {
00439       if (!FileSystem::removeFile(filename.c_str()))
00440       {
00441          OW_THROW_ERRNO_MSG(SocketException,
00442             Format("ServerSocketImpl::doListen(): Unable to unlink Unix Domain Socket: %1",
00443                filename).c_str());
00444       }
00445    }
00446       
00447    if (::bind(m_sockfd, m_localAddress.getNativeForm(),
00448       m_localAddress.getNativeFormSize()) == -1)
00449    {
00450       close();
00451       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind()");
00452    }
00453    
00454    
00455    if (::chmod(filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == -1)
00456    {
00457       close();
00458       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): chmod()");
00459    }
00460    if (::listen(m_sockfd, queueSize) == -1)
00461    {
00462       close();
00463       OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen()");
00464    }
00465    fillAddrParms();
00466    m_isActive = true;
00467 }
00469 bool
00470 ServerSocketImpl::waitForIO(int fd, int timeOutSecs,
00471    SocketFlags::EWaitDirectionFlag forInput)
00472 {
00473    return SocketUtils::waitForIO(fd, timeOutSecs, forInput) == 0;
00474 }
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00484 Socket
00485 ServerSocketImpl::accept(int timeoutSecs)
00486 {
00487    if (!m_isActive)
00488    {
00489       OW_THROW(SocketException, "ServerSocketImpl::accept(): m_isActive == false");
00490    }
00491    if (SocketUtils::waitForIO(m_sockfd, timeoutSecs, SocketFlags::E_WAIT_FOR_INPUT) == 0)
00492    {
00493       int clntfd;
00494       socklen_t clntlen;
00495       struct sockaddr_in clntInetAddr;
00496       struct sockaddr_un clntUnixAddr;
00497       struct sockaddr* pSA(0);
00498       if (m_localAddress.getType() == SocketAddress::INET)
00499       {
00500          pSA = reinterpret_cast<struct sockaddr*>(&clntInetAddr);
00501          clntlen = sizeof(clntInetAddr);
00502       }
00503       else if (m_localAddress.getType() == SocketAddress::UDS)
00504       {
00505          pSA = reinterpret_cast<struct sockaddr*>(&clntUnixAddr);
00506          clntlen = sizeof(clntUnixAddr);
00507       }
00508       else
00509       {
00510          OW_ASSERT(0);
00511       }
00512       
00513       clntfd = ::accept(m_sockfd, pSA, &clntlen);
00514       if (clntfd < 0)
00515       {
00516          
00517          
00518          if (errno == EWOULDBLOCK
00519              || errno == ECONNABORTED
00520 #ifdef EPROTO
00521              || errno == EPROTO
00522 #endif
00523             )
00524          {
00525             OW_THROW(SocketException, "Client aborted TCP connection "
00526                "between select() and accept()");
00527          }
00528       
00529          if (errno == EINTR)
00530          {
00531             Thread::testCancel();
00532          }
00533          OW_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::accept(): accept()");
00534       }
00535       
00536       
00537       int fdflags = ::fcntl(clntfd, F_GETFL, 0);
00538       
00539       
00540       if ((fdflags & O_NONBLOCK) == O_NONBLOCK)
00541       {
00542          ::fcntl(clntfd, F_SETFL, fdflags ^ O_NONBLOCK);
00543       }
00544       
00545       
00546       if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00547       {
00548          return Socket(clntfd, m_localAddress.getType(), m_isSSL); 
00549       }
00550       return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00551    }
00552    else
00553    {
00554       
00555       OW_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00556    }
00557 }
00558 #endif
00559 
00561 void
00562 ServerSocketImpl::close()
00563 {
00564    if (m_isActive)
00565    {
00566 #if defined(OW_WIN32)
00567       ::closesocket(m_sockfd);
00568       m_sockfd = INVALID_SOCKET;
00569 #else
00570 		::close(m_sockfd);
00571       if (m_localAddress.getType() == SocketAddress::UDS)
00572       {
00573          String filename = m_localAddress.toString();
00574          if (!FileSystem::removeFile(filename.c_str()))
00575          {
00576             OW_THROW_ERRNO_MSG(SocketException,
00577                Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket: %1",
00578                   filename).c_str());
00579          }
00580          if (m_udsFile)
00581          {
00582             String lockfilename = filename + ".lock";
00583             if (m_udsFile.unlock() == -1)
00584             {
00585                OW_THROW_ERRNO_MSG(SocketException,
00586                   Format("ServerSocketImpl::close(): Failed to unlock Unix Domain Socket: %1",
00587                      lockfilename).c_str());
00588             }
00589             m_udsFile.close();
00590             if (!FileSystem::removeFile(lockfilename.c_str()))
00591             {
00592                OW_THROW_ERRNO_MSG(SocketException,
00593                   Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket lock: %1",
00594                      lockfilename).c_str());
00595             }
00596          }
00597       }
00598 #endif
00599       m_isActive = false;
00600    }
00601 }
00603 void
00604 ServerSocketImpl::fillAddrParms()
00605 {
00606    socklen_t len;
00607    if (m_localAddress.getType() == SocketAddress::INET)
00608    {
00609       struct sockaddr_in addr;
00610       memset(&addr, 0, sizeof(addr));
00611       len = sizeof(addr);
00612       if (getsockname(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr), &len) == -1)
00613       {
00614          OW_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00615       }
00616       m_localAddress.assignFromNativeForm(&addr, len);
00617    }
00618 #if !defined(OW_WIN32)
00619    else if (m_localAddress.getType() == SocketAddress::UDS)
00620    {
00621       struct sockaddr_un addr;
00622       memset(&addr, 0, sizeof(addr));
00623       len = sizeof(addr);
00624       if (getsockname(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr), &len) == -1)
00625       {
00626          OW_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00627       }
00628       m_localAddress.assignFromNativeForm(&addr, len);
00629    }
00630 #endif
00631    else
00632    {
00633       OW_ASSERT(0);
00634    }
00635 }
00636 
00637 } 
00638