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