1
0
mirror of synced 2025-04-19 00:24:02 +03:00

Refactor setting socket options (#2053)

Add detail::set_socket_opt() and detail::set_socket_opt_time() to avoid
repetition of platform-specific code.
This commit is contained in:
Florian Albrechtskirchinger 2025-02-15 04:40:24 +01:00 committed by GitHub
parent 03cf43ebaa
commit 233f0fb1b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

147
httplib.h
View File

@ -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) { namespace detail {
int opt = 1;
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 *>(optval),
reinterpret_cast<const char *>(&opt), sizeof(opt));
#else #else
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
timeval timeout;
timeout.tv_sec = static_cast<long>(sec);
timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(usec);
#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 #ifdef SO_REUSEPORT
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, SO_REUSEPORT,
reinterpret_cast<const void *>(&opt), sizeof(opt));
#else #else
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, SO_REUSEADDR,
reinterpret_cast<const void *>(&opt), sizeof(opt));
#endif
#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) { if (tcp_nodelay) { set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); }
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 (rp->ai_family == AF_INET6) { if (rp->ai_family == AF_INET6) {
auto opt = ipv6_v6only ? 1 : 0; set_socket_opt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 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
} }
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);
set_socket_opt_time(sock2, SOL_SOCKET, SO_RCVTIMEO, read_timeout_sec,
{ read_timeout_usec);
#ifdef _WIN32 set_socket_opt_time(sock2, SOL_SOCKET, SO_SNDTIMEO, write_timeout_sec,
auto timeout = static_cast<uint32_t>(read_timeout_sec * 1000 + write_timeout_usec);
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
}
error = Error::Success; error = Error::Success;
return true; return true;
@ -6946,35 +6940,10 @@ inline bool Server::listen_internal() {
break; break;
} }
{ detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO,
#ifdef _WIN32 read_timeout_sec_, read_timeout_usec_);
auto timeout = static_cast<uint32_t>(read_timeout_sec_ * 1000 + detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
read_timeout_usec_ / 1000); write_timeout_sec_, write_timeout_usec_);
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
}
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; detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO, 1, 0);
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<const void *>(&tv), sizeof(tv));
auto ret = SSL_shutdown(ssl); auto ret = SSL_shutdown(ssl);
while (ret == 0) { while (ret == 0) {