class H3Connection
{
public:
- H3Connection(const ComboAddress& peer, QuicheConfig config, QuicheConnection&& conn) :
- d_peer(peer), d_conn(std::move(conn)), d_config(std::move(config))
+ H3Connection(const ComboAddress& peer, const ComboAddress& localAddr, QuicheConfig config, QuicheConnection&& conn) :
+ d_peer(peer), d_localAddr(localAddr), d_conn(std::move(conn)), d_config(std::move(config))
{
}
H3Connection(const H3Connection&) = delete;
~H3Connection() = default;
ComboAddress d_peer;
+ ComboAddress d_localAddr;
QuicheConnection d_conn;
QuicheConfig d_config;
QuicheHTTP3Connection d_http3{nullptr, quiche_h3_conn_free};
}
}
-static std::optional<std::reference_wrapper<H3Connection>> createConnection(DOH3ServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& local, const ComboAddress& peer)
+static std::optional<std::reference_wrapper<H3Connection>> createConnection(DOH3ServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& localAddr, const ComboAddress& peer)
{
auto quicheConfig = std::atomic_load_explicit(&config.config, std::memory_order_acquire);
auto quicheConn = QuicheConnection(quiche_accept(serverSideID.data(), serverSideID.size(),
originalDestinationID.data(), originalDestinationID.size(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- reinterpret_cast<const struct sockaddr*>(&local),
- local.getSocklen(),
+ reinterpret_cast<const struct sockaddr*>(&localAddr),
+ localAddr.getSocklen(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const struct sockaddr*>(&peer),
peer.getSocklen(),
quiche_conn_set_keylog_path(quicheConn.get(), config.df->d_quicheParams.d_keyLogFile.c_str());
}
- auto conn = H3Connection(peer, std::move(quicheConfig), std::move(quicheConn));
+ auto conn = H3Connection(peer, localAddr, std::move(quicheConfig), std::move(quicheConn));
auto pair = config.d_connections.emplace(serverSideID, std::move(conn));
return pair.first->second;
}
return;
}
DEBUGLOG("Dispatching GET query");
- doh3_dispatch_query(*(frontend.d_server_config), std::move(*payload), clientState.local, client, serverConnID, streamID);
+ doh3_dispatch_query(*(frontend.d_server_config), std::move(*payload), conn.d_localAddr, client, serverConnID, streamID);
conn.d_streamBuffers.erase(streamID);
conn.d_headersBuffers.erase(streamID);
return;
}
DEBUGLOG("Dispatching POST query");
- doh3_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), clientState.local, client, serverConnID, streamID);
+ doh3_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), conn.d_localAddr, client, serverConnID, streamID);
conn.d_headersBuffers.erase(streamID);
conn.d_streamBuffers.erase(streamID);
}
PacketBuffer tokenBuf;
while (true) {
ComboAddress client;
+ ComboAddress localAddr;
+ client.sin4.sin_family = clientState.local.sin4.sin_family;
+ localAddr.sin4.sin_family = clientState.local.sin4.sin_family;
buffer.resize(4096);
- if (!sock.recvFromAsync(buffer, client) || buffer.empty()) {
+ if (!dnsdist::doq::recvAsync(sock, buffer, client, localAddr)) {
return;
}
+ if (localAddr.sin4.sin_family == 0) {
+ localAddr = clientState.local;
+ }
+ else {
+ /* we don't get the port, only the address */
+ localAddr.sin4.sin_port = clientState.local.sin4.sin_port;
+ }
+
DEBUGLOG("Received DoH3 datagram of size " << buffer.size() << " from " << client.toStringWithPort());
uint32_t version{0};
if (!quiche_version_is_supported(version)) {
DEBUGLOG("Unsupported version");
++frontend.d_doh3UnsupportedVersionErrors;
- handleVersionNegociation(sock, clientConnID, serverConnID, client, buffer);
+ handleVersionNegociation(sock, clientConnID, serverConnID, client, localAddr, buffer);
continue;
}
if (token_len == 0) {
/* stateless retry */
DEBUGLOG("No token received");
- handleStatelessRetry(sock, clientConnID, serverConnID, client, version, buffer);
+ handleStatelessRetry(sock, clientConnID, serverConnID, client, localAddr, version, buffer);
continue;
}
}
DEBUGLOG("Creating a new connection");
- conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, clientState.local, client);
+ conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, localAddr, client);
if (!conn) {
continue;
}
reinterpret_cast<struct sockaddr*>(&client),
client.getSocklen(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- reinterpret_cast<struct sockaddr*>(&clientState.local),
- clientState.local.getSocklen(),
+ reinterpret_cast<struct sockaddr*>(&localAddr),
+ localAddr.getSocklen(),
};
auto done = quiche_conn_recv(conn->get().d_conn.get(), buffer.data(), buffer.size(), &recv_info);
processH3Events(clientState, frontend, conn->get(), client, serverConnID, buffer);
- flushEgress(sock, conn->get().d_conn, client, buffer);
+ flushEgress(sock, conn->get().d_conn, client, localAddr, buffer);
}
else {
DEBUGLOG("Connection not established");
for (auto conn = frontend->d_server_config->d_connections.begin(); conn != frontend->d_server_config->d_connections.end();) {
quiche_conn_on_timeout(conn->second.d_conn.get());
- flushEgress(sock, conn->second.d_conn, conn->second.d_peer, buffer);
+ flushEgress(sock, conn->second.d_conn, conn->second.d_peer, conn->second.d_localAddr, buffer);
if (quiche_conn_is_closed(conn->second.d_conn.get())) {
#ifdef DEBUGLOG_ENABLED