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