]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tests/server: de-dupe/merge three `sockdaemon()` clones into one
authorViktor Szakats <commit@vsz.me>
Mon, 23 Jun 2025 12:51:37 +0000 (14:51 +0200)
committerViktor Szakats <commit@vsz.me>
Mon, 23 Jun 2025 15:02:43 +0000 (17:02 +0200)
Also: tidy up `if()` expressions here and there.

Follow-up to f4f25505df1d2ede727071eb0c518368a206f64b #15000

Closes #17719

tests/server/dnsd.c
tests/server/first.h
tests/server/mqttd.c
tests/server/rtspd.c
tests/server/sockfilt.c
tests/server/socksd.c
tests/server/sws.c
tests/server/tftpd.c
tests/server/util.c

index 305030376021427eefce493a593d27f47938f758..e64fa642227cfdba6a8fe606d040e1053f538c06 100644 (file)
@@ -504,7 +504,7 @@ static int test_dnsd(int argc, char **argv)
     rc = bind(sock, &me.sa, sizeof(me.sa6));
   }
 #endif /* USE_IPV6 */
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
     logmsg("Error binding socket on port %hu (%d) %s", port, error,
            sstrerror(error));
index 4fb32c44bd3298ba6e6805f521655ccf1e739baa..b7b795c835c6fbdcf0562fe7545420acde286fa3 100644 (file)
@@ -135,6 +135,10 @@ extern int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
                             struct sockaddr_un *sau);
 #endif
 extern unsigned short util_ultous(unsigned long ulnum);
+extern curl_socket_t sockdaemon(curl_socket_t sock,
+                                unsigned short *listenport,
+                                const char *unix_socket,
+                                bool bind_only);
 
 /* global variables */
 static const char *srcpath = "."; /* pointing to the test dir */
index fb89ccb77e7cfb102aeb65bf0c9832d0f97446fb..d42b277d9309b95b6f860e6639693b69897e7d71 100644 (file)
@@ -715,149 +715,6 @@ static bool mqttd_incoming(curl_socket_t listenfd)
   return TRUE;
 }
 
