|
|
@@ -18,6 +18,10 @@
|
|
|
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
|
|
|
#endif
|
|
|
|
|
|
+#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND
|
|
|
+#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND 10000
|
|
|
+#endif
|
|
|
+
|
|
|
#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
|
|
|
#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 100
|
|
|
#endif
|
|
|
@@ -3251,6 +3255,41 @@ private:
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+inline bool keep_alive(const std::atomic<socket_t> &svr_sock, socket_t sock,
|
|
|
+ time_t keep_alive_timeout_sec) {
|
|
|
+ using namespace std::chrono;
|
|
|
+
|
|
|
+ const auto interval_usec =
|
|
|
+ CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND;
|
|
|
+
|
|
|
+ // Avoid expensive `steady_clock::now()` call for the first time
|
|
|
+ if (select_read(sock, 0, interval_usec) > 0) { return true; }
|
|
|
+
|
|
|
+ const auto start = steady_clock::now() - microseconds{interval_usec};
|
|
|
+ const auto timeout = seconds{keep_alive_timeout_sec};
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ if (svr_sock == INVALID_SOCKET) {
|
|
|
+ break; // Server socket is closed
|
|
|
+ }
|
|
|
+
|
|
|
+ auto val = select_read(sock, 0, interval_usec);
|
|
|
+ if (val < 0) {
|
|
|
+ break; // Ssocket error
|
|
|
+ } else if (val == 0) {
|
|
|
+ if (steady_clock::now() - start > timeout) {
|
|
|
+ break; // Timeout
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return true; // Ready for read
|
|
|
+ }
|
|
|
+
|
|
|
+ std::this_thread::sleep_for(microseconds{interval_usec});
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
template <typename T>
|
|
|
inline bool
|
|
|
process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
|
|
|
@@ -3259,8 +3298,7 @@ process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
|
|
|
assert(keep_alive_max_count > 0);
|
|
|
auto ret = false;
|
|
|
auto count = keep_alive_max_count;
|
|
|
- while (svr_sock != INVALID_SOCKET && count > 0 &&
|
|
|
- select_read(sock, keep_alive_timeout_sec, 0) > 0) {
|
|
|
+ while (count > 0 && keep_alive(svr_sock, sock, keep_alive_timeout_sec)) {
|
|
|
auto close_connection = count == 1;
|
|
|
auto connection_closed = false;
|
|
|
ret = callback(close_connection, connection_closed);
|