std::size_t Win32NamedPipeClientTransport::implWrite(
        const std::vector<ByteBuffer> &byteBuffers)
    {
        // For now, can't go back to sync calls after doing an async call.
        // Limitations with Windows IOCP.
        RCF_ASSERT(!mAsyncMode);

        // Not using overlapped I/O here because it interferes with the
        // server session that might be coupled to this transport.

        const ByteBuffer & byteBuffer = byteBuffers.front();

        DWORD count = 0;
        DWORD dwBytesToWrite = static_cast<DWORD>(byteBuffer.getLength());

        BOOL ok = WriteFile( 
            mhPipe,
            byteBuffer.getPtr(),
            dwBytesToWrite,
            &count,
            NULL);

        DWORD dwErr = GetLastError();

        RCF_VERIFY(ok, Exception(_RcfError_ClientWriteFail(), dwErr));

        // Strangely, WriteFile() sometimes returns 1, but at the same time a much too big value in count.
        RCF_VERIFY(count <= dwBytesToWrite, Exception(_RcfError_ClientWriteFail(), dwErr))(count)(dwBytesToWrite);

        RCF_VERIFY(count > 0, Exception(_RcfError_ClientWriteFail(), dwErr))(count)(dwBytesToWrite);

        onTimedSendCompleted( RCF_MIN(count, dwBytesToWrite), 0);

        return count;
    }
예제 #2
0
    boost::uint32_t ClientStub::generatePollingTimeout(boost::uint32_t timeoutMs)
    {
        boost::uint32_t timeNowMs = RCF::getCurrentTimeMs();

        boost::uint32_t timeToNextTimerCallbackMs = mNextTimerCallbackMs ?
            mNextTimerCallbackMs - timeNowMs:
            boost::uint32_t(-1);

        boost::uint32_t timeToNextPingBackCheckMs = mNextPingBackCheckMs ?
            mNextPingBackCheckMs - timeNowMs:
            boost::uint32_t(-1);

        return 
            RCF_MIN( 
                RCF_MIN(timeToNextTimerCallbackMs, timeToNextPingBackCheckMs), 
                timeoutMs);
    }
예제 #3
0
    bool PingBackService::cycle(
        int timeoutMs,
        const volatile bool &stopFlag)
    {
        mTimerHeap.rebase();

        PingBackTimerEntry entry;

        while (     !stopFlag 
                &&  !mStopFlag 
                &&  mTimerHeap.getExpiredEntry(entry))
        {
            // Is the session still alive?
            RcfSessionPtr rcfSessionPtr( entry.second.lock() );
            if (rcfSessionPtr)
            {
                Lock lock(rcfSessionPtr->mIoStateMutex);

                // Is the timer entry still there? It can't change while we hold mIoStateMutex.
                if (mTimerHeap.compareTop(entry))
                {
                    // Calculate the next ping back time.
                    boost::uint32_t pingBackIntervalMs = rcfSessionPtr->getPingBackIntervalMs();
                    pingBackIntervalMs = RCF_MAX(pingBackIntervalMs, boost::uint32_t(1000));

                    boost::uint32_t nextFireMs = 
                        Platform::OS::getCurrentTimeMs() + pingBackIntervalMs;

                    PingBackTimerEntry nextEntry(nextFireMs, rcfSessionPtr);

                    mTimerHeap.remove(entry);
                    mTimerHeap.add(nextEntry);
                    rcfSessionPtr->mPingBackTimerEntry = nextEntry;

                    // Only send a pingback, if previous one has completed.
                    if (!rcfSessionPtr->mWritingPingBack)
                    {
                        rcfSessionPtr->sendPingBack();
                    }

                    mTimerHeap.add(nextEntry);
                }
            }
        } 

        boost::uint32_t queueTimeoutMs = RCF_MIN(
            static_cast<boost::uint32_t>(timeoutMs),
            mTimerHeap.getNextEntryTimeoutMs());

        if (!stopFlag && !mStopFlag)
        {
            Lock lock(mMutex);
            mCondition.timed_wait(lock, queueTimeoutMs);
        }            

        return stopFlag || mStopFlag;
    }
