void Win32NamedPipeNetworkSession::implWrite(const std::vector<ByteBuffer> & buffers)
    {
        if ( !mSocketPtr )
        {
            RCF_LOG_4() << "Win32NamedPipeNetworkSession - connection has been closed.";
            return;
        }

        RCF_LOG_4()(RCF::lengthByteBuffers(buffers))
            << "Win32NamedPipeNetworkSession - calling WriteFile().";


        ASIO_NS::windows::overlapped_ptr overlapped(
            mSocketPtr->get_io_service(), 
            WriteHandler(sharedFromThis()));

        const ByteBuffer & byteBuffer = buffers.front();

        DWORD dwBytesWritten = 0;

        bool writeOk = false;

        HANDLE hPipe = mSocketPtr->native();

        BOOL ok = WriteFile(
            hPipe,
            byteBuffer.getPtr(),
            static_cast<DWORD>(byteBuffer.getLength()),
            &dwBytesWritten,
            overlapped.get());

        DWORD dwErr = GetLastError();;

        if (!ok &&  (
            dwErr == ERROR_IO_PENDING 
            ||  dwErr == ERROR_MORE_DATA))
        {
            writeOk = true;
        }
        else if (dwBytesWritten)
        {
            writeOk = true;
        }

        if (writeOk)
        {
            overlapped.release();
        }
        else
        {
            AsioErrorCode ec(
                dwErr,
                ASIO_NS::error::get_system_category());

            overlapped.complete(ec, 0);
        }
    }
    void FileIoRequest::complete()
    {
        RCF_LOG_4() << "FileIoRequest::complete() - entry";

        RCF::Lock lock(mFts.mCompletionMutex);
        while (!mCompleted)
        {
            mFts.mCompletionCondition.timed_wait(lock, 1000);
        }
        mInitiated = false;

        RCF_LOG_4() << "FileIoRequest::complete() - exit";
    }
AsioSessionState::~AsioSessionState()
{
    RCF_DTOR_BEGIN

    // TODO: invoke accept if appropriate
    // TODO: need a proper acceptex strategy in the first place
    //RCF_ASSERT(mState != Accepting);

    mTransport.unregisterSession(mWeakThisPtr);

    RCF_LOG_4()(mState)(mSessionPtr.get())(mSessionPtr->mDisableIo)
            << "AsioSessionState - destructor.";

    // close reflecting session if appropriate
    if (mReflecting)
    {
        AsioSessionStatePtr sessionStatePtr(mReflecteeWeakPtr.lock());
        if (sessionStatePtr)
        {
            sessionStatePtr->close();
        }
    }

    RCF_DTOR_END;
}
    bool FileIoRequest::isInitiated()
    {
        RCF_LOG_4() << "FileIoRequest::isInitiated()";

        RCF::Lock lock(mFts.mCompletionMutex);
        return mInitiated;
    }
Exemple #5
0
    bool FileIoRequest::completed()
    {
        RCF_LOG_4() << "FileIoRequest::completed";

        RCF::Lock lock(mFts.mCompletionMutex);
        return mCompleted;
    }
Exemple #6
0
 FileIoRequest::FileIoRequest() :
     mFts( getFileIoThreadPool() ),
     mBytesTransferred(0),
     mInitiated(false),
     mCompleted(true)
 {
     RCF_LOG_4() << "FileIoRequest::FileIoRequest";
 }
