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 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 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);
            }
        }
    }
    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);
        }

    }