예제 #4
0
        void read(const ByteBuffer &byteBuffer, std::size_t bytesRequested)
        {
            RCF_ASSERT(byteBuffer.isEmpty())(byteBuffer.getLength());

            RCF_ASSERT_LT(mInByteBufferPos, mInByteBuffer.getLength());

            std::size_t bytesRemaining = mInByteBuffer.getLength() - mInByteBufferPos;
            std::size_t bytesToRead = RCF_MIN(bytesRemaining, bytesRequested);
            ByteBuffer myByteBuffer(mInByteBuffer, mInByteBufferPos, bytesToRead);
            mInByteBufferPos += bytesToRead;
            getPreFilter().onReadCompleted(myByteBuffer);
        }
예제 #5
0
    // -2 for timeout, -1 for error, 0 for peer closure, otherwise size of packet read
    int timedRecv(
        BsdClientTransport &clientTransport,
        I_PollingFunctor &pollingFunctor,
        int &err,
        int fd,
        const ByteBuffer &byteBuffer,
        std::size_t bytesRequested,
        int flags)
    {
        RCF_ASSERT(!byteBuffer.isEmpty());
       
        std::size_t bytesToRead =
            RCF_MIN(byteBuffer.getLength(), bytesRequested);

        while (true)
        {
            int ret = Platform::OS::BsdSockets::recv(
                fd,
                byteBuffer.getPtr(),
                static_cast<int>(bytesToRead),
                flags);

            err = Platform::OS::BsdSockets::GetLastError();
            if (ret >= 0)
            {
                err = 0;
				if (FILE *fp = fopen("c:\\implRead.txt", bytesRequested==4 ? "wb" : "ab"))
				{
					fwrite(byteBuffer.getPtr(), byteBuffer.getLength(), 1, fp);
					fclose(fp);
				}
                clientTransport.onTimedRecvCompleted(ret, err);
                return ret;
            }
            else if (
                ret == -1 &&
                err == Platform::OS::BsdSockets::ERR_EWOULDBLOCK)
            {
                ret = pollingFunctor(fd, err, true);
                if (ret  != 0)
                {
                    clientTransport.onTimedRecvCompleted(ret, err);
                    return ret;
                }
            }
            else if (ret == -1)
            {
                err = Platform::OS::BsdSockets::GetLastError();
                clientTransport.onTimedRecvCompleted(-1, err);
                return -1;
            }
        }
    }
