mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-26 12:24:46 +00:00
Add set_socket_opt function and corresponding test for TCP_NODELAY option (Resolve #2411)
This commit is contained in:
1 parent
6fd97aeca0
commit
9a97e948f0
2 files changed
+28
-15
No files matched your search
@@ -1480,6 +1480,8 @@ using SocketOptions = std::function<void(socket_t sock)>;
|
|||||||
|
|
||||||
void default_socket_options(socket_t sock);
|
void default_socket_options(socket_t sock);
|
||||||
|
|
||||||
|
bool set_socket_opt(socket_t sock, int level, int optname, int optval);
|
||||||
|
|
||||||
const char *status_message(int status);
|
const char *status_message(int status);
|
||||||
|
|
||||||
std::string to_string(Error error);
|
std::string to_string(Error error);
|
||||||
@@ -4338,10 +4340,6 @@ inline bool set_socket_opt_impl(socket_t sock, int level, int optname,
|
|||||||
optlen) == 0;
|
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,
|
inline bool set_socket_opt_time(socket_t sock, int level, int optname,
|
||||||
time_t sec, time_t usec) {
|
time_t sec, time_t usec) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -6089,7 +6087,7 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Setting SO_REUSEADDR seems not to work well with AF_UNIX on windows, so
|
// Setting SO_REUSEADDR seems not to work well with AF_UNIX on windows, so
|
||||||
// remove the option.
|
// remove the option.
|
||||||
detail::set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 0);
|
set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool dummy;
|
bool dummy;
|
||||||
@@ -9135,13 +9133,18 @@ inline bool setup_client_tls_session(const std::string &host, tls::ctx_t &ctx,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
inline void default_socket_options(socket_t sock) {
|
inline void default_socket_options(socket_t sock) {
|
||||||
detail::set_socket_opt(sock, SOL_SOCKET,
|
set_socket_opt(sock, SOL_SOCKET,
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
SO_REUSEPORT,
|
SO_REUSEPORT,
|
||||||
#else
|
#else
|
||||||
SO_REUSEADDR,
|
SO_REUSEADDR,
|
||||||
#endif
|
#endif
|
||||||
1);
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool set_socket_opt(socket_t sock, int level, int optname, int optval) {
|
||||||
|
return detail::set_socket_opt_impl(sock, level, optname, &optval,
|
||||||
|
sizeof(optval));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string get_bearer_token_auth(const Request &req) {
|
inline std::string get_bearer_token_auth(const Request &req) {
|
||||||
@@ -11561,9 +11564,7 @@ inline bool Server::listen_internal() {
|
|||||||
detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
|
detail::set_socket_opt_time(sock, SOL_SOCKET, SO_SNDTIMEO,
|
||||||
write_timeout_sec_, write_timeout_usec_);
|
write_timeout_sec_, write_timeout_usec_);
|
||||||
|
|
||||||
if (tcp_nodelay_) {
|
if (tcp_nodelay_) { set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); }
|
||||||
detail::set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!task_queue->enqueue(
|
if (!task_queue->enqueue(
|
||||||
[this, sock]() { process_and_close_socket(sock); })) {
|
[this, sock]() { process_and_close_socket(sock); })) {
|
||||||
|
|||||||
+15
-3
@@ -316,6 +316,19 @@ TEST(SocketStream, wait_writable_INET) {
|
|||||||
}
|
}
|
||||||
#endif // #ifndef _WIN32
|
#endif // #ifndef _WIN32
|
||||||
|
|
||||||
|
TEST(SetSocketOptTest, TcpNoDelay) {
|
||||||
|
auto sock = ::socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
ASSERT_NE(sock, INVALID_SOCKET);
|
||||||
|
EXPECT_TRUE(set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1));
|
||||||
|
|
||||||
|
int val = 0;
|
||||||
|
socklen_t len = sizeof(val);
|
||||||
|
ASSERT_EQ(0, ::getsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
||||||
|
reinterpret_cast<char *>(&val), &len));
|
||||||
|
EXPECT_NE(val, 0);
|
||||||
|
detail::close_socket(sock);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ClientTest, MoveConstructible) {
|
TEST(ClientTest, MoveConstructible) {
|
||||||
EXPECT_FALSE(std::is_copy_constructible<Client>::value);
|
EXPECT_FALSE(std::is_copy_constructible<Client>::value);
|
||||||
EXPECT_TRUE(std::is_nothrow_move_constructible<Client>::value);
|
EXPECT_TRUE(std::is_nothrow_move_constructible<Client>::value);
|
||||||
@@ -17315,8 +17328,7 @@ TEST(RequestSmugglingTest, UnconsumedGETBodyOnFileHandler) {
|
|||||||
"\r\n"
|
"\r\n"
|
||||||
"\r\n";
|
"\r\n";
|
||||||
|
|
||||||
auto sent =
|
auto sent = send(sock, outer_headers.data(), outer_headers.size(), 0);
|
||||||
send(sock, outer_headers.data(), outer_headers.size(), MSG_NOSIGNAL);
|
|
||||||
ASSERT_EQ(static_cast<ssize_t>(outer_headers.size()), sent);
|
ASSERT_EQ(static_cast<ssize_t>(outer_headers.size()), sent);
|
||||||
|
|
||||||
// Step 2: Read the first response (server serves file without reading body)
|
// Step 2: Read the first response (server serves file without reading body)
|
||||||
@@ -17346,7 +17358,7 @@ TEST(RequestSmugglingTest, UnconsumedGETBodyOnFileHandler) {
|
|||||||
|
|
||||||
// Step 3: Now send the body, which looks like a new HTTP request.
|
// Step 3: Now send the body, which looks like a new HTTP request.
|
||||||
// On a vulnerable server the keep-alive loop reads this as a second request.
|
// On a vulnerable server the keep-alive loop reads this as a second request.
|
||||||
sent = send(sock, smuggled.data(), smuggled.size(), MSG_NOSIGNAL);
|
sent = send(sock, smuggled.data(), smuggled.size(), 0);
|
||||||
ASSERT_EQ(static_cast<ssize_t>(smuggled.size()), sent);
|
ASSERT_EQ(static_cast<ssize_t>(smuggled.size()), sent);
|
||||||
|
|
||||||
// Step 4: Try to read a second response (should NOT exist after fix)
|
// Step 4: Try to read a second response (should NOT exist after fix)
|
||||||
|
|||||||
Reference in new issue
Block a user