void AsioSessionState::onNetworkReadCompleted(
    AsioErrorCode error, size_t bytesTransferred)
{
    RCF_LOG_4()(this)(bytesTransferred) << "AsioSessionState - read from socket completed.";

    ThreadTouchGuard threadTouchGuard;

    mLastError = error;

    mBytesReceivedCounter += bytesTransferred;

#ifdef BOOST_WINDOWS

    if (error.value() == ERROR_OPERATION_ABORTED)
    {
        error = AsioErrorCode();
    }

#endif

    if (!error && !mTransport.mStopFlag)
    {
        if (bytesTransferred == 0 && mIssueZeroByteRead)
        {
            // TCP framing.
            if (!mAppReadBufferPtr || !mAppReadBufferPtr.unique())
            {
                mAppReadBufferPtr = getObjectPool().getReallocBufferPtr();
            }
            mAppReadBufferPtr->resize(4);

            mReadBufferRemaining = 4;
            mIssueZeroByteRead = false;
            beginRead();
        }
        else if (mReflecting)
        {
            AsioErrorCode ec;
            onReflectedReadWriteCompleted(ec, bytesTransferred);
        }
        else
        {
            CurrentRcfSessionSentry guard(*mSessionPtr);

            mNetworkReadByteBuffer = ByteBuffer(
                                         mNetworkReadByteBuffer,
                                         0,
                                         bytesTransferred);

            mTransportFilters.empty() ?
            onAppReadWriteCompleted(bytesTransferred) :
            mTransportFilters.back()->onReadCompleted(mNetworkReadByteBuffer);
        }
    }
}
Exemple #8
0
    void FileIoRequest::complete()
    {
        RCF_LOG_4() << "FileIoRequest::complete()";

        RCF::Lock lock(mFts.mCompletionMutex);
        while (!mCompleted)
        {
            mFts.mCompletionCondition.wait(lock);
        }
        mInitiated = false;
    }
Exemple #9
0
    void FileIoRequest::doTransfer()
    {
        if (mFinPtr)
        {
            RCF_LOG_4() << "FileIoRequest::doTransfer() - initiate read.";

            char * szBuffer = mBuffer.getPtr();
            std::size_t szBufferLen = mBuffer.getLength();
            mFinPtr->read(szBuffer, szBufferLen);
            mBytesTransferred = mFinPtr->gcount();
            mFinPtr.reset();

            RCF_LOG_4()(mBytesTransferred) << "FileIoRequest::doTransfer() - read complete.";
        }
        else if (mFoutPtr)
        {
            RCF_LOG_4() << "FileIoRequest::doTransfer() - initiate write.";

            char * szBuffer = mBuffer.getPtr();
            std::size_t szBufferLen = mBuffer.getLength();
            
            boost::uint64_t pos0 = mFoutPtr->tellp();
            mFoutPtr->write(szBuffer, szBufferLen);
            boost::uint64_t pos1 = mFoutPtr->tellp();

            RCF_ASSERT_GTEQ(pos1 , pos0);
            mBytesTransferred = pos1 - pos0;
            RCF_ASSERT_EQ(mBytesTransferred , szBufferLen);
            mFoutPtr.reset();

            RCF_LOG_4()(mBytesTransferred) << "FileIoRequest::doTransfer() - write complete.";
        }
        else
        {
            RCF_ASSERT(0);
            mBytesTransferred = 0;
        }
    }
    int UdpClientTransport::send(
        I_ClientTransportCallback &clientStub, 
        const std::vector<ByteBuffer> &data,
        unsigned int timeoutMs)
    {
        RCF_LOG_4()(mSock)(mDestIp.string()) << "UdpClientTransport - sending data on socket.";

        RCF_UNUSED_VARIABLE(timeoutMs);

        RCF_ASSERT(!mAsync);

        // TODO: optimize for case of single byte buffer with left margin

        if (mWriteVecPtr.get() == NULL || !mWriteVecPtr.unique())
        {
            mWriteVecPtr.reset( new ReallocBuffer());
        }

        mLastRequestSize = lengthByteBuffers(data);
        mRunningTotalBytesSent += lengthByteBuffers(data);

        ReallocBuffer &buffer = *mWriteVecPtr;
        buffer.resize(lengthByteBuffers(data));

        copyByteBuffers(data, &buffer[0]);

        sockaddr * pDestAddr = NULL;
        Platform::OS::BsdSockets::socklen_t destAddrSize = 0;
        mDestIp.getSockAddr(pDestAddr, destAddrSize);

        int len = sendto(
            mSock,
            &buffer[0],
            static_cast<int>(buffer.size()),
            0,
            pDestAddr, 
            destAddrSize);

        int err = Platform::OS::BsdSockets::GetLastError();
        RCF_VERIFY(
            len > 0,
            Exception(
                _RcfError_Socket("sendto()"),
                err,
                RcfSubsystem_Os));

        clientStub.onSendCompleted();

        return 1;
    }
    void Win32NamedPipeNetworkSession::implAccept()
    {
        RCF_LOG_4()<< "Win32NamedPipeNetworkSession - calling ConnectNamedPipe().";

        ASIO_NS::windows::overlapped_ptr overlapped(
            mSocketPtr->get_io_service(), 
            boost::bind(
                &AsioNetworkSession::onAcceptCompleted,
                sharedFromThis(),
                ASIO_NS::placeholders::error));

        HANDLE hPipe = mSocketPtr->native();
        BOOL ok = ConnectNamedPipe(hPipe, overlapped.get());
        DWORD dwErr = GetLastError();

        // ConnectNamedPipe() can complete either synchronously or
        // asynchronously. We need to cater for both possibilities.

        if ( !ok && dwErr == ERROR_IO_PENDING )
        {
            // Asynchronous accept.
            overlapped.release();
        }
        else if (!ok && dwErr == ERROR_PIPE_CONNECTED)
        {
            // Synchronous connect.
            AsioErrorCode ec;
            overlapped.complete(ec, 0);
        }
        else
        {
            // ConnectNamedPipe() may return a synchronous error. In particular we sometimes
            // get ERROR_NO_DATA ("The pipe is being closed"). So, here we need another 
            // accept call.

            // MSDN says ConectNamedPipe will always return 0, in overlapped mode.
            RCF_ASSERT(!ok);

            mTransport.createNetworkSession()->beginAccept();
        }
    }
