Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00010 #include "vlistenersocket.h" 00011 #include "vtypes_internal.h" 00012 00013 #include "vexception.h" 00014 #include "vsocketfactory.h" 00015 00016 VListenerSocket::VListenerSocket(int portNumber, const VString& bindAddress, VSocketFactory* factory, int backlog) 00017 : VSocket() 00018 , mBindAddress(bindAddress) 00019 , mBacklog(backlog) 00020 , mFactory(factory) 00021 { 00022 this->setHostIPAddressAndPort(VSTRING_FORMAT("listener(%s:%d)", bindAddress.chars(), portNumber), portNumber); 00023 00024 /* 00025 We need to have our listen() calls timeout if we expect to allow 00026 other threads (e.g., a thread that is handling a remote server 00027 management command) to shut us down. Otherwise, we'll be blocked 00028 on listen() and never get a chance to even check isRunning(). 00029 */ 00030 struct timeval timeout; 00031 00032 timeout.tv_sec = 5; 00033 timeout.tv_usec = 0; 00034 00035 VListenerSocket::setReadTimeOut(timeout); 00036 } 00037 00038 VListenerSocket::~VListenerSocket() { 00039 } 00040 00041 VSocket* VListenerSocket::accept() { 00042 if (mSocketID == kNoSocketID) { 00043 throw VStackTraceException("VListenerSocket::accept called before socket is listening."); 00044 } 00045 00046 struct sockaddr_in clientaddr; 00047 VSocklenT clientaddrLength = sizeof(clientaddr); 00048 VSocketID handlerSockID = kNoSocketID; 00049 VSocket* handlerSocket = NULL; 00050 bool shouldAccept = true; 00051 00052 if (mReadTimeOutActive) { 00053 /* then we need to do a select call */ 00054 struct timeval timeout = mReadTimeOut; 00055 fd_set readset; 00056 00057 FD_ZERO(&readset); 00058 //lint -e573 Signed-unsigned mix with divide" 00059 FD_SET(mSocketID, &readset); 00060 00061 int result = ::select(static_cast<int>(mSocketID + 1), &readset, NULL, NULL, &timeout); 00062 00063 if (result == -1) { 00064 throw VException(VSystemError::getSocketError(), VSTRING_FORMAT("VListenerSocket[%s:%d]::accept select() failed.", mBindAddress.chars(), mPortNumber)); 00065 } 00066 00067 //lint -e573 Signed-unsigned mix with divide" 00068 shouldAccept = ((result > 0) && FD_ISSET(mSocketID, &readset)); 00069 } 00070 00071 if (shouldAccept) { 00072 ::memset(&clientaddr, 0, static_cast<Vu32>(clientaddrLength)); 00073 handlerSockID = ::accept(mSocketID, (struct sockaddr*) &clientaddr, &clientaddrLength); 00074 00075 if (handlerSockID == kNoSocketID) { 00076 throw VException(VSystemError::getSocketError(), VSTRING_FORMAT("VListenerSocket[%s:%d]::accept accept() failed.", mBindAddress.chars(), mPortNumber)); 00077 } else { 00078 handlerSocket = mFactory->createSocket(handlerSockID); 00079 } 00080 } 00081 00082 return handlerSocket; 00083 } 00084 00085 void VListenerSocket::listen() { 00086 this->_listen(mBindAddress, mBacklog); 00087 } 00088