Example #1
0
    Win32NamedPipeServerTransport::Win32NamedPipeServerTransport(
        const tstring & pipeName) :
            IocpServerTransport(),
            mpSec(RCF_DEFAULT_INIT),
            mQueuedAccepts(RCF_DEFAULT_INIT),
            mPipeNameLock(INVALID_HANDLE_VALUE)
    {
        if (pipeName.empty())
        {
            // Generate a pipe name dynamically, that won't conflict with any
            // other test executables that may be running concurrently.

            std::pair<tstring, HANDLE> pipeAndHandle = generateNewPipeName();
            mPipeName = pipeAndHandle.first + RCF_T("_0");
            mPipeNameLock = pipeAndHandle.second;
        }
        else
        {
            if (pipeName.at(0) == RCF_T('\\'))
            {
                mPipeName = pipeName;
            }
            else
            {
                mPipeName = RCF_T("\\\\.\\pipe\\") + pipeName;
            }
        }
    }
    TransportPair Win32NamedPipeTransportFactory::createNonListeningTransports()
    {
        return std::make_pair(
            ServerTransportPtr( new Win32NamedPipeServerTransport( RCF_T("")) ),
            ClientTransportAutoPtrPtr());

    }
    TransportPair Win32NamedPipeTransportFactory::createTransports()
    {
        typedef boost::shared_ptr<Win32NamedPipeServerTransport> Win32NamedPipeServerTransportPtr;
        Win32NamedPipeServerTransportPtr serverTransportPtr(
            new Win32NamedPipeServerTransport(RCF_T("")));

        tstring pipeName = serverTransportPtr->getPipeName();

        ClientTransportAutoPtrPtr clientTransportAutoPtrPtr(
            new ClientTransportAutoPtr(
                new Win32NamedPipeClientTransport(pipeName)));

        return std::make_pair(
            ServerTransportPtr(serverTransportPtr), 
            clientTransportAutoPtrPtr);

    }
    std::pair<tstring, HANDLE> generateNewPipeName()
    {
        tstring pipePrefix = RCF_T("\\\\.\\pipe\\RcfTestPipe_");
        static unsigned int i = 0;
        while (true)
        {

#ifdef UNICODE
            typedef std::wostringstream     tostringstream;
#else
            typedef std::ostringstream      tostringstream;
#endif
            tostringstream tos;
            tos 
                << pipePrefix
                << ++i;

            tstring candidateName = tos.str();

            HANDLE hPipe = CreateNamedPipe( 
                candidateName.c_str(),
                PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
                PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                1,          // MaxPipeInstances
                4096,       // OutBufferSize
                4096,       // InBufferSize
                0,          // DefaultTimeoutMs
                NULL);      // pSecurityASttributes

            DWORD dwErr = GetLastError();
            RCF_UNUSED_VARIABLE(dwErr);

            if (hPipe != INVALID_HANDLE_VALUE)
            {
                return std::make_pair(candidateName, hPipe);
            }

            CloseHandle(hPipe);
        }
    }