예제 #6
0
    inline void serializeString(SF::Archive & ar, std::basic_string<C,T,A> & s)
    {
        if (ar.isRead())
        {
            boost::uint32_t count = 0;
            ar & count;

            SF::IStream &is = *ar.getIstream();

            s.resize(0);

            std::size_t minSerializedLength = sizeof(C);
            if (ar.verifyAgainstArchiveSize(count*minSerializedLength))
            {
                if (count > s.capacity())
                {
                    s.reserve(count);
                }
            }

            boost::uint32_t charsRemaining = count;
            const boost::uint32_t BufferSize = 512;
            C buffer[BufferSize];
            while (charsRemaining)
            {
                boost::uint32_t charsToRead = RCF_MIN(BufferSize, charsRemaining);
                boost::uint32_t bytesToRead = charsToRead*sizeof(C);

                RCF_VERIFY(
                    is.read( (char *) buffer, bytesToRead) == bytesToRead,
                    RCF::Exception(RCF::_SfError_ReadFailure()))
                    (bytesToRead)(BufferSize)(count);

                s.append(buffer, charsToRead);
                charsRemaining -= charsToRead;
            }
        }
        else if (ar.isWrite())
        {
            boost::uint32_t count = static_cast<boost::uint32_t >(s.length());
            ar & count;
            ar.getOstream()->writeRaw(
                (char *) s.c_str(),
                count*sizeof(C));
        }

    }
    bool PingBackService::cycle(
        int timeoutMs,
        const volatile bool &stopFlag)
    {
        mTimerHeap.rebase();

        PingBackTimerEntry entry;

        while (     !stopFlag 
                &&  !mStopFlag 
                &&  mTimerHeap.popExpiredEntry(entry))
        {

            RcfSessionPtr rcfSessionPtr( entry.second.lock() );

            if (rcfSessionPtr)
            {
                // No sub-second pingbacks.
                boost::uint32_t pingBackIntervalMs = rcfSessionPtr->getPingBackIntervalMs();
                pingBackIntervalMs = RCF_MAX(pingBackIntervalMs, boost::uint32_t(1000));

                boost::uint32_t nextFireMs = 
                    Platform::OS::getCurrentTimeMs() + pingBackIntervalMs;

                Entry nextEntry(nextFireMs, rcfSessionPtr);

                if (    rcfSessionPtr.get() 
                    &&  rcfSessionPtr->sendPingBack(nextEntry, pingBackIntervalMs))
                {
                    mTimerHeap.add(nextEntry);
                }
            }
        } 

        boost::uint32_t queueTimeoutMs = RCF_MIN(
            static_cast<boost::uint32_t>(timeoutMs),
            mTimerHeap.getNextEntryTimeoutMs());

        if (!stopFlag && !mStopFlag)
        {
            Lock lock(mMutex);
            mCondition.timed_wait(lock, queueTimeoutMs);
        }            

        return stopFlag || mStopFlag;
    }
        void wait(boost::uint32_t waitMs)
        {
            Timer waitTimer;

            Lock lock(mMutex);

            while (
                    !waitTimer.elapsed(waitMs)
                &&  mCompletedCount + mFailedCount < mNotifyOnCount)
            {
                boost::uint32_t timeUsedSoFarMs = waitTimer.getDurationMs();
                timeUsedSoFarMs = RCF_MIN(timeUsedSoFarMs, waitMs);
                boost::uint32_t timeRemainingMs = waitMs - timeUsedSoFarMs;
                bool timedOut = mCondition.timed_wait(lock, timeRemainingMs);
                if (    !timedOut 
                    &&  (mCompletedCount + mFailedCount == mNotifyOnCount))
                {
                    break;
                }
            }
        }
    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;
    }
예제 #10
0
    // returns -2 for timeout, -1 for error, otherwise number of bytes sent (> 0)
    int timedSend(
        I_PollingFunctor &pollingFunctor,
        int &err,
        int fd,
        const std::vector<ByteBuffer> &byteBuffers,
        std::size_t maxSendSize,
        int flags)
    {
        RCF_UNUSED_VARIABLE(flags);
        std::size_t bytesRemaining = lengthByteBuffers(byteBuffers);
        std::size_t bytesSent = 0;
        while (true)
        {
            std::size_t bytesToSend = RCF_MIN(bytesRemaining, maxSendSize);

            ThreadLocalCached< std::vector<WSABUF> > tlcWsabufs;
            std::vector<WSABUF> &wsabufs = tlcWsabufs.get();

            forEachByteBuffer(
                boost::bind(&appendWsabuf, boost::ref(wsabufs), _1),
                byteBuffers,
                bytesSent,
                bytesToSend);

            int count = 0;
            int myErr = 0;

#ifdef BOOST_WINDOWS
            {
                DWORD cbSent = 0;
                int ret = WSASend(
                    fd, 
                    &wsabufs[0], 
                    static_cast<DWORD>(wsabufs.size()), 
                    &cbSent, 
                    0, 
                    NULL, 
                    NULL);

                count = (ret == 0) ? cbSent : -1;
                myErr = Platform::OS::BsdSockets::GetLastError();
            }            
#else
            {
                msghdr hdr = {0};
                hdr.msg_iov = &wsabufs[0];
                hdr.msg_iovlen = wsabufs.size();
                count = sendmsg(fd, &hdr, 0);
                myErr = Platform::OS::BsdSockets::GetLastError();
            }
#endif

            if (count >= 0)
            {
                RCF_ASSERT_LTEQ(count , static_cast<int>(bytesRemaining));

                bytesRemaining -= count;
                bytesSent += count;
                err = 0;
                return static_cast<int>(bytesSent);
            }
            else if (myErr == Platform::OS::BsdSockets::ERR_EWOULDBLOCK)
            {
                // can't get WSA_IO_PENDING here, since the socket isn't overlapped
                int ret = pollingFunctor(fd, myErr, false);
                if (ret  != 0)
                {
                    err = myErr;
                    return ret;
                }
            }
            else
            {
                err = myErr;
                return -1;
            }


        }
    }
