@fugood/llama.node 0.3.12 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/darwin/arm64/llama-node.node +0 -0
- package/bin/darwin/x64/llama-node.node +0 -0
- package/bin/linux/arm64/llama-node.node +0 -0
- package/bin/linux/x64/llama-node.node +0 -0
- package/bin/linux-cuda/arm64/llama-node.node +0 -0
- package/bin/linux-cuda/x64/llama-node.node +0 -0
- package/bin/linux-vulkan/arm64/llama-node.node +0 -0
- package/bin/linux-vulkan/x64/llama-node.node +0 -0
- package/bin/win32/arm64/llama-node.node +0 -0
- package/bin/win32/arm64/node.lib +0 -0
- package/bin/win32/x64/llama-node.node +0 -0
- package/bin/win32/x64/node.lib +0 -0
- package/bin/win32-vulkan/arm64/llama-node.node +0 -0
- package/bin/win32-vulkan/arm64/node.lib +0 -0
- package/bin/win32-vulkan/x64/llama-node.node +0 -0
- package/bin/win32-vulkan/x64/node.lib +0 -0
- package/lib/binding.ts +1 -0
- package/package.json +1 -1
- package/src/LlamaCompletionWorker.cpp +14 -0
- package/src/LlamaContext.cpp +13 -4
- package/src/llama.cpp/.github/workflows/build.yml +35 -3
- package/src/llama.cpp/.github/workflows/docker.yml +2 -0
- package/src/llama.cpp/.github/workflows/labeler.yml +1 -1
- package/src/llama.cpp/common/CMakeLists.txt +20 -3
- package/src/llama.cpp/common/arg.cpp +180 -3
- package/src/llama.cpp/common/chat-template.hpp +21 -7
- package/src/llama.cpp/common/chat.cpp +220 -101
- package/src/llama.cpp/common/chat.hpp +3 -0
- package/src/llama.cpp/common/common.h +15 -7
- package/src/llama.cpp/common/llguidance.cpp +3 -3
- package/src/llama.cpp/common/log.cpp +1 -0
- package/src/llama.cpp/common/log.h +2 -1
- package/src/llama.cpp/common/minja.hpp +24 -9
- package/src/llama.cpp/common/sampling.cpp +52 -46
- package/src/llama.cpp/common/speculative.h +1 -1
- package/src/llama.cpp/docs/build.md +2 -2
- package/src/llama.cpp/examples/imatrix/imatrix.cpp +2 -1
- package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +6 -5
- package/src/llama.cpp/examples/llama.android/llama/src/main/cpp/CMakeLists.txt +1 -1
- package/src/llama.cpp/examples/perplexity/perplexity.cpp +1 -0
- package/src/llama.cpp/examples/run/run.cpp +5 -12
- package/src/llama.cpp/examples/server/CMakeLists.txt +1 -1
- package/src/llama.cpp/examples/server/httplib.h +381 -292
- package/src/llama.cpp/examples/server/server.cpp +58 -47
- package/src/llama.cpp/examples/server/utils.hpp +7 -5
- package/src/llama.cpp/ggml/include/ggml-cpu.h +1 -1
- package/src/llama.cpp/ggml/include/ggml-metal.h +1 -1
- package/src/llama.cpp/ggml/include/ggml-vulkan.h +0 -2
- package/src/llama.cpp/ggml/include/ggml.h +1 -1
- package/src/llama.cpp/ggml/src/ggml-common.h +0 -2
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-impl.h +6 -12
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-quants.c +852 -268
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.c +200 -107
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.cpp +2 -5
- package/src/llama.cpp/ggml/src/ggml-cpu/llamafile/sgemm.cpp +9 -8
- package/src/llama.cpp/ggml/src/ggml-cuda/CMakeLists.txt +2 -2
- package/src/llama.cpp/ggml/src/ggml-opencl/ggml-opencl.cpp +26 -4
- package/src/llama.cpp/ggml/src/ggml-sycl/ggml-sycl.cpp +6 -7
- package/src/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +812 -569
- package/src/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +25 -1
- package/src/llama.cpp/ggml/src/ggml.c +1 -1
- package/src/llama.cpp/include/llama.h +14 -10
- package/src/llama.cpp/src/llama-grammar.cpp +1 -1
- package/src/llama.cpp/src/llama-grammar.h +1 -1
- package/src/llama.cpp/src/llama-impl.h +6 -6
- package/src/llama.cpp/src/llama-kv-cache.h +1 -1
- package/src/llama.cpp/src/llama-mmap.h +1 -0
- package/src/llama.cpp/src/llama-model.cpp +1 -1
- package/src/llama.cpp/src/llama-sampling.cpp +131 -57
- package/src/llama.cpp/src/llama.cpp +7 -5
- package/src/llama.cpp/src/unicode.cpp +9 -2
- package/src/llama.cpp/tests/test-backend-ops.cpp +5 -5
- package/src/llama.cpp/tests/test-chat.cpp +237 -69
- package/src/llama.cpp/tests/test-gguf.cpp +4 -4
- package/src/llama.cpp/tests/test-sampling.cpp +15 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
//
|
|
2
2
|
// httplib.h
|
|
3
3
|
//
|
|
4
|
-
// Copyright (c)
|
|
4
|
+
// Copyright (c) 2025 Yuji Hirose. All rights reserved.
|
|
5
5
|
// MIT License
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#ifndef CPPHTTPLIB_HTTPLIB_H
|
|
9
9
|
#define CPPHTTPLIB_HTTPLIB_H
|
|
10
10
|
|
|
11
|
-
#define CPPHTTPLIB_VERSION "0.
|
|
11
|
+
#define CPPHTTPLIB_VERSION "0.19.0"
|
|
12
12
|
|
|
13
13
|
/*
|
|
14
14
|
* Configuration
|
|
@@ -66,6 +66,10 @@
|
|
|
66
66
|
#define CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND 0
|
|
67
67
|
#endif
|
|
68
68
|
|
|
69
|
+
#ifndef CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND
|
|
70
|
+
#define CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND 0
|
|
71
|
+
#endif
|
|
72
|
+
|
|
69
73
|
#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND
|
|
70
74
|
#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0
|
|
71
75
|
#endif
|
|
@@ -189,6 +193,7 @@ using ssize_t = long;
|
|
|
189
193
|
#endif
|
|
190
194
|
|
|
191
195
|
using socket_t = SOCKET;
|
|
196
|
+
using socklen_t = int;
|
|
192
197
|
#ifdef CPPHTTPLIB_USE_POLL
|
|
193
198
|
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
|
|
194
199
|
#endif
|
|
@@ -218,7 +223,9 @@ using socket_t = SOCKET;
|
|
|
218
223
|
#include <csignal>
|
|
219
224
|
#include <pthread.h>
|
|
220
225
|
#include <sys/mman.h>
|
|
226
|
+
#ifndef __VMS
|
|
221
227
|
#include <sys/select.h>
|
|
228
|
+
#endif
|
|
222
229
|
#include <sys/socket.h>
|
|
223
230
|
#include <sys/un.h>
|
|
224
231
|
#include <unistd.h>
|
|
@@ -662,6 +669,8 @@ struct Request {
|
|
|
662
669
|
ContentProvider content_provider_;
|
|
663
670
|
bool is_chunked_content_provider_ = false;
|
|
664
671
|
size_t authorization_count_ = 0;
|
|
672
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time_ =
|
|
673
|
+
std::chrono::steady_clock::time_point::min();
|
|
665
674
|
};
|
|
666
675
|
|
|
667
676
|
struct Response {
|
|
@@ -735,6 +744,8 @@ public:
|
|
|
735
744
|
virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0;
|
|
736
745
|
virtual socket_t socket() const = 0;
|
|
737
746
|
|
|
747
|
+
virtual time_t duration() const = 0;
|
|
748
|
+
|
|
738
749
|
ssize_t write(const char *ptr);
|
|
739
750
|
ssize_t write(const std::string &s);
|
|
740
751
|
};
|
|
@@ -838,6 +849,16 @@ using Logger = std::function<void(const Request &, const Response &)>;
|
|
|
838
849
|
|
|
839
850
|
using SocketOptions = std::function<void(socket_t sock)>;
|
|
840
851
|
|
|
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
|
+
|
|
841
862
|
void default_socket_options(socket_t sock);
|
|
842
863
|
|
|
843
864
|
const char *status_message(int status);
|
|
@@ -1421,6 +1442,10 @@ public:
|
|
|
1421
1442
|
template <class Rep, class Period>
|
|
1422
1443
|
void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);
|
|
1423
1444
|
|
|
1445
|
+
void set_max_timeout(time_t msec);
|
|
1446
|
+
template <class Rep, class Period>
|
|
1447
|
+
void set_max_timeout(const std::chrono::duration<Rep, Period> &duration);
|
|
1448
|
+
|
|
1424
1449
|
void set_basic_auth(const std::string &username, const std::string &password);
|
|
1425
1450
|
void set_bearer_token_auth(const std::string &token);
|
|
1426
1451
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
@@ -1529,6 +1554,7 @@ protected:
|
|
|
1529
1554
|
time_t read_timeout_usec_ = CPPHTTPLIB_CLIENT_READ_TIMEOUT_USECOND;
|
|
1530
1555
|
time_t write_timeout_sec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND;
|
|
1531
1556
|
time_t write_timeout_usec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND;
|
|
1557
|
+
time_t max_timeout_msec_ = CPPHTTPLIB_CLIENT_MAX_TIMEOUT_MSECOND;
|
|
1532
1558
|
|
|
1533
1559
|
std::string basic_auth_username_;
|
|
1534
1560
|
std::string basic_auth_password_;
|
|
@@ -1583,9 +1609,6 @@ private:
|
|
|
1583
1609
|
bool send_(Request &req, Response &res, Error &error);
|
|
1584
1610
|
Result send_(Request &&req);
|
|
1585
1611
|
|
|
1586
|
-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
1587
|
-
bool is_ssl_peer_could_be_closed(SSL *ssl) const;
|
|
1588
|
-
#endif
|
|
1589
1612
|
socket_t create_client_socket(Error &error) const;
|
|
1590
1613
|
bool read_response_line(Stream &strm, const Request &req,
|
|
1591
1614
|
Response &res) const;
|
|
@@ -1611,8 +1634,10 @@ private:
|
|
|
1611
1634
|
|
|
1612
1635
|
std::string adjust_host_string(const std::string &host) const;
|
|
1613
1636
|
|
|
1614
|
-
virtual bool
|
|
1615
|
-
|
|
1637
|
+
virtual bool
|
|
1638
|
+
process_socket(const Socket &socket,
|
|
1639
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
1640
|
+
std::function<bool(Stream &strm)> callback);
|
|
1616
1641
|
virtual bool is_ssl() const;
|
|
1617
1642
|
};
|
|
1618
1643
|
|
|
@@ -1854,6 +1879,10 @@ public:
|
|
|
1854
1879
|
template <class Rep, class Period>
|
|
1855
1880
|
void set_write_timeout(const std::chrono::duration<Rep, Period> &duration);
|
|
1856
1881
|
|
|
1882
|
+
void set_max_timeout(time_t msec);
|
|
1883
|
+
template <class Rep, class Period>
|
|
1884
|
+
void set_max_timeout(const std::chrono::duration<Rep, Period> &duration);
|
|
1885
|
+
|
|
1857
1886
|
void set_basic_auth(const std::string &username, const std::string &password);
|
|
1858
1887
|
void set_bearer_token_auth(const std::string &token);
|
|
1859
1888
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
@@ -1971,12 +2000,16 @@ private:
|
|
|
1971
2000
|
void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override;
|
|
1972
2001
|
void shutdown_ssl_impl(Socket &socket, bool shutdown_gracefully);
|
|
1973
2002
|
|
|
1974
|
-
bool
|
|
1975
|
-
|
|
2003
|
+
bool
|
|
2004
|
+
process_socket(const Socket &socket,
|
|
2005
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
2006
|
+
std::function<bool(Stream &strm)> callback) override;
|
|
1976
2007
|
bool is_ssl() const override;
|
|
1977
2008
|
|
|
1978
|
-
bool connect_with_proxy(
|
|
1979
|
-
|
|
2009
|
+
bool connect_with_proxy(
|
|
2010
|
+
Socket &sock,
|
|
2011
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
2012
|
+
Response &res, bool &success, Error &error);
|
|
1980
2013
|
bool initialize_ssl(Socket &socket, Error &error);
|
|
1981
2014
|
|
|
1982
2015
|
bool load_certs();
|
|
@@ -2053,20 +2086,45 @@ inline uint64_t Response::get_header_value_u64(const std::string &key,
|
|
|
2053
2086
|
return detail::get_header_value_u64(headers, key, def, id);
|
|
2054
2087
|
}
|
|
2055
2088
|
|
|
2056
|
-
|
|
2057
|
-
|
|
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,
|
|
2058
2094
|
#ifdef _WIN32
|
|
2059
|
-
|
|
2060
|
-
reinterpret_cast<const char *>(&opt), sizeof(opt));
|
|
2095
|
+
reinterpret_cast<const char *>(optval),
|
|
2061
2096
|
#else
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
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);
|
|
2065
2110
|
#else
|
|
2066
|
-
|
|
2067
|
-
|
|
2111
|
+
timeval timeout;
|
|
2112
|
+
timeout.tv_sec = static_cast<long>(sec);
|
|
2113
|
+
timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(usec);
|
|
2068
2114
|
#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,
|
|
2069
2126
|
#endif
|
|
2127
|
+
1);
|
|
2070
2128
|
}
|
|
2071
2129
|
|
|
2072
2130
|
inline const char *status_message(int status) {
|
|
@@ -2238,6 +2296,14 @@ inline void ClientImpl::set_write_timeout(
|
|
|
2238
2296
|
duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); });
|
|
2239
2297
|
}
|
|
2240
2298
|
|
|
2299
|
+
template <class Rep, class Period>
|
|
2300
|
+
inline void ClientImpl::set_max_timeout(
|
|
2301
|
+
const std::chrono::duration<Rep, Period> &duration) {
|
|
2302
|
+
auto msec =
|
|
2303
|
+
std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
|
|
2304
|
+
set_max_timeout(msec);
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2241
2307
|
template <class Rep, class Period>
|
|
2242
2308
|
inline void Client::set_connection_timeout(
|
|
2243
2309
|
const std::chrono::duration<Rep, Period> &duration) {
|
|
@@ -2256,6 +2322,12 @@ Client::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
|
|
|
2256
2322
|
cli_->set_write_timeout(duration);
|
|
2257
2323
|
}
|
|
2258
2324
|
|
|
2325
|
+
template <class Rep, class Period>
|
|
2326
|
+
inline void
|
|
2327
|
+
Client::set_max_timeout(const std::chrono::duration<Rep, Period> &duration) {
|
|
2328
|
+
cli_->set_max_timeout(duration);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2259
2331
|
/*
|
|
2260
2332
|
* Forward declarations and types that will be part of the .h file if split into
|
|
2261
2333
|
* .h + .cc.
|
|
@@ -2330,10 +2402,12 @@ void split(const char *b, const char *e, char d,
|
|
|
2330
2402
|
void split(const char *b, const char *e, char d, size_t m,
|
|
2331
2403
|
std::function<void(const char *, const char *)> fn);
|
|
2332
2404
|
|
|
2333
|
-
bool process_client_socket(
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2405
|
+
bool process_client_socket(
|
|
2406
|
+
socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
2407
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
2408
|
+
time_t max_timeout_msec,
|
|
2409
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
2410
|
+
std::function<bool(Stream &)> callback);
|
|
2337
2411
|
|
|
2338
2412
|
socket_t create_client_socket(const std::string &host, const std::string &ip,
|
|
2339
2413
|
int port, int address_family, bool tcp_nodelay,
|
|
@@ -2381,6 +2455,7 @@ public:
|
|
|
2381
2455
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
2382
2456
|
void get_local_ip_and_port(std::string &ip, int &port) const override;
|
|
2383
2457
|
socket_t socket() const override;
|
|
2458
|
+
time_t duration() const override;
|
|
2384
2459
|
|
|
2385
2460
|
const std::string &get_buffer() const;
|
|
2386
2461
|
|
|
@@ -2547,7 +2622,7 @@ inline bool is_obs_text(char c) { return 128 <= static_cast<unsigned char>(c); }
|
|
|
2547
2622
|
inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
|
|
2548
2623
|
|
|
2549
2624
|
inline bool is_field_content(const std::string &s) {
|
|
2550
|
-
if (s.empty()) { return
|
|
2625
|
+
if (s.empty()) { return true; }
|
|
2551
2626
|
|
|
2552
2627
|
if (s.size() == 1) {
|
|
2553
2628
|
return is_field_vchar(s[0]);
|
|
@@ -3171,60 +3246,43 @@ inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size,
|
|
|
3171
3246
|
});
|
|
3172
3247
|
}
|
|
3173
3248
|
|
|
3174
|
-
|
|
3249
|
+
template <bool Read>
|
|
3250
|
+
inline ssize_t select_impl(socket_t sock, time_t sec, time_t usec) {
|
|
3175
3251
|
#ifdef CPPHTTPLIB_USE_POLL
|
|
3176
|
-
struct pollfd
|
|
3177
|
-
|
|
3178
|
-
|
|
3252
|
+
struct pollfd pfd;
|
|
3253
|
+
pfd.fd = sock;
|
|
3254
|
+
pfd.events = (Read ? POLLIN : POLLOUT);
|
|
3179
3255
|
|
|
3180
3256
|
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
|
3181
3257
|
|
|
3182
|
-
return handle_EINTR([&]() { return poll(&
|
|
3258
|
+
return handle_EINTR([&]() { return poll(&pfd, 1, timeout); });
|
|
3183
3259
|
#else
|
|
3184
3260
|
#ifndef _WIN32
|
|
3185
3261
|
if (sock >= FD_SETSIZE) { return -1; }
|
|
3186
3262
|
#endif
|
|
3187
3263
|
|
|
3188
|
-
fd_set fds;
|
|
3264
|
+
fd_set fds, *rfds, *wfds;
|
|
3189
3265
|
FD_ZERO(&fds);
|
|
3190
3266
|
FD_SET(sock, &fds);
|
|
3267
|
+
rfds = (Read ? &fds : nullptr);
|
|
3268
|
+
wfds = (Read ? nullptr : &fds);
|
|
3191
3269
|
|
|
3192
3270
|
timeval tv;
|
|
3193
3271
|
tv.tv_sec = static_cast<long>(sec);
|
|
3194
3272
|
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);
|
|
3195
3273
|
|
|
3196
3274
|
return handle_EINTR([&]() {
|
|
3197
|
-
return select(static_cast<int>(sock + 1),
|
|
3275
|
+
return select(static_cast<int>(sock + 1), rfds, wfds, nullptr, &tv);
|
|
3198
3276
|
});
|
|
3199
3277
|
#endif
|
|
3200
3278
|
}
|
|
3201
3279
|
|
|
3202
|
-
inline ssize_t
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
pfd_read.fd = sock;
|
|
3206
|
-
pfd_read.events = POLLOUT;
|
|
3207
|
-
|
|
3208
|
-
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
|
3209
|
-
|
|
3210
|
-
return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); });
|
|
3211
|
-
#else
|
|
3212
|
-
#ifndef _WIN32
|
|
3213
|
-
if (sock >= FD_SETSIZE) { return -1; }
|
|
3214
|
-
#endif
|
|
3215
|
-
|
|
3216
|
-
fd_set fds;
|
|
3217
|
-
FD_ZERO(&fds);
|
|
3218
|
-
FD_SET(sock, &fds);
|
|
3219
|
-
|
|
3220
|
-
timeval tv;
|
|
3221
|
-
tv.tv_sec = static_cast<long>(sec);
|
|
3222
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);
|
|
3280
|
+
inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) {
|
|
3281
|
+
return select_impl<true>(sock, sec, usec);
|
|
3282
|
+
}
|
|
3223
3283
|
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
});
|
|
3227
|
-
#endif
|
|
3284
|
+
inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
|
|
3285
|
+
return select_impl<false>(sock, sec, usec);
|
|
3228
3286
|
}
|
|
3229
3287
|
|
|
3230
3288
|
inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
|
|
@@ -3298,7 +3356,10 @@ inline bool is_socket_alive(socket_t sock) {
|
|
|
3298
3356
|
class SocketStream final : public Stream {
|
|
3299
3357
|
public:
|
|
3300
3358
|
SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
3301
|
-
time_t write_timeout_sec, time_t write_timeout_usec
|
|
3359
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
3360
|
+
time_t max_timeout_msec = 0,
|
|
3361
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time =
|
|
3362
|
+
std::chrono::steady_clock::time_point::min());
|
|
3302
3363
|
~SocketStream() override;
|
|
3303
3364
|
|
|
3304
3365
|
bool is_readable() const override;
|
|
@@ -3308,6 +3369,7 @@ public:
|
|
|
3308
3369
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
3309
3370
|
void get_local_ip_and_port(std::string &ip, int &port) const override;
|
|
3310
3371
|
socket_t socket() const override;
|
|
3372
|
+
time_t duration() const override;
|
|
3311
3373
|
|
|
3312
3374
|
private:
|
|
3313
3375
|
socket_t sock_;
|
|
@@ -3315,6 +3377,8 @@ private:
|
|
|
3315
3377
|
time_t read_timeout_usec_;
|
|
3316
3378
|
time_t write_timeout_sec_;
|
|
3317
3379
|
time_t write_timeout_usec_;
|
|
3380
|
+
time_t max_timeout_msec_;
|
|
3381
|
+
const std::chrono::time_point<std::chrono::steady_clock> start_time;
|
|
3318
3382
|
|
|
3319
3383
|
std::vector<char> read_buff_;
|
|
3320
3384
|
size_t read_buff_off_ = 0;
|
|
@@ -3326,9 +3390,12 @@ private:
|
|
|
3326
3390
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
3327
3391
|
class SSLSocketStream final : public Stream {
|
|
3328
3392
|
public:
|
|
3329
|
-
SSLSocketStream(
|
|
3330
|
-
|
|
3331
|
-
|
|
3393
|
+
SSLSocketStream(
|
|
3394
|
+
socket_t sock, SSL *ssl, time_t read_timeout_sec,
|
|
3395
|
+
time_t read_timeout_usec, time_t write_timeout_sec,
|
|
3396
|
+
time_t write_timeout_usec, time_t max_timeout_msec = 0,
|
|
3397
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time =
|
|
3398
|
+
std::chrono::steady_clock::time_point::min());
|
|
3332
3399
|
~SSLSocketStream() override;
|
|
3333
3400
|
|
|
3334
3401
|
bool is_readable() const override;
|
|
@@ -3338,6 +3405,7 @@ public:
|
|
|
3338
3405
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
3339
3406
|
void get_local_ip_and_port(std::string &ip, int &port) const override;
|
|
3340
3407
|
socket_t socket() const override;
|
|
3408
|
+
time_t duration() const override;
|
|
3341
3409
|
|
|
3342
3410
|
private:
|
|
3343
3411
|
socket_t sock_;
|
|
@@ -3346,6 +3414,8 @@ private:
|
|
|
3346
3414
|
time_t read_timeout_usec_;
|
|
3347
3415
|
time_t write_timeout_sec_;
|
|
3348
3416
|
time_t write_timeout_usec_;
|
|
3417
|
+
time_t max_timeout_msec_;
|
|
3418
|
+
const std::chrono::time_point<std::chrono::steady_clock> start_time;
|
|
3349
3419
|
};
|
|
3350
3420
|
#endif
|
|
3351
3421
|
|
|
@@ -3416,13 +3486,15 @@ process_server_socket(const std::atomic<socket_t> &svr_sock, socket_t sock,
|
|
|
3416
3486
|
});
|
|
3417
3487
|
}
|
|
3418
3488
|
|
|
3419
|
-
inline bool process_client_socket(
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3489
|
+
inline bool process_client_socket(
|
|
3490
|
+
socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
3491
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
3492
|
+
time_t max_timeout_msec,
|
|
3493
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
3494
|
+
std::function<bool(Stream &)> callback) {
|
|
3424
3495
|
SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
|
|
3425
|
-
write_timeout_sec, write_timeout_usec
|
|
3496
|
+
write_timeout_sec, write_timeout_usec, max_timeout_msec,
|
|
3497
|
+
start_time);
|
|
3426
3498
|
return callback(strm);
|
|
3427
3499
|
}
|
|
3428
3500
|
|
|
@@ -3569,26 +3641,10 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
|
|
3569
3641
|
}
|
|
3570
3642
|
#endif
|
|
3571
3643
|
|
|
3572
|
-
if (tcp_nodelay) {
|
|
3573
|
-
auto opt = 1;
|
|
3574
|
-
#ifdef _WIN32
|
|
3575
|
-
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
|
3576
|
-
reinterpret_cast<const char *>(&opt), sizeof(opt));
|
|
3577
|
-
#else
|
|
3578
|
-
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
|
3579
|
-
reinterpret_cast<const void *>(&opt), sizeof(opt));
|
|
3580
|
-
#endif
|
|
3581
|
-
}
|
|
3644
|
+
if (tcp_nodelay) { set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); }
|
|
3582
3645
|
|
|
3583
3646
|
if (rp->ai_family == AF_INET6) {
|
|
3584
|
-
|
|
3585
|
-
#ifdef _WIN32
|
|
3586
|
-
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
|
3587
|
-
reinterpret_cast<const char *>(&opt), sizeof(opt));
|
|
3588
|
-
#else
|
|
3589
|
-
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
|
3590
|
-
reinterpret_cast<const void *>(&opt), sizeof(opt));
|
|
3591
|
-
#endif
|
|
3647
|
+
set_socket_opt(sock, IPPROTO_IPV6, IPV6_V6ONLY, ipv6_v6only ? 1 : 0);
|
|
3592
3648
|
}
|
|
3593
3649
|
|
|
3594
3650
|
if (socket_options) { socket_options(sock); }
|
|
@@ -3731,36 +3787,10 @@ inline socket_t create_client_socket(
|
|
|
3731
3787
|
}
|
|
3732
3788
|
|
|
3733
3789
|
set_nonblocking(sock2, false);
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
read_timeout_usec / 1000);
|
|
3739
|
-
setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
|
|
3740
|
-
reinterpret_cast<const char *>(&timeout), sizeof(timeout));
|
|
3741
|
-
#else
|
|
3742
|
-
timeval tv;
|
|
3743
|
-
tv.tv_sec = static_cast<long>(read_timeout_sec);
|
|
3744
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec);
|
|
3745
|
-
setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
|
|
3746
|
-
reinterpret_cast<const void *>(&tv), sizeof(tv));
|
|
3747
|
-
#endif
|
|
3748
|
-
}
|
|
3749
|
-
{
|
|
3750
|
-
|
|
3751
|
-
#ifdef _WIN32
|
|
3752
|
-
auto timeout = static_cast<uint32_t>(write_timeout_sec * 1000 +
|
|
3753
|
-
write_timeout_usec / 1000);
|
|
3754
|
-
setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
|
|
3755
|
-
reinterpret_cast<const char *>(&timeout), sizeof(timeout));
|
|
3756
|
-
#else
|
|
3757
|
-
timeval tv;
|
|
3758
|
-
tv.tv_sec = static_cast<long>(write_timeout_sec);
|
|
3759
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(write_timeout_usec);
|
|
3760
|
-
setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
|
|
3761
|
-
reinterpret_cast<const void *>(&tv), sizeof(tv));
|
|
3762
|
-
#endif
|
|
3763
|
-
}
|
|
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);
|
|
3764
3794
|
|
|
3765
3795
|
error = Error::Success;
|
|
3766
3796
|
return true;
|
|
@@ -4212,22 +4242,21 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
|
|
|
4212
4242
|
if (!key_len) { return false; }
|
|
4213
4243
|
|
|
4214
4244
|
auto key = std::string(beg, key_end);
|
|
4215
|
-
auto val = case_ignore::equal(key, "Location")
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
fn(key, val);
|
|
4245
|
+
// auto val = (case_ignore::equal(key, "Location") ||
|
|
4246
|
+
// case_ignore::equal(key, "Referer"))
|
|
4247
|
+
// ? std::string(p, end)
|
|
4248
|
+
// : decode_url(std::string(p, end), false);
|
|
4249
|
+
auto val = std::string(p, end);
|
|
4250
|
+
|
|
4251
|
+
if (!detail::fields::is_field_value(val)) { return false; }
|
|
4252
|
+
|
|
4253
|
+
if (case_ignore::equal(key, "Location") ||
|
|
4254
|
+
case_ignore::equal(key, "Referer")) {
|
|
4255
|
+
fn(key, val);
|
|
4256
|
+
} else {
|
|
4257
|
+
fn(key, decode_url(val, false));
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4231
4260
|
return true;
|
|
4232
4261
|
}
|
|
4233
4262
|
|
|
@@ -4263,7 +4292,7 @@ inline bool read_headers(Stream &strm, Headers &headers) {
|
|
|
4263
4292
|
auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
|
|
4264
4293
|
|
|
4265
4294
|
if (!parse_header(line_reader.ptr(), end,
|
|
4266
|
-
[&](const std::string &key, std::string &val) {
|
|
4295
|
+
[&](const std::string &key, const std::string &val) {
|
|
4267
4296
|
headers.emplace(key, val);
|
|
4268
4297
|
})) {
|
|
4269
4298
|
return false;
|
|
@@ -4312,7 +4341,7 @@ inline bool read_content_without_length(Stream &strm,
|
|
|
4312
4341
|
uint64_t r = 0;
|
|
4313
4342
|
for (;;) {
|
|
4314
4343
|
auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
|
|
4315
|
-
if (n <= 0) { return
|
|
4344
|
+
if (n <= 0) { return false; }
|
|
4316
4345
|
|
|
4317
4346
|
if (!out(buf, static_cast<size_t>(n), r, 0)) { return false; }
|
|
4318
4347
|
r += static_cast<uint64_t>(n);
|
|
@@ -4456,9 +4485,9 @@ bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status,
|
|
|
4456
4485
|
ret = read_content_without_length(strm, out);
|
|
4457
4486
|
} else {
|
|
4458
4487
|
auto is_invalid_value = false;
|
|
4459
|
-
auto len = get_header_value_u64(
|
|
4460
|
-
|
|
4461
|
-
|
|
4488
|
+
auto len = get_header_value_u64(
|
|
4489
|
+
x.headers, "Content-Length",
|
|
4490
|
+
(std::numeric_limits<uint64_t>::max)(), 0, is_invalid_value);
|
|
4462
4491
|
|
|
4463
4492
|
if (is_invalid_value) {
|
|
4464
4493
|
ret = false;
|
|
@@ -5380,10 +5409,14 @@ write_multipart_ranges_data(Stream &strm, const Request &req, Response &res,
|
|
|
5380
5409
|
|
|
5381
5410
|
inline bool expect_content(const Request &req) {
|
|
5382
5411
|
if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" ||
|
|
5383
|
-
req.method == "
|
|
5412
|
+
req.method == "DELETE") {
|
|
5413
|
+
return true;
|
|
5414
|
+
}
|
|
5415
|
+
if (req.has_header("Content-Length") &&
|
|
5416
|
+
req.get_header_value_u64("Content-Length") > 0) {
|
|
5384
5417
|
return true;
|
|
5385
5418
|
}
|
|
5386
|
-
|
|
5419
|
+
if (is_chunked_transfer_encoding(req.headers)) { return true; }
|
|
5387
5420
|
return false;
|
|
5388
5421
|
}
|
|
5389
5422
|
|
|
@@ -5428,9 +5461,76 @@ inline std::string SHA_256(const std::string &s) {
|
|
|
5428
5461
|
inline std::string SHA_512(const std::string &s) {
|
|
5429
5462
|
return message_digest(s, EVP_sha512());
|
|
5430
5463
|
}
|
|
5431
|
-
#endif
|
|
5432
5464
|
|
|
5433
|
-
|
|
5465
|
+
inline std::pair<std::string, std::string> make_digest_authentication_header(
|
|
5466
|
+
const Request &req, const std::map<std::string, std::string> &auth,
|
|
5467
|
+
size_t cnonce_count, const std::string &cnonce, const std::string &username,
|
|
5468
|
+
const std::string &password, bool is_proxy = false) {
|
|
5469
|
+
std::string nc;
|
|
5470
|
+
{
|
|
5471
|
+
std::stringstream ss;
|
|
5472
|
+
ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count;
|
|
5473
|
+
nc = ss.str();
|
|
5474
|
+
}
|
|
5475
|
+
|
|
5476
|
+
std::string qop;
|
|
5477
|
+
if (auth.find("qop") != auth.end()) {
|
|
5478
|
+
qop = auth.at("qop");
|
|
5479
|
+
if (qop.find("auth-int") != std::string::npos) {
|
|
5480
|
+
qop = "auth-int";
|
|
5481
|
+
} else if (qop.find("auth") != std::string::npos) {
|
|
5482
|
+
qop = "auth";
|
|
5483
|
+
} else {
|
|
5484
|
+
qop.clear();
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
std::string algo = "MD5";
|
|
5489
|
+
if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); }
|
|
5490
|
+
|
|
5491
|
+
std::string response;
|
|
5492
|
+
{
|
|
5493
|
+
auto H = algo == "SHA-256" ? detail::SHA_256
|
|
5494
|
+
: algo == "SHA-512" ? detail::SHA_512
|
|
5495
|
+
: detail::MD5;
|
|
5496
|
+
|
|
5497
|
+
auto A1 = username + ":" + auth.at("realm") + ":" + password;
|
|
5498
|
+
|
|
5499
|
+
auto A2 = req.method + ":" + req.path;
|
|
5500
|
+
if (qop == "auth-int") { A2 += ":" + H(req.body); }
|
|
5501
|
+
|
|
5502
|
+
if (qop.empty()) {
|
|
5503
|
+
response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2));
|
|
5504
|
+
} else {
|
|
5505
|
+
response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce +
|
|
5506
|
+
":" + qop + ":" + H(A2));
|
|
5507
|
+
}
|
|
5508
|
+
}
|
|
5509
|
+
|
|
5510
|
+
auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : "";
|
|
5511
|
+
|
|
5512
|
+
auto field = "Digest username=\"" + username + "\", realm=\"" +
|
|
5513
|
+
auth.at("realm") + "\", nonce=\"" + auth.at("nonce") +
|
|
5514
|
+
"\", uri=\"" + req.path + "\", algorithm=" + algo +
|
|
5515
|
+
(qop.empty() ? ", response=\""
|
|
5516
|
+
: ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" +
|
|
5517
|
+
cnonce + "\", response=\"") +
|
|
5518
|
+
response + "\"" +
|
|
5519
|
+
(opaque.empty() ? "" : ", opaque=\"" + opaque + "\"");
|
|
5520
|
+
|
|
5521
|
+
auto key = is_proxy ? "Proxy-Authorization" : "Authorization";
|
|
5522
|
+
return std::make_pair(key, field);
|
|
5523
|
+
}
|
|
5524
|
+
|
|
5525
|
+
inline bool is_ssl_peer_could_be_closed(SSL *ssl, socket_t sock) {
|
|
5526
|
+
detail::set_nonblocking(sock, true);
|
|
5527
|
+
auto se = detail::scope_exit([&]() { detail::set_nonblocking(sock, false); });
|
|
5528
|
+
|
|
5529
|
+
char buf[1];
|
|
5530
|
+
return !SSL_peek(ssl, buf, 1) &&
|
|
5531
|
+
SSL_get_error(ssl, 0) == SSL_ERROR_ZERO_RETURN;
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5434
5534
|
#ifdef _WIN32
|
|
5435
5535
|
// NOTE: This code came up with the following stackoverflow post:
|
|
5436
5536
|
// https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store
|
|
@@ -5569,68 +5669,6 @@ public:
|
|
|
5569
5669
|
static WSInit wsinit_;
|
|
5570
5670
|
#endif
|
|
5571
5671
|
|
|
5572
|
-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
5573
|
-
inline std::pair<std::string, std::string> make_digest_authentication_header(
|
|
5574
|
-
const Request &req, const std::map<std::string, std::string> &auth,
|
|
5575
|
-
size_t cnonce_count, const std::string &cnonce, const std::string &username,
|
|
5576
|
-
const std::string &password, bool is_proxy = false) {
|
|
5577
|
-
std::string nc;
|
|
5578
|
-
{
|
|
5579
|
-
std::stringstream ss;
|
|
5580
|
-
ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count;
|
|
5581
|
-
nc = ss.str();
|
|
5582
|
-
}
|
|
5583
|
-
|
|
5584
|
-
std::string qop;
|
|
5585
|
-
if (auth.find("qop") != auth.end()) {
|
|
5586
|
-
qop = auth.at("qop");
|
|
5587
|
-
if (qop.find("auth-int") != std::string::npos) {
|
|
5588
|
-
qop = "auth-int";
|
|
5589
|
-
} else if (qop.find("auth") != std::string::npos) {
|
|
5590
|
-
qop = "auth";
|
|
5591
|
-
} else {
|
|
5592
|
-
qop.clear();
|
|
5593
|
-
}
|
|
5594
|
-
}
|
|
5595
|
-
|
|
5596
|
-
std::string algo = "MD5";
|
|
5597
|
-
if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); }
|
|
5598
|
-
|
|
5599
|
-
std::string response;
|
|
5600
|
-
{
|
|
5601
|
-
auto H = algo == "SHA-256" ? detail::SHA_256
|
|
5602
|
-
: algo == "SHA-512" ? detail::SHA_512
|
|
5603
|
-
: detail::MD5;
|
|
5604
|
-
|
|
5605
|
-
auto A1 = username + ":" + auth.at("realm") + ":" + password;
|
|
5606
|
-
|
|
5607
|
-
auto A2 = req.method + ":" + req.path;
|
|
5608
|
-
if (qop == "auth-int") { A2 += ":" + H(req.body); }
|
|
5609
|
-
|
|
5610
|
-
if (qop.empty()) {
|
|
5611
|
-
response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2));
|
|
5612
|
-
} else {
|
|
5613
|
-
response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce +
|
|
5614
|
-
":" + qop + ":" + H(A2));
|
|
5615
|
-
}
|
|
5616
|
-
}
|
|
5617
|
-
|
|
5618
|
-
auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : "";
|
|
5619
|
-
|
|
5620
|
-
auto field = "Digest username=\"" + username + "\", realm=\"" +
|
|
5621
|
-
auth.at("realm") + "\", nonce=\"" + auth.at("nonce") +
|
|
5622
|
-
"\", uri=\"" + req.path + "\", algorithm=" + algo +
|
|
5623
|
-
(qop.empty() ? ", response=\""
|
|
5624
|
-
: ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" +
|
|
5625
|
-
cnonce + "\", response=\"") +
|
|
5626
|
-
response + "\"" +
|
|
5627
|
-
(opaque.empty() ? "" : ", opaque=\"" + opaque + "\"");
|
|
5628
|
-
|
|
5629
|
-
auto key = is_proxy ? "Proxy-Authorization" : "Authorization";
|
|
5630
|
-
return std::make_pair(key, field);
|
|
5631
|
-
}
|
|
5632
|
-
#endif
|
|
5633
|
-
|
|
5634
5672
|
inline bool parse_www_authenticate(const Response &res,
|
|
5635
5673
|
std::map<std::string, std::string> &auth,
|
|
5636
5674
|
bool is_proxy) {
|
|
@@ -5949,20 +5987,45 @@ inline ssize_t Stream::write(const std::string &s) {
|
|
|
5949
5987
|
|
|
5950
5988
|
namespace detail {
|
|
5951
5989
|
|
|
5990
|
+
inline void calc_actual_timeout(time_t max_timeout_msec,
|
|
5991
|
+
time_t duration_msec, time_t timeout_sec,
|
|
5992
|
+
time_t timeout_usec, time_t &actual_timeout_sec,
|
|
5993
|
+
time_t &actual_timeout_usec) {
|
|
5994
|
+
auto timeout_msec = (timeout_sec * 1000) + (timeout_usec / 1000);
|
|
5995
|
+
|
|
5996
|
+
auto actual_timeout_msec =
|
|
5997
|
+
std::min(max_timeout_msec - duration_msec, timeout_msec);
|
|
5998
|
+
|
|
5999
|
+
actual_timeout_sec = actual_timeout_msec / 1000;
|
|
6000
|
+
actual_timeout_usec = (actual_timeout_msec % 1000) * 1000;
|
|
6001
|
+
}
|
|
6002
|
+
|
|
5952
6003
|
// Socket stream implementation
|
|
5953
|
-
inline SocketStream::SocketStream(
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
6004
|
+
inline SocketStream::SocketStream(
|
|
6005
|
+
socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
6006
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
6007
|
+
time_t max_timeout_msec,
|
|
6008
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time)
|
|
5957
6009
|
: sock_(sock), read_timeout_sec_(read_timeout_sec),
|
|
5958
6010
|
read_timeout_usec_(read_timeout_usec),
|
|
5959
6011
|
write_timeout_sec_(write_timeout_sec),
|
|
5960
|
-
write_timeout_usec_(write_timeout_usec),
|
|
6012
|
+
write_timeout_usec_(write_timeout_usec),
|
|
6013
|
+
max_timeout_msec_(max_timeout_msec), start_time(start_time),
|
|
6014
|
+
read_buff_(read_buff_size_, 0) {}
|
|
5961
6015
|
|
|
5962
6016
|
inline SocketStream::~SocketStream() = default;
|
|
5963
6017
|
|
|
5964
6018
|
inline bool SocketStream::is_readable() const {
|
|
5965
|
-
|
|
6019
|
+
if (max_timeout_msec_ <= 0) {
|
|
6020
|
+
return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
|
|
6021
|
+
}
|
|
6022
|
+
|
|
6023
|
+
time_t read_timeout_sec;
|
|
6024
|
+
time_t read_timeout_usec;
|
|
6025
|
+
calc_actual_timeout(max_timeout_msec_, duration(), read_timeout_sec_,
|
|
6026
|
+
read_timeout_usec_, read_timeout_sec, read_timeout_usec);
|
|
6027
|
+
|
|
6028
|
+
return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
|
|
5966
6029
|
}
|
|
5967
6030
|
|
|
5968
6031
|
inline bool SocketStream::is_writable() const {
|
|
@@ -6039,6 +6102,12 @@ inline void SocketStream::get_local_ip_and_port(std::string &ip,
|
|
|
6039
6102
|
|
|
6040
6103
|
inline socket_t SocketStream::socket() const { return sock_; }
|
|
6041
6104
|
|
|
6105
|
+
inline time_t SocketStream::duration() const {
|
|
6106
|
+
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
6107
|
+
std::chrono::steady_clock::now() - start_time)
|
|
6108
|
+
.count();
|
|
6109
|
+
}
|
|
6110
|
+
|
|
6042
6111
|
// Buffer stream implementation
|
|
6043
6112
|
inline bool BufferStream::is_readable() const { return true; }
|
|
6044
6113
|
|
|
@@ -6067,6 +6136,8 @@ inline void BufferStream::get_local_ip_and_port(std::string & /*ip*/,
|
|
|
6067
6136
|
|
|
6068
6137
|
inline socket_t BufferStream::socket() const { return 0; }
|
|
6069
6138
|
|
|
6139
|
+
inline time_t BufferStream::duration() const { return 0; }
|
|
6140
|
+
|
|
6070
6141
|
inline const std::string &BufferStream::get_buffer() const { return buffer; }
|
|
6071
6142
|
|
|
6072
6143
|
inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
|
|
@@ -6869,35 +6940,10 @@ inline bool Server::listen_internal() {
|
|
|
6869
6940
|
break;
|
|
6870
6941
|
}
|
|
6871
6942
|
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
|
|
6877
|
-
reinterpret_cast<const char *>(&timeout), sizeof(timeout));
|
|
6878
|
-
#else
|
|
6879
|
-
timeval tv;
|
|
6880
|
-
tv.tv_sec = static_cast<long>(read_timeout_sec_);
|
|
6881
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec_);
|
|
6882
|
-
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
|
|
6883
|
-
reinterpret_cast<const void *>(&tv), sizeof(tv));
|
|
6884
|
-
#endif
|
|
6885
|
-
}
|
|
6886
|
-
{
|
|
6887
|
-
|
|
6888
|
-
#ifdef _WIN32
|
|
6889
|
-
auto timeout = static_cast<uint32_t>(write_timeout_sec_ * 1000 +
|
|
6890
|
-
write_timeout_usec_ / 1000);
|
|
6891
|
-
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
|
|
6892
|
-
reinterpret_cast<const char *>(&timeout), sizeof(timeout));
|
|
6893
|
-
#else
|
|
6894
|
-
timeval tv;
|
|
6895
|
-
tv.tv_sec = static_cast<long>(write_timeout_sec_);
|
|
6896
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(write_timeout_usec_);
|
|
6897
|
-
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
|
|
6898
|
-
reinterpret_cast<const void *>(&tv), sizeof(tv));
|
|
6899
|
-
#endif
|
|
6900
|
-
}
|
|
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_);
|
|
6901
6947
|
|
|
6902
6948
|
if (!task_queue->enqueue(
|
|
6903
6949
|
[this, sock]() { process_and_close_socket(sock); })) {
|
|
@@ -7157,14 +7203,6 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|
|
7157
7203
|
#endif
|
|
7158
7204
|
#endif
|
|
7159
7205
|
|
|
7160
|
-
// Check if the request URI doesn't exceed the limit
|
|
7161
|
-
if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
|
|
7162
|
-
Headers dummy;
|
|
7163
|
-
detail::read_headers(strm, dummy);
|
|
7164
|
-
res.status = StatusCode::UriTooLong_414;
|
|
7165
|
-
return write_response(strm, close_connection, req, res);
|
|
7166
|
-
}
|
|
7167
|
-
|
|
7168
7206
|
// Request line and headers
|
|
7169
7207
|
if (!parse_request_line(line_reader.ptr(), req) ||
|
|
7170
7208
|
!detail::read_headers(strm, req.headers)) {
|
|
@@ -7172,6 +7210,14 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|
|
7172
7210
|
return write_response(strm, close_connection, req, res);
|
|
7173
7211
|
}
|
|
7174
7212
|
|
|
7213
|
+
// Check if the request URI doesn't exceed the limit
|
|
7214
|
+
if (req.target.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
|
|
7215
|
+
Headers dummy;
|
|
7216
|
+
detail::read_headers(strm, dummy);
|
|
7217
|
+
res.status = StatusCode::UriTooLong_414;
|
|
7218
|
+
return write_response(strm, close_connection, req, res);
|
|
7219
|
+
}
|
|
7220
|
+
|
|
7175
7221
|
if (req.get_header_value("Connection") == "close") {
|
|
7176
7222
|
connection_closed = true;
|
|
7177
7223
|
}
|
|
@@ -7363,6 +7409,7 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) {
|
|
|
7363
7409
|
read_timeout_usec_ = rhs.read_timeout_usec_;
|
|
7364
7410
|
write_timeout_sec_ = rhs.write_timeout_sec_;
|
|
7365
7411
|
write_timeout_usec_ = rhs.write_timeout_usec_;
|
|
7412
|
+
max_timeout_msec_ = rhs.max_timeout_msec_;
|
|
7366
7413
|
basic_auth_username_ = rhs.basic_auth_username_;
|
|
7367
7414
|
basic_auth_password_ = rhs.basic_auth_password_;
|
|
7368
7415
|
bearer_token_auth_token_ = rhs.bearer_token_auth_token_;
|
|
@@ -7509,18 +7556,6 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) {
|
|
|
7509
7556
|
return ret;
|
|
7510
7557
|
}
|
|
7511
7558
|
|
|
7512
|
-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
7513
|
-
inline bool ClientImpl::is_ssl_peer_could_be_closed(SSL *ssl) const {
|
|
7514
|
-
detail::set_nonblocking(socket_.sock, true);
|
|
7515
|
-
auto se = detail::scope_exit(
|
|
7516
|
-
[&]() { detail::set_nonblocking(socket_.sock, false); });
|
|
7517
|
-
|
|
7518
|
-
char buf[1];
|
|
7519
|
-
return !SSL_peek(ssl, buf, 1) &&
|
|
7520
|
-
SSL_get_error(ssl, 0) == SSL_ERROR_ZERO_RETURN;
|
|
7521
|
-
}
|
|
7522
|
-
#endif
|
|
7523
|
-
|
|
7524
7559
|
inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
7525
7560
|
{
|
|
7526
7561
|
std::lock_guard<std::mutex> guard(socket_mutex_);
|
|
@@ -7535,7 +7570,9 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
7535
7570
|
|
|
7536
7571
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
7537
7572
|
if (is_alive && is_ssl()) {
|
|
7538
|
-
if (is_ssl_peer_could_be_closed(socket_.ssl)) {
|
|
7573
|
+
if (detail::is_ssl_peer_could_be_closed(socket_.ssl, socket_.sock)) {
|
|
7574
|
+
is_alive = false;
|
|
7575
|
+
}
|
|
7539
7576
|
}
|
|
7540
7577
|
#endif
|
|
7541
7578
|
|
|
@@ -7560,7 +7597,8 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
7560
7597
|
auto &scli = static_cast<SSLClient &>(*this);
|
|
7561
7598
|
if (!proxy_host_.empty() && proxy_port_ != -1) {
|
|
7562
7599
|
auto success = false;
|
|
7563
|
-
if (!scli.connect_with_proxy(socket_, res, success,
|
|
7600
|
+
if (!scli.connect_with_proxy(socket_, req.start_time_, res, success,
|
|
7601
|
+
error)) {
|
|
7564
7602
|
return success;
|
|
7565
7603
|
}
|
|
7566
7604
|
}
|
|
@@ -7606,7 +7644,7 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
7606
7644
|
}
|
|
7607
7645
|
});
|
|
7608
7646
|
|
|
7609
|
-
ret = process_socket(socket_, [&](Stream &strm) {
|
|
7647
|
+
ret = process_socket(socket_, req.start_time_, [&](Stream &strm) {
|
|
7610
7648
|
return handle_request(strm, req, res, close_connection, error);
|
|
7611
7649
|
});
|
|
7612
7650
|
|
|
@@ -8015,6 +8053,9 @@ inline Result ClientImpl::send_with_content_provider(
|
|
|
8015
8053
|
req.headers = headers;
|
|
8016
8054
|
req.path = path;
|
|
8017
8055
|
req.progress = progress;
|
|
8056
|
+
if (max_timeout_msec_ > 0) {
|
|
8057
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8058
|
+
}
|
|
8018
8059
|
|
|
8019
8060
|
auto error = Error::Success;
|
|
8020
8061
|
|
|
@@ -8041,7 +8082,7 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
|
|
|
8041
8082
|
if (is_ssl()) {
|
|
8042
8083
|
auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1;
|
|
8043
8084
|
if (!is_proxy_enabled) {
|
|
8044
|
-
if (is_ssl_peer_could_be_closed(socket_.ssl)) {
|
|
8085
|
+
if (detail::is_ssl_peer_could_be_closed(socket_.ssl, socket_.sock)) {
|
|
8045
8086
|
error = Error::SSLPeerCouldBeClosed_;
|
|
8046
8087
|
return false;
|
|
8047
8088
|
}
|
|
@@ -8166,12 +8207,14 @@ inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
|
|
|
8166
8207
|
};
|
|
8167
8208
|
}
|
|
8168
8209
|
|
|
8169
|
-
inline bool
|
|
8170
|
-
|
|
8171
|
-
|
|
8210
|
+
inline bool ClientImpl::process_socket(
|
|
8211
|
+
const Socket &socket,
|
|
8212
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
8213
|
+
std::function<bool(Stream &strm)> callback) {
|
|
8172
8214
|
return detail::process_client_socket(
|
|
8173
8215
|
socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
|
|
8174
|
-
write_timeout_usec_,
|
|
8216
|
+
write_timeout_usec_, max_timeout_msec_, start_time,
|
|
8217
|
+
std::move(callback));
|
|
8175
8218
|
}
|
|
8176
8219
|
|
|
8177
8220
|
inline bool ClientImpl::is_ssl() const { return false; }
|
|
@@ -8195,6 +8238,9 @@ inline Result ClientImpl::Get(const std::string &path, const Headers &headers,
|
|
|
8195
8238
|
req.path = path;
|
|
8196
8239
|
req.headers = headers;
|
|
8197
8240
|
req.progress = std::move(progress);
|
|
8241
|
+
if (max_timeout_msec_ > 0) {
|
|
8242
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8243
|
+
}
|
|
8198
8244
|
|
|
8199
8245
|
return send_(std::move(req));
|
|
8200
8246
|
}
|
|
@@ -8260,6 +8306,9 @@ inline Result ClientImpl::Get(const std::string &path, const Headers &headers,
|
|
|
8260
8306
|
return content_receiver(data, data_length);
|
|
8261
8307
|
};
|
|
8262
8308
|
req.progress = std::move(progress);
|
|
8309
|
+
if (max_timeout_msec_ > 0) {
|
|
8310
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8311
|
+
}
|
|
8263
8312
|
|
|
8264
8313
|
return send_(std::move(req));
|
|
8265
8314
|
}
|
|
@@ -8305,6 +8354,9 @@ inline Result ClientImpl::Head(const std::string &path,
|
|
|
8305
8354
|
req.method = "HEAD";
|
|
8306
8355
|
req.headers = headers;
|
|
8307
8356
|
req.path = path;
|
|
8357
|
+
if (max_timeout_msec_ > 0) {
|
|
8358
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8359
|
+
}
|
|
8308
8360
|
|
|
8309
8361
|
return send_(std::move(req));
|
|
8310
8362
|
}
|
|
@@ -8722,6 +8774,9 @@ inline Result ClientImpl::Delete(const std::string &path,
|
|
|
8722
8774
|
req.headers = headers;
|
|
8723
8775
|
req.path = path;
|
|
8724
8776
|
req.progress = progress;
|
|
8777
|
+
if (max_timeout_msec_ > 0) {
|
|
8778
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8779
|
+
}
|
|
8725
8780
|
|
|
8726
8781
|
if (!content_type.empty()) { req.set_header("Content-Type", content_type); }
|
|
8727
8782
|
req.body.assign(body, content_length);
|
|
@@ -8769,6 +8824,9 @@ inline Result ClientImpl::Options(const std::string &path,
|
|
|
8769
8824
|
req.method = "OPTIONS";
|
|
8770
8825
|
req.headers = headers;
|
|
8771
8826
|
req.path = path;
|
|
8827
|
+
if (max_timeout_msec_ > 0) {
|
|
8828
|
+
req.start_time_ = std::chrono::steady_clock::now();
|
|
8829
|
+
}
|
|
8772
8830
|
|
|
8773
8831
|
return send_(std::move(req));
|
|
8774
8832
|
}
|
|
@@ -8822,6 +8880,10 @@ inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) {
|
|
|
8822
8880
|
write_timeout_usec_ = usec;
|
|
8823
8881
|
}
|
|
8824
8882
|
|
|
8883
|
+
inline void ClientImpl::set_max_timeout(time_t msec) {
|
|
8884
|
+
max_timeout_msec_ = msec;
|
|
8885
|
+
}
|
|
8886
|
+
|
|
8825
8887
|
inline void ClientImpl::set_basic_auth(const std::string &username,
|
|
8826
8888
|
const std::string &password) {
|
|
8827
8889
|
basic_auth_username_ = username;
|
|
@@ -9004,11 +9066,7 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
|
|
|
9004
9066
|
(void)(sock);
|
|
9005
9067
|
SSL_shutdown(ssl);
|
|
9006
9068
|
#else
|
|
9007
|
-
|
|
9008
|
-
tv.tv_sec = 1;
|
|
9009
|
-
tv.tv_usec = 0;
|
|
9010
|
-
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
|
|
9011
|
-
reinterpret_cast<const void *>(&tv), sizeof(tv));
|
|
9069
|
+
detail::set_socket_opt_time(sock, SOL_SOCKET, SO_RCVTIMEO, 1, 0);
|
|
9012
9070
|
|
|
9013
9071
|
auto ret = SSL_shutdown(ssl);
|
|
9014
9072
|
while (ret == 0) {
|
|
@@ -9060,12 +9118,14 @@ inline bool process_server_socket_ssl(
|
|
|
9060
9118
|
}
|
|
9061
9119
|
|
|
9062
9120
|
template <typename T>
|
|
9063
|
-
inline bool
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9121
|
+
inline bool process_client_socket_ssl(
|
|
9122
|
+
SSL *ssl, socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
9123
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
9124
|
+
time_t max_timeout_msec,
|
|
9125
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time, T callback) {
|
|
9067
9126
|
SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
|
|
9068
|
-
write_timeout_sec, write_timeout_usec
|
|
9127
|
+
write_timeout_sec, write_timeout_usec,
|
|
9128
|
+
max_timeout_msec, start_time);
|
|
9069
9129
|
return callback(strm);
|
|
9070
9130
|
}
|
|
9071
9131
|
|
|
@@ -9078,27 +9138,37 @@ public:
|
|
|
9078
9138
|
};
|
|
9079
9139
|
|
|
9080
9140
|
// SSL socket stream implementation
|
|
9081
|
-
inline SSLSocketStream::SSLSocketStream(
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9141
|
+
inline SSLSocketStream::SSLSocketStream(
|
|
9142
|
+
socket_t sock, SSL *ssl, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
9143
|
+
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
9144
|
+
time_t max_timeout_msec,
|
|
9145
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time)
|
|
9086
9146
|
: sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec),
|
|
9087
9147
|
read_timeout_usec_(read_timeout_usec),
|
|
9088
9148
|
write_timeout_sec_(write_timeout_sec),
|
|
9089
|
-
write_timeout_usec_(write_timeout_usec)
|
|
9149
|
+
write_timeout_usec_(write_timeout_usec),
|
|
9150
|
+
max_timeout_msec_(max_timeout_msec), start_time(start_time) {
|
|
9090
9151
|
SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
|
|
9091
9152
|
}
|
|
9092
9153
|
|
|
9093
9154
|
inline SSLSocketStream::~SSLSocketStream() = default;
|
|
9094
9155
|
|
|
9095
9156
|
inline bool SSLSocketStream::is_readable() const {
|
|
9096
|
-
|
|
9157
|
+
if (max_timeout_msec_ <= 0) {
|
|
9158
|
+
return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
|
|
9159
|
+
}
|
|
9160
|
+
|
|
9161
|
+
time_t read_timeout_sec;
|
|
9162
|
+
time_t read_timeout_usec;
|
|
9163
|
+
calc_actual_timeout(max_timeout_msec_, duration(), read_timeout_sec_,
|
|
9164
|
+
read_timeout_usec_, read_timeout_sec, read_timeout_usec);
|
|
9165
|
+
|
|
9166
|
+
return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
|
|
9097
9167
|
}
|
|
9098
9168
|
|
|
9099
9169
|
inline bool SSLSocketStream::is_writable() const {
|
|
9100
9170
|
return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
|
|
9101
|
-
is_socket_alive(sock_);
|
|
9171
|
+
is_socket_alive(sock_) && !is_ssl_peer_could_be_closed(ssl_, sock_);
|
|
9102
9172
|
}
|
|
9103
9173
|
|
|
9104
9174
|
inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
|
|
@@ -9129,8 +9199,9 @@ inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
|
|
|
9129
9199
|
}
|
|
9130
9200
|
}
|
|
9131
9201
|
return ret;
|
|
9202
|
+
} else {
|
|
9203
|
+
return -1;
|
|
9132
9204
|
}
|
|
9133
|
-
return -1;
|
|
9134
9205
|
}
|
|
9135
9206
|
|
|
9136
9207
|
inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
|
|
@@ -9176,6 +9247,12 @@ inline void SSLSocketStream::get_local_ip_and_port(std::string &ip,
|
|
|
9176
9247
|
|
|
9177
9248
|
inline socket_t SSLSocketStream::socket() const { return sock_; }
|
|
9178
9249
|
|
|
9250
|
+
inline time_t SSLSocketStream::duration() const {
|
|
9251
|
+
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
9252
|
+
std::chrono::steady_clock::now() - start_time)
|
|
9253
|
+
.count();
|
|
9254
|
+
}
|
|
9255
|
+
|
|
9179
9256
|
static SSLInit sslinit_;
|
|
9180
9257
|
|
|
9181
9258
|
} // namespace detail
|
|
@@ -9416,16 +9493,22 @@ inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
|
|
|
9416
9493
|
}
|
|
9417
9494
|
|
|
9418
9495
|
// Assumes that socket_mutex_ is locked and that there are no requests in flight
|
|
9419
|
-
inline bool SSLClient::connect_with_proxy(
|
|
9420
|
-
|
|
9496
|
+
inline bool SSLClient::connect_with_proxy(
|
|
9497
|
+
Socket &socket,
|
|
9498
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
9499
|
+
Response &res, bool &success, Error &error) {
|
|
9421
9500
|
success = true;
|
|
9422
9501
|
Response proxy_res;
|
|
9423
9502
|
if (!detail::process_client_socket(
|
|
9424
9503
|
socket.sock, read_timeout_sec_, read_timeout_usec_,
|
|
9425
|
-
write_timeout_sec_, write_timeout_usec_,
|
|
9504
|
+
write_timeout_sec_, write_timeout_usec_, max_timeout_msec_,
|
|
9505
|
+
start_time, [&](Stream &strm) {
|
|
9426
9506
|
Request req2;
|
|
9427
9507
|
req2.method = "CONNECT";
|
|
9428
9508
|
req2.path = host_and_port_;
|
|
9509
|
+
if (max_timeout_msec_ > 0) {
|
|
9510
|
+
req2.start_time_ = std::chrono::steady_clock::now();
|
|
9511
|
+
}
|
|
9429
9512
|
return process_request(strm, req2, proxy_res, false, error);
|
|
9430
9513
|
})) {
|
|
9431
9514
|
// Thread-safe to close everything because we are assuming there are no
|
|
@@ -9445,7 +9528,8 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
|
|
|
9445
9528
|
proxy_res = Response();
|
|
9446
9529
|
if (!detail::process_client_socket(
|
|
9447
9530
|
socket.sock, read_timeout_sec_, read_timeout_usec_,
|
|
9448
|
-
write_timeout_sec_, write_timeout_usec_,
|
|
9531
|
+
write_timeout_sec_, write_timeout_usec_, max_timeout_msec_,
|
|
9532
|
+
start_time, [&](Stream &strm) {
|
|
9449
9533
|
Request req3;
|
|
9450
9534
|
req3.method = "CONNECT";
|
|
9451
9535
|
req3.path = host_and_port_;
|
|
@@ -9453,6 +9537,9 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
|
|
|
9453
9537
|
req3, auth, 1, detail::random_string(10),
|
|
9454
9538
|
proxy_digest_auth_username_, proxy_digest_auth_password_,
|
|
9455
9539
|
true));
|
|
9540
|
+
if (max_timeout_msec_ > 0) {
|
|
9541
|
+
req3.start_time_ = std::chrono::steady_clock::now();
|
|
9542
|
+
}
|
|
9456
9543
|
return process_request(strm, req3, proxy_res, false, error);
|
|
9457
9544
|
})) {
|
|
9458
9545
|
// Thread-safe to close everything because we are assuming there are
|
|
@@ -9608,13 +9695,15 @@ inline void SSLClient::shutdown_ssl_impl(Socket &socket,
|
|
|
9608
9695
|
assert(socket.ssl == nullptr);
|
|
9609
9696
|
}
|
|
9610
9697
|
|
|
9611
|
-
inline bool
|
|
9612
|
-
|
|
9613
|
-
|
|
9698
|
+
inline bool SSLClient::process_socket(
|
|
9699
|
+
const Socket &socket,
|
|
9700
|
+
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
|
9701
|
+
std::function<bool(Stream &strm)> callback) {
|
|
9614
9702
|
assert(socket.ssl);
|
|
9615
9703
|
return detail::process_client_socket_ssl(
|
|
9616
9704
|
socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_,
|
|
9617
|
-
write_timeout_sec_, write_timeout_usec_,
|
|
9705
|
+
write_timeout_sec_, write_timeout_usec_, max_timeout_msec_, start_time,
|
|
9706
|
+
std::move(callback));
|
|
9618
9707
|
}
|
|
9619
9708
|
|
|
9620
9709
|
inline bool SSLClient::is_ssl() const { return true; }
|