int UdpClientTransport::receive( I_ClientTransportCallback &clientStub, ByteBuffer &byteBuffer, unsigned int timeoutMs) { // try to receive a UDP message from server, within the current timeout RCF_LOG_4()(mSock)(mDestIp.string())(timeoutMs) << "UdpClientTransport - receiving data from socket."; RCF_ASSERT(!mAsync); unsigned int startTimeMs = getCurrentTimeMs(); unsigned int endTimeMs = startTimeMs + timeoutMs; while (true) { unsigned int timeoutMs = generateTimeoutMs(endTimeMs); fd_set fdSet; FD_ZERO(&fdSet); FD_SET( static_cast<SOCKET>(mSock), &fdSet); timeval timeout; timeout.tv_sec = timeoutMs/1000; timeout.tv_usec = 1000*(timeoutMs%1000); int ret = Platform::OS::BsdSockets::select( mSock+1, &fdSet, NULL, NULL, &timeout); int err = Platform::OS::BsdSockets::GetLastError(); RCF_ASSERT(-1 <= ret && ret <= 1)(ret); if (ret == -1) { Exception e( _RcfError_Socket("select()"), err, RcfSubsystem_Os); RCF_THROW(e); } else if (ret == 0) { Exception e( _RcfError_ClientReadTimeout() ); RCF_THROW(e); } RCF_ASSERT_EQ(ret , 1); if (mReadVecPtr.get() == NULL || !mReadVecPtr.unique()) { mReadVecPtr.reset( new ReallocBuffer()); } // TODO: optimize ReallocBuffer &buffer = *mReadVecPtr; buffer.resize(4); SockAddrStorage fromAddr; memset(&fromAddr, 0, sizeof(fromAddr)); int fromAddrLen = sizeof(fromAddr); sockaddr * pDestAddr = NULL; Platform::OS::BsdSockets::socklen_t destAddrSize = 0; mDestIp.getSockAddr(pDestAddr, destAddrSize); int len = Platform::OS::BsdSockets::recvfrom( mSock, &buffer[0], 4, MSG_PEEK, (sockaddr *) &fromAddr, &fromAddrLen); err = Platform::OS::BsdSockets::GetLastError(); if ( len == 4 || (len == -1 && err == Platform::OS::BsdSockets::ERR_EMSGSIZE)) { mFromIp.init( (sockaddr&) fromAddr, fromAddrLen, mDestIp.getType()); if (mDestIp.matches(mFromIp)) { boost::uint32_t dataLength = 0; memcpy( &dataLength, &buffer[0], 4); RCF::networkToMachineOrder(&dataLength, 4, 1); if (getMaxMessageLength()) { RCF_VERIFY( 0 < dataLength && dataLength <= getMaxMessageLength(), Exception(_RcfError_ClientMessageLength(dataLength, getMaxMessageLength()))); } buffer.resize(4+dataLength); memset(&fromAddr, 0, sizeof(fromAddr)); fromAddrLen = sizeof(fromAddr); len = Platform::OS::BsdSockets::recvfrom( mSock, &buffer[0], dataLength+4, 0, (sockaddr *) &fromAddr, &fromAddrLen); if (len == static_cast<int>(dataLength+4)) { mLastResponseSize = dataLength+4; mRunningTotalBytesReceived += dataLength+4; byteBuffer = ByteBuffer( &buffer[4], dataLength, 4, mReadVecPtr); clientStub.onReceiveCompleted(); return 1; } } else { // The packet is not a valid response, but we need to read // it so we can receive more packets. const std::size_t BufferSize = 4096; char Buffer[BufferSize]; Platform::OS::BsdSockets::recvfrom( mSock, Buffer, BufferSize, 0, NULL, NULL); } } else { RCF_THROW( Exception( _RcfError_ClientReadFail() ) )(len)(err); } } }
std::size_t Win32NamedPipeClientTransport::implRead( const ByteBuffer &byteBuffer, std::size_t bytesRequested) { // For now, can't go back to sync calls after doing an async call. // Limitations with Windows IOCP. RCF_ASSERT(!mAsyncMode); std::size_t bytesToRead = RCF_MIN(bytesRequested, byteBuffer.getLength()); BOOL ok = ResetEvent(mhEvent); DWORD dwErr = GetLastError(); RCF_VERIFY(ok, Exception(_RcfError_Pipe(), dwErr)); OVERLAPPED overlapped = {0}; overlapped.hEvent = mhEvent; DWORD dwRead = 0; DWORD dwBytesToRead = static_cast<DWORD>(bytesToRead); ok = ReadFile( mhPipe, byteBuffer.getPtr(), dwBytesToRead, &dwRead, &overlapped); dwErr = GetLastError(); if (!ok) { RCF_VERIFY( dwErr == ERROR_IO_PENDING || dwErr == WSA_IO_PENDING || dwErr == ERROR_MORE_DATA, Exception(_RcfError_ClientReadFail(), dwErr)); } ClientStub & clientStub = *getTlsClientStubPtr(); DWORD dwRet = WAIT_TIMEOUT; while (dwRet == WAIT_TIMEOUT) { boost::uint32_t timeoutMs = generateTimeoutMs(mEndTimeMs); timeoutMs = clientStub.generatePollingTimeout(timeoutMs); dwRet = WaitForSingleObject(overlapped.hEvent, timeoutMs); dwErr = GetLastError(); RCF_VERIFY( dwRet == WAIT_OBJECT_0 || dwRet == WAIT_TIMEOUT, Exception(_RcfError_Pipe(), dwErr)); RCF_VERIFY( generateTimeoutMs(mEndTimeMs), Exception(_RcfError_ClientReadTimeout())) (mEndTimeMs)(bytesToRead); if (dwRet == WAIT_TIMEOUT) { clientStub.onPollingTimeout(); } } RCF_ASSERT_EQ(dwRet , WAIT_OBJECT_0); dwRead = 0; ok = GetOverlappedResult(mhPipe, &overlapped, &dwRead, FALSE); dwErr = GetLastError(); RCF_VERIFY(ok && dwRead > 0, Exception(_RcfError_Pipe(), dwErr)); onTimedRecvCompleted(dwRead, 0); return dwRead; }
void OverlappedAmi::onCompletion( std::size_t index, const AsioErrorCode & ec, std::size_t bytesTransferred) { RecursiveLock lock(mMutex); if (mIndex == index && mpTransport) { ++mIndex; if (mpTransport->mAsioTimerPtr) { mpTransport->mAsioTimerPtr->cancel(); } #ifdef BOOST_WINDOWS // Do we need to impersonate? boost::scoped_ptr<Win32ThreadImpersonator> impersonator; HANDLE hImpersonationToken = static_cast<ClientStub *>(mpTransport->mpClientStub) ->getWindowsImpersonationToken(); if (hImpersonationToken != INVALID_HANDLE_VALUE) { impersonator.reset( new Win32ThreadImpersonator(hImpersonationToken) ); } #endif if (ec) { try { RCF::Exception e; switch (mOpType) { case Wait: RCF_ASSERT(0); break; case Connect: e = RCF::Exception( _RcfError_ClientConnectFail(), ec.value()); break; case Write: e = RCF::Exception( _RcfError_ClientWriteFail(), ec.value()); break; case Read: e = RCF::Exception( _RcfError_ClientReadFail(), ec.value()); break; default: RCF_ASSERT(0); }; mOpType = None; mpTransport->mpClientStub->onError(e); } catch(const std::exception &e) { mpTransport->mpClientStub->onError(e); } catch(...) { RCF::Exception e( _RcfError_NonStdException() ); mpTransport->mpClientStub->onError(e); } } else { mOpType = None; try { mpTransport->onCompletion( static_cast<int>(bytesTransferred) ); } catch(const std::exception &e) { mpTransport->mpClientStub->onError(e); } catch(...) { RCF::Exception e( _RcfError_NonStdException() ); mpTransport->mpClientStub->onError(e); } } getTlsAmiNotification().run(); } }