void UdpServerTransport::cycle(int timeoutMs) { RCF::ThreadInfoPtr tiPtr = getTlsThreadInfoPtr(); RCF::ThreadPool & threadPool = tiPtr->getThreadPool(); if (threadPool.shouldStop()) { return; } // poll the UDP socket for messages, and read a message if one is available fd_set fdSet; FD_ZERO(&fdSet); FD_SET( static_cast<SOCKET>(mFd), &fdSet); timeval timeout; timeout.tv_sec = timeoutMs/1000; timeout.tv_usec = 1000*(timeoutMs%1000); int ret = Platform::OS::BsdSockets::select( mFd+1, &fdSet, NULL, NULL, timeoutMs < 0 ? NULL : &timeout); int err = Platform::OS::BsdSockets::GetLastError(); if (ret == 1) { SessionStatePtr sessionStatePtr = getTlsUdpSessionStatePtr(); if (sessionStatePtr.get() == NULL) { sessionStatePtr = SessionStatePtr(new SessionState(*this)); sessionStatePtr->mSessionPtr = getSessionManager().createSession(); sessionStatePtr->mSessionPtr->setSessionState(*sessionStatePtr); setTlsUdpSessionStatePtr(sessionStatePtr); } { // read a message ReallocBufferPtr &readVecPtr = sessionStatePtr->mReadVecPtr; if (readVecPtr.get() == NULL || !readVecPtr.unique()) { readVecPtr.reset( new ReallocBuffer()); } ReallocBuffer &buffer = *readVecPtr; SockAddrStorage from; int fromlen = sizeof(from); memset(&from, 0, sizeof(from)); buffer.resize(4); int len = Platform::OS::BsdSockets::recvfrom( mFd, &buffer[0], 4, MSG_PEEK, (sockaddr *) &from, &fromlen); err = Platform::OS::BsdSockets::GetLastError(); sessionStatePtr->mRemoteAddress.init( (sockaddr&) from, fromlen, mIpAddress.getType()); if (!isIpAllowed(sessionStatePtr->mRemoteAddress)) { RCF_LOG_2()(sessionStatePtr->mRemoteAddress.getIp()) << "Client IP does not match server's IP access rules. Closing connection."; discardPacket(mFd); } else if ( len == 4 || (len == -1 && err == Platform::OS::BsdSockets::ERR_EMSGSIZE)) { unsigned int dataLength = 0; memcpy(&dataLength, &buffer[0], 4); networkToMachineOrder(&dataLength, 4, 1); if (getMaxMessageLength() && dataLength > getMaxMessageLength()) { ByteBuffer byteBuffer; encodeServerError(getSessionManager(), byteBuffer, RcfError_ServerMessageLength); byteBuffer.expandIntoLeftMargin(4); * (boost::uint32_t *) ( byteBuffer.getPtr() ) = static_cast<boost::uint32_t>(byteBuffer.getLength()-4); RCF::machineToNetworkOrder(byteBuffer.getPtr(), 4, 1); char *buffer = byteBuffer.getPtr(); std::size_t bufferLen = byteBuffer.getLength(); sockaddr * pRemoteAddr = NULL; Platform::OS::BsdSockets::socklen_t remoteAddrSize = 0; sessionStatePtr->mRemoteAddress.getSockAddr(pRemoteAddr, remoteAddrSize); int len = sendto( mFd, buffer, static_cast<int>(bufferLen), 0, pRemoteAddr, remoteAddrSize); RCF_UNUSED_VARIABLE(len); discardPacket(mFd); } else { buffer.resize(4+dataLength); memset(&from, 0, sizeof(from)); fromlen = sizeof(from); len = Platform::OS::BsdSockets::recvfrom( mFd, &buffer[0], 4+dataLength, 0, (sockaddr *) &from, &fromlen); if (static_cast<unsigned int>(len) == 4+dataLength) { getSessionManager().onReadCompleted(sessionStatePtr->mSessionPtr); } } } else { discardPacket(mFd); } } } else if (ret == 0) { //RCF_LOG_4()(mFd)(mPort)(timeoutMs) << "UdpServerTransport - no messages received within polling interval."; } else if (ret == -1) { Exception e( _RcfError_Socket("select()"), err, RcfSubsystem_Os); RCF_THROW(e)(mFd)(mIpAddress.string())(err); } }
void UdpServerTransport::cycle( int timeoutMs, const volatile bool &) //stopFlag { // poll the UDP socket for messages, and read a message if one is available fd_set fdSet; FD_ZERO(&fdSet); FD_SET( static_cast<SOCKET>(mFd), &fdSet); timeval timeout; timeout.tv_sec = timeoutMs/1000; timeout.tv_usec = 1000*(timeoutMs%1000); int ret = Platform::OS::BsdSockets::select( mFd+1, &fdSet, NULL, NULL, timeoutMs < 0 ? NULL : &timeout); int err = Platform::OS::BsdSockets::GetLastError(); if (ret == 1) { SessionStatePtr sessionStatePtr = getCurrentUdpSessionStatePtr(); if (sessionStatePtr.get() == NULL) { sessionStatePtr = SessionStatePtr(new SessionState(*this)); SessionPtr sessionPtr = getSessionManager().createSession(); sessionPtr->setProactor(*sessionStatePtr); sessionStatePtr->mSessionPtr = sessionPtr; setCurrentUdpSessionStatePtr(sessionStatePtr); RcfSessionPtr rcfSessionPtr = boost::static_pointer_cast<RcfSession>(sessionPtr); rcfSessionPtr->mIoState = RcfSession::Reading; } { // read a message boost::shared_ptr<std::vector<char> > &readVecPtr = sessionStatePtr->mReadVecPtr; if (readVecPtr.get() == NULL || !readVecPtr.unique()) { readVecPtr.reset( new std::vector<char>()); } std::vector<char> &buffer = *readVecPtr; sockaddr from; int fromlen = sizeof(from); memset(&from, 0, sizeof(from)); buffer.resize(4); int len = Platform::OS::BsdSockets::recvfrom( mFd, &buffer[0], 4, MSG_PEEK, &from, &fromlen); err = Platform::OS::BsdSockets::GetLastError(); if (isClientAddrAllowed( *(sockaddr_in *) &from ) && (len == 4 || (len == -1 && err == Platform::OS::BsdSockets::ERR_EMSGSIZE))) { sockaddr_in *remoteAddr = reinterpret_cast<sockaddr_in*>(&from); sessionStatePtr->remoteAddress = IpAddress(*remoteAddr); unsigned int dataLength = 0; memcpy(&dataLength, &buffer[0], 4); networkToMachineOrder(&dataLength, 4, 1); if (dataLength <= static_cast<unsigned int>(getMaxMessageLength())) { buffer.resize(4+dataLength); memset(&from, 0, sizeof(from)); fromlen = sizeof(from); len = Platform::OS::BsdSockets::recvfrom( mFd, &buffer[0], 4+dataLength, 0, &from, &fromlen); if (static_cast<unsigned int>(len) == 4+dataLength) { getSessionManager().onReadCompleted(sessionStatePtr->mSessionPtr); } } else { ByteBuffer byteBuffer; encodeServerError(byteBuffer, RcfError_ServerMessageLength); byteBuffer.expandIntoLeftMargin(4); * (boost::uint32_t *) ( byteBuffer.getPtr() ) = static_cast<boost::uint32_t>(byteBuffer.getLength()-4); RCF::machineToNetworkOrder(byteBuffer.getPtr(), 4, 1); char *buffer = byteBuffer.getPtr(); std::size_t bufferLen = byteBuffer.getLength(); const sockaddr_in &remoteAddr = sessionStatePtr->remoteAddress.getSockAddr(); int len = sendto( mFd, buffer, static_cast<int>(bufferLen), 0, (const sockaddr *) &remoteAddr, sizeof(remoteAddr)); RCF_UNUSED_VARIABLE(len); discardPacket(mFd); } } else { // discard the message (sender ip not allowed, or message format bad) discardPacket(mFd); } } } else if (ret == 0) { RCF_TRACE("server udp poll - no messages")(mFd)(mPort); } else if (ret == -1) { RCF_THROW( Exception( RcfError_Socket, err, RcfSubsystem_Os, "udp server select() failed ")) (mFd)(mPort)(err); } }