| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- //
- // TCPServerTest.cpp
- //
- // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // SPDX-License-Identifier: BSL-1.0
- //
- #include "TCPServerTest.h"
- #include "CppUnit/TestCaller.h"
- #include "CppUnit/TestSuite.h"
- #include "Poco/Net/TCPServer.h"
- #include "Poco/Net/TCPServerConnection.h"
- #include "Poco/Net/TCPServerConnectionFactory.h"
- #include "Poco/Net/TCPServerParams.h"
- #include "Poco/Net/SecureStreamSocket.h"
- #include "Poco/Net/SecureServerSocket.h"
- #include "Poco/Net/Context.h"
- #include "Poco/Net/RejectCertificateHandler.h"
- #include "Poco/Net/AcceptCertificateHandler.h"
- #include "Poco/Net/Session.h"
- #include "Poco/Net/SSLManager.h"
- #include "Poco/Util/Application.h"
- #include "Poco/Util/AbstractConfiguration.h"
- #include "Poco/Thread.h"
- #include "Poco/Mutex.h"
- #include <iostream>
- using Poco::Net::TCPServer;
- using Poco::Net::TCPServerConnection;
- using Poco::Net::TCPServerConnectionFactory;
- using Poco::Net::TCPServerConnectionFactoryImpl;
- using Poco::Net::TCPServerParams;
- using Poco::Net::StreamSocket;
- using Poco::Net::SecureStreamSocket;
- using Poco::Net::SecureServerSocket;
- using Poco::Net::SocketAddress;
- using Poco::Net::Context;
- using Poco::Net::Session;
- using Poco::Net::SSLManager;
- using Poco::Thread;
- using Poco::Util::Application;
- namespace
- {
- static Poco::FastMutex cerrMutex;
- class EchoConnection: public TCPServerConnection
- {
- public:
- EchoConnection(const StreamSocket& s): TCPServerConnection(s)
- {
- }
- void run()
- {
- StreamSocket& ss = socket();
- try
- {
- char buffer[256];
- int n = ss.receiveBytes(buffer, sizeof(buffer));
- while (n > 0)
- {
- ss.sendBytes(buffer, n);
- n = ss.receiveBytes(buffer, sizeof(buffer));
- }
- }
- catch (const Poco::Exception& exc)
- {
- Poco::FastMutex::ScopedLock l(cerrMutex);
- std::cerr << "EchoConnection: " << exc.displayText() << std::endl;
- }
- }
- };
- class NullConnection: public TCPServerConnection
- {
- public:
- NullConnection(const StreamSocket& s): TCPServerConnection(s)
- {
- }
- void run()
- {
- SecureStreamSocket ss = socket();
- try
- {
- ss.completeHandshake();
- }
- catch (...)
- {
- }
- }
- };
- }
- TCPServerTest::TCPServerTest(const std::string& name): CppUnit::TestCase(name)
- {
- }
- TCPServerTest::~TCPServerTest()
- {
- }
- void TCPServerTest::testOneConnection()
- {
- SecureServerSocket svs(0);
- TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs);
- srv.start();
- assertTrue (srv.currentConnections() == 0);
- assertTrue (srv.currentThreads() == 0);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 0);
- SocketAddress sa("127.0.0.1", svs.address().port());
- SecureStreamSocket ss1(sa);
- std::string data("hello, world");
- ss1.sendBytes(data.data(), (int) data.size());
- char buffer[256];
- int n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.currentThreads() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 1);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- }
- void TCPServerTest::testTwoConnections()
- {
- SecureServerSocket svs(0);
- TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs);
- srv.start();
- assertTrue (srv.currentConnections() == 0);
- assertTrue (srv.currentThreads() == 0);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 0);
- SocketAddress sa("127.0.0.1", svs.address().port());
- SecureStreamSocket ss1(sa);
- SecureStreamSocket ss2(sa);
- std::string data("hello, world");
- ss1.sendBytes(data.data(), (int) data.size());
- ss2.sendBytes(data.data(), (int) data.size());
- char buffer[256];
- int n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- n = ss2.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 2);
- assertTrue (srv.currentThreads() == 2);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 2);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.currentThreads() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 2);
- ss2.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- }
- void TCPServerTest::testMultiConnections()
- {
- SecureServerSocket svs(0);
- TCPServerParams* pParams = new TCPServerParams;
- pParams->setMaxThreads(4);
- pParams->setMaxQueued(4);
- pParams->setThreadIdleTime(100);
- TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs, pParams);
- srv.start();
- assertTrue (srv.currentConnections() == 0);
- assertTrue (srv.currentThreads() == 0);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 0);
- SocketAddress sa("127.0.0.1", svs.address().port());
- SecureStreamSocket ss1(sa);
- SecureStreamSocket ss2(sa);
- SecureStreamSocket ss3(sa);
- SecureStreamSocket ss4(sa);
- std::string data("hello, world");
- ss1.sendBytes(data.data(), (int) data.size());
- ss2.sendBytes(data.data(), (int) data.size());
- ss3.sendBytes(data.data(), (int) data.size());
- ss4.sendBytes(data.data(), (int) data.size());
- char buffer[256];
- int n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- n = ss2.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- n = ss3.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- n = ss4.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 4);
- assertTrue (srv.currentThreads() == 4);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 4);
- SecureStreamSocket ss5;
- ss5.setLazyHandshake();
- ss5.connect(sa);
- Thread::sleep(200);
- assertTrue (srv.queuedConnections() == 1);
- SecureStreamSocket ss6;
- ss6.setLazyHandshake();
- ss6.connect(sa);
- Thread::sleep(200);
- assertTrue (srv.queuedConnections() == 2);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 4);
- assertTrue (srv.currentThreads() == 4);
- assertTrue (srv.queuedConnections() == 1);
- assertTrue (srv.totalConnections() == 5);
- ss2.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 4);
- assertTrue (srv.currentThreads() == 4);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 6);
- ss3.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 3);
- assertTrue (srv.currentThreads() == 3);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 6);
- ss4.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 2);
- assertTrue (srv.currentThreads() == 2);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 6);
- ss5.close();
- ss6.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- }
- void TCPServerTest::testReuseSocket()
- {
- SecureServerSocket svs(0);
- TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs);
- srv.start();
- assertTrue (srv.currentConnections() == 0);
- assertTrue (srv.currentThreads() == 0);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 0);
- SocketAddress sa("127.0.0.1", svs.address().port());
- SecureStreamSocket ss1(sa);
- std::string data("hello, world");
- ss1.sendBytes(data.data(), (int) data.size());
- char buffer[256];
- int n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.currentThreads() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 1);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- ss1.connect(sa);
- ss1.sendBytes(data.data(), (int) data.size());
- n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 2);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- }
- void TCPServerTest::testReuseSession()
- {
- // ensure OpenSSL machinery is fully setup
- Context::Ptr pDefaultServerContext = SSLManager::instance().defaultServerContext();
- Context::Ptr pDefaultClientContext = SSLManager::instance().defaultClientContext();
- Context::Ptr pServerContext = new Context(
- Context::SERVER_USE,
- Application::instance().config().getString("openSSL.server.privateKeyFile"),
- Application::instance().config().getString("openSSL.server.privateKeyFile"),
- Application::instance().config().getString("openSSL.server.caConfig"),
- Context::VERIFY_NONE,
- 9,
- true,
- "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
- pServerContext->disableProtocols(Context::PROTO_TLSV1_3);
- pServerContext->enableSessionCache(true, "TestSuite");
- pServerContext->setSessionTimeout(10);
- pServerContext->setSessionCacheSize(1000);
- pServerContext->disableStatelessSessionResumption();
- SecureServerSocket svs(0, 64, pServerContext);
- TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>(), svs);
- srv.start();
- assertTrue (srv.currentConnections() == 0);
- assertTrue (srv.currentThreads() == 0);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 0);
- Context::Ptr pClientContext = new Context(
- Context::CLIENT_USE,
- Application::instance().config().getString("openSSL.client.privateKeyFile"),
- Application::instance().config().getString("openSSL.client.privateKeyFile"),
- Application::instance().config().getString("openSSL.client.caConfig"),
- Context::VERIFY_RELAXED,
- 9,
- true,
- "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
- pClientContext->enableSessionCache(true);
- SocketAddress sa("127.0.0.1", svs.address().port());
- SecureStreamSocket ss1(sa, pClientContext);
- assertTrue (!ss1.sessionWasReused());
- std::string data("hello, world");
- ss1.sendBytes(data.data(), (int) data.size());
- char buffer[256];
- int n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.currentThreads() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 1);
- Session::Ptr pSession = ss1.currentSession();
- if (!pSession || !pSession->isResumable())
- {
- std::cerr << "WARNING: Server did not return a session or session is not resumable. Aborting test." << std::endl;
- return;
- }
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- ss1.useSession(pSession);
- ss1.connect(sa);
- ss1.sendBytes(data.data(), (int) data.size());
- n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (ss1.sessionWasReused());
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 2);
- pSession = ss1.currentSession();
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- Thread::sleep(15000); // wait for session to expire
- pServerContext->flushSessionCache();
- ss1.useSession(pSession);
- ss1.connect(sa);
- ss1.sendBytes(data.data(), (int) data.size());
- n = ss1.receiveBytes(buffer, sizeof(buffer));
- assertTrue (!ss1.sessionWasReused());
- assertTrue (n > 0);
- assertTrue (std::string(buffer, n) == data);
- assertTrue (srv.currentConnections() == 1);
- assertTrue (srv.queuedConnections() == 0);
- assertTrue (srv.totalConnections() == 3);
- ss1.close();
- Thread::sleep(300);
- assertTrue (srv.currentConnections() == 0);
- }
- void TCPServerTest::testContextInvalidCertificateHandler()
- {
- SecureServerSocket svs(0);
- TCPServer srv(new TCPServerConnectionFactoryImpl<NullConnection>(), svs);
- srv.start();
- Context::Ptr pClientContext = new Context(
- Context::CLIENT_USE,
- "",
- "",
- "",
- Context::VERIFY_RELAXED,
- 9,
- true,
- "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
- pClientContext->setInvalidCertificateHandler(new Poco::Net::RejectCertificateHandler(false));
- SocketAddress sa("127.0.0.1", svs.address().port());
- try
- {
- SecureStreamSocket ss1(sa, pClientContext);
- fail("must throw with RejectCertificateHandler");
- }
- catch (...)
- {
- }
- pClientContext->setInvalidCertificateHandler(new Poco::Net::AcceptCertificateHandler(false));
- try
- {
- SecureStreamSocket ss1(sa, pClientContext);
- }
- catch (...)
- {
- fail("must not throw with AcceptCertificateHandler");
- }
- srv.stop();
- }
- void TCPServerTest::setUp()
- {
- }
- void TCPServerTest::tearDown()
- {
- }
- CppUnit::Test* TCPServerTest::suite()
- {
- CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TCPServerTest");
- CppUnit_addTest(pSuite, TCPServerTest, testOneConnection);
- CppUnit_addTest(pSuite, TCPServerTest, testTwoConnections);
- CppUnit_addTest(pSuite, TCPServerTest, testMultiConnections);
- CppUnit_addTest(pSuite, TCPServerTest, testReuseSocket);
- CppUnit_addTest(pSuite, TCPServerTest, testReuseSession);
- CppUnit_addTest(pSuite, TCPServerTest, testContextInvalidCertificateHandler);
- return pSuite;
- }
|