ServerSocketImpl.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/ServerSocketImpl.hpp"
00040 #include "blocxx/Format.hpp"
00041 #include "blocxx/ByteSwap.hpp"
00042 #include "blocxx/FileSystem.hpp"
00043 #include "blocxx/File.hpp"
00044 #include "blocxx/Thread.hpp"
00045 #include "blocxx/SocketUtils.hpp"
00046 #include "blocxx/System.hpp"
00047 
00048 extern "C"
00049 {
00050 #if !defined(BLOCXX_WIN32)
00051 #include <sys/types.h>
00052 #include <sys/stat.h>
00053 #include <sys/socket.h>
00054 #include <sys/time.h>
00055 #include <netinet/in.h>
00056 #include <arpa/inet.h>
00057 #include <netdb.h>
00058 #include <unistd.h>
00059 #include <fcntl.h>
00060 #endif
00061 }
00062 
00063 #include <cerrno>
00064 
00065 namespace BLOCXX_NAMESPACE
00066 {
00068 ServerSocketImpl::ServerSocketImpl(SSLServerCtxRef sslCtx)
00069    : m_sockfd(-1)
00070    , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00071    , m_isActive(false)
00072    , m_sslCtx(sslCtx)
00073 #if defined(BLOCXX_WIN32)
00074    , m_event(NULL)
00075    , m_shuttingDown(false)
00076 {
00077    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00078    BLOCXX_ASSERT(m_event != NULL);
00079 }
00080 #else
00081    , m_udsFile()
00082 {
00083 }
00084 #endif
00085 
00087 ServerSocketImpl::ServerSocketImpl(SocketFlags::ESSLFlag isSSL)
00088    : m_sockfd(-1)
00089    , m_localAddress(SocketAddress::allocEmptyAddress(SocketAddress::INET))
00090    , m_isActive(false)
00091    , m_isSSL(isSSL)
00092 #if defined(BLOCXX_WIN32)
00093    , m_event(NULL)
00094    , m_shuttingDown(false)
00095 {
00096    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00097    BLOCXX_ASSERT(m_event != NULL);
00098 }
00099 #else
00100    , m_udsFile()
00101 {
00102 }
00103 #endif
00104 
00106 ServerSocketImpl::~ServerSocketImpl()
00107 {
00108    try
00109    {
00110       close();
00111    }
00112    catch (...)
00113    {
00114       // don't let exceptions escape
00115    }
00116 #if defined(BLOCXX_WIN32)
00117    ::CloseHandle(m_event);
00118 #endif
00119 }
00120 
00122 Select_t
00123 ServerSocketImpl::getSelectObj() const
00124 {
00125 #if defined(BLOCXX_WIN32)
00126    Select_t st;
00127    st.event = m_event;
00128    st.sockfd = m_sockfd;
00129    st.networkevents = FD_ACCEPT;
00130    return st;
00131 #else
00132    return m_sockfd;
00133 #endif
00134 }
00135 
00137 void
00138 ServerSocketImpl::doListen(UInt16 port, SocketFlags::ESSLFlag isSSL,
00139    int queueSize, const String& listenAddr,
00140    SocketFlags::EReuseAddrFlag reuseAddr)
00141 {
00142    m_isSSL = isSSL;
00143    doListen(port, queueSize,listenAddr, reuseAddr);
00144 }
00145 
00146 #if defined(BLOCXX_WIN32)
00147 
00148 void
00149 ServerSocketImpl::doListen(UInt16 port,
00150    int queueSize, const String& listenAddr,
00151    SocketFlags::EReuseAddrFlag reuseAddr)
00152 {
00153    m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00154    close();
00155    if ((m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
00156    {
00157       BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00158          System::lastErrorMsg(true)).c_str());
00159    }
00160 
00161    // Set listen socket to nonblocking
00162    unsigned long cmdArg = 1;
00163    if (::ioctlsocket(m_sockfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00164    {
00165       BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00166          System::lastErrorMsg(true)).c_str());
00167    }
00168 
00169    if (reuseAddr)
00170    {
00171       DWORD reuse = 1;
00172       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
00173          (const char*)&reuse, sizeof(reuse));
00174    }
00175       
00176    InetSocketAddress_t inetAddr;
00177    inetAddr.sin_family = AF_INET;
00178    if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00179    {
00180       inetAddr.sin_addr.s_addr = hton32(INADDR_ANY);
00181    }
00182    else
00183    {
00184       SocketAddress addr = SocketAddress::getByName(listenAddr);
00185       inetAddr.sin_addr.s_addr = addr.getInetAddress()->sin_addr.s_addr;
00186    }
00187    inetAddr.sin_port = hton16(port);
00188    if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00189    {
00190       close();
00191       BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00192          System::lastErrorMsg(true)).c_str());
00193    }
00194    if (::listen(m_sockfd, queueSize) == -1)
00195    {
00196       close();
00197       BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00198          System::lastErrorMsg(true)).c_str());
00199    }
00200    fillAddrParms();
00201    m_isActive = true;
00202 }
00203 
00204 namespace
00205 {
00206 
00207 int
00208 waitForAcceptIO(SocketHandle_t fd, HANDLE eventArg, int timeOutSecs,
00209    long networkEvents)
00210 {
00211    DWORD timeout = (timeOutSecs != -1)
00212       ? static_cast<DWORD>(timeOutSecs * 1000)
00213       : INFINITE;
00214 
00215    if (networkEvents != -1L)
00216    {
00217       if(::WSAEventSelect(fd, eventArg, networkEvents) != 0)
00218       {
00219          BLOCXX_THROW(SocketException,
00220             Format("WSAEventSelect failed in waitForAcceptIO: %1",
00221             System::lastErrorMsg(true)).c_str());
00222       }
00223    }
00224 
00225    int cc;
00226    switch(::WaitForSingleObject(eventArg, timeout))
00227    {
00228       case WAIT_OBJECT_0:
00229          ::ResetEvent(eventArg);
00230          cc = 0;
00231          break;
00232       case WAIT_TIMEOUT:
00233          cc = ETIMEDOUT;
00234          break;
00235       default:
00236          cc = -1;
00237          break;
00238    }
00239 
00240    return cc;
00241 }
00242 
00243 }
00244 
00246 Socket
00247 ServerSocketImpl::accept(int timeoutSecs)
00248 {
00249    BLOCXX_ASSERT(m_localAddress.getType() == SocketAddress::INET);
00250 
00251    if (!m_isActive)
00252    {
00253       BLOCXX_THROW(SocketException, "ServerSocketImpl::accept: NONE");
00254    }
00255 
00256    // Register interest in FD_ACCEPT events
00257    if(::WSAEventSelect(m_sockfd, m_event, FD_ACCEPT) != 0)
00258    {
00259       BLOCXX_THROW(SocketException,
00260          Format("WSAEventSelect failed in accept: %1",
00261          System::lastErrorMsg(true)).c_str());
00262    }
00263 
00264    SOCKET clntfd;
00265    socklen_t clntlen;
00266    struct sockaddr_in clntInetAddr;
00267    HANDLE events[2];
00268    int cc;
00269 
00270    while (true)
00271    {
00272       clntlen = sizeof(clntInetAddr);
00273       clntfd = ::accept(m_sockfd,
00274          reinterpret_cast<struct sockaddr*>(&clntInetAddr), &clntlen);
00275       if (clntfd != INVALID_SOCKET)
00276       {
00277          // Got immediate connection
00278          break;
00279       }
00280 
00281       if (::WSAGetLastError() != WSAEWOULDBLOCK)
00282       {
00283          BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00284             System::lastErrorMsg(true)).c_str());
00285       }
00286 
00287       //cc = SocketUtils::waitForIO(m_sockfd, m_event, INFINITE, FD_ACCEPT);
00288       cc = waitForAcceptIO(m_sockfd, m_event, timeoutSecs, FD_ACCEPT);
00289       if(m_shuttingDown)
00290       {
00291          cc = -2;
00292       }
00293 
00294       switch (cc)
00295       {
00296          case -1:
00297             BLOCXX_THROW(SocketException, "Error while waiting for network events");
00298          case -2:
00299             BLOCXX_THROW(SocketException, "Shutdown event was signaled");
00300          case ETIMEDOUT:
00301             BLOCXX_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00302       }
00303    }
00304 
00305    // Unregister for any events.  necessary to put us back in blocking mode.
00306    if(::WSAEventSelect(clntfd, NULL, 0) != 0)
00307    {
00308       BLOCXX_THROW(SocketException,
00309          Format("WSAEventSelect failed in accept: %1",
00310          System::lastErrorMsg(true)).c_str());
00311    }
00312 
00313    // set socket back to blocking; otherwise it'll inherit non-blocking from the listening socket
00314    unsigned long cmdArg = 0;
00315    if (::ioctlsocket(clntfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
00316    {
00317       BLOCXX_THROW(SocketException, Format("ServerSocketImpl: %1",
00318          System::lastErrorMsg(true)).c_str());
00319    }
00320 
00321    if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00322    {
00323       return Socket(clntfd, m_localAddress.getType(), m_isSSL);
00324    }
00325 
00326    return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00327 }
00328 #else
00329 
00330 void
00331 ServerSocketImpl::doListen(UInt16 port,
00332    int queueSize, const String& listenAddr,
00333    SocketFlags::EReuseAddrFlag reuseAddr)
00334 {
00335    m_localAddress = SocketAddress::allocEmptyAddress(SocketAddress::INET);
00336    close();
00337    if ((m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
00338    {
00339       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00340    }
00341    // set the close on exec flag so child process can't keep the socket.
00342    if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00343    {
00344       close();
00345       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00346          "close-on-exec flag on listen socket");
00347    }
00348    // set listen socket to nonblocking; see Unix Network Programming,
00349    // pages 422-424.
00350    int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00351    ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00352    // is this safe? Should be, but some OS kernels have problems with it.
00353    // It's OK on current linux versions.  Definitely not on
00354    // OLD (kernel < 1.3.60) ones.  Who knows about on other OS's like UnixWare or
00355    // OpenServer?
00356    // See http://monkey.org/openbsd/archive/misc/9601/msg00031.html
00357    // or just google for "bind() Security Problems"
00358    // Let the kernel reuse the port without waiting for it to time out.
00359    // Without this line, you can't stop and immediately re-start the daemon.
00360    if (reuseAddr)
00361    {
00362       int reuse = 1;
00363       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00364    }
00365       
00366    InetSocketAddress_t inetAddr;
00367    inetAddr.sin_family = AF_INET;
00368    if (listenAddr == SocketAddress::ALL_LOCAL_ADDRESSES)
00369    {
00370       inetAddr.sin_addr.s_addr = hton32(INADDR_ANY);
00371    }
00372    else
00373    {
00374       SocketAddress addr = SocketAddress::getByName(listenAddr);
00375       inetAddr.sin_addr.s_addr = addr.getInetAddress()->sin_addr.s_addr;
00376    }
00377    inetAddr.sin_port = hton16(port);
00378    if (::bind(m_sockfd, reinterpret_cast<sockaddr*>(&inetAddr), sizeof(inetAddr)) == -1)
00379    {
00380       close();
00381       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind");
00382    }
00383    if (::listen(m_sockfd, queueSize) == -1)
00384    {
00385       close();
00386       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen");
00387    }
00388    fillAddrParms();
00389    m_isActive = true;
00390 }
00391 
00393 void
00394 ServerSocketImpl::doListen(const String& filename, int queueSize, bool reuseAddr)
00395 {
00396    m_localAddress = SocketAddress::getUDS(filename);
00397    close();
00398    if ((m_sockfd = ::socket(PF_UNIX,SOCK_STREAM, 0)) == -1)
00399    {
00400       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): socket()");
00401    }
00402    // set the close on exec flag so child process can't keep the socket.
00403    if (::fcntl(m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
00404    {
00405       close();
00406       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): fcntl() failed to set "
00407          "close-on-exec flag on listen socket");
00408    }
00409 
00410    // set listen socket to nonblocking; see Unix Network Programming,
00411    // pages 422-424.
00412    int fdflags = ::fcntl(m_sockfd, F_GETFL, 0);
00413    ::fcntl(m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
00414    
00415    if (reuseAddr)
00416    {
00417       // Let the kernel reuse the port without waiting for it to time out.
00418       // Without this line, you can't stop and immediately re-start the daemon.
00419       int reuse = 1;
00420       ::setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
00421    }
00422    String lockfilename = filename + ".lock";
00423    m_udsFile = FileSystem::openOrCreateFile(lockfilename);
00424    if (!m_udsFile)
00425    {
00426       BLOCXX_THROW_ERRNO_MSG(SocketException,
00427          Format("ServerSocketImpl::doListen(): Unable to open or create Unix Domain Socket lock: %1",
00428             lockfilename).c_str());
00429    }
00430    // if we can't get a lock, someone else has got it open.
00431    if (m_udsFile.tryLock() == -1)
00432    {
00433       BLOCXX_THROW_ERRNO_MSG(SocketException,
00434          Format("ServerSocketImpl::doListen(): Unable to lock Unix Domain Socket: %1",
00435             filename).c_str());
00436    }
00437    // We got the lock, so clobber the UDS if it's there so bind will succeed.
00438    // If it's not gone, bind will fail.
00439    if (FileSystem::exists(filename))
00440    {
00441       if (!FileSystem::removeFile(filename.c_str()))
00442       {
00443          BLOCXX_THROW_ERRNO_MSG(SocketException,
00444             Format("ServerSocketImpl::doListen(): Unable to unlink Unix Domain Socket: %1",
00445                filename).c_str());
00446       }
00447    }
00448       
00449    if (::bind(m_sockfd, m_localAddress.getNativeForm(),
00450       m_localAddress.getNativeFormSize()) == -1)
00451    {
00452       close();
00453       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): bind()");
00454    }
00455    // give anybody access to the socket
00456    // unfortunately, fchmod() doesn't work on a UDS
00457    if (::chmod(filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == -1)
00458    {
00459       close();
00460       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): chmod()");
00461    }
00462    if (::listen(m_sockfd, queueSize) == -1)
00463    {
00464       close();
00465       BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::doListen(): listen()");
00466    }
00467    fillAddrParms();
00468    m_isActive = true;
00469 }
00471 Socket
00472 ServerSocketImpl::accept(int timeoutSecs)
00473 {
00474    if (!m_isActive)
00475    {
00476       BLOCXX_THROW(SocketException, "ServerSocketImpl::accept(): m_isActive == false");
00477    }
00478    if (SocketUtils::waitForIO(m_sockfd, timeoutSecs, SocketFlags::E_WAIT_FOR_INPUT) == 0)
00479    {
00480       int clntfd;
00481       socklen_t clntlen;
00482       struct sockaddr_in clntInetAddr;
00483       struct sockaddr_un clntUnixAddr;
00484       struct sockaddr* pSA(0);
00485       if (m_localAddress.getType() == SocketAddress::INET)
00486       {
00487          pSA = reinterpret_cast<struct sockaddr*>(&clntInetAddr);
00488          clntlen = sizeof(clntInetAddr);
00489       }
00490       else if (m_localAddress.getType() == SocketAddress::UDS)
00491       {
00492          pSA = reinterpret_cast<struct sockaddr*>(&clntUnixAddr);
00493          clntlen = sizeof(clntUnixAddr);
00494       }
00495       else
00496       {
00497          BLOCXX_ASSERT(0);
00498       }
00499       
00500       clntfd = ::accept(m_sockfd, pSA, &clntlen);
00501       if (clntfd < 0)
00502       {
00503          // check to see if client aborts connection between select and accept.
00504          // see Unix Network Programming pages 422-424.
00505          if (errno == EWOULDBLOCK
00506              || errno == ECONNABORTED
00507 #ifdef EPROTO
00508              || errno == EPROTO
00509 #endif
00510             )
00511          {
00512             BLOCXX_THROW(SocketException, "Client aborted TCP connection "
00513                "between select() and accept()");
00514          }
00515       
00516          if (errno == EINTR)
00517          {
00518             Thread::testCancel();
00519          }
00520          BLOCXX_THROW_ERRNO_MSG(SocketException, "ServerSocketImpl::accept(): accept()");
00521       }
00522       // set socket back to blocking; see Unix Network Programming,
00523       // pages 422-424.
00524       int fdflags = ::fcntl(clntfd, F_GETFL, 0);
00525       // On most OSs non-blocking is inherited from the listen socket,
00526       // but it's not on Openserver.
00527       if ((fdflags & O_NONBLOCK) == O_NONBLOCK)
00528       {
00529          ::fcntl(clntfd, F_SETFL, fdflags ^ O_NONBLOCK);
00530       }
00531       // TODO, how to make this bw compatible?
00532       //return Socket(clntfd, m_localAddress.getType(), m_isSSL);
00533       if (!m_sslCtx && m_isSSL == SocketFlags::E_SSL)
00534       {
00535          return Socket(clntfd, m_localAddress.getType(), m_isSSL); // for bw compat.
00536       }
00537       return Socket(clntfd, m_localAddress.getType(), m_sslCtx);
00538    }
00539    else
00540    {
00541       // The timeout expired.
00542       BLOCXX_THROW(SocketTimeoutException,"Timed out waiting for a connection");
00543    }
00544 }
00545 #endif
00546 
00548 void
00549 ServerSocketImpl::close()
00550 {
00551    if (m_isActive)
00552    {
00553 #if defined(BLOCXX_WIN32)
00554       ::closesocket(m_sockfd);
00555       m_sockfd = INVALID_SOCKET;
00556 #else
00557 		::close(m_sockfd);
00558       if (m_localAddress.getType() == SocketAddress::UDS)
00559       {
00560          String filename = m_localAddress.toString();
00561          if (!FileSystem::removeFile(filename.c_str()))
00562          {
00563             BLOCXX_THROW_ERRNO_MSG(SocketException,
00564                Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket: %1",
00565                   filename).c_str());
00566          }
00567          if (m_udsFile)
00568          {
00569             String lockfilename = filename + ".lock";
00570             if (m_udsFile.unlock() == -1)
00571             {
00572                BLOCXX_THROW_ERRNO_MSG(SocketException,
00573                   Format("ServerSocketImpl::close(): Failed to unlock Unix Domain Socket: %1",
00574                      lockfilename).c_str());
00575             }
00576             m_udsFile.close();
00577             if (!FileSystem::removeFile(lockfilename.c_str()))
00578             {
00579                BLOCXX_THROW_ERRNO_MSG(SocketException,
00580                   Format("ServerSocketImpl::close(): Unable to unlink Unix Domain Socket lock: %1",
00581                      lockfilename).c_str());
00582             }
00583          }
00584       }
00585 #endif
00586       m_isActive = false;
00587    }
00588 }
00590 void
00591 ServerSocketImpl::fillAddrParms()
00592 {
00593    socklen_t len;
00594    if (m_localAddress.getType() == SocketAddress::INET)
00595    {
00596       struct sockaddr_in addr;
00597       memset(&addr, 0, sizeof(addr));
00598       len = sizeof(addr);
00599       if (getsockname(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr), &len) == -1)
00600       {
00601          BLOCXX_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00602       }
00603       m_localAddress.assignFromNativeForm(&addr, len);
00604    }
00605 #if !defined(BLOCXX_WIN32)
00606    else if (m_localAddress.getType() == SocketAddress::UDS)
00607    {
00608       struct sockaddr_un addr;
00609       memset(&addr, 0, sizeof(addr));
00610       len = sizeof(addr);
00611       if (getsockname(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr), &len) == -1)
00612       {
00613          BLOCXX_THROW_ERRNO_MSG(SocketException, "SocketImpl::fillAddrParms(): getsockname");
00614       }
00615       m_localAddress.assignFromNativeForm(&addr, len);
00616    }
00617 #endif
00618    else
00619    {
00620       BLOCXX_ASSERT(0);
00621    }
00622 }
00623 
00624 } // end namespace BLOCXX_NAMESPACE
00625 

Generated on Fri Jun 16 15:39:09 2006 for blocxx by  doxygen 1.4.6