From: Remi Gacogne Date: Tue, 27 Apr 2021 13:06:25 +0000 (+0200) Subject: dnsdist: Handle health checks over TCP and DNS over TLS X-Git-Tag: dnsdist-1.7.0-alpha1~45^2~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bcf26e85f4b156f4868c03b44e49e599eed2564e;p=thirdparty%2Fpdns.git dnsdist: Handle health checks over TCP and DNS over TLS --- diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index d0a0822da4..4e44913e19 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -441,13 +441,17 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } if(vars.count("checkFunction")) { - ret->checkFunction= boost::get(vars["checkFunction"]); + ret->checkFunction = boost::get(vars["checkFunction"]); } if(vars.count("checkTimeout")) { ret->checkTimeout = std::stoi(boost::get(vars["checkTimeout"])); } + if (vars.count("checkTCP")) { + ret->d_tcpCheck = boost::get(vars.at("checkTCP")); + } + if(vars.count("setCD")) { ret->setCD=boost::get(vars["setCD"]); } diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 16bde52b51..7accc1e680 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1712,7 +1712,7 @@ static void healthChecksThread() if (dss->availability == DownstreamState::Availability::Auto) { if (!queueHealthCheck(mplexer, dss)) { - updateHealthCheckResult(dss, false); + updateHealthCheckResult(dss, false, false); } } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index ba505177ef..95121e0167 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -188,7 +188,7 @@ struct DNSResponse : DNSQuestion class DNSAction { public: - enum class Action { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw }; + enum class Action : uint8_t { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw }; static std::string typeToString(const Action& action) { switch(action) { @@ -659,6 +659,7 @@ struct DownstreamState SharedLockGuarded> hashes; std::vector sockets; const std::string sourceItfName; + std::string d_tlsSubjectName; std::mutex connectLock; LockGuarded> mplexer{nullptr}; std::shared_ptr d_tlsCtx{nullptr}; @@ -670,7 +671,6 @@ struct DownstreamState checkfunc_t checkFunction; DNSName checkName{"a.root-servers.net."}; QType checkType{QType::A}; - std::string d_tlsSubjectName; uint16_t checkClass{QClass::IN}; std::atomic idOffset{0}; std::atomic hashesComputed{false}; @@ -723,7 +723,7 @@ struct DownstreamState uint8_t minRiseSuccesses{1}; StopWatch sw; set pools; - enum class Availability { Up, Down, Auto} availability{Availability::Auto}; + enum class Availability : uint8_t { Up, Down, Auto} availability{Availability::Auto}; bool mustResolve{false}; bool upStatus{false}; bool useECS{false}; @@ -735,6 +735,7 @@ struct DownstreamState bool tcpFastOpen{false}; bool ipBindAddrNoPort{true}; bool reconnectOnUp{false}; + bool d_tcpCheck{false}; bool isUp() const { @@ -804,6 +805,11 @@ struct DownstreamState void incCurrentConnectionsCount(); + bool doHealthcheckOverTCP() const + { + return d_tcpCheck || d_tlsCtx != nullptr; + } + private: std::string name; std::string nameWithAddr; @@ -992,7 +998,7 @@ extern std::set g_capabilitiesToRetain; static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value static const size_t s_maxPacketCacheEntrySize{4096}; // don't cache responses larger than this value -enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend }; +enum class ProcessQueryResult : uint8_t { Drop, SendAnswer, PassToBackend }; ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr& selectedBackend); DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data); diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.cc b/pdns/dnsdistdist/dnsdist-healthchecks.cc index 44629e7ba1..f1b1fd5925 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.cc +++ b/pdns/dnsdistdist/dnsdist-healthchecks.cc @@ -21,13 +21,44 @@ */ #include "dnsdist-healthchecks.hh" +#include "tcpiohandler-mplexer.hh" #include "dnswriter.hh" #include "dolog.hh" bool g_verboseHealthChecks{false}; -void updateHealthCheckResult(const std::shared_ptr& dss, bool newState) +struct HealthCheckData { + enum class TCPState : uint8_t { WritingQuery, ReadingResponseSize, ReadingResponse }; + + HealthCheckData(std::shared_ptr& mplexer, const std::shared_ptr& ds, DNSName&& checkName, uint16_t checkType, uint16_t checkClass, uint16_t queryID): d_ds(ds), d_mplexer(mplexer), d_udpSocket(-1), d_checkName(std::move(checkName)), d_checkType(checkType), d_checkClass(checkClass), d_queryID(queryID) + { + } + + const std::shared_ptr d_ds; + std::shared_ptr d_mplexer; + std::unique_ptr d_tcpHandler{nullptr}; + std::unique_ptr d_ioState{nullptr}; + PacketBuffer d_buffer; + Socket d_udpSocket; + DNSName d_checkName; + struct timeval d_ttd{0, 0}; + size_t d_bufferPos{0}; + uint16_t d_checkType; + uint16_t d_checkClass; + uint16_t d_queryID; + TCPState d_tcpState{TCPState::WritingQuery}; + bool d_initial{false}; +}; + +void updateHealthCheckResult(const std::shared_ptr& dss, bool initial, bool newState) +{ + if (initial) { + warnlog("Marking downstream %s as '%s'", dss->getNameWithAddr(), newState ? "up" : "down"); + dss->setUpStatus(newState); + return; + } + if (newState) { /* check succeeded */ dss->currentCheckFailures = 0; @@ -57,7 +88,8 @@ void updateHealthCheckResult(const std::shared_ptr& dss, bool n } } } - if(newState != dss->upStatus) { + + if (newState != dss->upStatus) { warnlog("Marking downstream %s as '%s'", dss->getNameWithAddr(), newState ? "up" : "down"); if (newState && (!dss->connected || dss->reconnectOnUp)) { @@ -81,27 +113,14 @@ static bool handleResponse(std::shared_ptr& data) { auto& ds = data->d_ds; try { - string reply; - ComboAddress from; - data->d_sock.recvFrom(reply, from); - - /* we are using a connected socket but hey.. */ - if (from != ds->remote) { + if (data->d_buffer.size() < sizeof(dnsheader)) { if (g_verboseHealthChecks) { - infolog("Invalid health check response received from %s, expecting one from %s", from.toStringWithPort(), ds->remote.toStringWithPort()); - } - return false; - } - - const dnsheader * responseHeader = reinterpret_cast(reply.c_str()); - - if (reply.size() < sizeof(*responseHeader)) { - if (g_verboseHealthChecks) { - infolog("Invalid health check response of size %d from backend %s, expecting at least %d", reply.size(), ds->getNameWithAddr(), sizeof(*responseHeader)); + infolog("Invalid health check response of size %d from backend %s, expecting at least %d", data->d_buffer.size(), ds->getNameWithAddr(), sizeof(dnsheader)); } return false; } + const dnsheader * responseHeader = reinterpret_cast(data->d_buffer.data()); if (responseHeader->id != data->d_queryID) { if (g_verboseHealthChecks) { infolog("Invalid health check response id %d from backend %s, expecting %d", data->d_queryID, ds->getNameWithAddr(), data->d_queryID); @@ -132,7 +151,7 @@ static bool handleResponse(std::shared_ptr& data) uint16_t receivedType; uint16_t receivedClass; - DNSName receivedName(reply.c_str(), reply.size(), sizeof(dnsheader), false, &receivedType, &receivedClass); + DNSName receivedName(reinterpret_cast(data->d_buffer.data()), data->d_buffer.size(), sizeof(dnsheader), false, &receivedType, &receivedClass); if (receivedName != data->d_checkName || receivedType != data->d_checkType || receivedClass != data->d_checkClass) { if (g_verboseHealthChecks) { @@ -159,20 +178,90 @@ static bool handleResponse(std::shared_ptr& data) return true; } -static void healthCheckCallback(int fd, FDMultiplexer::funcparam_t& param) +static void healthCheckUDPCallback(int fd, FDMultiplexer::funcparam_t& param) { auto data = boost::any_cast>(param); data->d_mplexer->removeReadFD(fd); - updateHealthCheckResult(data->d_ds, handleResponse(data)); + + ComboAddress from; + from.sin4.sin_family = data->d_ds->remote.sin4.sin_family; + auto fromlen = from.getSocklen(); + data->d_buffer.resize(512); + auto got = recvfrom(data->d_udpSocket.getHandle(), &data->d_buffer.at(0), data->d_buffer.size(), 0, reinterpret_cast(&from), &fromlen); + if (got < 0) { + if (g_verboseHealthChecks) { + infolog("Error receiving health check response from %s: %s", data->d_ds->remote.toStringWithPort(), stringerror()); + } + updateHealthCheckResult(data->d_ds, data->d_initial, false); + } + + /* we are using a connected socket but hey.. */ + if (from != data->d_ds->remote) { + if (g_verboseHealthChecks) { + infolog("Invalid health check response received from %s, expecting one from %s", from.toStringWithPort(), data->d_ds->remote.toStringWithPort()); + } + updateHealthCheckResult(data->d_ds, data->d_initial, false); + } + + updateHealthCheckResult(data->d_ds, data->d_initial, handleResponse(data)); } -static void initialHealthCheckCallback(int fd, FDMultiplexer::funcparam_t& param) +static void healthCheckTCPCallback(int fd, FDMultiplexer::funcparam_t& param) { auto data = boost::any_cast>(param); - data->d_mplexer->removeReadFD(fd); - bool up = handleResponse(data); - warnlog("Marking downstream %s as '%s'", data->d_ds->getNameWithAddr(), up ? "up" : "down"); - data->d_ds->setUpStatus(up); + + IOStateGuard ioGuard(data->d_ioState); + try { + auto ioState = IOState::Done; + + if (data->d_tcpState == HealthCheckData::TCPState::WritingQuery) { + ioState = data->d_tcpHandler->tryWrite(data->d_buffer, data->d_bufferPos, data->d_buffer.size()); + if (ioState == IOState::Done) { + data->d_bufferPos = 0; + data->d_buffer.resize(sizeof(uint16_t)); + data->d_tcpState = HealthCheckData::TCPState::ReadingResponseSize; + } + } + + if (data->d_tcpState == HealthCheckData::TCPState::ReadingResponseSize) { + ioState = data->d_tcpHandler->tryRead(data->d_buffer, data->d_bufferPos, data->d_buffer.size()); + if (ioState == IOState::Done) { + data->d_bufferPos = 0; + uint16_t responseSize; + memcpy(&responseSize, &data->d_buffer.at(0), sizeof(responseSize)); + data->d_buffer.resize(ntohs(responseSize)); + data->d_tcpState = HealthCheckData::TCPState::ReadingResponse; + } + } + + if (data->d_tcpState == HealthCheckData::TCPState::ReadingResponse) { + ioState = data->d_tcpHandler->tryRead(data->d_buffer, data->d_bufferPos, data->d_buffer.size()); + if (ioState == IOState::Done) { + updateHealthCheckResult(data->d_ds, data->d_initial, handleResponse(data)); + } + } + + if (ioState == IOState::Done) { + /* remove us from the mplexer, we are done */ + data->d_ioState->update(ioState, healthCheckTCPCallback, data); + } + else { + data->d_ioState->update(ioState, healthCheckTCPCallback, data, data->d_ttd); + } + + /* the state has been updated, we can release the guard */ + ioGuard.release(); + } + catch (const std::exception& e) { + if (g_verboseHealthChecks) { + infolog("Error checking the health of backend %s: %s", data->d_ds->getNameWithAddr(), e.what()); + } + } + catch (...) { + if (g_verboseHealthChecks) { + infolog("Unknown exception while checking the health of backend %s", data->d_ds->getNameWithAddr()); + } + } } bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared_ptr& ds, bool initialCheck) @@ -204,18 +293,29 @@ bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared PacketBuffer packet; GenericDNSPacketWriter dpw(packet, checkName, checkType, checkClass); - dnsheader * requestHeader = dpw.getHeader(); + dnsheader* requestHeader = dpw.getHeader(); *requestHeader = checkHeader; + /* we need to compute that _before_ adding the proxy protocol payload */ + uint16_t packetSize = packet.size(); + size_t proxyProtocolPayloadSize = 0; if (ds->useProxyProtocol) { auto payload = makeLocalProxyHeader(); + proxyProtocolPayloadSize = payload.size(); packet.insert(packet.begin(), payload.begin(), payload.end()); } - Socket sock(ds->remote.sin4.sin_family, SOCK_DGRAM); + Socket sock(ds->remote.sin4.sin_family, ds->doHealthcheckOverTCP() ? SOCK_STREAM : SOCK_DGRAM); + sock.setNonBlocking(); if (!IsAnyAddress(ds->sourceAddr)) { sock.setReuseAddr(); +#ifdef IP_BIND_ADDRESS_NO_PORT + if (ds->ipBindAddrNoPort) { + SSetsockopt(sock.getHandle(), SOL_IP, IP_BIND_ADDRESS_NO_PORT, 1); + } +#endif + if (!ds->sourceItfName.empty()) { #ifdef SO_BINDTODEVICE int res = setsockopt(sock.getHandle(), SOL_SOCKET, SO_BINDTODEVICE, ds->sourceItfName.c_str(), ds->sourceItfName.length()); @@ -226,29 +326,56 @@ bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared } sock.bind(ds->sourceAddr); } - sock.connect(ds->remote); - ssize_t sent = udpClientSendRequestToBackend(ds, sock.getHandle(), packet, true); - if (sent < 0) { - int ret = errno; - if (g_verboseHealthChecks) - infolog("Error while sending a health check query to backend %s: %d", ds->getNameWithAddr(), ret); - return false; + + auto data = std::make_shared(mplexer, ds, std::move(checkName), checkType, checkClass, queryID); + data->d_initial = initialCheck; + + gettimeofday(&data->d_ttd, nullptr); + data->d_ttd.tv_sec += ds->checkTimeout / 1000; /* ms to seconds */ + data->d_ttd.tv_usec += (ds->checkTimeout % 1000) * 1000; /* remaining ms to us */ + if (data->d_ttd.tv_usec > 1000000) { + ++data->d_ttd.tv_sec; + data->d_ttd.tv_usec -= 1000000; + } + + if (!ds->doHealthcheckOverTCP()) { + sock.connect(ds->remote); + data->d_udpSocket = std::move(sock); + ssize_t sent = udpClientSendRequestToBackend(ds, data->d_udpSocket.getHandle(), packet, true); + if (sent < 0) { + int ret = errno; + if (g_verboseHealthChecks) { + infolog("Error while sending a health check query to backend %s: %d", ds->getNameWithAddr(), ret); + } + return false; + } + + mplexer->addReadFD(data->d_udpSocket.getHandle(), &healthCheckUDPCallback, data, &data->d_ttd); } + else { + data->d_tcpHandler = std::make_unique(ds->d_tlsSubjectName, sock.releaseHandle(), timeval{ds->checkTimeout,0}, ds->d_tlsCtx, time(nullptr)); + data->d_ioState = std::make_unique(*mplexer, data->d_tcpHandler->getDescriptor()); + + data->d_tcpHandler->tryConnect(ds->tcpFastOpen, ds->remote); + + const uint8_t sizeBytes[] = { static_cast(packetSize / 256), static_cast(packetSize % 256) }; + packet.insert(packet.begin() + proxyProtocolPayloadSize, sizeBytes, sizeBytes + 2); + data->d_buffer = std::move(packet); - auto data = std::make_shared(mplexer, ds, std::move(sock), std::move(checkName), checkType, checkClass, queryID); - struct timeval ttd; - gettimeofday(&ttd, nullptr); - ttd.tv_sec += ds->checkTimeout / 1000; /* ms to seconds */ - ttd.tv_usec += (ds->checkTimeout % 1000) * 1000; /* remaining ms to us */ - if (ttd.tv_usec > 1000000) { - ++ttd.tv_sec; - ttd.tv_usec -= 1000000; + auto ioState = data->d_tcpHandler->tryWrite(data->d_buffer, data->d_bufferPos, data->d_buffer.size()); + if (ioState == IOState::Done) { + data->d_bufferPos = 0; + data->d_buffer.resize(sizeof(uint16_t)); + data->d_tcpState = HealthCheckData::TCPState::ReadingResponseSize; + ioState = IOState::NeedRead; + } + + data->d_ioState->update(ioState, healthCheckTCPCallback, data, data->d_ttd); } - mplexer->addReadFD(data->d_sock.getHandle(), initialCheck ? &initialHealthCheckCallback : &healthCheckCallback, data, &ttd); return true; } - catch(const std::exception& e) + catch (const std::exception& e) { if (g_verboseHealthChecks) { infolog("Error checking the health of backend %s: %s", ds->getNameWithAddr(), e.what()); @@ -266,7 +393,7 @@ bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared void handleQueuedHealthChecks(std::shared_ptr& mplexer, bool initial) { - while (mplexer->getWatchedFDCount(false) > 0) { + while (mplexer->getWatchedFDCount(false) > 0 || mplexer->getWatchedFDCount(true) > 0) { struct timeval now; int ret = mplexer->run(&now, 100); if (ret == -1) { @@ -277,17 +404,52 @@ void handleQueuedHealthChecks(std::shared_ptr& mplexer, bool init } auto timeouts = mplexer->getTimeouts(now); for (const auto& timeout : timeouts) { - mplexer->removeReadFD(timeout.first); auto data = boost::any_cast>(timeout.second); - if (g_verboseHealthChecks) { - infolog("Timeout while waiting for the health check response from backend %s", data->d_ds->getNameWithAddr()); + try { + if (data->d_ioState) { + data->d_ioState.reset(); + } + else { + mplexer->removeReadFD(timeout.first); + } + if (g_verboseHealthChecks) { + infolog("Timeout while waiting for the health check response from backend %s", data->d_ds->getNameWithAddr()); + } + + updateHealthCheckResult(data->d_ds, initial, false); } - if (initial) { - warnlog("Marking downstream %s as 'down'", data->d_ds->getNameWithAddr()); - data->d_ds->setUpStatus(false); + catch (const std::exception& e) { + if (g_verboseHealthChecks) { + infolog("Error while delaing with a timeout for the health check response from backend %s: %s", data->d_ds->getNameWithAddr(), e.what()); + } + } + catch (...) { + if (g_verboseHealthChecks) { + infolog("Error while delaing with a timeout for the health check response from backend %s", data->d_ds->getNameWithAddr()); + } } - else { - updateHealthCheckResult(data->d_ds, false); + } + + timeouts = mplexer->getTimeouts(now, true); + for (const auto& timeout : timeouts) { + auto data = boost::any_cast>(timeout.second); + try { + data->d_ioState.reset(); + if (g_verboseHealthChecks) { + infolog("Timeout while waiting for the health check response from backend %s", data->d_ds->getNameWithAddr()); + } + + updateHealthCheckResult(data->d_ds, initial, false); + } + catch (const std::exception& e) { + if (g_verboseHealthChecks) { + infolog("Error while delaing with a timeout for the health check response from backend %s: %s", data->d_ds->getNameWithAddr(), e.what()); + } + } + catch (...) { + if (g_verboseHealthChecks) { + infolog("Error while delaing with a timeout for the health check response from backend %s", data->d_ds->getNameWithAddr()); + } } } } diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.hh b/pdns/dnsdistdist/dnsdist-healthchecks.hh index 99d512b8c3..08ac59948d 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.hh +++ b/pdns/dnsdistdist/dnsdist-healthchecks.hh @@ -25,24 +25,9 @@ #include "mplexer.hh" #include "sstuff.hh" -struct HealthCheckData -{ - HealthCheckData(std::shared_ptr& mplexer, const std::shared_ptr& ds, Socket&& sock, DNSName&& checkName, uint16_t checkType, uint16_t checkClass, uint16_t queryID): d_mplexer(mplexer), d_ds(ds), d_sock(std::move(sock)), d_checkName(std::move(checkName)), d_checkType(checkType), d_checkClass(checkClass), d_queryID(queryID) - { - } - - std::shared_ptr d_mplexer; - const std::shared_ptr d_ds; - Socket d_sock; - DNSName d_checkName; - uint16_t d_checkType; - uint16_t d_checkClass; - uint16_t d_queryID; -}; - extern bool g_verboseHealthChecks; -void updateHealthCheckResult(const std::shared_ptr& dss, bool newState); +void updateHealthCheckResult(const std::shared_ptr& dss, bool initial, bool newState); bool queueHealthCheck(std::shared_ptr& mplexer, const std::shared_ptr& ds, bool initial=false); void handleQueuedHealthChecks(std::shared_ptr& mplexer, bool initial=false); diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc index e7f67a056f..6b11c68094 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc @@ -167,7 +167,7 @@ void TCPConnectionToBackend::handleIO(std::shared_ptr& c try { if (conn->reconnect()) { - conn->d_ioState = make_unique(conn->d_mplexer, conn->d_handler->getDescriptor()); + conn->d_ioState = make_unique(*conn->d_mplexer, conn->d_handler->getDescriptor()); /* we need to resend the queries that were in flight, if any */ for (auto& pending : conn->d_pendingResponses) { @@ -271,7 +271,7 @@ void TCPConnectionToBackend::queueQuery(std::shared_ptr& sender, { if (!d_sender) { d_sender = sender; - d_ioState = make_unique(d_mplexer, d_handler->getDescriptor()); + d_ioState = make_unique(*d_mplexer, d_handler->getDescriptor()); } else if (d_sender != sender) { throw std::runtime_error("Assigning a query from a different client to an existing backend connection with pending queries"); diff --git a/pdns/dnsdistdist/dnsdist-tcp-upstream.hh b/pdns/dnsdistdist/dnsdist-tcp-upstream.hh index 7db91dca5e..e628e7c908 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-upstream.hh +++ b/pdns/dnsdistdist/dnsdist-tcp-upstream.hh @@ -18,7 +18,7 @@ public: class IncomingTCPConnectionState : public TCPQuerySender, public std::enable_shared_from_this { public: - IncomingTCPConnectionState(ConnectionInfo&& ci, TCPClientThreadData& threadData, const struct timeval& now): d_buffer(s_maxPacketCacheEntrySize), d_threadData(threadData), d_ci(std::move(ci)), d_handler(d_ci.fd, timeval{g_tcpRecvTimeout,0}, d_ci.cs->tlsFrontend ? d_ci.cs->tlsFrontend->getContext() : nullptr, now.tv_sec), d_ioState(make_unique(threadData.mplexer, d_ci.fd)), d_connectionStartTime(now) + IncomingTCPConnectionState(ConnectionInfo&& ci, TCPClientThreadData& threadData, const struct timeval& now): d_buffer(s_maxPacketCacheEntrySize), d_threadData(threadData), d_ci(std::move(ci)), d_handler(d_ci.fd, timeval{g_tcpRecvTimeout,0}, d_ci.cs->tlsFrontend ? d_ci.cs->tlsFrontend->getContext() : nullptr, now.tv_sec), d_ioState(make_unique(*threadData.mplexer, d_ci.fd)), d_connectionStartTime(now) { d_origDest.reset(); d_origDest.sin4.sin_family = d_ci.remote.sin4.sin_family; diff --git a/pdns/dnsdistdist/tcpiohandler-mplexer.hh b/pdns/dnsdistdist/tcpiohandler-mplexer.hh index c7d0c26e09..7aae6e3df6 100644 --- a/pdns/dnsdistdist/tcpiohandler-mplexer.hh +++ b/pdns/dnsdistdist/tcpiohandler-mplexer.hh @@ -14,11 +14,11 @@ class IOStateHandler { public: - IOStateHandler(std::unique_ptr& mplexer, const int fd): d_mplexer(mplexer), d_fd(fd), d_currentState(IOState::Done) + IOStateHandler(FDMultiplexer& mplexer, const int fd): d_mplexer(mplexer), d_fd(fd), d_currentState(IOState::Done) { } - IOStateHandler(std::unique_ptr& mplexer): d_mplexer(mplexer), d_fd(-1), d_currentState(IOState::Done) + IOStateHandler(FDMultiplexer& mplexer): d_mplexer(mplexer), d_fd(-1), d_currentState(IOState::Done) { } @@ -53,12 +53,12 @@ public: DEBUGLOG("in "<<__PRETTY_FUNCTION__<<" for fd "<removeReadFD(d_fd); + d_mplexer.removeReadFD(d_fd); d_currentState = IOState::Done; } else if (d_currentState == IOState::NeedWrite && iostate == IOState::Done) { DEBUGLOG(__PRETTY_FUNCTION__<<": remove write FD "<removeWriteFD(d_fd); + d_mplexer.removeWriteFD(d_fd); d_currentState = IOState::Done; } @@ -66,17 +66,17 @@ public: if (d_currentState == IOState::NeedRead) { if (ttd) { /* let's update the TTD ! */ - d_mplexer->setReadTTD(d_fd, *ttd, /* we pass 0 here because we already have a TTD */0); + d_mplexer.setReadTTD(d_fd, *ttd, /* we pass 0 here because we already have a TTD */0); } return; } if (d_currentState == IOState::NeedWrite) { - d_mplexer->alterFDToRead(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); + d_mplexer.alterFDToRead(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); DEBUGLOG(__PRETTY_FUNCTION__<<": alter from write to read FD "<addReadFD(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); + d_mplexer.addReadFD(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); DEBUGLOG(__PRETTY_FUNCTION__<<": add read FD "<setWriteTTD(d_fd, *ttd, /* we pass 0 here because we already have a TTD */0); + d_mplexer.setWriteTTD(d_fd, *ttd, /* we pass 0 here because we already have a TTD */0); } return; } if (d_currentState == IOState::NeedRead) { - d_mplexer->alterFDToWrite(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); + d_mplexer.alterFDToWrite(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); DEBUGLOG(__PRETTY_FUNCTION__<<": alter from read to write FD "<addWriteFD(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); + d_mplexer.addWriteFD(d_fd, callback, callbackData, ttd ? &*ttd : nullptr); DEBUGLOG(__PRETTY_FUNCTION__<<": add write FD "<& d_mplexer; + FDMultiplexer& d_mplexer; int d_fd; IOState d_currentState; }; diff --git a/pdns/libssl.hh b/pdns/libssl.hh index 514b2ad7df..b090afa7b1 100644 --- a/pdns/libssl.hh +++ b/pdns/libssl.hh @@ -11,7 +11,7 @@ #include "circular_buffer.hh" #include "lock.hh" -enum class LibsslTLSVersion { Unknown, TLS10, TLS11, TLS12, TLS13 }; +enum class LibsslTLSVersion : uint8_t { Unknown, TLS10, TLS11, TLS12, TLS13 }; class TLSConfig { diff --git a/pdns/sstuff.hh b/pdns/sstuff.hh index 5787f41fb7..f84d50c364 100644 --- a/pdns/sstuff.hh +++ b/pdns/sstuff.hh @@ -63,6 +63,14 @@ public: rhs.d_socket = -1; } + Socket& operator=(Socket&& rhs) + { + d_socket = rhs.d_socket; + rhs.d_socket = -1; + d_buffer = std::move(rhs.d_buffer); + return *this; + } + ~Socket() { try { diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index 6b8a4c1fba..c73d4d0999 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -190,7 +190,7 @@ protected: class TCPIOHandler { public: - enum class Type { Client, Server }; + enum class Type : uint8_t { Client, Server }; TCPIOHandler(const std::string& host, int socket, const struct timeval& timeout, std::shared_ptr ctx, time_t now): d_socket(socket) {