-static curl_socket_t mqttd_sockdaemon(curl_socket_t sock,
-                                      unsigned short *listenport,
-                                      bool bind_only)
-{
-  /* passive daemon style */
-  srvr_sockaddr_union_t listener;
-  int flag;
-  int rc;
-  int totdelay = 0;
-  int maxretr = 10;
-  int delay = 20;
-  int attempt = 0;
-  int error = 0;
-
-  do {
-    attempt++;
-    flag = 1;
-    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-         (void *)&flag, sizeof(flag));
-    if(rc) {
-      error = SOCKERRNO;
-      logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
-             error, sstrerror(error));
-      if(maxretr) {
-        rc = curlx_wait_ms(delay);
-        if(rc) {
-          /* should not happen */
-          error = SOCKERRNO;
-          logmsg("curlx_wait_ms() failed with error (%d) %s",
-                 error, sstrerror(error));
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        if(got_exit_signal) {
-          logmsg("signalled to die, exiting...");
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        totdelay += delay;
-        delay *= 2; /* double the sleep for next attempt */
-      }
-    }
-  } while(rc && maxretr--);
-
-  if(rc) {
-    logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
-           attempt, totdelay, error, strerror(error));
-    logmsg("Continuing anyway...");
-  }
-
-  /* When the specified listener port is zero, it is actually a
-     request to let the system choose a non-zero available port. */
-
-#ifdef USE_IPV6
-  if(!use_ipv6) {
-#endif
-    memset(&listener.sa4, 0, sizeof(listener.sa4));
-    listener.sa4.sin_family = AF_INET;
-    listener.sa4.sin_addr.s_addr = INADDR_ANY;
-    listener.sa4.sin_port = htons(*listenport);
-    rc = bind(sock, &listener.sa, sizeof(listener.sa4));
-#ifdef USE_IPV6
-  }
-  else {
-    memset(&listener.sa6, 0, sizeof(listener.sa6));
-    listener.sa6.sin6_family = AF_INET6;
-    listener.sa6.sin6_addr = in6addr_any;
-    listener.sa6.sin6_port = htons(*listenport);
-    rc = bind(sock, &listener.sa, sizeof(listener.sa6));
-  }
-#endif /* USE_IPV6 */
-  if(rc) {
-    error = SOCKERRNO;
-    logmsg("Error binding socket on port %hu (%d) %s",
-           *listenport, error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  if(!*listenport) {
-    /* The system was supposed to choose a port number, figure out which
-       port we actually got and update the listener port value with it. */
-    curl_socklen_t la_size;
-    srvr_sockaddr_union_t localaddr;
-#ifdef USE_IPV6
-    if(!use_ipv6)
-#endif
-      la_size = sizeof(localaddr.sa4);
-#ifdef USE_IPV6
-    else
-      la_size = sizeof(localaddr.sa6);
-#endif
-    memset(&localaddr.sa, 0, (size_t)la_size);
-    if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
-      error = SOCKERRNO;
-      logmsg("getsockname() failed with error (%d) %s",
-             error, sstrerror(error));
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-    switch(localaddr.sa.sa_family) {
-    case AF_INET:
-      *listenport = ntohs(localaddr.sa4.sin_port);
-      break;
-#ifdef USE_IPV6
-    case AF_INET6:
-      *listenport = ntohs(localaddr.sa6.sin6_port);
-      break;
-#endif
-    default:
-      break;
-    }
-    if(!*listenport) {
-      /* Real failure, listener port shall not be zero beyond this point. */
-      logmsg("Apparently getsockname() succeeded, with listener port zero.");
-      logmsg("A valid reason for this failure is a binary built without");
-      logmsg("proper network library linkage. This might not be the only");
-      logmsg("reason, but double check it before anything else.");
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-  }
-
-  /* bindonly option forces no listening */
-  if(bind_only) {
-    logmsg("instructed to bind port without listening");
-    return sock;
-  }
-
-  /* start accepting connections */
-  rc = listen(sock, 5);
-  if(0 != rc) {
-    error = SOCKERRNO;
-    logmsg("listen(%ld, 5) failed with error (%d) %s",
-           (long)sock, error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  return sock;
-}
-
-
 static int test_mqttd(int argc, char *argv[])
 {
   curl_socket_t sock = CURL_SOCKET_BAD;
@@ -912,16 +769,16 @@ static int test_mqttd(int argc, char *argv[])
     }
     else if(!strcmp("--ipv6", argv[arg])) {
 #ifdef USE_IPV6
+      socket_domain = AF_INET6;
       ipv_inuse = "IPv6";
-      use_ipv6 = TRUE;
 #endif
       arg++;
     }
     else if(!strcmp("--ipv4", argv[arg])) {
       /* for completeness, we support this option as well */
 #ifdef USE_IPV6
+      socket_domain = AF_INET;
       ipv_inuse = "IPv4";
-      use_ipv6 = FALSE;
 #endif
       arg++;
     }
@@ -969,14 +826,7 @@ static int test_mqttd(int argc, char *argv[])
 
   install_signal_handlers(FALSE);
 
-#ifdef USE_IPV6
-  if(!use_ipv6)
-#endif
-    sock = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef USE_IPV6
-  else
-    sock = socket(AF_INET6, SOCK_STREAM, 0);
-#endif
+  sock = socket(socket_domain, SOCK_STREAM, 0);
 
   if(CURL_SOCKET_BAD == sock) {
     error = SOCKERRNO;
@@ -986,7 +836,7 @@ static int test_mqttd(int argc, char *argv[])
 
   {
     /* passive daemon style */
-    sock = mqttd_sockdaemon(sock, &server_port, FALSE);
+    sock = sockdaemon(sock, &server_port, NULL, FALSE);
     if(CURL_SOCKET_BAD == sock) {
       goto mqttd_cleanup;
     }
index 1825361718bc1666c325e3c85484f7d03e5835bc..d4baa3ff1a90e6640349bdbfbc34b053e636c862 100644 (file)
@@ -1127,7 +1127,7 @@ static int test_rtspd(int argc, char *argv[])
     rc = bind(sock, &me.sa, sizeof(me.sa6));
   }
 #endif /* USE_IPV6 */
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
     logmsg("Error binding socket on port %hu (%d) %s",
            port, error, sstrerror(error));
@@ -1181,7 +1181,7 @@ static int test_rtspd(int argc, char *argv[])
 
   /* start accepting connections */
   rc = listen(sock, 5);
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
     logmsg("listen() failed with error (%d) %s",
            error, sstrerror(error));
index 477e433f8ecc8fa1de7e41e10fece05eadf7edeb..c17bca34bf2ef10db475889211d6dc2856010a53 100644 (file)
@@ -554,6 +554,7 @@ static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
 
   return 0;
 }
+
 static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
 {
   typedef uintptr_t curl_win_thread_handle_t;
@@ -578,6 +579,7 @@ static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
   }
   return NULL;
 }
+
 struct select_ws_data {
   int fd;                /* provided file descriptor  (indexed by nfd) */
   long wsastate;         /* internal pre-select state (indexed by nfd) */
@@ -586,6 +588,7 @@ struct select_ws_data {
   HANDLE signal;         /* internal thread signal    (indexed by nth) */
   HANDLE thread;         /* internal thread handle    (indexed by nth) */
 };
+
 static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
                      fd_set *exceptfds, struct timeval *tv)
 {
@@ -1206,149 +1209,6 @@ static bool juggle(curl_socket_t *sockfdp,
 #endif
 }
 
-static curl_socket_t sockfilt_sockdaemon(curl_socket_t sock,
-                                         unsigned short *listenport,
-                                         bool bind_only)
-{
-  /* passive daemon style */
-  srvr_sockaddr_union_t listener;
-  int flag;
-  int rc;
-  int totdelay = 0;
-  int maxretr = 10;
-  int delay = 20;
-  int attempt = 0;
-  int error = 0;
-
-  do {
-    attempt++;
-    flag = 1;
-    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-         (void *)&flag, sizeof(flag));
-    if(rc) {
-      error = SOCKERRNO;
-      logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
-             error, sstrerror(error));
-      if(maxretr) {
-        rc = curlx_wait_ms(delay);
-        if(rc) {
-          /* should not happen */
-          error = SOCKERRNO;
-          logmsg("curlx_wait_ms() failed with error (%d) %s",
-                 error, sstrerror(error));
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        if(got_exit_signal) {
-          logmsg("signalled to die, exiting...");
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        totdelay += delay;
-        delay *= 2; /* double the sleep for next attempt */
-      }
-    }
-  } while(rc && maxretr--);
-
-  if(rc) {
-    logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
-           attempt, totdelay, error, strerror(error));
-    logmsg("Continuing anyway...");
-  }
-
-  /* When the specified listener port is zero, it is actually a
-     request to let the system choose a non-zero available port. */
-
-#ifdef USE_IPV6
-  if(!use_ipv6) {
-#endif
-    memset(&listener.sa4, 0, sizeof(listener.sa4));
-    listener.sa4.sin_family = AF_INET;
-    listener.sa4.sin_addr.s_addr = INADDR_ANY;
-    listener.sa4.sin_port = htons(*listenport);
-    rc = bind(sock, &listener.sa, sizeof(listener.sa4));
-#ifdef USE_IPV6
-  }
-  else {
-    memset(&listener.sa6, 0, sizeof(listener.sa6));
-    listener.sa6.sin6_family = AF_INET6;
-    listener.sa6.sin6_addr = in6addr_any;
-    listener.sa6.sin6_port = htons(*listenport);
-    rc = bind(sock, &listener.sa, sizeof(listener.sa6));
-  }
-#endif /* USE_IPV6 */
-  if(rc) {
-    error = SOCKERRNO;
-    logmsg("Error binding socket on port %hu (%d) %s",
-           *listenport, error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  if(!*listenport) {
-    /* The system was supposed to choose a port number, figure out which
-       port we actually got and update the listener port value with it. */
-    curl_socklen_t la_size;
-    srvr_sockaddr_union_t localaddr;
-#ifdef USE_IPV6
-    if(!use_ipv6)
-#endif
-      la_size = sizeof(localaddr.sa4);
-#ifdef USE_IPV6
-    else
-      la_size = sizeof(localaddr.sa6);
-#endif
-    memset(&localaddr.sa, 0, (size_t)la_size);
-    if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
-      error = SOCKERRNO;
-      logmsg("getsockname() failed with error (%d) %s",
-             error, sstrerror(error));
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-    switch(localaddr.sa.sa_family) {
-    case AF_INET:
-      *listenport = ntohs(localaddr.sa4.sin_port);
-      break;
-#ifdef USE_IPV6
-    case AF_INET6:
-      *listenport = ntohs(localaddr.sa6.sin6_port);
-      break;
-#endif
-    default:
-      break;
-    }
-    if(!*listenport) {
-      /* Real failure, listener port shall not be zero beyond this point. */
-      logmsg("Apparently getsockname() succeeded, with listener port zero.");
-      logmsg("A valid reason for this failure is a binary built without");
-      logmsg("proper network library linkage. This might not be the only");
-      logmsg("reason, but double check it before anything else.");
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-  }
-
-  /* bindonly option forces no listening */
-  if(bind_only) {
-    logmsg("instructed to bind port without listening");
-    return sock;
-  }
-
-  /* start accepting connections */
-  rc = listen(sock, 5);
-  if(0 != rc) {
-    error = SOCKERRNO;
-    logmsg("listen() failed with error (%d) %s",
-           error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  return sock;
-}
-
-
 static int test_sockfilt(int argc, char *argv[])
 {
   srvr_sockaddr_union_t me;
@@ -1399,16 +1259,16 @@ static int test_sockfilt(int argc, char *argv[])
     }
     else if(!strcmp("--ipv6", argv[arg])) {
 #ifdef USE_IPV6
+      socket_domain = AF_INET6;
       ipv_inuse = "IPv6";
-      use_ipv6 = TRUE;
 #endif
       arg++;
     }
     else if(!strcmp("--ipv4", argv[arg])) {
       /* for completeness, we support this option as well */
 #ifdef USE_IPV6
+      socket_domain = AF_INET;
       ipv_inuse = "IPv4";
-      use_ipv6 = FALSE;
 #endif
       arg++;
     }
@@ -1478,14 +1338,7 @@ static int test_sockfilt(int argc, char *argv[])
 
   install_signal_handlers(false);
 
-#ifdef USE_IPV6
-  if(!use_ipv6)
-#endif
-    sock = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef USE_IPV6
-  else
-    sock = socket(AF_INET6, SOCK_STREAM, 0);
-#endif
+  sock = socket(socket_domain, SOCK_STREAM, 0);
 
   if(CURL_SOCKET_BAD == sock) {
     error = SOCKERRNO;
@@ -1497,31 +1350,33 @@ static int test_sockfilt(int argc, char *argv[])
   if(server_connectport) {
     /* Active mode, we should connect to the given port number */
     mode = ACTIVE;
+    switch(socket_domain) {
+      case AF_INET:
+        memset(&me.sa4, 0, sizeof(me.sa4));
+        me.sa4.sin_family = AF_INET;
+        me.sa4.sin_port = htons(server_connectport);
+        me.sa4.sin_addr.s_addr = INADDR_ANY;
+        if(!addr)
+          addr = "127.0.0.1";
+        curlx_inet_pton(AF_INET, addr, &me.sa4.sin_addr);
+
+        rc = connect(sock, &me.sa, sizeof(me.sa4));
+        break;
 #ifdef USE_IPV6
-    if(!use_ipv6) {
-#endif
-      memset(&me.sa4, 0, sizeof(me.sa4));
-      me.sa4.sin_family = AF_INET;
-      me.sa4.sin_port = htons(server_connectport);
-      me.sa4.sin_addr.s_addr = INADDR_ANY;
-      if(!addr)
-        addr = "127.0.0.1";
-      curlx_inet_pton(AF_INET, addr, &me.sa4.sin_addr);
-
-      rc = connect(sock, &me.sa, sizeof(me.sa4));
-#ifdef USE_IPV6
-    }
-    else {
-      memset(&me.sa6, 0, sizeof(me.sa6));
-      me.sa6.sin6_family = AF_INET6;
-      me.sa6.sin6_port = htons(server_connectport);
-      if(!addr)
-        addr = "::1";
-      curlx_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
-
-      rc = connect(sock, &me.sa, sizeof(me.sa6));
-    }
+      case AF_INET6:
+        memset(&me.sa6, 0, sizeof(me.sa6));
+        me.sa6.sin6_family = AF_INET6;
+        me.sa6.sin6_port = htons(server_connectport);
+        if(!addr)
+          addr = "::1";
+        curlx_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
+
+        rc = connect(sock, &me.sa, sizeof(me.sa6));
+        break;
 #endif /* USE_IPV6 */
+      default:
+        rc = 1;
+    }
     if(rc) {
       error = SOCKERRNO;
       logmsg("Error connecting to port %hu (%d) %s",
@@ -1534,7 +1389,7 @@ static int test_sockfilt(int argc, char *argv[])
   }
   else {
     /* passive daemon style */
-    sock = sockfilt_sockdaemon(sock, &server_port, s_bind_only);
+    sock = sockdaemon(sock, &server_port, NULL, s_bind_only);
     if(CURL_SOCKET_BAD == sock) {
       write_stdout("FAIL\n", 5);
       goto sockfilt_cleanup;
index 64c55a64e70cbdd19d562c9fb8cb47eec6b74f0f..70e27af2ff4c5d16e735903fa6661f383a43b33a 100644 (file)
@@ -730,166 +730,6 @@ static bool socksd_incoming(curl_socket_t listenfd)
   return TRUE;
 }
 
-static curl_socket_t socksd_sockdaemon(curl_socket_t sock,
-                                       unsigned short *listenport,
-                                       const char *unix_socket,
-                                       bool bind_only)
-{
-  /* passive daemon style */
-  srvr_sockaddr_union_t listener;
-  int flag;
-  int rc;
-  int totdelay = 0;
-  int maxretr = 10;
-  int delay = 20;
-  int attempt = 0;
-  int error = 0;
-
-#ifndef USE_UNIX_SOCKETS
-  (void)unix_socket;
-#endif
-
-  do {
-    attempt++;
-    flag = 1;
-    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-         (void *)&flag, sizeof(flag));
-    if(rc) {
-      error = SOCKERRNO;
-      logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
-             error, sstrerror(error));
-      if(maxretr) {
-        rc = curlx_wait_ms(delay);
-        if(rc) {
-          /* should not happen */
-          error = SOCKERRNO;
-          logmsg("curlx_wait_ms() failed with error (%d) %s",
-                 error, sstrerror(error));
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        if(got_exit_signal) {
-          logmsg("signalled to die, exiting...");
-          sclose(sock);
-          return CURL_SOCKET_BAD;
-        }
-        totdelay += delay;
-        delay *= 2; /* double the sleep for next attempt */
-      }
-    }
-  } while(rc && maxretr--);
-
-  if(rc) {
-    logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
-           attempt, totdelay, error, strerror(error));
-    logmsg("Continuing anyway...");
-  }
-
-  /* When the specified listener port is zero, it is actually a
-     request to let the system choose a non-zero available port. */
-
-  switch(socket_domain) {
-    case AF_INET:
-      memset(&listener.sa4, 0, sizeof(listener.sa4));
-      listener.sa4.sin_family = AF_INET;
-      listener.sa4.sin_addr.s_addr = INADDR_ANY;
-      listener.sa4.sin_port = htons(*listenport);
-      rc = bind(sock, &listener.sa, sizeof(listener.sa4));
-      break;
-#ifdef USE_IPV6
-    case AF_INET6:
-      memset(&listener.sa6, 0, sizeof(listener.sa6));
-      listener.sa6.sin6_family = AF_INET6;
-      listener.sa6.sin6_addr = in6addr_any;
-      listener.sa6.sin6_port = htons(*listenport);
-      rc = bind(sock, &listener.sa, sizeof(listener.sa6));
-      break;
-#endif /* USE_IPV6 */
-#ifdef USE_UNIX_SOCKETS
-    case AF_UNIX:
-      rc = bind_unix_socket(sock, unix_socket, &listener.sau);
-#endif
-  }
-
-  if(rc) {
-    error = SOCKERRNO;
-#ifdef USE_UNIX_SOCKETS
-    if(socket_domain == AF_UNIX)
-      logmsg("Error binding socket on path %s (%d) %s",
-             unix_socket, error, sstrerror(error));
-    else
-#endif
-      logmsg("Error binding socket on port %hu (%d) %s",
-             *listenport, error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  if(!*listenport
-#ifdef USE_UNIX_SOCKETS
-          && !unix_socket
-#endif
-    ) {
-    /* The system was supposed to choose a port number, figure out which
-       port we actually got and update the listener port value with it. */
-    curl_socklen_t la_size;
-    srvr_sockaddr_union_t localaddr;
-#ifdef USE_IPV6
-    if(socket_domain == AF_INET6)
-      la_size = sizeof(localaddr.sa6);
-    else
-#endif
-      la_size = sizeof(localaddr.sa4);
-    memset(&localaddr.sa, 0, (size_t)la_size);
-    if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
-      error = SOCKERRNO;
-      logmsg("getsockname() failed with error (%d) %s",
-             error, sstrerror(error));
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-    switch(localaddr.sa.sa_family) {
-    case AF_INET:
-      *listenport = ntohs(localaddr.sa4.sin_port);
-      break;
-#ifdef USE_IPV6
-    case AF_INET6:
-      *listenport = ntohs(localaddr.sa6.sin6_port);
-      break;
-#endif
-    default:
-      break;
-    }
-    if(!*listenport) {
-      /* Real failure, listener port shall not be zero beyond this point. */
-      logmsg("Apparently getsockname() succeeded, with listener port zero.");
-      logmsg("A valid reason for this failure is a binary built without");
-      logmsg("proper network library linkage. This might not be the only");
-      logmsg("reason, but double check it before anything else.");
-      sclose(sock);
-      return CURL_SOCKET_BAD;
-    }
-  }
-
-  /* bindonly option forces no listening */
-  if(bind_only) {
-    logmsg("instructed to bind port without listening");
-    return sock;
-  }
-
-  /* start accepting connections */
-  rc = listen(sock, 5);
-  if(0 != rc) {
-    error = SOCKERRNO;
-    logmsg("listen() failed with error (%d) %s", error, sstrerror(error));
-    sclose(sock);
-    return CURL_SOCKET_BAD;
-  }
-
-  return sock;
-}
-
-
 static int test_socksd(int argc, char *argv[])
 {
   curl_socket_t sock = CURL_SOCKET_BAD;
@@ -1038,7 +878,7 @@ static int test_socksd(int argc, char *argv[])
 
   {
     /* passive daemon style */
-    sock = socksd_sockdaemon(sock, &server_port, unix_socket, FALSE);
+    sock = sockdaemon(sock, &server_port, unix_socket, FALSE);
     if(CURL_SOCKET_BAD == sock) {
       goto socks5_cleanup;
     }
index 30bc2f0f618d8dc2cb1d6b752ca138c37076218b..7b90e510b4f64c5983c822f515c40fb93d1528e1 100644 (file)
@@ -2200,7 +2200,7 @@ static int test_sws(int argc, char *argv[])
     rc = bind_unix_socket(sock, unix_socket, &me.sau);
 #endif /* USE_UNIX_SOCKETS */
   }
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
 #ifdef USE_UNIX_SOCKETS
     if(socket_domain == AF_UNIX)
@@ -2266,7 +2266,7 @@ static int test_sws(int argc, char *argv[])
 
   /* start accepting connections */
   rc = listen(sock, 50);
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
     logmsg("listen() failed with error (%d) %s", error, sstrerror(error));
     goto sws_cleanup;
index 1505d4de179892e99eaafb1f436cb11c4d92dd75..fc08c729ed369ddc34622d9a4180e959e1111110 100644 (file)
@@ -689,7 +689,7 @@ static int test_tftpd(int argc, char **argv)
     rc = bind(sock, &me.sa, sizeof(me.sa6));
   }
 #endif /* USE_IPV6 */
-  if(0 != rc) {
+  if(rc) {
     error = SOCKERRNO;
     logmsg("Error binding socket on port %hu (%d) %s", port, error,
            sstrerror(error));
index 8297c2027045b0e1a27fa0d9687dd11dc9a66f65..b4d0e92c0db74c9ad0439b06ab53a05a5b29d943 100644 (file)
@@ -707,7 +707,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
   }
   strcpy(sau->sun_path, unix_socket);
   rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
-  if(0 != rc && SOCKERRNO == SOCKEADDRINUSE) {
+  if(rc && SOCKERRNO == SOCKEADDRINUSE) {
     struct_stat statbuf;
     /* socket already exists. Perhaps it is stale? */
     curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -720,7 +720,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
     rc = connect(unixfd, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
     error = SOCKERRNO;
     sclose(unixfd);
-    if(0 != rc && SOCKECONNREFUSED != error) {
+    if(rc && error != SOCKECONNREFUSED) {
       logmsg("Failed to connect to %s (%d) %s",
              unix_socket, error, sstrerror(error));
       return rc;
@@ -732,7 +732,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
 #else
     rc = lstat(unix_socket, &statbuf);
 #endif
-    if(0 != rc) {
+    if(rc) {
       logmsg("Error binding socket, failed to stat %s (%d) %s",
              unix_socket, errno, strerror(errno));
       return rc;
@@ -745,7 +745,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
 #endif
     /* dead socket, cleanup and retry bind */
     rc = unlink(unix_socket);
-    if(0 != rc) {
+    if(rc) {
       logmsg("Error binding socket, failed to unlink %s (%d) %s",
              unix_socket, errno, strerror(errno));
       return rc;
@@ -777,3 +777,166 @@ unsigned short util_ultous(unsigned long ulnum)
 #  pragma warning(pop)
 #endif
 }
+
+curl_socket_t sockdaemon(curl_socket_t sock,
+                         unsigned short *listenport,
+                         const char *unix_socket,
+                         bool bind_only)
+{
+  /* passive daemon style */
+  srvr_sockaddr_union_t listener;
+  int flag;
+  int rc;
+  int totdelay = 0;
+  int maxretr = 10;
+  int delay = 20;
+  int attempt = 0;
+  int error = 0;
+
+#ifndef USE_UNIX_SOCKETS
+  (void)unix_socket;
+#endif
+
+  do {
+    attempt++;
+    flag = 1;
+    rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                    (void *)&flag, sizeof(flag));
+    if(rc) {
+      error = SOCKERRNO;
+      logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
+             error, sstrerror(error));
+      if(maxretr) {
+        rc = curlx_wait_ms(delay);
+        if(rc) {
+          /* should not happen */
+          error = SOCKERRNO;
+          logmsg("curlx_wait_ms() failed with error (%d) %s",
+                 error, sstrerror(error));
+          sclose(sock);
+          return CURL_SOCKET_BAD;
+        }
+        if(got_exit_signal) {
+          logmsg("signalled to die, exiting...");
+          sclose(sock);
+          return CURL_SOCKET_BAD;
+        }
+        totdelay += delay;
+        delay *= 2; /* double the sleep for next attempt */
+      }
+    }
+  } while(rc && maxretr--);
+
+  if(rc) {
+    logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
+           attempt, totdelay, error, strerror(error));
+    logmsg("Continuing anyway...");
+  }
+
+  /* When the specified listener port is zero, it is actually a
+     request to let the system choose a non-zero available port. */
+
+  switch(socket_domain) {
+    case AF_INET:
+      memset(&listener.sa4, 0, sizeof(listener.sa4));
+      listener.sa4.sin_family = AF_INET;
+      listener.sa4.sin_addr.s_addr = INADDR_ANY;
+      listener.sa4.sin_port = htons(*listenport);
+      rc = bind(sock, &listener.sa, sizeof(listener.sa4));
+      break;
+#ifdef USE_IPV6
+    case AF_INET6:
+      memset(&listener.sa6, 0, sizeof(listener.sa6));
+      listener.sa6.sin6_family = AF_INET6;
+      listener.sa6.sin6_addr = in6addr_any;
+      listener.sa6.sin6_port = htons(*listenport);
+      rc = bind(sock, &listener.sa, sizeof(listener.sa6));
+      break;
+#endif /* USE_IPV6 */
+#ifdef USE_UNIX_SOCKETS
+    case AF_UNIX:
+      rc = bind_unix_socket(sock, unix_socket, &listener.sau);
+      break;
+#endif
+    default:
+      rc = 1;
+  }
+
+  if(rc) {
+    error = SOCKERRNO;
+#ifdef USE_UNIX_SOCKETS
+    if(socket_domain == AF_UNIX)
+      logmsg("Error binding socket on path %s (%d) %s",
+             unix_socket, error, sstrerror(error));
+    else
+#endif
+      logmsg("Error binding socket on port %hu (%d) %s",
+             *listenport, error, sstrerror(error));
+    sclose(sock);
+    return CURL_SOCKET_BAD;
+  }
+
+  if(!*listenport
+#ifdef USE_UNIX_SOCKETS
+     && !unix_socket
+#endif
+    ) {
+    /* The system was supposed to choose a port number, figure out which
+       port we actually got and update the listener port value with it. */
+    curl_socklen_t la_size;
+    srvr_sockaddr_union_t localaddr;
+#ifdef USE_IPV6
+    if(socket_domain == AF_INET6)
+      la_size = sizeof(localaddr.sa6);
+    else
+#endif
+      la_size = sizeof(localaddr.sa4);
+    memset(&localaddr.sa, 0, (size_t)la_size);
+    if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
+      error = SOCKERRNO;
+      logmsg("getsockname() failed with error (%d) %s",
+             error, sstrerror(error));
+      sclose(sock);
+      return CURL_SOCKET_BAD;
+    }
+    switch(localaddr.sa.sa_family) {
+    case AF_INET:
+      *listenport = ntohs(localaddr.sa4.sin_port);
+      break;
+#ifdef USE_IPV6
+    case AF_INET6:
+      *listenport = ntohs(localaddr.sa6.sin6_port);
+      break;
+#endif
+    default:
+      break;
+    }
+    if(!*listenport) {
+      /* Real failure, listener port shall not be zero beyond this point. */
+      logmsg("Apparently getsockname() succeeded, with listener port zero.");
+      logmsg("A valid reason for this failure is a binary built without");
+      logmsg("proper network library linkage. This might not be the only");
+      logmsg("reason, but double check it before anything else.");
+      sclose(sock);
+      return CURL_SOCKET_BAD;
+    }
+  }
+
+  /* bindonly option forces no listening */
+  if(bind_only) {
+    logmsg("instructed to bind port without listening");
+    return sock;
+  }
+
+  /* start accepting connections */
+  rc = listen(sock, 5);
+  if(rc) {
+    error = SOCKERRNO;
+    logmsg("listen(%ld, 5) failed with error (%d) %s",
+           (long)sock, error, sstrerror(error));
+    sclose(sock);
+    return CURL_SOCKET_BAD;
+  }
+
+  return sock;
+}