void AsioSessionState::onNetworkWriteCompleted(
    AsioErrorCode error,
    size_t bytesTransferred)
{
    RCF_LOG_4()(this)(bytesTransferred) << "AsioSessionState - write to socket completed.";

    ThreadTouchGuard threadTouchGuard;

    mLastError = error;

    mBytesSentCounter += bytesTransferred;

#ifdef BOOST_WINDOWS

    if (error.value() == ERROR_OPERATION_ABORTED)
    {
        error = AsioErrorCode();
    }

#endif

    if (!error && !mTransport.mStopFlag)
    {
        if (mReflecting)
        {
            if (mReflecteePtr)
            {
                mReflecteePtr.reset();
            }
            AsioErrorCode ec;
            onReflectedReadWriteCompleted(ec, bytesTransferred);
        }
        else
        {
            CurrentRcfSessionSentry guard(*mSessionPtr);
            mTransportFilters.empty() ?
            onAppReadWriteCompleted(bytesTransferred) :
            mTransportFilters.back()->onWriteCompleted(bytesTransferred);
        }
    }
}
Exemple #13
0
    void FileIoRequest::write(boost::shared_ptr<std::ofstream> foutPtr, RCF::ByteBuffer buffer)
    {
        RCF_LOG_4()(foutPtr.get())((void*)buffer.getPtr())(buffer.getLength()) << "FileIoRequest::write()";

        mFinPtr.reset();
        mFoutPtr = foutPtr;
        mBuffer = buffer;
        mBytesTransferred = 0;
        mInitiated = true;
        mCompleted = false;

        mFts.registerOp( shared_from_this() );

        // For debugging purposes, we can wait in this function until the file I/O is completed.
        if (mFts.mSerializeFileIo)
        {
            RCF::Lock lock(mFts.mCompletionMutex);
            while (!mCompleted)
            {
                mFts.mCompletionCondition.wait(lock);
            }
        }
    }
