Skip to content

Commit 233f0fb

Browse files
Refactor setting socket options (#2053)
Add detail::set_socket_opt() and detail::set_socket_opt_time() to avoid repetition of platform-specific code.
1 parent 03cf43e commit 233f0fb

File tree

1 file changed

+56
-91
lines changed

1 file changed

+56
-91
lines changed

httplib.h

+56-91
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ using ssize_t = long;
193193
#endif
194194

195195
using 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

849850
using 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+
851862
void default_socket_options(socket_t sock);
852863

853864
const 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

20942130
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,
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

Comments
 (0)