From: Remi Gacogne Date: Mon, 15 Feb 2021 14:47:56 +0000 (+0100) Subject: dnsdist: Stricter IO checks in the TCP unit tests and more OOOR tests X-Git-Tag: dnsdist-1.6.0-alpha2~11^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bb039d3f00bbb98761bc6a1dff5f1be1ecb9163;p=thirdparty%2Fpdns.git dnsdist: Stricter IO checks in the TCP unit tests and more OOOR tests --- diff --git a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc index 77bad0e33e..e43e00585d 100644 --- a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc +++ b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_SUITE(test_dnsdisttcp_cc) struct ExpectedStep { public: - enum class ExpectedRequest { handshake, connect, read, write, close }; + enum class ExpectedRequest { handshakeClient, readFromClient, writeToClient, closeClient, connectToBackend, readFromBackend, writeToBackend, closeBackend }; ExpectedStep(ExpectedRequest r, IOState n, size_t b = 0, std::function fn = nullptr): cb(fn), request(r), nextState(n), bytes(b) { @@ -112,13 +112,6 @@ public: }; static std::deque s_steps; -static ExpectedStep getStep() -{ - BOOST_REQUIRE(!s_steps.empty()); - auto res = s_steps.front(); - s_steps.pop_front(); - return res; -} static PacketBuffer s_readBuffer; static PacketBuffer s_writeBuffer; @@ -129,7 +122,7 @@ std::ostream& operator<<(std::ostream &os, const ExpectedStep::ExpectedRequest d std::ostream& operator<<(std::ostream &os, const ExpectedStep::ExpectedRequest d) { - static const std::vector requests = { "handshake", "connect", "read", "write", "close" }; + static const std::vector requests = { "handshake with client", "read from client", "write to client", "close connection to client", "connect to the backend", "read from the backend", "write to the backend", "close connection to backend" }; os<(d)); return os; } @@ -146,7 +139,7 @@ public: IOState tryHandshake() override { auto step = getStep(); - BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::handshake); + BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::handshakeClient); return step.nextState; } @@ -158,7 +151,7 @@ public: } auto step = getStep(); - BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::write); + BOOST_REQUIRE_EQUAL(step.request, !d_client ? ExpectedStep::ExpectedRequest::writeToClient : ExpectedStep::ExpectedRequest::writeToBackend); if (step.bytes == 0) { if (step.nextState == IOState::NeedWrite) { @@ -188,7 +181,7 @@ public: } auto step = getStep(); - BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::read); + BOOST_REQUIRE_EQUAL(step.request, !d_client ? ExpectedStep::ExpectedRequest::readFromClient : ExpectedStep::ExpectedRequest::readFromBackend); if (step.bytes == 0) { if (step.nextState == IOState::NeedRead) { @@ -203,6 +196,7 @@ public: if (step.bytes < toRead) { toRead = step.bytes; } + BOOST_REQUIRE_GE(buffer.size(), toRead); BOOST_REQUIRE_GE(externalBuffer.size(), toRead); @@ -216,11 +210,7 @@ public: IOState tryConnect(bool fastOpen, const ComboAddress& remote) override { auto step = getStep(); - BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::connect); - - if (step.cb) { - step.cb(d_descriptor, step); - } + BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::connectToBackend); return step.nextState; } @@ -228,7 +218,7 @@ public: void close() override { auto step = getStep(); - BOOST_REQUIRE_EQUAL(step.request, ExpectedStep::ExpectedRequest::close); + BOOST_REQUIRE_EQUAL(step.request, !d_client ? ExpectedStep::ExpectedRequest::closeClient : ExpectedStep::ExpectedRequest::closeBackend); } bool hasBufferedData() const override @@ -270,6 +260,19 @@ public: return 0; } private: + ExpectedStep getStep() const + { + BOOST_REQUIRE(!s_steps.empty()); + auto step = s_steps.front(); + s_steps.pop_front(); + + if (step.cb) { + step.cb(d_descriptor, step); + } + + return step; + } + const int d_descriptor; bool d_client{false}; }; @@ -318,7 +321,9 @@ public: gettimeofday(tv, nullptr); // MANDATORY - for (const auto fd : ready) { + /* 'ready' might be altered by a callback while we are iterating */ + const auto readyFDs = ready; + for (const auto fd : readyFDs) { { const auto& it = d_readCallbacks.find(fd); @@ -408,10 +413,10 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { return ProcessQueryResult::Drop; @@ -428,12 +433,12 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 65537 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, 65537 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { // Would be nicer to actually turn it into a response @@ -455,17 +460,17 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::NeedWrite }, - { ExpectedStep::ExpectedRequest::handshake, IOState::NeedRead }, - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, 1 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 1 }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, query.size() - 3 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 1 }, - { ExpectedStep::ExpectedRequest::write, IOState::NeedWrite, query.size() - 1}, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 1 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::NeedWrite }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::NeedRead }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, 1 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, query.size() - 3 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::NeedWrite, query.size() - 1}, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { // Would be nicer to actually turn it into a response @@ -490,10 +495,10 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { throw std::runtime_error("Something unexpected happened"); @@ -512,16 +517,16 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) size_t count = 10000; s_readBuffer.clear(); s_writeBuffer.clear(); - s_steps = { { ExpectedStep::ExpectedRequest::handshake, IOState::Done } }; + s_steps = { { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done } }; for (size_t idx = 0; idx < count; idx++) { s_readBuffer.insert(s_readBuffer.end(), query.begin(), query.end()); - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() + 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() + 2 }); }; - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::close, IOState::Done }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::closeClient, IOState::Done }); size_t counter = 0; s_processQuery = [&counter](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -541,10 +546,10 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, query.size() - 2 - 2 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, query.size() - 2 - 2 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { /* should not be reached */ @@ -578,11 +583,11 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_SelfAnswered) s_readBuffer = query; s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::NeedWrite, 1 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::NeedWrite, 1 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { return ProcessQueryResult::SendAnswer; @@ -647,17 +652,17 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered) s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, s_proxyProtocolMinimumHeaderSize }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, proxyPayload.size() - s_proxyProtocolMinimumHeaderSize }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 65537 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 65537 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, s_proxyProtocolMinimumHeaderSize }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, proxyPayload.size() - s_proxyProtocolMinimumHeaderSize }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, 65537 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, 65537 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { return ProcessQueryResult::SendAnswer; @@ -684,9 +689,9 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered) s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, s_proxyProtocolMinimumHeaderSize }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, s_proxyProtocolMinimumHeaderSize }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { return ProcessQueryResult::SendAnswer; @@ -711,10 +716,10 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered) s_writeBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, s_proxyProtocolMinimumHeaderSize }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, proxyPayload.size() - s_proxyProtocolMinimumHeaderSize - 1}, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, s_proxyProtocolMinimumHeaderSize }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, proxyPayload.size() - s_proxyProtocolMinimumHeaderSize - 1}, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; s_processQuery = [](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { return ProcessQueryResult::SendAnswer; @@ -762,8 +767,6 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) const uint8_t sizeBytes[] = { static_cast(querySize / 256), static_cast(querySize % 256) }; query.insert(query.begin(), sizeBytes, sizeBytes + 2); - g_verbose = true; - g_proxyProtocolACL.clear(); { @@ -776,20 +779,20 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* closing a connection to the backend */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; s_processQuery = [tlsCtx](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -821,18 +824,18 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* closing a connection to the backend */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; s_processQuery = [tlsCtx](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -863,18 +866,18 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* closing a connection to the backend */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; s_processQuery = [tlsCtx](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -909,18 +912,18 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* closing a connection to the backend */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; s_processQuery = [tlsCtx](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -955,42 +958,42 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* connect to backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::NeedWrite, 0, [&threadData](int desc, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::NeedWrite, 0, [&threadData](int desc, const ExpectedStep& step) { /* set the outgoing descriptor (backend connection) as ready */ dynamic_cast(threadData.mplexer.get())->setReady(desc); } }, /* send query */ - { ExpectedStep::ExpectedRequest::write, IOState::NeedWrite, 1 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() - 1 }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::NeedWrite, 1 }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() - 1 }, /* read response */ - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, 1 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 1 }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, query.size() - 3 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::NeedRead, 1 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::NeedRead, query.size() - 3 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 1 }, /* write response to client */ - { ExpectedStep::ExpectedRequest::write, IOState::NeedWrite, query.size() - 1 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 1 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::NeedWrite, query.size() - 1 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, 1 }, /* read second query */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* write second query to backend */ - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, /* read second response */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* write second response */ - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() }, /* read from client */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, /* close connection to client */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* close connection to the backend, eventually */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false); @@ -1027,37 +1030,37 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend (5 tries by default) */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { throw NetworkError("Connection refused by the backend"); } }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { throw NetworkError("Connection refused by the backend"); } }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { throw NetworkError("Connection refused by the backend"); } }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { throw NetworkError("Connection refused by the backend"); } }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done, 0, [](int descriptor, const ExpectedStep& step) { throw NetworkError("Connection refused by the backend"); } }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false); backend->d_tlsCtx = tlsCtx; @@ -1089,15 +1092,15 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend (retrying 5 times) */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::NeedWrite }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::NeedWrite }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1139,16 +1142,16 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::NeedRead, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::NeedRead, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1190,27 +1193,27 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend, connection closed on first write (5 attempts) */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1242,35 +1245,35 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend, connection closed on first write (5 attempts) */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, /* reading the response */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* send the response to the client */ - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() }, /* client closes the connection */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* then eventually the backend one */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1303,32 +1306,32 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend, connection closed on read, 5 attempts, last one succeeds */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1360,39 +1363,39 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendWriteBuffer.clear(); s_steps = { - { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend, connection closed on read, 5 attempts, last one succeeds */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, /* this time it works */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, /* sending the response to the client */ - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() }, /* client closes the connection */ - { ExpectedStep::ExpectedRequest::read, IOState::Done, 0 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* the eventually the backend one */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1438,32 +1441,32 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnection_BackendNoOOOR) s_backendReadBuffer.insert(s_backendReadBuffer.end(), query.begin(), query.end()); } - s_steps = { { ExpectedStep::ExpectedRequest::handshake, IOState::Done }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, + s_steps = { { ExpectedStep::ExpectedRequest::handshakeClient, IOState::Done }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }, /* opening a connection to the backend */ - { ExpectedStep::ExpectedRequest::connect, IOState::Done }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() + 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }, - { ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }, - { ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() + 2 } + { ExpectedStep::ExpectedRequest::connectToBackend, IOState::Done }, + { ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() + 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }, + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() + 2 } }; for (size_t idx = 0; idx < count - 1; idx++) { /* read a new query */ - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, query.size() - 2 }); /* pass it to the backend */ - s_steps.push_back({ ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() + 2 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, 2 }); - s_steps.push_back({ ExpectedStep::ExpectedRequest::read, IOState::Done, query.size() - 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::writeToBackend, IOState::Done, query.size() + 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, query.size() - 2 }); /* send the response */ - s_steps.push_back({ ExpectedStep::ExpectedRequest::write, IOState::Done, query.size() + 2 }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, query.size() + 2 }); }; /* close the connection with the client */ - s_steps.push_back({ ExpectedStep::ExpectedRequest::close, IOState::Done }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::closeClient, IOState::Done }); /* eventually with the backend as well */ - s_steps.push_back({ ExpectedStep::ExpectedRequest::close, IOState::Done }); + s_steps.push_back({ ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }); auto backend = std::make_shared(ComboAddress("192.0.2.42:53"), ComboAddress("0.0.0.0:0"), 0, std::string(), 1, false);; backend->d_tlsCtx = tlsCtx; @@ -1504,6 +1507,8 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR) backend->d_tlsCtx = tlsCtx; /* enable out-of-order on the backend side as well */ backend->d_maxInFlightQueriesPerConn = 65536; + /* shorter than the client one */ + backend->tcpRecvTimeout = 1; TCPClientThreadData threadData; threadData.mplexer = std::make_unique(); @@ -1511,41 +1516,151 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR) struct timeval now; gettimeofday(&now, nullptr); - PacketBuffer query; - GenericDNSPacketWriter pwQ(query, DNSName("powerdns.com."), QType::A, QClass::IN, 0); - pwQ.getHeader()->rd = 1; + std::vector queries(5); + std::vector responses(5); + + size_t counter = 0; + size_t totalQueriesSize = 0; + for (auto& query : queries) { + GenericDNSPacketWriter pwQ(query, DNSName("powerdns" + std::to_string(counter) + ".com."), QType::A, QClass::IN, 0); + pwQ.getHeader()->rd = 1; + pwQ.getHeader()->id = counter; + uint16_t querySize = static_cast(query.size()); + const uint8_t sizeBytes[] = { static_cast(querySize / 256), static_cast(querySize % 256) }; + query.insert(query.begin(), sizeBytes, sizeBytes + 2); + totalQueriesSize += query.size(); + ++counter; + } - uint16_t querySize = static_cast(query.size()); - const uint8_t sizeBytes[] = { static_cast(querySize / 256), static_cast(querySize % 256) }; - query.insert(query.begin(), sizeBytes, sizeBytes + 2); + counter = 0; + size_t totalResponsesSize = 0; + for (auto& response : responses) { + DNSName name("powerdns" + std::to_string(counter) + ".com."); + GenericDNSPacketWriter pwR(response, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.getHeader()->rd = 1; + pwR.getHeader()->ra = 1; + pwR.getHeader()->id = counter; + pwR.startRecord(name, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfr32BitInt(0x01020304); + pwR.commit(); + + uint16_t responseSize = static_cast(response.size()); + const uint8_t sizeBytes[] = { static_cast(responseSize / 256), static_cast(responseSize % 256) }; + response.insert(response.begin(), sizeBytes, sizeBytes + 2); + totalResponsesSize += response.size(); + ++counter; + } g_verbose = true; g_proxyProtocolACL.clear(); { - cerr<<"=> 5 OOOR queries to the backend, backend responds out of order"< 5 OOOR queries to the backend, backend responds in reverse order"<(threadData.mplexer.get())->setReady(desc); + } }, + + /* no more queries from the client */ + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, 0 }, + + /* reading a response from the backend */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(4).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(4).size() }, + /* sending it to the client */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(4).size() }, + + /* reading a response from the backend */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(3).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(3).size() }, + /* sending it to the client */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(3).size() }, + + /* reading a response from the backend */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(2).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(2).size() }, + /* sending it to the client */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(2).size() }, + + /* reading a response from the backend */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(1).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(1).size() }, + /* sending it to the client */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(1).size() }, + + /* reading a response from the backend */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(0).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(0).size() }, + /* sending it to the client, the client descriptor becomes ready */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(0).size(), [&threadData](int desc, const ExpectedStep& step) { + /* set the incoming descriptor (client connection) as ready */ + dynamic_cast(threadData.mplexer.get())->setReady(desc); + } }, + + /* client is closing the connection */ + { ExpectedStep::ExpectedRequest::readFromClient, IOState::Done, 0 }, /* closing client connection */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, /* closing a connection to the backend */ - { ExpectedStep::ExpectedRequest::close, IOState::Done }, + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, }; s_processQuery = [backend](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { @@ -1558,19 +1673,173 @@ BOOST_AUTO_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR) auto state = std::make_shared(ConnectionInfo(&localCS), threadData, now); IncomingTCPConnectionState::handleIO(state, now); - BOOST_CHECK_EQUAL(s_writeBuffer.size(), query.size()); - BOOST_CHECK(s_writeBuffer == query); - BOOST_CHECK_EQUAL(s_backendWriteBuffer.size(), query.size()); - BOOST_CHECK(s_backendWriteBuffer == query); + while (threadData.mplexer->getWatchedFDCount(false) != 0 || threadData.mplexer->getWatchedFDCount(true) != 0) { + threadData.mplexer->run(&now); + } + + BOOST_CHECK_EQUAL(s_writeBuffer.size(), totalResponsesSize); + BOOST_CHECK(s_writeBuffer == expectedWriteBuffer); + BOOST_CHECK_EQUAL(s_backendWriteBuffer.size(), totalQueriesSize); + BOOST_CHECK(s_backendWriteBuffer == expectedBackendWriteBuffer); + + /* we need to clear them now, otherwise we end up with dangling pointers to the steps via the TLS context, etc */ + IncomingTCPConnectionState::clearAllDownstreamConnections(); + } + + { + cerr<<"=> 3 queries sent to the backend, 1 self-answered, 1 new query sent to the backend which responds to the first query right away, then to the last one, then the connection to the backend times out"<(threadData.mplexer.get())->setReady(desc); + } }, + /* sending it to the client (1) */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(0).size(), [&threadData](int desc, const ExpectedStep& step) { + /* set the client descriptor as NOT ready */ + dynamic_cast(threadData.mplexer.get())->setNotReady(desc); + } }, + /* reading from the client (not ready) */ + { ExpectedStep::ExpectedRequest::readFromClient, IOState::NeedRead, 0 }, + /* reading a response from the backend (5) */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(4).size() - 2 }, + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::Done, responses.at(4).size() }, + /* sending it to the client (5) */ + { ExpectedStep::ExpectedRequest::writeToClient, IOState::Done, responses.at(4).size() }, + + /* try to read from the backend but there is no answer ready yet */ + { ExpectedStep::ExpectedRequest::readFromBackend, IOState::NeedRead, 0, [&threadData, &timeout](int desc, const ExpectedStep& step) { + /* set the backend descriptor as NOT ready */ + dynamic_cast(threadData.mplexer.get())->setNotReady(desc); + timeout = true; + } }, + + /* A timeout occurs */ + + /* closing client connection */ + { ExpectedStep::ExpectedRequest::closeClient, IOState::Done }, + + /* closing a connection to the backend */ + { ExpectedStep::ExpectedRequest::closeBackend, IOState::Done }, + }; + + s_processQuery = [backend,&responses](DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend) -> ProcessQueryResult { + static size_t count = 0; + if (count++ == 3) { + /* self answered */ + dq.getMutableData() = responses.at(3); + /* remove the length */ + dq.getMutableData().erase(dq.getMutableData().begin(), dq.getMutableData().begin() + 2); + + return ProcessQueryResult::SendAnswer; + } + selectedBackend = backend; + return ProcessQueryResult::PassToBackend; + }; + s_processResponse = [](PacketBuffer& response, LocalStateHolder >& localRespRulactions, DNSResponse& dr, bool muted) -> bool { + return true; + }; + + auto state = std::make_shared(ConnectionInfo(&localCS), threadData, now); + IncomingTCPConnectionState::handleIO(state, now); + + while (!timeout && (threadData.mplexer->getWatchedFDCount(false) != 0 || threadData.mplexer->getWatchedFDCount(true) != 0)) { + threadData.mplexer->run(&now); + } + + struct timeval later = now; + later.tv_sec += backend->tcpRecvTimeout + 1; + auto expiredConns = threadData.mplexer->getTimeouts(later, false); + BOOST_CHECK_EQUAL(expiredConns.size(), 1U); + for (const auto& cbData : expiredConns) { + if (cbData.second.type() == typeid(std::shared_ptr)) { + auto cbState = boost::any_cast>(cbData.second); + cbState->handleTimeout(later, false); + } + } + + BOOST_CHECK_EQUAL(s_writeBuffer.size(), expectedWriteBuffer.size()); + BOOST_CHECK(s_writeBuffer == expectedWriteBuffer); + BOOST_CHECK_EQUAL(s_backendWriteBuffer.size(), expectedBackendWriteBuffer.size()); + BOOST_CHECK(s_backendWriteBuffer == expectedBackendWriteBuffer); + /* we need to clear them now, otherwise we end up with dangling pointers to the steps via the TLS context, etc */ IncomingTCPConnectionState::clearAllDownstreamConnections(); + + // restore the client timeout + g_tcpRecvTimeout = 2; } } #warning TODO: -// proxy protocol to backend? - // OOOR: OOOR enabled but packet cache hit // OOOR: OOOR enabled but backend answers very fast // OOOR: OOOR, get 10 queries before the backend can answer. backend doesn't support OOOR, we should get 10 connections. Check that we do reuse them on two subsequent queries