Exemple #14
0
    boost::uint64_t FileIoRequest::getBytesTransferred()
    {
        RCF_LOG_4()(mBytesTransferred) << "FileIoRequest::getBytesTransferred()";

        return mBytesTransferred;
    }
Exemple #15
0
 FileIoRequest::~FileIoRequest()
 {
     RCF_LOG_4() << "FileIoRequest::~FileIoRequest";
 }
    void UdpServerTransport::open()
    {
        RCF_LOG_4()(mIpAddress.string()) << "UdpServerTransport - creating server socket.";

        int mPort = mIpAddress.getPort();

        // create and bind a socket for receiving UDP messages
        if (mFd == -1 && mPort >= 0)
        {
            int ret = 0;
            int err = 0;

            mIpAddress.resolve();
            mFd = mIpAddress.createSocket(SOCK_DGRAM, IPPROTO_UDP);

            // enable reception of broadcast messages
            int enable = 1;
            ret = setsockopt(mFd, SOL_SOCKET, SO_BROADCAST, (char *) &enable, sizeof(enable));
            err = Platform::OS::BsdSockets::GetLastError();
            if (ret)
            {
                RCF_LOG_1()(ret)(err) << "setsockopt() - failed to set SO_BROADCAST on listening udp socket.";
            }

            // Share the address binding, if appropriate.
            if (mEnableSharedAddressBinding)
            {
                enable = 1;

                // Set SO_REUSEADDR socket option.
                ret = setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable));
                err = Platform::OS::BsdSockets::GetLastError();
                if (ret)
                {
                    RCF_LOG_1()(ret)(err) << "setsockopt() - failed to set SO_REUSEADDR on listening udp multicast socket.";
                }

                // On OS X and BSD variants, need to set SO_REUSEPORT as well.

#if (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) 

                ret = setsockopt(mFd, SOL_SOCKET, SO_REUSEPORT, (char *) &enable, sizeof(enable));
                err = Platform::OS::BsdSockets::GetLastError();
                if (ret)
                {
                    RCF_LOG_1()(ret)(err) << "setsockopt() - failed to set SO_REUSEPORT on listening udp multicast socket.";
                }
#endif

            }
            
            sockaddr * pServerAddr = NULL;
            Platform::OS::BsdSockets::socklen_t serverAddrSize = 0;
            mIpAddress.getSockAddr(pServerAddr, serverAddrSize);

            // bind the socket
            ret = ::bind(mFd, pServerAddr, serverAddrSize);
            if (ret < 0)
            {
                err = Platform::OS::BsdSockets::GetLastError();
                Exception e(_RcfError_Socket("bind()"), err, RcfSubsystem_Os);
                RCF_THROW(e)(mFd)(mIpAddress.string())(ret);
            }
            RCF_ASSERT_NEQ( mFd , -1 );

            if (!mMulticastIpAddress.empty())
            {
                // set socket option for receiving multicast messages

                mMulticastIpAddress.resolve();

                // TODO: implement for IPv6.
                RCF_ASSERT(
                        mIpAddress.getType() == IpAddress::V4 
                    &&  mMulticastIpAddress.getType() == IpAddress::V4);

                std::string ip = mMulticastIpAddress.getIp();
            
                ip_mreq imr;
                imr.imr_multiaddr.s_addr = inet_addr(ip.c_str());
                imr.imr_interface.s_addr = INADDR_ANY;
                int ret = setsockopt(mFd,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*) &imr, sizeof(imr));
                int err = Platform::OS::BsdSockets::GetLastError();

                RCF_VERIFY(
                    ret ==  0,
                    Exception(
                        _RcfError_Socket("setsockopt() with IPPROTO_IP/IP_ADD_MEMBERSHIP"),
                        err,
                        RcfSubsystem_Os))
                        (mMulticastIpAddress.string())(mIpAddress.string());

                // TODO: enable source-filtered multicast messages
                //ip_mreq_source imr;
                //imr.imr_multiaddr.s_addr = inet_addr("232.5.6.7");
                //imr.imr_sourceaddr.s_addr = INADDR_ANY;//inet_addr("10.1.1.2");
                //imr.imr_interface.s_addr = INADDR_ANY;
                //int ret = setsockopt(mFd,IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (const char*) &imr, sizeof(imr));
                //int err = Platform::OS::BsdSockets::GetLastError();
            }

            // set the socket to nonblocking mode
            Platform::OS::BsdSockets::setblocking(mFd, false);

            // retrieve the port number, if it's generated by the system
            if (mPort == 0)
            {
                IpAddress ip(mFd, mIpAddress.getType());
                mPort = ip.getPort();
                mIpAddress.setPort(mPort);
            }

            RCF_LOG_2() << "UdpServerTransport - listening on port " << mPort << ".";
        }
    }
    void Win32NamedPipeNetworkSession::implRead(char * buffer, std::size_t bufferLen)
    {
        if ( !mSocketPtr )
        {
            RCF_LOG_4() << "Win32NamedPipeNetworkSession - connection has been closed.";
            return;
        }

        RCF_LOG_4()(bufferLen) 
            << "Win32NamedPipeNetworkSession - calling ReadFile().";

        ASIO_NS::windows::overlapped_ptr overlapped(
            mSocketPtr->get_io_service(), 
            ReadHandler(sharedFromThis()));

        DWORD dwBytesRead = 0;

        bool readOk = false;

        HANDLE hPipe = mSocketPtr->native();

        BOOL ok = ReadFile(
            hPipe,
            buffer,
            static_cast<DWORD>(bufferLen),
            &dwBytesRead,
            overlapped.get());

        DWORD realError = 0;
        DWORD dwErr = 0;

        if (!ok)
        {
            dwErr = GetLastError();

            if (    dwErr != ERROR_IO_PENDING 
                &&  dwErr != ERROR_MORE_DATA)
            {
                realError = dwErr;
            }
        }

        if (    dwBytesRead
            ||  (ok && dwBytesRead == 0 && bufferLen == 0)
            ||  (!ok && realError == 0))
        {
            readOk = true;
        }

        if (readOk)
        {
            overlapped.release();
        }
        else
        {
            AsioErrorCode ec(
                dwErr,
                ASIO_NS::error::get_system_category());

            overlapped.complete(ec, 0);
        }
    }
    void UdpClientTransport::connect(
        I_ClientTransportCallback &clientStub, 
        unsigned int timeoutMs)
    {
        RCF_LOG_4()(mSock)(mDestIp.string()) << "UdpClientTransport - creating socket.";

        RCF_UNUSED_VARIABLE(timeoutMs);

        RCF_ASSERT(!mAsync);

        // TODO: replace throw with return value
        if (mSock == -1)
        {
            int ret = 0;
            int err = 0;

            // remote address
            mDestIp.resolve();

            // local address
            if (mLocalIp.empty())
            {
                std::string localIp = mDestIp.getType() == IpAddress::V4 ?
                    "0.0.0.0" :
                    "::0" ;

                mSrcIp = IpAddress(localIp, 0);             
            }
            else
            {
                mSrcIp = mLocalIp;
            }

            mSrcIp.resolve();
            
            mSock = mSrcIp.createSocket(SOCK_DGRAM, IPPROTO_UDP);

            sockaddr * pSrcAddr = NULL;
            Platform::OS::BsdSockets::socklen_t srcAddrSize = 0;
            mSrcIp.getSockAddr(pSrcAddr, srcAddrSize);

            ret = ::bind(mSock, pSrcAddr, srcAddrSize);
            err = Platform::OS::BsdSockets::GetLastError();

            RCF_VERIFY(
                ret == 0,
                Exception(
                    _RcfError_Socket("bind()"), err, RcfSubsystem_Os));

            mAssignedLocalIp = IpAddress(mSock, mSrcIp.getType());

#if defined(BOOST_WINDOWS) && defined(SIO_UDP_CONNRESET)

            // On Windows XP and later, disable the SIO_UDP_CONNRESET socket option.
            BOOL enable = FALSE;
            DWORD dwBytesRet = 0;
            DWORD dwStatus = WSAIoctl(mSock, SIO_UDP_CONNRESET, &enable, sizeof(enable), NULL, 0, &dwBytesRet, NULL, NULL);
            err = Platform::OS::BsdSockets::GetLastError();

            RCF_VERIFY(
                dwStatus == 0,
                Exception(
                    _RcfError_Socket("WSAIoctl() with SIO_UDP_CONNRESET"),
                    err,
                    RcfSubsystem_Os));

#endif // BOOST_WINDOWS

            if (mDestIp.isBroadcast())
            {
                // set socket option to allow transmission of broadcast messages
                int enable = 1;
                int ret = setsockopt(mSock, SOL_SOCKET, SO_BROADCAST, (char *) &enable, sizeof(enable));
                int err = Platform::OS::BsdSockets::GetLastError();

                RCF_VERIFY(
                    ret ==  0,
                    Exception(
                        _RcfError_Socket("setsockopt() with SO_BROADCAST"),
                        err,
                        RcfSubsystem_Os));
            }

            if (mDestIp.isMulticast())
            {
                // char for Solaris, int for everyone else.
#if defined(__SVR4) && defined(__sun)
                char hops = 16;
#else
                int hops = 16;
#endif
                int ret = setsockopt(mSock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &hops, sizeof (hops));
                int err = Platform::OS::BsdSockets::GetLastError();

                RCF_VERIFY(
                    ret ==  0,
                    Exception(
                        _RcfError_Socket("setsockopt() with IPPROTO_IP/IP_MULTICAST_TTL"),
                        err,
                        RcfSubsystem_Os))(hops);
            }
        }

        clientStub.onConnectCompleted();
    }
    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);
            }
        }
    }
