]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add support for TCP Fast Open on macOS 16071/head
authorKarel Bilek <kb@karelbilek.com>
Wed, 3 Sep 2025 07:54:45 +0000 (09:54 +0200)
committerKarel Bilek <kb@karelbilek.com>
Tue, 7 Oct 2025 09:35:38 +0000 (11:35 +0200)
This uses Apple's connectx() API instead of UNIX connect() API.

Signed-off-by: Karel Bilek <kb@karelbilek.com>
pdns/dnsdistdist/dnsdist-backend.cc
pdns/dnsdistdist/dnsdist-console.cc
pdns/dnsdistdist/dnsdist-lua.cc
pdns/dnsdistdist/test-dnsdistnghttp2_common.hh
pdns/dnsdistdist/test-dnsdisttcp_cc.cc
pdns/iputils.cc
pdns/iputils.hh
pdns/sstuff.hh
pdns/tcpiohandler.hh

index fa44589457e144ca507874f637a87ec1823e9843..2bf6ff55e9f3dc5750b55a7121b0581cb55504fc 100644 (file)
@@ -141,7 +141,7 @@ bool DownstreamState::reconnect(bool initialAttempt)
 
     try {
       setDscp(fd, d_config.remote.sin4.sin_family, d_config.dscp);
-      SConnect(fd, d_config.remote);
+      SConnect(fd, d_config.tcpFastOpen, d_config.remote);
       if (sockets.size() > 1) {
         (*mplexer.lock())->addReadFD(fd, [](int, boost::any) {});
       }
index db0e9735fb8c0ea8800a8a4857a07c8c28e0af2d..9a6f36127e7faa0544d589df01ffebf2a0ea3e45 100644 (file)
@@ -245,7 +245,7 @@ void doClient(const std::string& command)
     cerr << "Unable to connect to " << server.toStringWithPort() << endl;
     return;
   }
-  SConnect(fileDesc.getHandle(), server);
+  SConnect(fileDesc.getHandle(), false, server);
   setTCPNoDelay(fileDesc.getHandle());
   dnsdist::crypto::authenticated::Nonce theirs;
   dnsdist::crypto::authenticated::Nonce ours;
index 151f935647508b0344dba5be6a15f8b250c47bc2..13e8f3241ccf890b8f7d06103688807b9faf643b 100644 (file)
@@ -69,6 +69,7 @@
 #include "doq-common.hh"
 #include "dolog.hh"
 #include "threadname.hh"
+#include "iputils.hh"
 
 #ifdef HAVE_LIBSSL
 #include "libssl.hh"
