16
16
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
17
17
#endif
18
18
19
- #ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND
20
- #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND 0
21
- #endif
22
-
23
19
#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
24
20
#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5
25
21
#endif
@@ -180,6 +176,7 @@ using socket_t = int;
180
176
#include < array>
181
177
#include < atomic>
182
178
#include < cassert>
179
+ #include < cctype>
183
180
#include < climits>
184
181
#include < condition_variable>
185
182
#include < errno.h>
@@ -196,7 +193,6 @@ using socket_t = int;
196
193
#include < string>
197
194
#include < sys/stat.h>
198
195
#include < thread>
199
- #include < cctype>
200
196
201
197
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
202
198
#include < openssl/err.h>
@@ -596,6 +592,7 @@ class Server {
596
592
void set_socket_options (SocketOptions socket_options);
597
593
598
594
void set_keep_alive_max_count (size_t count);
595
+ void set_keep_alive_timeout (time_t sec);
599
596
void set_read_timeout (time_t sec, time_t usec = 0 );
600
597
void set_write_timeout (time_t sec, time_t usec = 0 );
601
598
void set_idle_interval (time_t sec, time_t usec = 0 );
@@ -620,6 +617,7 @@ class Server {
620
617
621
618
std::atomic<socket_t > svr_sock_;
622
619
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
620
+ time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
623
621
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
624
622
time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
625
623
time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
@@ -1740,7 +1738,7 @@ class BufferStream : public Stream {
1740
1738
size_t position = 0 ;
1741
1739
};
1742
1740
1743
- inline bool keep_alive (socket_t sock) {
1741
+ inline bool keep_alive (socket_t sock, time_t keep_alive_timeout_sec ) {
1744
1742
using namespace std ::chrono;
1745
1743
auto start = steady_clock::now ();
1746
1744
while (true ) {
@@ -1750,8 +1748,7 @@ inline bool keep_alive(socket_t sock) {
1750
1748
} else if (val == 0 ) {
1751
1749
auto current = steady_clock::now ();
1752
1750
auto duration = duration_cast<milliseconds>(current - start);
1753
- auto timeout = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND * 1000 +
1754
- CPPHTTPLIB_KEEPALIVE_TIMEOUT_USECOND / 1000 ;
1751
+ auto timeout = keep_alive_timeout_sec * 1000 ;
1755
1752
if (duration.count () > timeout) { return false ; }
1756
1753
std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
1757
1754
} else {
@@ -1761,13 +1758,13 @@ inline bool keep_alive(socket_t sock) {
1761
1758
}
1762
1759
1763
1760
template <typename T>
1764
- inline bool process_server_socket_core ( socket_t sock,
1765
- size_t keep_alive_max_count,
1766
- T callback) {
1761
+ inline bool
1762
+ process_server_socket_core ( socket_t sock, size_t keep_alive_max_count,
1763
+ time_t keep_alive_timeout_sec, T callback) {
1767
1764
assert (keep_alive_max_count > 0 );
1768
1765
auto ret = false ;
1769
1766
auto count = keep_alive_max_count;
1770
- while (count > 0 && keep_alive (sock)) {
1767
+ while (count > 0 && keep_alive (sock, keep_alive_timeout_sec )) {
1771
1768
auto close_connection = count == 1 ;
1772
1769
auto connection_closed = false ;
1773
1770
ret = callback (close_connection, connection_closed);
@@ -1778,13 +1775,13 @@ inline bool process_server_socket_core(socket_t sock,
1778
1775
}
1779
1776
1780
1777
template <typename T>
1781
- inline bool process_server_socket ( socket_t sock, size_t keep_alive_max_count,
1782
- time_t read_timeout_sec ,
1783
- time_t read_timeout_usec ,
1784
- time_t write_timeout_sec,
1785
- time_t write_timeout_usec, T callback) {
1778
+ inline bool
1779
+ process_server_socket ( socket_t sock, size_t keep_alive_max_count ,
1780
+ time_t keep_alive_timeout_sec, time_t read_timeout_sec ,
1781
+ time_t read_timeout_usec, time_t write_timeout_sec,
1782
+ time_t write_timeout_usec, T callback) {
1786
1783
return process_server_socket_core (
1787
- sock, keep_alive_max_count,
1784
+ sock, keep_alive_max_count, keep_alive_timeout_sec,
1788
1785
[&](bool close_connection, bool connection_closed) {
1789
1786
SocketStream strm (sock, read_timeout_sec, read_timeout_usec,
1790
1787
write_timeout_sec, write_timeout_usec);
@@ -2397,9 +2394,7 @@ class brotli_decompressor : public decompressor {
2397
2394
2398
2395
if (decoder_r == BROTLI_DECODER_RESULT_ERROR) { return false ; }
2399
2396
2400
- if (!callback (buff.data (), buff.size () - avail_out)) {
2401
- return false ;
2402
- }
2397
+ if (!callback (buff.data (), buff.size () - avail_out)) { return false ; }
2403
2398
}
2404
2399
2405
2400
return decoder_r == BROTLI_DECODER_RESULT_SUCCESS ||
@@ -3896,6 +3891,10 @@ inline void Server::set_keep_alive_max_count(size_t count) {
3896
3891
keep_alive_max_count_ = count;
3897
3892
}
3898
3893
3894
+ inline void Server::set_keep_alive_timeout (time_t sec) {
3895
+ keep_alive_timeout_sec_ = sec;
3896
+ }
3897
+
3899
3898
inline void Server::set_read_timeout (time_t sec, time_t usec) {
3900
3899
read_timeout_sec_ = sec;
3901
3900
read_timeout_usec_ = usec;
@@ -3979,10 +3978,11 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
3979
3978
// Headers
3980
3979
if (close_connection || req.get_header_value (" Connection" ) == " close" ) {
3981
3980
res.set_header (" Connection" , " close" );
3982
- }
3983
-
3984
- if (!close_connection && req.get_header_value (" Connection" ) == " Keep-Alive" ) {
3985
- res.set_header (" Connection" , " Keep-Alive" );
3981
+ } else {
3982
+ std::stringstream ss;
3983
+ ss << " timeout=" << keep_alive_timeout_sec_
3984
+ << " , max=" << keep_alive_max_count_;
3985
+ res.set_header (" Keep-Alive" , ss.str ());
3986
3986
}
3987
3987
3988
3988
if (!res.has_header (" Content-Type" ) &&
@@ -4583,8 +4583,8 @@ inline bool Server::is_valid() const { return true; }
4583
4583
4584
4584
inline bool Server::process_and_close_socket (socket_t sock) {
4585
4585
auto ret = detail::process_server_socket (
4586
- sock, keep_alive_max_count_, read_timeout_sec_, read_timeout_usec_ ,
4587
- write_timeout_sec_, write_timeout_usec_,
4586
+ sock, keep_alive_max_count_, keep_alive_timeout_sec_, read_timeout_sec_ ,
4587
+ read_timeout_usec_, write_timeout_sec_, write_timeout_usec_,
4588
4588
[this ](Stream &strm, bool close_connection, bool &connection_closed) {
4589
4589
return process_request (strm, close_connection, connection_closed,
4590
4590
nullptr );
@@ -5527,11 +5527,12 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl,
5527
5527
template <typename T>
5528
5528
inline bool
5529
5529
process_server_socket_ssl (SSL *ssl, socket_t sock, size_t keep_alive_max_count,
5530
+ time_t keep_alive_timeout_sec,
5530
5531
time_t read_timeout_sec, time_t read_timeout_usec,
5531
5532
time_t write_timeout_sec, time_t write_timeout_usec,
5532
5533
T callback) {
5533
5534
return process_server_socket_core (
5534
- sock, keep_alive_max_count,
5535
+ sock, keep_alive_max_count, keep_alive_timeout_sec,
5535
5536
[&](bool close_connection, bool connection_closed) {
5536
5537
SSLSocketStream strm (sock, ssl, read_timeout_sec, read_timeout_usec,
5537
5538
write_timeout_sec, write_timeout_usec);
@@ -5738,8 +5739,9 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
5738
5739
5739
5740
if (ssl) {
5740
5741
auto ret = detail::process_server_socket_ssl (
5741
- ssl, sock, keep_alive_max_count_, read_timeout_sec_, read_timeout_usec_,
5742
- write_timeout_sec_, write_timeout_usec_,
5742
+ ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
5743
+ read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
5744
+ write_timeout_usec_,
5743
5745
[this , ssl](Stream &strm, bool close_connection,
5744
5746
bool &connection_closed) {
5745
5747
return process_request (strm, close_connection, connection_closed,
0 commit comments