Example #5
0
int test_main(int, char**)
{

    RCF::RcfInitDeinit rcfinitDeinit;

#ifdef BOOST_WINDOWS
    RCF::tstring pipeName = RCF_T("TestPipe");
#else
    RCF::tstring pipeName = RCF_TEMP_DIR "TestPipe";
#endif

    RCF::NamedPipeEndpoint ep(pipeName);

    Echo echo;
    RCF::RcfServer server(ep);
    
    // 10 server threads
    server.setThreadPool( RCF::ThreadPoolPtr( new RCF::ThreadPool(10)) );

    server.bind( (I_Echo *) 0, echo);
    server.start();

    {
        // Make a single call, no waiting

        std::string s1 = "test";
        RCF::NamedPipeEndpoint ep(pipeName);
        RcfClient<I_Echo> client(ep);
        std::string s2 = client.echo(s1);
        RCF_CHECK_EQ(s1 , s2 );
    }

    {
        // Make 5 calls, in parallel, each one waiting 2 seconds

        boost::uint32_t t0 = RCF::getCurrentTimeMs();

        boost::uint32_t waitMs = 2000;
        ThreadGroup clients;
        for (std::size_t i=0; i<5; ++i)
        {
            clients.push_back( RCF::ThreadPtr( new RCF::Thread(
                boost::bind(clientTask, pipeName, waitMs))));
        }
        joinThreadGroup(clients);

        // Total time should be little more than 2 seconds
        boost::uint32_t t1 = RCF::getCurrentTimeMs();
        std::cout << "Total time: " << t1-t0 << " ms..." << std::endl;
        RCF_CHECK_LT(t1-t0 , 2*waitMs);
    }

#ifdef BOOST_WINDOWS

    {
        // Named pipe impersonation - use our own credentials

        RCF::tstring tUserName = RCF::getMyUserName();
        std::string userName(util::toString(tUserName));
        RCF::NamedPipeEndpoint ep(pipeName);
        RcfClient<I_Echo> client(ep);
        std::string s = client.whatsMyWin32UserName();
        RCF_CHECK_EQ(s , userName);
    }

    {
        // SSPI impersonation - use our own credentials

        server.stop();

        RCF::FilterServicePtr filterServicePtr(new RCF::FilterService());
        filterServicePtr->addFilterFactory( 
            RCF::FilterFactoryPtr( new RCF::NtlmFilterFactory()));
        server.addService(filterServicePtr);

        server.start();

        RCF::tstring tUserName = RCF::getMyUserName();
        std::string userName(util::toString(tUserName));
        RCF::NamedPipeEndpoint ep(pipeName);
        RcfClient<I_Echo> client(ep);

        RCF::FilterPtr ntlmFilterPtr( new RCF::NtlmFilter() );
        client.getClientStub().requestTransportFilters(ntlmFilterPtr);

        client.getClientStub().setRemoteCallTimeoutMs(1000*3600);
        std::string s = client.whatsMyWin32UserName();
        RCF_CHECK_EQ(s , userName);

        server.stop();
        server.removeService(filterServicePtr);
        server.start();
    }

#endif

    {
        // Test error reporting, by exceeding the max message length.
        int maxLengthOrig = server.getServerTransport().getMaxMessageLength();
        server.getServerTransport().setMaxMessageLength(10*1024);

        RCF::ByteBuffer byteBuffer(50*1024);
        for (std::size_t i=0; i<byteBuffer.getLength(); ++i)
        {
            byteBuffer.getPtr()[i] = i%256 ;
        }
        RCF::NamedPipeEndpoint ep(pipeName);
        RcfClient<I_Echo> client(ep);
        try
        {
            RCF_CHECK(byteBuffer == client.echo(byteBuffer) );
            RCF_CHECK_FAIL();
        }
        catch(RCF::Exception &e)
        {
            RCF_CHECK_OK();

#ifdef BOOST_WINDOWS
            RCF_CHECK_EQ(e.getErrorId() , RCF::RcfError_ClientWriteFail )(e.getError());
#else
            RCF_CHECK_EQ(e.getErrorId() , RCF::RcfError_ServerMessageLength )(e.getError());
#endif

        }

        server.getServerTransport().setMaxMessageLength(maxLengthOrig);

        // This time, turn up the message length and check that it goes through.
        server.getServerTransport().setMaxMessageLength(-1);
        client.getClientStub().getTransport().setMaxMessageLength(-1);
        RCF_CHECK(byteBuffer == client.echo(byteBuffer) );

    }

    /*
    {
        // Some performance testing. RCF Win32 named pipe server sessions have a 
        // reuse-instead-of-delete feature that needs some exercise.

        // Several threads, concurrently connecting and disconnecting, especially
        // disconnecting while a call is in progress.

        void clientTask2(const std::string & pipeName);

        std::vector<RCF::ThreadPtr> threads;
        for (std::size_t i=0; i<10; ++i)
        {
            threads.push_back( RCF::ThreadPtr( new RCF::Thread(
                boost::bind(clientTask2, pipeName))));
        }

        joinThreadGroup(threads);
    }
    */

    return 0;
}