Browse Source

Refactor setting socket options (#2053)

Add detail::set_socket_opt() and detail::set_socket_opt_time() to avoid
repetition of platform-specific code.
Florian Albrechtskirchinger 10 months ago
parent
commit
233f0fb1b8
1 changed files with 56 additions and 91 deletions
  1. 56 91
      httplib.h

+ 56 - 91
httplib.h

@@ -193,6 +193,7 @@ using ssize_t = long;
 #endif
 #endif
 
 
 using socket_t = SOCKET;
 using socket_t = SOCKET;
+using socklen_t = int;
 #ifdef CPPHTTPLIB_USE_POLL
 #ifdef CPPHTTPLIB_USE_POLL
 #define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
 #define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
 #endif
 #endif
@@ -848,6 +849,16 @@ using Logger = std::function<void(const Request &, const Response &)>;
 
 
 using SocketOptions = std::function<void(socket_t sock)>;
 using SocketOptions = std::function<void(socket_t sock)>;
 
 
+namespace detail {
+
+bool set_socket_opt_impl(socket_t sock, int level, int optname,
+                         const void *optval, socklen_t optlen);
+bool set_socket_opt(socket_t sock, int level, int optname, int opt);
+bool set_socket_opt_time(socket_t sock, int level, int optname, time_t sec,
+                         time_t usec);
+
+} // namespace detail
+
 void default_socket_options(socket_t sock);
 void default_socket_options(socket_t sock);
 
 
 const char *status_message(int status);
 const char *status_message(int status);
@@ -2075,20 +2086,45 @@ inline uint64_t Response::get_header_value_u64(const std::string &key,
   return detail::get_header_value_u64(headers, key, def, id);
   return detail::get_header_value_u64(headers, key, def, id);
 }
 }
 
 
-inline void default_socket_options(socket_t sock) {
-  int opt = 1;
+namespace detail {
+
+inline bool set_socket_opt_impl(socket_t sock, int level, int optname,
+                                const void *optval, socklen_t optlen) {
+  return setsockopt(sock, level, optname,
 #ifdef _WIN32
 #ifdef _WIN32
-  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-             reinterpret_cast<const char *>(&opt), sizeof(opt));
+                    reinterpret_cast<const char *>(optval),
 #else
 #else
-#ifdef SO_REUSEPORT
-  setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
-             reinterpret_cast<const void *>(&opt), sizeof(opt));
+                    optval,
+#endif
+                    optlen) == 0;
+}
+
+inline bool set_socket_opt(socket_t sock, int level, int optname, int optval) {
+  return set_socket_opt_impl(sock, level, optname, &optval, sizeof(optval));
+}
+
+inline bool set_socket_opt_time(socket_t sock, int level, int optname,
+                                time_t sec, time_t usec) {
+#ifdef _WIN32
+  auto timeout = static_cast<uint32_t>(sec * 1000 + usec / 1000);
 #else
 #else
-  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-             reinterpret_cast<const void *>(&opt), sizeof(opt));
+  timeval timeout;
+  timeout.tv_sec = static_cast<long>(sec);
+  timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(usec);
 #endif
 #endif
+  return set_socket_opt_impl(sock, level, optname, &timeout, sizeof(timeout));
+}
+
+} // namespace detail
+
+inline void default_socket_options(socket_t sock) {
+  detail::set_socket_opt(sock, SOL_SOCKET,
+#ifdef SO_REUSEPORT
+                         SO_REUSEPORT,
+#else
+                         SO_REUSEADDR,
 #endif
 #endif
+                         1);
 }
 }
 
 
 inline const char *status_message(int status) {
 inline const char *status_message(int status) {
@@ -3605,26 +3641,10 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
     }
     }
 #endif
 #endif
 
 
-    if (tcp_nodelay) {
-      auto opt = 1;
-#ifdef _WIN32
-      setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
-                 reinterpret_cast<const char *>(&opt), sizeof(opt));
-#else
-      setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
-                 reinterpret_cast<const void *>(&opt), sizeof(opt));
-#endif
-    }
+    if (tcp_nodelay) { set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); }
 
 
     if (rp->ai_family == AF_INET6) {
     if (rp->ai_family == AF_INET6) {
-      auto opt = ipv6_v6only ? 1 : 0;
-#ifdef _WIN32
-      setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
-                 reinterpret_cast<const char *>(&opt), sizeof(opt));
-#else
-      setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
-                 reinterpret_cast<const void *>(&opt), sizeof(opt));
-#endif
+      set_socket_opt(sock, IPPROTO_IPV6, IPV6_V6ONLY, ipv6_v6only ? 1 : 0);
     }
     }
 
 
     if (socket_options) { socket_options(sock); }
     if (socket_options) { socket_options(sock); }