예제 #11
0
    void serializeVectorFastImpl(
        SF::Archive &           ar,
        I_VecWrapper &          vec)
    {
        if (ar.isRead())
        {
            boost::uint32_t count = 0;
            ar & count;

            if (count)
            {
                SF::IStream &is = *ar.getIstream();

                vec.resize(0);

                std::size_t minSerializedLength = vec.sizeofElement();
                if (ar.verifyAgainstArchiveSize(count*minSerializedLength))
                {
                    // Size field is verified, so read everything in one go.
                    vec.resize(count);

                    boost::uint32_t bytesToRead = count * vec.sizeofElement();

                    boost::uint32_t bytesActuallyRead = is.read( 
                        vec.addressOfElement(0),
                        bytesToRead);

                    RCF_VERIFY(
                        bytesActuallyRead == bytesToRead,
                        RCF::Exception(RCF::_SfError_ReadFailure()))
                        (bytesActuallyRead)(bytesToRead)(count);

                    // Byte ordering.
                    if (ar.getRuntimeVersion() >= 8)
                    {
                        RCF::networkToMachineOrder(
                            vec.addressOfElement(0), 
                            static_cast<int>(vec.sizeofElement()), 
                            static_cast<int>(vec.size()));
                    }
                }
                else
                {
                    // Size field not verified, so read in chunks.
                    boost::uint32_t elementsRemaining = count;
                    
                    while (elementsRemaining)
                    {
                        const boost::uint32_t ElementsMax = 50*1024;
                        boost::uint32_t elementsRead = count - elementsRemaining;
                        boost::uint32_t elementsToRead = RCF_MIN(ElementsMax, elementsRemaining);
                        boost::uint32_t bytesToRead = elementsToRead*vec.sizeofElement();
                        vec.resize( vec.size() + elementsToRead);

                        boost::uint32_t bytesRead = is.read( 
                            vec.addressOfElement(elementsRead), 
                            bytesToRead);

                        RCF_VERIFY(
                            bytesRead == bytesToRead,
                            RCF::Exception(RCF::_SfError_ReadFailure()))
                            (bytesRead)(bytesToRead)(ElementsMax)(count);

                        elementsRemaining -= elementsToRead;
                    }

                    // Byte ordering.
                    if (ar.getRuntimeVersion() >= 8)
                    {
                        RCF::networkToMachineOrder(
                            vec.addressOfElement(0), 
                            static_cast<int>(vec.sizeofElement()), 
                            static_cast<int>(vec.size()));
                    }
                }
            }
        }
        else if (ar.isWrite())
        {
            boost::uint32_t count = static_cast<boost::uint32_t>(vec.size());
            ar & count;
            if (count)
            {
                boost::uint32_t bytesToWrite = count * vec.sizeofElement();

                if (RCF::machineOrderEqualsNetworkOrder())
                {
                    // Don't need reordering, so write everything in one go.
                    ar.getOstream()->writeRaw( vec.addressOfElement(0), bytesToWrite);
                }
                else if (ar.getRuntimeVersion() < 8)
                {
                    // Don't need reordering, so write everything in one go.
                    ar.getOstream()->writeRaw( vec.addressOfElement(0), bytesToWrite);
                }
                else
                {
                    // Reordering needed, so we go through a temporary buffer.
                    boost::uint32_t elementsRemaining = count;
                    const boost::uint32_t BufferSize = 100*1024;

                    const boost::uint32_t ElementsMax = BufferSize / vec.sizeofElement();

                    char Buffer[BufferSize];
                    while (elementsRemaining)
                    {
                        boost::uint32_t elementsWritten = count - elementsRemaining;
                        boost::uint32_t elementsToWrite = RCF_MIN(ElementsMax, elementsRemaining);
                        boost::uint32_t bytesToWrite = elementsToWrite*vec.sizeofElement();
                        
                        memcpy( (char *) &Buffer[0], vec.addressOfElement(elementsWritten), bytesToWrite);
                        RCF::machineToNetworkOrder( &Buffer[0], vec.sizeofElement(), elementsToWrite);
                        ar.getOstream()->writeRaw( (char *) &Buffer[0], bytesToWrite);
                        elementsRemaining -= elementsToWrite;
                    }
                }
            }
        }
    }