void AsioSessionState::onAcceptCompleted(
    const AsioErrorCode & error)
{
    RCF_LOG_4()(error.value())
            << "AsioSessionState - onAccept().";

    if (mTransport.mStopFlag)
    {
        RCF_LOG_4()(error.value())
                << "AsioSessionState - onAccept(). Returning early, stop flag is set.";

        return;
    }

    //if (
    //    error == ASIO_NS::error::connection_aborted ||
    //    error == ASIO_NS::error::operation_aborted)
    //{
    //    beginAccept();
    //    return;
    //}

    // create a new SessionState, and do an accept on that
    mTransport.createSessionState()->beginAccept();

    if (!error)
    {
        // save the remote address in the SessionState object
        bool clientAddrAllowed = implOnAccept();
        mState = WritingData;

        // set current RCF session
        CurrentRcfSessionSentry guard(*mSessionPtr);

        mSessionPtr->touch();

        if (clientAddrAllowed)
        {
            // Check the connection limit.
            bool allowConnect = true;
            std::size_t connectionLimit = mTransport.getConnectionLimit();
            if (connectionLimit)
            {
                Lock lock(mTransport.mSessionsMutex);

                RCF_ASSERT_LTEQ(
                    mTransport.mSessions.size() , 1+1+connectionLimit);

                if (mTransport.mSessions.size() == 1+1+connectionLimit)
                {
                    allowConnect = false;
                }
            }

            if (allowConnect)
            {
                time_t now = 0;
                now = time(NULL);
                mSessionPtr->setConnectedAtTime(now);

                // start things rolling by faking a completed write operation
                onAppReadWriteCompleted(0);
            }
            else
            {
                sendServerError(RcfError_ConnectionLimitExceeded);
            }
        }
    }
}