@@ -3767,36 +3787,10 @@ inline socket_t create_client_socket(
         }
         }
 
 
         set_nonblocking(sock2, false);
         set_nonblocking(sock2, false);
-
-        {
-#ifdef _WIN32
-          auto timeout = static_cast<uint32_t>(read_timeout_sec * 1000 +
-                                               read_timeout_usec / 1000);
-          setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
-                     reinterpret_cast<const char *>(&timeout), sizeof(timeout));
-#else
-          timeval tv;
-          tv.tv_sec = static_cast<long>(read_timeout_sec);
-          tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec);
-          setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
-                     reinterpret_cast<const void *>(&tv), sizeof(tv));
-#endif
-        }
-        {
-
-#ifdef _WIN32
-          auto timeout = static_cast<uint32_t>(write_timeout_sec * 1000 +
-                                               write_timeout_usec / 1000);
-          setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
-                     reinterpret_cast<const char *>(&timeout), sizeof(timeout));
-#else
-          timeval tv;
-          tv.tv_sec = static_cast<long>(write_timeout_sec);
-          tv.tv_usec = static_cast<decltype(tv.tv_usec)>(write_timeout_usec);
-          setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
-                     reinterpret_cast<const void *>(&tv), sizeof(tv));
-#endif
-        }
+        set_socket_opt_time(sock2, SOL_SOCKET, SO_RCVTIMEO, read_timeout_sec,
+                            read_timeout_usec);
+        set_socket_opt_time(sock2, SOL_SOCKET, SO_SNDTIMEO, write_timeout_sec,
+                            write_timeout_usec);
 
 
         error = Error::Success;
         error = Error::Success;
         return true;
         return true;
@@ -6946,35 +6940,10 @@ inline bool Server::listen_internal() {
         break;
         break;
       }
       }
 
 
-      {
-#ifdef _WIN32
-        auto timeout = static_cast<uint32_t>(read_timeout_sec_ * 1000 +
-                                             read_timeout_usec_ / 1000);
-        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
-                   reinterpret_cast<const char *>(&timeout), sizeof(timeout));
-#else
-        timeval tv;
-        tv.tv_sec = static_cast<long>(read_timeout_sec_);
-        tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec_);
-        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
-                   reinterpret_cast<const void *>(&tv), sizeof(tv));
-#endif
-      }
-      {
-
-#ifdef _WIN32
-        auto timeout = static_cast<uint32_t>(write_timeout_sec_ * 1000 +
-                                             write_timeout_usec_ / 1000);
-        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
-                   reinterpret_cast<const char *>(&timeout), sizeof(timeout));
-#else
-        timeval tv;
-        tv.tv_sec = static_cast<long>(write_timeout_sec_);
-        tv.tv_usec = static_cast<decltype(tv.tv_usec)>(write_timeout_usec_);
-        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
-                   reinterpret_cast<const void *>(&tv), sizeof(tv));
-#endif
-      }
+      detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO,
+                                  read_timeout_sec_, read_timeout_usec_);
+      detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
+                                  write_timeout_sec_, write_timeout_usec_);
 
 
       if (!task_queue->enqueue(
       if (!task_queue->enqueue(
               [this, sock]() { process_and_close_socket(sock); })) {
               [this, sock]() { process_and_close_socket(sock); })) {
@@ -9097,11 +9066,7 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
     (void)(sock);
     (void)(sock);
     SSL_shutdown(ssl);
     SSL_shutdown(ssl);
 #else
 #else
-    timeval tv;
-    tv.tv_sec = 1;
-    tv.tv_usec = 0;
-    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
-               reinterpret_cast<const void *>(&tv), sizeof(tv));
+    detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO, 1, 0);
 
 
     auto ret = SSL_shutdown(ssl);
     auto ret = SSL_shutdown(ssl);
     while (ret == 0) {
     while (ret == 0) {