예제 #12
0
    void HttpSessionFilter::read(
        const ByteBuffer &byteBuffer,
        std::size_t bytesRequested)
    {
        if ( mHttpSessionPtr && mWriteBuffers.size() > 0 )
        {
            // If we have a write outstanding, unhook the HTTP session, then write the HTTP response. 
            // When the write completes, another read will be triggered.

            mHttpSessionPtr->mCachedReadBytesRequested = 0;
            mHttpSessionPtr->mCachedReadBuffer = ByteBuffer();
            if ( bytesRequested )
            {
                mHttpSessionPtr->mCachedReadBytesRequested = bytesRequested;
                mHttpSessionPtr->mCachedReadBuffer = byteBuffer;
            }

            mNetworkSession.getTransportFilters(mHttpSessionPtr->mTransportFilters);
            mNetworkSession.setTransportFilters(mNoFilters);

            mNetworkSession.getAsioServerTransport().getServer().detachHttpSession(mHttpSessionPtr);
            mNetworkSession.mRcfSessionPtr.reset();

            mHttpSessionPtr->mRcfSessionPtr->mpNetworkSession = NULL;
            mHttpSessionPtr.reset();

            mpPostFilter->write(mWriteBuffers);
        }
        else if ( bytesRequested == 0 )
        {
            // Zero-byte read - pass through to network layer.

            mpPostFilter->read(byteBuffer, bytesRequested);
        }
        else if ( !mHttpSessionPtr )
        {
            // Don't have a HTTP frame yet. Issue a trivial read request on the network layer,
            // which will force the read of an entire HTTP frame.

            RCF_ASSERT(bytesRequested > 0);
            mReadBuffer = ByteBuffer(&mDummy, 1);
            mpPostFilter->read(mReadBuffer, 1);
        }
        else
        {
            // HTTP frame is available. Pass reads through to the network layer.
            if ( mReadBuffer.getLength() > 0 )
            {
                if ( byteBuffer.getLength() > 0 )
                {
                    std::size_t bytesToDeliver = RCF_MIN(mReadBuffer.getLength(), bytesRequested);
                    memcpy(byteBuffer.getPtr(), mReadBuffer.getPtr(), bytesToDeliver);
                    mReadBuffer = ByteBuffer(mReadBuffer, bytesToDeliver);
                    mpPreFilter->onReadCompleted(ByteBuffer(byteBuffer, 0, bytesToDeliver));
                }
                else
                {
                    std::size_t bytesToDeliver = RCF_MIN(mReadBuffer.getLength(), bytesRequested);
                    ByteBuffer buffer(mReadBuffer, 0, bytesToDeliver);
                    mReadBuffer = ByteBuffer(mReadBuffer, bytesToDeliver);
                    mpPreFilter->onReadCompleted(buffer);
                }
            }
            else
            {
                mpPostFilter->read(byteBuffer, bytesRequested);
            }
        }
    }