summaryrefslogtreecommitdiffstats
path: root/doq-common.cc
diff options
context:
space:
mode:
Diffstat (limited to 'doq-common.cc')
-rw-r--r--doq-common.cc85
1 files changed, 76 insertions, 9 deletions
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<PacketBuffer> 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<const struct sockaddr*>(&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<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+ buffer.resize(static_cast<size_t>(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<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+
+ buffer.resize(static_cast<size_t>(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<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+ buffer.resize(static_cast<size_t>(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<char*>(&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<size_t>(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