@@ -193,6 +193,7 @@ using ssize_t = long;
193193#endif
194194
195195using socket_t = SOCKET;
196+ using socklen_t = int ;
196197#ifdef CPPHTTPLIB_USE_POLL
197198#define poll (fds, nfds, timeout ) WSAPoll(fds, nfds, timeout)
198199#endif
@@ -848,6 +849,16 @@ using Logger = std::function<void(const Request &, const Response &)>;
848849
849850using SocketOptions = std::function<void (socket_t sock)>;
850851
852+ namespace detail {
853+
854+ bool set_socket_opt_impl (socket_t sock, int level, int optname,
855+ const void *optval, socklen_t optlen);
856+ bool set_socket_opt (socket_t sock, int level, int optname, int opt);
857+ bool set_socket_opt_time (socket_t sock, int level, int optname, time_t sec,
858+ time_t usec);
859+
860+ } // namespace detail
861+
851862void default_socket_options (socket_t sock);
852863
853864const char *status_message (int status);
@@ -2075,20 +2086,45 @@ inline uint64_t Response::get_header_value_u64(const std::string &key,
20752086 return detail::get_header_value_u64 (headers, key, def, id);
20762087}
20772088
2078- inline void default_socket_options (socket_t sock) {
2079- int opt = 1 ;
2089+ namespace detail {
2090+
2091+ inline bool set_socket_opt_impl (socket_t sock, int level, int optname,
2092+ const void *optval, socklen_t optlen) {
2093+ return setsockopt (sock, level, optname,
20802094#ifdef _WIN32
2081- setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
2082- reinterpret_cast <const char *>(&opt), sizeof (opt));
2095+ reinterpret_cast <const char *>(optval),
20832096#else
2084- #ifdef SO_REUSEPORT
2085- setsockopt (sock, SOL_SOCKET, SO_REUSEPORT,
2086- reinterpret_cast <const void *>(&opt), sizeof (opt));
2097+ optval,
2098+ #endif
2099+ optlen) == 0 ;
2100+ }
2101+
2102+ inline bool set_socket_opt (socket_t sock, int level, int optname, int optval) {
2103+ return set_socket_opt_impl (sock, level, optname, &optval, sizeof (optval));
2104+ }
2105+
2106+ inline bool set_socket_opt_time (socket_t sock, int level, int optname,
2107+ time_t sec, time_t usec) {
2108+ #ifdef _WIN32
2109+ auto timeout = static_cast <uint32_t >(sec * 1000 + usec / 1000 );
20872110#else
2088- setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
2089- reinterpret_cast <const void *>(&opt), sizeof (opt));
2111+ timeval timeout;
2112+ timeout.tv_sec = static_cast <long >(sec);
2113+ timeout.tv_usec = static_cast <decltype (timeout.tv_usec )>(usec);
20902114#endif
2115+ return set_socket_opt_impl (sock, level, optname, &timeout, sizeof (timeout));
2116+ }
2117+
2118+ } // namespace detail
2119+
2120+ inline void default_socket_options (socket_t sock) {
2121+ detail::set_socket_opt (sock, SOL_SOCKET,
2122+ #ifdef SO_REUSEPORT
2123+ SO_REUSEPORT,
2124+ #else
2125+ SO_REUSEADDR,
20912126#endif
2127+ 1 );
20922128}
20932129
20942130inline const char *status_message (int status) {
@@ -3605,26 +3641,10 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
36053641 }
36063642#endif
36073643
3608- if (tcp_nodelay) {
3609- auto opt = 1 ;
3610- #ifdef _WIN32
3611- setsockopt (sock, IPPROTO_TCP, TCP_NODELAY,
3612- reinterpret_cast <const char *>(&opt), sizeof (opt));
3613- #else
3614- setsockopt (sock, IPPROTO_TCP, TCP_NODELAY,
3615- reinterpret_cast <const void *>(&opt), sizeof (opt));
3616- #endif
3617- }
3644+ if (tcp_nodelay) { set_socket_opt (sock, IPPROTO_TCP, TCP_NODELAY, 1 ); }
36183645
36193646 if (rp->ai_family == AF_INET6) {
3620- auto opt = ipv6_v6only ? 1 : 0 ;
3621- #ifdef _WIN32
3622- setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
3623- reinterpret_cast <const char *>(&opt), sizeof (opt));
3624- #else
3625- setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
3626- reinterpret_cast <const void *>(&opt), sizeof (opt));
3627- #endif
3647+ set_socket_opt (sock, IPPROTO_IPV6, IPV6_V6ONLY, ipv6_v6only ? 1 : 0 );
36283648 }
36293649
36303650 if (socket_options) { socket_options (sock); }
@@ -3767,36 +3787,10 @@ inline socket_t create_client_socket(
37673787 }
37683788
37693789 set_nonblocking (sock2, false );
3770-
3771- {
3772- #ifdef _WIN32
3773- auto timeout = static_cast <uint32_t >(read_timeout_sec * 1000 +
3774- read_timeout_usec / 1000 );
3775- setsockopt (sock2, SOL_SOCKET, SO_RCVTIMEO,
3776- reinterpret_cast <const char *>(&timeout), sizeof (timeout));
3777- #else
3778- timeval tv;
3779- tv.tv_sec = static_cast <long >(read_timeout_sec);
3780- tv.tv_usec = static_cast <decltype (tv.tv_usec )>(read_timeout_usec);
3781- setsockopt (sock2, SOL_SOCKET, SO_RCVTIMEO,
3782- reinterpret_cast <const void *>(&tv), sizeof (tv));
3783- #endif
3784- }
3785- {
3786-
3787- #ifdef _WIN32
3788- auto timeout = static_cast <uint32_t >(write_timeout_sec * 1000 +
3789- write_timeout_usec / 1000 );
3790- setsockopt (sock2, SOL_SOCKET, SO_SNDTIMEO,
3791- reinterpret_cast <const char *>(&timeout), sizeof (timeout));
3792- #else
3793- timeval tv;
3794- tv.tv_sec = static_cast <long >(write_timeout_sec);
3795- tv.tv_usec = static_cast <decltype (tv.tv_usec )>(write_timeout_usec);
3796- setsockopt (sock2, SOL_SOCKET, SO_SNDTIMEO,
3797- reinterpret_cast <const void *>(&tv), sizeof (tv));
3798- #endif
3799- }
3790+ set_socket_opt_time (sock2, SOL_SOCKET, SO_RCVTIMEO, read_timeout_sec,
3791+ read_timeout_usec);
3792+ set_socket_opt_time (sock2, SOL_SOCKET, SO_SNDTIMEO, write_timeout_sec,
3793+ write_timeout_usec);
38003794
38013795 error = Error::Success;
38023796 return true ;
@@ -6946,35 +6940,10 @@ inline bool Server::listen_internal() {
69466940 break ;
69476941 }
69486942
6949- {
6950- #ifdef _WIN32
6951- auto timeout = static_cast <uint32_t >(read_timeout_sec_ * 1000 +
6952- read_timeout_usec_ / 1000 );
6953- setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO,
6954- reinterpret_cast <const char *>(&timeout), sizeof (timeout));
6955- #else
6956- timeval tv;
6957- tv.tv_sec = static_cast <long >(read_timeout_sec_);
6958- tv.tv_usec = static_cast <decltype (tv.tv_usec )>(read_timeout_usec_);
6959- setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO,
6960- reinterpret_cast <const void *>(&tv), sizeof (tv));
6961- #endif
6962- }
6963- {
6964-
6965- #ifdef _WIN32
6966- auto timeout = static_cast <uint32_t >(write_timeout_sec_ * 1000 +
6967- write_timeout_usec_ / 1000 );
6968- setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO,
6969- reinterpret_cast <const char *>(&timeout), sizeof (timeout));
6970- #else
6971- timeval tv;
6972- tv.tv_sec = static_cast <long >(write_timeout_sec_);
6973- tv.tv_usec = static_cast <decltype (tv.tv_usec )>(write_timeout_usec_);
6974- setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO,
6975- reinterpret_cast <const void *>(&tv), sizeof (tv));
6976- #endif
6977- }
6943+ detail::set_socket_opt_time (sock, SOL_SOCKET, SO_RCVTIMEO,
6944+ read_timeout_sec_, read_timeout_usec_);
6945+ detail::set_socket_opt_time (sock, SOL_SOCKET, SO_SNDTIMEO,
6946+ write_timeout_sec_, write_timeout_usec_);
69786947
69796948 if (!task_queue->enqueue (
69806949 [this , sock]() { process_and_close_socket (sock); })) {
@@ -9097,11 +9066,7 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
90979066 (void )(sock);
90989067 SSL_shutdown (ssl);
90999068#else
9100- timeval tv;
9101- tv.tv_sec = 1 ;
9102- tv.tv_usec = 0 ;
9103- setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO,
9104- reinterpret_cast <const void *>(&tv), sizeof (tv));
9069+ detail::set_socket_opt_time (sock, SOL_SOCKET, SO_RCVTIMEO, 1 , 0 );
91059070
91069071 auto ret = SSL_shutdown (ssl);
91079072 while (ret == 0 ) {
0 commit comments