@@ -459,7 +460,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
                          bool fastOpen{false};
                          if (getOptionalValue<bool>(vars, "tcpFastOpen", fastOpen) > 0) {
                            if (fastOpen) {
-#ifdef MSG_FASTOPEN
+#if defined(MSG_FASTOPEN) || defined(CONNECTX_FASTOPEN)
                              config.tcpFastOpen = true;
 #else
           warnlog("TCP Fast Open has been configured on downstream server %s but is not supported", serverAddressStr);
index afcdc38d26ebb56be0ffefd6148b06bf0169ebd3..538b4c2d9e52e3fe442f2193e343297b74b6a70b 100644 (file)
@@ -144,7 +144,7 @@ static bool isIPv6Supported()
     ComboAddress addr("[2001:db8:53::1]:53");
     auto socket = std::make_unique<Socket>(addr.sin4.sin_family, SOCK_STREAM, 0);
     socket->setNonBlocking();
-    int res = SConnectWithTimeout(socket->getHandle(), addr, timeval{0, 0});
+    int res = SConnectWithTimeout(socket->getHandle(), false, addr, timeval{0, 0});
     if (res == 0 || res == EINPROGRESS) {
       return true;
     }
index 53c8b1110a51f824952e58539ee1c55f62e5dfa2..6bb9a36116959515f018a84f0c0f0ac25f6e4969 100644 (file)
@@ -449,7 +449,7 @@ static bool isIPv6Supported()
     ComboAddress addr("[2001:db8:53::1]:53");
     auto socket = std::make_unique<Socket>(addr.sin4.sin_family, SOCK_STREAM, 0);
     socket->setNonBlocking();
-    int res = SConnectWithTimeout(socket->getHandle(), addr, timeval{0, 0});
+    int res = SConnectWithTimeout(socket->getHandle(), false, addr, timeval{0, 0});
     if (res == 0 || res == EINPROGRESS) {
       return true;
     }
index e578f0110a46c00700a5a53c0735f8a046906b55..74b61c9e4a76ca84e563fbff14a13c260401a575 100644 (file)
@@ -54,9 +54,29 @@ int SSocket(int family, int type, int flags)
   return ret;
 }
 
-int SConnect(int sockfd, const ComboAddress& remote)
+static int doConnect(int sockfd, [[maybe_unused]] bool fastopen, const ComboAddress& remote)
 {
-  int ret = connect(sockfd, reinterpret_cast<const struct sockaddr*>(&remote), remote.getSocklen()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
+#ifdef CONNECTX_FASTOPEN
+  if (fastopen) {
+    sa_endpoints_t endpoints{};
+
+    endpoints.sae_dstaddr = reinterpret_cast<const struct sockaddr*>(&remote); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
+    endpoints.sae_dstaddrlen = remote.getSocklen();
+
+    int flags = CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE;
+    return connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, flags, nullptr, 0, nullptr, nullptr);
+  }
+  else {
+#endif
+    return connect(sockfd, reinterpret_cast<const struct sockaddr*>(&remote), remote.getSocklen()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
+#ifdef CONNECTX_FASTOPEN
+  }
+#endif
+}
+
+int SConnect(int sockfd, bool fastopen, const ComboAddress& remote)
+{
+  int ret = doConnect(sockfd, fastopen, remote);
   if (ret < 0) {
     int savederrno = errno;
     RuntimeError("connecting socket to " + remote.toStringWithPort() + ": " + stringerror(savederrno));
@@ -64,9 +84,9 @@ int SConnect(int sockfd, const ComboAddress& remote)
   return ret;
 }
 
-int SConnectWithTimeout(int sockfd, const ComboAddress& remote, const struct timeval& timeout)
+int SConnectWithTimeout(int sockfd, bool fastopen, const ComboAddress& remote, const struct timeval& timeout)
 {
-  int ret = connect(sockfd, reinterpret_cast<const struct sockaddr*>(&remote), remote.getSocklen()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
+  int ret = doConnect(sockfd, fastopen, remote);
   if (ret < 0) {
     int savederrno = errno;
     if (savederrno == EINPROGRESS) {
index d7b3ab9aecabeb6f50c24198eefa6d4ce56763fc..d472a6c264f14743f524db95c02ca09c0774207a 100644 (file)
 #define htole64(x) OSSwapHostToLittleInt64(x)
 #define be64toh(x) OSSwapBigToHostInt64(x)
 #define le64toh(x) OSSwapLittleToHostInt64(x)
+
+#if defined(CONNECT_DATA_IDEMPOTENT) && defined(CONNECT_RESUME_ON_READ_WRITE)
+#define CONNECTX_FASTOPEN 1
+#endif
+
 #endif
 
 #ifdef __sun
@@ -2040,12 +2045,12 @@ private:
 };
 
 int SSocket(int family, int type, int flags);
-int SConnect(int sockfd, const ComboAddress& remote);
+int SConnect(int sockfd, bool fastopen, const ComboAddress& remote);
 /* tries to connect to remote for a maximum of timeout seconds.
    sockfd should be set to non-blocking beforehand.
    returns 0 on success (the socket is writable), throw a
    runtime_error otherwise */
-int SConnectWithTimeout(int sockfd, const ComboAddress& remote, const struct timeval& timeout);
+int SConnectWithTimeout(int sockfd, bool fastopen, const ComboAddress& remote, const struct timeval& timeout);
 int SBind(int sockfd, const ComboAddress& local);
 int SAccept(int sockfd, ComboAddress& remote);
 int SListen(int sockfd, int limit);
index 50a81622dbac22640aa6115e589bf16cf0d9bec8..8dc21afdb41efbd883cc2da4da9679287228a38e 100644 (file)
@@ -179,7 +179,7 @@ public:
   //! Connect the socket to a specified endpoint
   void connect(const ComboAddress& address, int timeout = 0) const
   {
-    SConnectWithTimeout(d_socket, address, timeval{timeout, 0});
+    SConnectWithTimeout(d_socket, false, address, timeval{timeout, 0});
   }
 
   //! For datagram sockets, receive a datagram and learn where it came from
index 9450b611807144f875f88c42472a5b92ff1dcc43..2d6bd1004f126c1dab72af8eff9ac9d6fd69420f 100644 (file)
@@ -313,12 +313,12 @@ public:
     }
     else {
       if (!s_disableConnectForUnitTests) {
-        SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
+        SConnectWithTimeout(d_socket, fastOpen, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
       }
     }
 #else
     if (!s_disableConnectForUnitTests) {
-      SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
+      SConnectWithTimeout(d_socket, fastOpen, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
     }
 #endif /* MSG_FASTOPEN */
 
@@ -349,12 +349,12 @@ public:
     }
     else {
       if (!s_disableConnectForUnitTests) {
-        SConnectWithTimeout(d_socket, remote, timeout);
+        SConnectWithTimeout(d_socket, fastOpen, remote, timeout);
       }
     }
 #else
     if (!s_disableConnectForUnitTests) {
-      SConnectWithTimeout(d_socket, remote, timeout);
+      SConnectWithTimeout(d_socket, fastOpen, remote, timeout);
     }
 #endif /* MSG_FASTOPEN */