return true;
}
- const ClientState& getClientState() override
+ const ClientState* getClientState() override
{
- return d_cs;
+ return &d_cs;
}
void handleResponse(const struct timeval& now, TCPResponse&& response) override
for(;;) {
sleep(interval);
- auto mplexer = std::shared_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent());
+ auto mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent());
auto states = g_dstates.getLocal(); // this points to the actual shared_ptrs!
for(auto& dss : *states) {
if (++dss->lastCheck < dss->checkInterval) {
}
}
- handleQueuedHealthChecks(mplexer);
+ handleQueuedHealthChecks(*mplexer);
}
}
checkFileDescriptorsLimits(udpBindsCount, tcpBindsCount);
- auto mplexer = std::shared_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent());
+ auto mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent());
for(auto& dss : g_dstates.getCopy()) { // it is a copy, but the internal shared_ptrs are the real deal
if (dss->availability == DownstreamState::Availability::Auto) {
if (!queueHealthCheck(mplexer, dss, true)) {
}
}
}
- handleQueuedHealthChecks(mplexer, true);
+ handleQueuedHealthChecks(*mplexer, true);
/* we need to create the TCP worker threads before the
acceptor ones, otherwise we might crash when processing
#include "tcpiohandler-mplexer.hh"
#include "dnswriter.hh"
#include "dolog.hh"
+#include "dnsdist-tcp.hh"
+#include "dnsdist-nghttp2.hh"
bool g_verboseHealthChecks{false};
{
enum class TCPState : uint8_t { WritingQuery, ReadingResponseSize, ReadingResponse };
- HealthCheckData(std::shared_ptr<FDMultiplexer>& mplexer, const std::shared_ptr<DownstreamState>& 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)
+ HealthCheckData(FDMultiplexer& mplexer, const std::shared_ptr<DownstreamState>& 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<DownstreamState> d_ds;
- std::shared_ptr<FDMultiplexer> d_mplexer;
+ FDMultiplexer& d_mplexer;
std::unique_ptr<TCPIOHandler> d_tcpHandler{nullptr};
std::unique_ptr<IOStateHandler> d_ioState{nullptr};
PacketBuffer d_buffer;
return true;
}
+class HealthCheckQuerySender : public TCPQuerySender
+{
+public:
+ HealthCheckQuerySender(std::shared_ptr<HealthCheckData>& data): d_data(data)
+ {
+ }
+
+ ~HealthCheckQuerySender()
+ {
+ }
+
+ bool active() const override
+ {
+ return true;
+ }
+
+ const ClientState* getClientState() override
+ {
+ return nullptr;
+ }
+
+ void handleResponse(const struct timeval& now, TCPResponse&& response) override
+ {
+ d_data->d_buffer = std::move(response.d_buffer);
+ updateHealthCheckResult(d_data->d_ds, d_data->d_initial, ::handleResponse(d_data));
+ }
+
+ void handleXFRResponse(const struct timeval& now, TCPResponse&& response) override
+ {
+ throw std::runtime_error("Unexpected XFR reponse to a health check query");
+ }
+
+ void notifyIOError(IDState&& query, const struct timeval& now) override
+ {
+ updateHealthCheckResult(d_data->d_ds, d_data->d_initial, false);
+ }
+
+private:
+ std::shared_ptr<HealthCheckData> d_data;
+};
+
static void healthCheckUDPCallback(int fd, FDMultiplexer::funcparam_t& param)
{
auto data = boost::any_cast<std::shared_ptr<HealthCheckData>>(param);
- data->d_mplexer->removeReadFD(fd);
+ data->d_mplexer.removeReadFD(fd);
ComboAddress from;
from.sin4.sin_family = data->d_ds->remote.sin4.sin_family;
}
}
-bool queueHealthCheck(std::shared_ptr<FDMultiplexer>& mplexer, const std::shared_ptr<DownstreamState>& ds, bool initialCheck)
+bool queueHealthCheck(std::unique_ptr<FDMultiplexer>& mplexer, const std::shared_ptr<DownstreamState>& ds, bool initialCheck)
{
try
{
sock.bind(ds->sourceAddr);
}
- auto data = std::make_shared<HealthCheckData>(mplexer, ds, std::move(checkName), checkType, checkClass, queryID);
+ auto data = std::make_shared<HealthCheckData>(*mplexer, ds, std::move(checkName), checkType, checkClass, queryID);
data->d_initial = initialCheck;
gettimeofday(&data->d_ttd, nullptr);
mplexer->addReadFD(data->d_udpSocket.getHandle(), &healthCheckUDPCallback, data, &data->d_ttd);
}
+ else if (ds->isDoH()) {
+ InternalQuery query(std::move(packet), IDState());
+ auto sender = std::shared_ptr<TCPQuerySender>(new HealthCheckQuerySender(data));
+ if (!sendH2Query(ds, mplexer, sender, std::move(query))) {
+ updateHealthCheckResult(data->d_ds, data->d_initial, false);
+ }
+ }
else {
data->d_tcpHandler = std::make_unique<TCPIOHandler>(ds->d_tlsSubjectName, sock.releaseHandle(), timeval{ds->checkTimeout,0}, ds->d_tlsCtx, time(nullptr));
data->d_ioState = std::make_unique<IOStateHandler>(*mplexer, data->d_tcpHandler->getDescriptor());
}
}
-void handleQueuedHealthChecks(std::shared_ptr<FDMultiplexer>& mplexer, bool initial)
+void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial)
{
- while (mplexer->getWatchedFDCount(false) > 0 || mplexer->getWatchedFDCount(true) > 0) {
+ while (mplexer.getWatchedFDCount(false) > 0 || mplexer.getWatchedFDCount(true) > 0) {
struct timeval now;
- int ret = mplexer->run(&now, 100);
+ int ret = mplexer.run(&now, 100);
if (ret == -1) {
if (g_verboseHealthChecks) {
infolog("Error while waiting for the health check response from backends: %d", ret);
}
break;
}
- auto timeouts = mplexer->getTimeouts(now);
+ auto timeouts = mplexer.getTimeouts(now);
for (const auto& timeout : timeouts) {
auto data = boost::any_cast<std::shared_ptr<HealthCheckData>>(timeout.second);
try {
data->d_ioState.reset();
}
else {
- mplexer->removeReadFD(timeout.first);
+ mplexer.removeReadFD(timeout.first);
}
if (g_verboseHealthChecks) {
infolog("Timeout while waiting for the health check response from backend %s", data->d_ds->getNameWithAddr());
}
}
- timeouts = mplexer->getTimeouts(now, true);
+ timeouts = mplexer.getTimeouts(now, true);
for (const auto& timeout : timeouts) {
auto data = boost::any_cast<std::shared_ptr<HealthCheckData>>(timeout.second);
try {