}
}
-std::shared_ptr<TCPConnectionToBackend> IncomingTCPConnectionState::getDownstreamConnection(std::shared_ptr<DownstreamState>& ds, const struct timeval& now)
+std::shared_ptr<TCPConnectionToBackend> IncomingTCPConnectionState::getDownstreamConnection(std::shared_ptr<DownstreamState>& ds, const std::unique_ptr<std::vector<ProxyProtocolValue>>& tlvs, const struct timeval& now)
{
std::shared_ptr<TCPConnectionToBackend> downstream{nullptr};
- if (!ds->useProxyProtocol || !d_proxyProtocolPayloadHasTLV) {
- downstream = getActiveDownstreamConnection(ds);
- }
+ downstream = getActiveDownstreamConnection(ds, tlvs);
if (!downstream) {
/* we don't have a connection to this backend active yet, let's ask one (it might not be a fresh one, though) */
d_state = State::readingQuerySize;
}
-std::shared_ptr<TCPConnectionToBackend> IncomingTCPConnectionState::getActiveDownstreamConnection(const std::shared_ptr<DownstreamState>& ds)
+std::shared_ptr<TCPConnectionToBackend> IncomingTCPConnectionState::getActiveDownstreamConnection(const std::shared_ptr<DownstreamState>& ds, const std::unique_ptr<std::vector<ProxyProtocolValue>>& tlvs)
{
auto it = d_activeConnectionsToBackend.find(ds);
if (it == d_activeConnectionsToBackend.end()) {
}
for (auto& conn : it->second) {
- if (conn->canAcceptNewQueries()) {
+ if (conn->canAcceptNewQueries() && conn->matchesTLVs(tlvs)) {
DEBUGLOG("Got one active connection accepting more for "<<ds->getName());
+ conn->setReused();
return conn;
}
DEBUGLOG("not accepting more for "<<ds->getName());
dq.dnsCryptQuery = std::move(dnsCryptQuery);
dq.sni = state->d_handler.getServerNameIndication();
if (state->d_proxyProtocolValues) {
- dq.proxyProtocolValues = std::move(state->d_proxyProtocolValues);
+ /* we need to copy them, because the next queries received on that connection will
+ need to get the _unaltered_ values */
+ dq.proxyProtocolValues = make_unique<std::vector<ProxyProtocolValue>>(*state->d_proxyProtocolValues);
}
state->d_isXFR = (dq.qtype == QType::AXFR || dq.qtype == QType::IXFR);
especially alignment issues */
state->d_buffer.insert(state->d_buffer.begin(), sizeBytes, sizeBytes + 2);
+ auto downstreamConnection = state->getDownstreamConnection(ds, dq.proxyProtocolValues, now);
+ downstreamConnection->assignToClientConnection(state, state->d_isXFR);
+
bool proxyProtocolPayloadAdded = false;
std::string proxyProtocolPayload;
}
proxyProtocolPayload = getProxyProtocolPayload(dq);
-
- if (state->d_proxyProtocolPayloadHasTLV) {
+ if (state->d_proxyProtocolPayloadHasTLV && downstreamConnection->isFresh()) {
/* we will not be able to reuse an existing connection anyway so let's add the payload right now */
addProxyProtocol(state->d_buffer, proxyProtocolPayload);
proxyProtocolPayloadAdded = true;
}
}
- auto downstreamConnection = state->getDownstreamConnection(ds, now);
- downstreamConnection->assignToClientConnection(state, state->d_isXFR);
+ if (dq.proxyProtocolValues) {
+ downstreamConnection->setProxyProtocolValuesSent(std::move(dq.proxyProtocolValues));
+ }
if (proxyProtocolPayloadAdded) {
downstreamConnection->setProxyProtocolPayloadAdded(true);
{
d_proxyProtocolPayloadAdded = added;
}
+
+void TCPConnectionToBackend::setProxyProtocolValuesSent(std::unique_ptr<std::vector<ProxyProtocolValue>>&& proxyProtocolValuesSent)
+{
+ /* if we already have some values, we have already verified they match */
+ if (!d_proxyProtocolValuesSent) {
+ d_proxyProtocolValuesSent = std::move(proxyProtocolValuesSent);
+ }
+}
+
+bool TCPConnectionToBackend::matchesTLVs(const std::unique_ptr<std::vector<ProxyProtocolValue>>& tlvs) const
+{
+ if (tlvs == nullptr && d_proxyProtocolValuesSent == nullptr) {
+ return true;
+ }
+ if (tlvs == nullptr && d_proxyProtocolValuesSent != nullptr) {
+ return false;
+ }
+ if (tlvs != nullptr && d_proxyProtocolValuesSent == nullptr) {
+ return false;
+ }
+ return *tlvs == *d_proxyProtocolValuesSent;
+}
return true;
}
+ bool matchesTLVs(const std::unique_ptr<std::vector<ProxyProtocolValue>>& tlvs) const;
+
bool matches(const std::shared_ptr<DownstreamState>& ds) const
{
if (!ds || !d_ds) {
void setProxyProtocolPayload(std::string&& payload);
void setProxyProtocolPayloadAdded(bool added);
+ void setProxyProtocolValuesSent(std::unique_ptr<std::vector<ProxyProtocolValue>>&& proxyProtocolValuesSent);
private:
/* waitingForResponseFromBackend is a state where we have not yet started reading the size,
PacketBuffer d_responseBuffer;
std::deque<TCPQuery> d_pendingQueries;
std::unordered_map<uint16_t, TCPQuery> d_pendingResponses;
+ std::unique_ptr<std::vector<ProxyProtocolValue>> d_proxyProtocolValuesSent{nullptr};
std::unique_ptr<Socket> d_socket{nullptr};
std::unique_ptr<IOStateHandler> d_ioState{nullptr};
std::shared_ptr<DownstreamState> d_ds{nullptr};