void AsioSessionState::onAppReadWriteCompleted(
    size_t bytesTransferred)
{
    RCF_ASSERT(!mReflecting);
    switch(mState)
    {
    case ReadingDataCount:
    case ReadingData:

        if (mTransport.mCustomFraming)
        {
            doCustomFraming(bytesTransferred);
        }
        else
        {
            doRegularFraming(bytesTransferred);
        }

        break;

    case WritingData:

        RCF_ASSERT_LTEQ(bytesTransferred , mWriteBufferRemaining);

        mWriteBufferRemaining -= bytesTransferred;
        if (mWriteBufferRemaining > 0)
        {
            beginWrite();
        }
        else
        {
            if (mCloseAfterWrite)
            {
                // For TCP sockets, call shutdown() so client receives
                // the message before we close the connection.

                implCloseAfterWrite();
            }
            else
            {
                mState = Ready;

                mSlicedWriteByteBuffers.resize(0);
                mWriteByteBuffers.resize(0);

                mTransport.getSessionManager().onWriteCompleted(
                    getSessionPtr());
            }
        }
        break;

    default:
        RCF_ASSERT(0);
    }
}
void AsioSessionState::doRegularFraming(size_t bytesTransferred)
{
    RCF_ASSERT_LTEQ(bytesTransferred , mReadBufferRemaining);
    mReadBufferRemaining -= bytesTransferred;
    if (mReadBufferRemaining > 0)
    {
        beginRead();
    }
    else if (mReadBufferRemaining == 0 && mIssueZeroByteRead)
    {
        if (!mAppReadBufferPtr || !mAppReadBufferPtr.unique())
        {
            mAppReadBufferPtr = getObjectPool().getReallocBufferPtr();
        }
        mAppReadBufferPtr->resize(4);

        mReadBufferRemaining = 4;
        mIssueZeroByteRead = false;
        beginRead();
    }
    else
    {
        RCF_ASSERT_EQ(mReadBufferRemaining , 0);
        if (mState == ReadingDataCount)
        {
            ReallocBuffer & readBuffer = *mAppReadBufferPtr;
            RCF_ASSERT_EQ(readBuffer.size() , 4);

            unsigned int packetLength = 0;
            memcpy(&packetLength, &readBuffer[0], 4);
            networkToMachineOrder(&packetLength, 4, 1);

            if (    mTransport.getMaxMessageLength()
                    &&  packetLength > mTransport.getMaxMessageLength())
            {
                sendServerError(RcfError_ServerMessageLength);
            }
            else
            {
                readBuffer.resize(packetLength);
                mReadBufferRemaining = packetLength;
                mState = ReadingData;
                beginRead();
            }
        }
        else if (mState == ReadingData)
        {
            mState = Ready;

            mTransport.getSessionManager().onReadCompleted(
                getSessionPtr());
        }
    }
}
void AsioSessionState::doCustomFraming(size_t bytesTransferred)
{
    RCF_ASSERT_LTEQ(bytesTransferred , mReadBufferRemaining);
    mReadBufferRemaining -= bytesTransferred;
    if (mReadBufferRemaining > 0)
    {
        beginRead();
    }
    else if (mReadBufferRemaining == 0 && mIssueZeroByteRead)
    {
        if (!mAppReadBufferPtr || !mAppReadBufferPtr.unique())
        {
            mAppReadBufferPtr = getObjectPool().getReallocBufferPtr();
        }
        mAppReadBufferPtr->resize(4);

        mReadBufferRemaining = 4;
        mIssueZeroByteRead = false;
        beginRead();
    }
    else
    {
        RCF_ASSERT_EQ(mReadBufferRemaining , 0);
        if (mState == ReadingDataCount)
        {
            ReallocBuffer & readBuffer = *mAppReadBufferPtr;
            RCF_ASSERT_EQ(readBuffer.size() , 4);

            std::size_t messageLength = mTransportFilters[0]->getFrameSize();

            if (    mTransport.getMaxMessageLength()
                    &&  messageLength > mTransport.getMaxMessageLength())
            {
                sendServerError(RcfError_ServerMessageLength);
            }
            else
            {
                RCF_ASSERT( messageLength > 4 );
                readBuffer.resize(messageLength);
                mReadBufferRemaining = messageLength - 4;
                mState = ReadingData;
                beginRead();
            }
        }
        else if (mState == ReadingData)
        {
            mState = Ready;

            mTransport.getSessionManager().onReadCompleted(
                getSessionPtr());
        }
    }
}
    void AsioSessionState::onReadWrite(
        size_t bytesTransferred, 
        const boost::system::error_code& error)
    {
        RCF_ASSERT(!error);
        RCF_ASSERT(!mReflecting);
        {
            switch(mState)
            {
            case ReadingDataCount:
            case ReadingData:

                RCF_ASSERT(
                    bytesTransferred <= mReadBufferRemaining)
                    (bytesTransferred)(mReadBufferRemaining);

                mReadBufferRemaining -= bytesTransferred;
                if (mReadBufferRemaining > 0)
                {
                    invokeAsyncRead();
                }
                else
                {
                    RCF_ASSERT(mReadBufferRemaining == 0)(mReadBufferRemaining);
                    if (mState == ReadingDataCount)
                    {
                        std::vector<char> &readBuffer = getReadBuffer();
                        RCF_ASSERT(readBuffer.size() == 4)(readBuffer.size());

                        unsigned int packetLength = 0;
                        memcpy(&packetLength, &readBuffer[0], 4);
                        networkToMachineOrder(&packetLength, 4, 1);
                        
                        if (packetLength <= mTransport.getMaxMessageLength())
                        {
                            readBuffer.resize(packetLength);
                            mReadBufferRemaining = packetLength;
                            mState = ReadingData;
                            invokeAsyncRead();
                        }
                        else
                        {
                            sendServerError(RcfError_ServerMessageLength);
                        }

                    }
                    else if (mState == ReadingData)
                    {
                        mState = Ready;

                        mTransport.getSessionManager().onReadCompleted(
                            getSessionPtr());

                        if (mTransport.mInterrupt)
                        {
                            mTransport.mInterrupt = false;
                            mTransport.mDemuxerPtr->stop();
                        }
                    }
                }
                break;


            case WritingData:

                RCF_ASSERT(
                    bytesTransferred <= mWriteBufferRemaining)
                    (bytesTransferred)(mWriteBufferRemaining);

                mWriteBufferRemaining -= bytesTransferred;
                if (mWriteBufferRemaining > 0)
                {
                    invokeAsyncWrite();
                }
                else
                {
                    if (mCloseAfterWrite)
                    {
                        int fd = implGetNative();
                        const int BufferSize = 8*1024;
                        char buffer[BufferSize];
                        while (recv(fd, buffer, BufferSize, 0) > 0);
                    }
                    else
                    {
                        mState = Ready;

                        mSlicedWriteByteBuffers.resize(0);
                        mWriteByteBuffers.resize(0);

                        mTransport.getSessionManager().onWriteCompleted(
                            getSessionPtr());

                        if (mTransport.mInterrupt)
                        {
                            mTransport.mInterrupt = false;
                            mTransport.mDemuxerPtr->stop();
                        }
                    }
                }
                break;

            default:
                RCF_ASSERT(0);
            }
        }
    }