From 037d41a914237592dc3e82751b8be3ff06407af0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 26 Jun 2024 08:28:37 +0200 Subject: Merging upstream version 1.9.5. Signed-off-by: Daniel Baumann --- doq-common.cc | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 9 deletions(-) (limited to 'doq-common.cc') diff --git a/doq-common.cc b/doq-common.cc index e92ccff..bb79ddc 100644 --- a/doq-common.cc +++ b/doq-common.cc @@ -126,7 +126,28 @@ std::optional validateToken(const PacketBuffer& token, const Combo } } -void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, uint32_t version, PacketBuffer& buffer) +static void sendFromTo(Socket& sock, const ComboAddress& peer, const ComboAddress& local, PacketBuffer& buffer) +{ + const int flags = 0; + if (local.sin4.sin_family == 0) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + auto ret = sendto(sock.getHandle(), buffer.data(), buffer.size(), flags, reinterpret_cast(&peer), peer.getSocklen()); + if (ret < 0) { + auto error = errno; + vinfolog("Error while sending QUIC datagram of size %d to %s: %s", buffer.size(), peer.toStringWithPort(), stringerror(error)); + } + return; + } + + try { + sendMsgWithOptions(sock.getHandle(), buffer.data(), buffer.size(), &peer, &local, 0, 0); + } + catch (const std::exception& exp) { + vinfolog("Error while sending QUIC datagram of size %d from %s to %s: %s", buffer.size(), local.toStringWithPort(), peer.toStringWithPort(), exp.what()); + } +} + +void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, uint32_t version, PacketBuffer& buffer) { auto newServerConnID = getCID(); if (!newServerConnID) { @@ -148,11 +169,11 @@ void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const return; } - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - sock.sendTo(reinterpret_cast(buffer.data()), static_cast(written), peer); + buffer.resize(static_cast(written)); + sendFromTo(sock, peer, localAddr, buffer); } -void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, PacketBuffer& buffer) +void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer) { buffer.resize(MAX_DATAGRAM_SIZE); @@ -164,11 +185,12 @@ void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, co DEBUGLOG("failed to create vneg packet " << written); return; } - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - sock.sendTo(reinterpret_cast(buffer.data()), static_cast(written), peer); + + buffer.resize(static_cast(written)); + sendFromTo(sock, peer, localAddr, buffer); } -void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, PacketBuffer& buffer) +void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer) { buffer.resize(MAX_DATAGRAM_SIZE); quiche_send_info send_info; @@ -183,8 +205,8 @@ void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, return; } // FIXME pacing (as send_info.at should tell us when to send the packet) ? - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - sock.sendTo(reinterpret_cast(buffer.data()), static_cast(written), peer); + buffer.resize(static_cast(written)); + sendFromTo(sock, peer, localAddr, buffer); } } @@ -258,6 +280,51 @@ void configureQuiche(QuicheConfig& config, const QuicheParams& params, bool isHT } } +bool recvAsync(Socket& socket, PacketBuffer& buffer, ComboAddress& clientAddr, ComboAddress& localAddr) +{ + msghdr msgh{}; + iovec iov{}; + /* used by HarvestDestinationAddress */ + cmsgbuf_aligned cbuf; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + fillMSGHdr(&msgh, &iov, &cbuf, sizeof(cbuf), reinterpret_cast(&buffer.at(0)), buffer.size(), &clientAddr); + + ssize_t got = recvmsg(socket.getHandle(), &msgh, 0); + if (got < 0) { + int error = errno; + if (error != EAGAIN) { + throw NetworkError("Error in recvmsg: " + stringerror(error)); + } + return false; + } + + if ((msgh.msg_flags & MSG_TRUNC) != 0) { + return false; + } + + buffer.resize(static_cast(got)); + + if (HarvestDestinationAddress(&msgh, &localAddr)) { + /* so it turns out that sometimes the kernel lies to us: + the address is set to 0.0.0.0:0 which makes our sendfromto() use + the wrong address. In that case it's better to let the kernel + do the work by itself and use sendto() instead. + This is indicated by setting the family to 0 which is acted upon + in sendUDPResponse() and DelayedPacket::(). + */ + const ComboAddress bogusV4("0.0.0.0:0"); + const ComboAddress bogusV6("[::]:0"); + if ((localAddr.sin4.sin_family == AF_INET && localAddr == bogusV4) || (localAddr.sin4.sin_family == AF_INET6 && localAddr == bogusV6)) { + localAddr.sin4.sin_family = 0; + } + } + else { + localAddr.sin4.sin_family = 0; + } + + return !buffer.empty(); +} + }; #endif -- cgit v1.2.3