@fugood/llama.node 0.3.16 → 0.3.17
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/CMakeLists.txt +3 -0
- 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 +5 -0
- package/package.json +1 -1
- package/src/LlamaCompletionWorker.cpp +8 -0
- package/src/LlamaCompletionWorker.h +1 -0
- package/src/LlamaContext.cpp +3 -2
- package/src/llama.cpp/.github/workflows/build-linux-cross.yml +124 -0
- package/src/llama.cpp/.github/workflows/build.yml +70 -27
- package/src/llama.cpp/.github/workflows/docker.yml +6 -6
- package/src/llama.cpp/.github/workflows/server.yml +7 -11
- package/src/llama.cpp/CMakeLists.txt +23 -1
- package/src/llama.cpp/common/CMakeLists.txt +6 -3
- package/src/llama.cpp/common/arg.cpp +809 -105
- package/src/llama.cpp/common/arg.h +9 -0
- package/src/llama.cpp/common/chat.cpp +1 -1
- package/src/llama.cpp/common/common.cpp +31 -521
- package/src/llama.cpp/common/common.h +17 -36
- package/src/llama.cpp/common/json-schema-to-grammar.cpp +3 -0
- package/src/llama.cpp/common/llguidance.cpp +30 -47
- package/src/llama.cpp/common/minja/chat-template.hpp +15 -7
- package/src/llama.cpp/common/minja/minja.hpp +119 -93
- package/src/llama.cpp/common/sampling.cpp +3 -0
- package/src/llama.cpp/docs/build.md +122 -7
- package/src/llama.cpp/examples/CMakeLists.txt +0 -9
- package/src/llama.cpp/examples/batched/batched.cpp +1 -1
- package/src/llama.cpp/examples/batched-bench/batched-bench.cpp +1 -1
- package/src/llama.cpp/examples/embedding/embedding.cpp +7 -1
- package/src/llama.cpp/examples/export-lora/export-lora.cpp +1 -1
- package/src/llama.cpp/examples/gguf-split/gguf-split.cpp +15 -16
- package/src/llama.cpp/examples/gritlm/gritlm.cpp +1 -1
- package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +210 -8
- package/src/llama.cpp/examples/llama.android/llama/build.gradle.kts +1 -0
- package/src/llama.cpp/examples/llava/CMakeLists.txt +39 -24
- package/src/llama.cpp/examples/llava/clip-impl.h +345 -0
- package/src/llama.cpp/examples/llava/clip.cpp +2152 -1803
- package/src/llama.cpp/examples/llava/clip.h +39 -22
- package/src/llama.cpp/examples/llava/deprecation-warning.cpp +22 -0
- package/src/llama.cpp/examples/llava/llava.cpp +64 -52
- package/src/llama.cpp/examples/llava/mtmd-cli.cpp +344 -0
- package/src/llama.cpp/examples/llava/mtmd.cpp +708 -0
- package/src/llama.cpp/examples/llava/mtmd.h +168 -0
- package/src/llama.cpp/examples/llava/{qwen2vl-cli.cpp → qwen2vl-test.cpp} +83 -31
- package/src/llama.cpp/examples/main/main.cpp +16 -5
- package/src/llama.cpp/examples/parallel/parallel.cpp +3 -1
- package/src/llama.cpp/examples/passkey/passkey.cpp +1 -1
- package/src/llama.cpp/examples/perplexity/perplexity.cpp +17 -3
- package/src/llama.cpp/examples/quantize/quantize.cpp +115 -2
- package/src/llama.cpp/examples/rpc/CMakeLists.txt +4 -2
- package/src/llama.cpp/examples/rpc/rpc-server.cpp +163 -8
- package/src/llama.cpp/examples/run/CMakeLists.txt +12 -1
- package/src/llama.cpp/examples/run/run.cpp +14 -28
- package/src/llama.cpp/examples/server/httplib.h +313 -247
- package/src/llama.cpp/examples/server/server.cpp +238 -139
- package/src/llama.cpp/examples/server/utils.hpp +51 -2
- package/src/llama.cpp/examples/speculative/speculative.cpp +1 -1
- package/src/llama.cpp/examples/speculative-simple/speculative-simple.cpp +1 -1
- package/src/llama.cpp/examples/sycl/build.sh +2 -2
- package/src/llama.cpp/examples/sycl/win-build-sycl.bat +2 -2
- package/src/llama.cpp/examples/tts/tts.cpp +6 -9
- package/src/llama.cpp/ggml/CMakeLists.txt +8 -2
- package/src/llama.cpp/ggml/cmake/GitVars.cmake +22 -0
- package/src/llama.cpp/ggml/include/ggml-cpu.h +5 -0
- package/src/llama.cpp/ggml/include/ggml-rpc.h +6 -1
- package/src/llama.cpp/ggml/include/ggml.h +66 -99
- package/src/llama.cpp/ggml/src/CMakeLists.txt +10 -7
- package/src/llama.cpp/ggml/src/ggml-cann/CMakeLists.txt +0 -2
- package/src/llama.cpp/ggml/src/ggml-cann/acl_tensor.cpp +8 -4
- package/src/llama.cpp/ggml/src/ggml-cann/acl_tensor.h +5 -5
- package/src/llama.cpp/ggml/src/ggml-cann/aclnn_ops.cpp +692 -1534
- package/src/llama.cpp/ggml/src/ggml-cann/aclnn_ops.h +613 -122
- package/src/llama.cpp/ggml/src/ggml-cann/common.h +135 -1
- package/src/llama.cpp/ggml/src/ggml-cann/ggml-cann.cpp +507 -137
- package/src/llama.cpp/ggml/src/ggml-common.h +12 -6
- package/src/llama.cpp/ggml/src/ggml-cpu/CMakeLists.txt +48 -22
- package/src/llama.cpp/ggml/src/ggml-cpu/binary-ops.cpp +158 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/binary-ops.h +16 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/common.h +72 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/cpu-feats-x86.cpp +1 -1
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-aarch64.cpp +896 -192
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-impl.h +2 -21
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-quants.c +754 -404
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.c +1003 -13519
- package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.cpp +2 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/kleidiai/kernels.cpp +2 -7
- package/src/llama.cpp/ggml/src/ggml-cpu/kleidiai/kernels.h +0 -1
- package/src/llama.cpp/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +3 -4
- package/src/llama.cpp/ggml/src/ggml-cpu/llamafile/sgemm.cpp +533 -88
- package/src/llama.cpp/ggml/src/ggml-cpu/ops.cpp +8809 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/ops.h +110 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/simd-mappings.h +892 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/unary-ops.cpp +186 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/unary-ops.h +28 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/vec.cpp +258 -0
- package/src/llama.cpp/ggml/src/ggml-cpu/vec.h +802 -0
- package/src/llama.cpp/ggml/src/ggml-cuda/vendors/hip.h +7 -0
- package/src/llama.cpp/ggml/src/ggml-cuda/vendors/musa.h +1 -0
- package/src/llama.cpp/ggml/src/ggml-hip/CMakeLists.txt +0 -4
- package/src/llama.cpp/ggml/src/ggml-impl.h +52 -18
- package/src/llama.cpp/ggml/src/ggml-metal/ggml-metal-impl.h +70 -3
- package/src/llama.cpp/ggml/src/ggml-opencl/CMakeLists.txt +67 -119
- package/src/llama.cpp/ggml/src/ggml-opencl/ggml-opencl.cpp +1023 -260
- package/src/llama.cpp/ggml/src/ggml-rpc/ggml-rpc.cpp +293 -40
- package/src/llama.cpp/ggml/src/ggml-sycl/CMakeLists.txt +96 -22
- package/src/llama.cpp/ggml/src/ggml-sycl/backend.hpp +1 -0
- package/src/llama.cpp/ggml/src/ggml-sycl/binbcast.cpp +350 -0
- package/src/llama.cpp/ggml/src/ggml-sycl/binbcast.hpp +39 -0
- package/src/llama.cpp/ggml/src/ggml-sycl/common.cpp +0 -35
- package/src/llama.cpp/ggml/src/ggml-sycl/common.hpp +2 -292
- package/src/llama.cpp/ggml/src/ggml-sycl/dpct/helper.hpp +79 -90
- package/src/llama.cpp/ggml/src/ggml-sycl/element_wise.cpp +967 -438
- package/src/llama.cpp/ggml/src/ggml-sycl/element_wise.hpp +22 -23
- package/src/llama.cpp/ggml/src/ggml-sycl/getrows.cpp +24 -20
- package/src/llama.cpp/ggml/src/ggml-sycl/getrows.hpp +1 -4
- package/src/llama.cpp/ggml/src/ggml-sycl/ggml-sycl.cpp +204 -280
- package/src/llama.cpp/ggml/src/ggml-sycl/im2col.cpp +84 -74
- package/src/llama.cpp/ggml/src/ggml-sycl/im2col.hpp +1 -3
- package/src/llama.cpp/ggml/src/ggml-sycl/norm.cpp +37 -49
- package/src/llama.cpp/ggml/src/ggml-sycl/norm.hpp +7 -22
- package/src/llama.cpp/ggml/src/ggml-sycl/outprod.cpp +4 -14
- package/src/llama.cpp/ggml/src/ggml-sycl/rope.cpp +204 -118
- package/src/llama.cpp/ggml/src/ggml-sycl/rope.hpp +1 -3
- package/src/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt +23 -0
- package/src/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +646 -114
- package/src/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +12 -0
- package/src/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +17 -8
- package/src/llama.cpp/ggml/src/ggml.c +141 -245
- package/src/llama.cpp/ggml/src/gguf.cpp +1 -0
- package/src/llama.cpp/include/llama.h +30 -11
- package/src/llama.cpp/models/ggml-vocab-llama4.gguf.inp +112 -0
- package/src/llama.cpp/models/ggml-vocab-llama4.gguf.out +46 -0
- package/src/llama.cpp/models/ggml-vocab-pixtral.gguf.inp +112 -0
- package/src/llama.cpp/models/ggml-vocab-pixtral.gguf.out +46 -0
- package/src/llama.cpp/requirements/requirements-all.txt +2 -0
- package/src/llama.cpp/requirements/requirements-gguf_editor_gui.txt +3 -0
- package/src/llama.cpp/src/CMakeLists.txt +3 -2
- package/src/llama.cpp/src/llama-adapter.cpp +37 -1
- package/src/llama.cpp/src/llama-arch.cpp +160 -17
- package/src/llama.cpp/src/llama-arch.h +16 -0
- package/src/llama.cpp/src/llama-chat.cpp +82 -17
- package/src/llama.cpp/src/llama-chat.h +6 -2
- package/src/llama.cpp/src/llama-context.cpp +108 -92
- package/src/llama.cpp/src/llama-context.h +1 -2
- package/src/llama.cpp/src/llama-graph.cpp +189 -119
- package/src/llama.cpp/src/llama-graph.h +26 -6
- package/src/llama.cpp/src/llama-hparams.h +13 -0
- package/src/llama.cpp/src/llama-kv-cache.cpp +70 -123
- package/src/llama.cpp/src/llama-kv-cache.h +41 -115
- package/src/llama.cpp/src/llama-memory.h +1 -1
- package/src/llama.cpp/src/llama-mmap.cpp +1 -1
- package/src/llama.cpp/src/llama-model-loader.cpp +10 -5
- package/src/llama.cpp/src/llama-model-loader.h +5 -3
- package/src/llama.cpp/src/llama-model.cpp +1760 -534
- package/src/llama.cpp/src/llama-model.h +13 -1
- package/src/llama.cpp/src/llama-quant.cpp +29 -8
- package/src/llama.cpp/src/llama-sampling.cpp +7 -1
- package/src/llama.cpp/src/llama-vocab.cpp +44 -6
- package/src/llama.cpp/src/llama.cpp +1 -1
- package/src/llama.cpp/tests/CMakeLists.txt +43 -30
- package/src/llama.cpp/tests/test-arg-parser.cpp +51 -4
- package/src/llama.cpp/tests/test-backend-ops.cpp +82 -43
- package/src/llama.cpp/tests/test-chat-template.cpp +34 -13
- package/src/llama.cpp/tests/test-chat.cpp +12 -2
- package/src/llama.cpp/{examples/gbnf-validator/gbnf-validator.cpp → tests/test-gbnf-validator.cpp} +2 -2
- package/src/llama.cpp/tests/test-grammar-integration.cpp +3 -2
- package/src/llama.cpp/tests/test-grammar-llguidance.cpp +63 -2
- package/src/llama.cpp/tests/test-grammar-parser.cpp +3 -1
- package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +17 -1
- package/src/llama.cpp/tests/test-llama-grammar.cpp +2 -1
- package/src/llama.cpp/{examples/quantize-stats/quantize-stats.cpp → tests/test-quantize-stats.cpp} +3 -1
- package/src/llama.cpp/tests/test-tokenizer-1-bpe.cpp +2 -1
- package/src/llama.cpp/tests/test-tokenizer-1-spm.cpp +2 -1
- package/src/llama.cpp/examples/gbnf-validator/CMakeLists.txt +0 -5
- package/src/llama.cpp/examples/llava/gemma3-cli.cpp +0 -341
- package/src/llama.cpp/examples/llava/llava-cli.cpp +0 -332
- package/src/llama.cpp/examples/llava/minicpmv-cli.cpp +0 -354
- package/src/llama.cpp/examples/quantize-stats/CMakeLists.txt +0 -6
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/CMakeLists.txt +0 -30
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/ascendc_kernels.h +0 -19
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/dup.cpp +0 -234
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/get_row_f16.cpp +0 -197
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/get_row_f32.cpp +0 -190
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/get_row_q4_0.cpp +0 -204
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/get_row_q8_0.cpp +0 -191
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/quantize_f16_q8_0.cpp +0 -218
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/quantize_f32_q8_0.cpp +0 -216
- package/src/llama.cpp/ggml/src/ggml-cann/kernels/quantize_float_to_q4_0.cpp +0 -295
|
@@ -8,7 +8,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.20.0"
|
|
12
12
|
|
|
13
13
|
/*
|
|
14
14
|
* Configuration
|
|
@@ -188,15 +188,16 @@ using ssize_t = long;
|
|
|
188
188
|
#include <winsock2.h>
|
|
189
189
|
#include <ws2tcpip.h>
|
|
190
190
|
|
|
191
|
+
// afunix.h uses types declared in winsock2.h, so has to be included after it.
|
|
192
|
+
#include <afunix.h>
|
|
193
|
+
|
|
191
194
|
#ifndef WSA_FLAG_NO_HANDLE_INHERIT
|
|
192
195
|
#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
|
|
193
196
|
#endif
|
|
194
197
|
|
|
198
|
+
using nfds_t = unsigned long;
|
|
195
199
|
using socket_t = SOCKET;
|
|
196
200
|
using socklen_t = int;
|
|
197
|
-
#ifdef CPPHTTPLIB_USE_POLL
|
|
198
|
-
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
|
|
199
|
-
#endif
|
|
200
201
|
|
|
201
202
|
#else // not _WIN32
|
|
202
203
|
|
|
@@ -216,16 +217,11 @@ using socklen_t = int;
|
|
|
216
217
|
#ifdef __linux__
|
|
217
218
|
#include <resolv.h>
|
|
218
219
|
#endif
|
|
220
|
+
#include <csignal>
|
|
219
221
|
#include <netinet/tcp.h>
|
|
220
|
-
#ifdef CPPHTTPLIB_USE_POLL
|
|
221
222
|
#include <poll.h>
|
|
222
|
-
#endif
|
|
223
|
-
#include <csignal>
|
|
224
223
|
#include <pthread.h>
|
|
225
224
|
#include <sys/mman.h>
|
|
226
|
-
#ifndef __VMS
|
|
227
|
-
#include <sys/select.h>
|
|
228
|
-
#endif
|
|
229
225
|
#include <sys/socket.h>
|
|
230
226
|
#include <sys/un.h>
|
|
231
227
|
#include <unistd.h>
|
|
@@ -247,7 +243,6 @@ using socket_t = int;
|
|
|
247
243
|
#include <errno.h>
|
|
248
244
|
#include <exception>
|
|
249
245
|
#include <fcntl.h>
|
|
250
|
-
#include <fstream>
|
|
251
246
|
#include <functional>
|
|
252
247
|
#include <iomanip>
|
|
253
248
|
#include <iostream>
|
|
@@ -320,6 +315,10 @@ using socket_t = int;
|
|
|
320
315
|
#include <brotli/encode.h>
|
|
321
316
|
#endif
|
|
322
317
|
|
|
318
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
319
|
+
#include <zstd.h>
|
|
320
|
+
#endif
|
|
321
|
+
|
|
323
322
|
/*
|
|
324
323
|
* Declaration
|
|
325
324
|
*/
|
|
@@ -435,6 +434,15 @@ private:
|
|
|
435
434
|
|
|
436
435
|
} // namespace detail
|
|
437
436
|
|
|
437
|
+
enum SSLVerifierResponse {
|
|
438
|
+
// no decision has been made, use the built-in certificate verifier
|
|
439
|
+
NoDecisionMade,
|
|
440
|
+
// connection certificate is verified and accepted
|
|
441
|
+
CertificateAccepted,
|
|
442
|
+
// connection certificate was processed but is rejected
|
|
443
|
+
CertificateRejected
|
|
444
|
+
};
|
|
445
|
+
|
|
438
446
|
enum StatusCode {
|
|
439
447
|
// Information responses
|
|
440
448
|
Continue_100 = 100,
|
|
@@ -670,7 +678,7 @@ struct Request {
|
|
|
670
678
|
bool is_chunked_content_provider_ = false;
|
|
671
679
|
size_t authorization_count_ = 0;
|
|
672
680
|
std::chrono::time_point<std::chrono::steady_clock> start_time_ =
|
|
673
|
-
std::chrono::steady_clock::time_point::min();
|
|
681
|
+
(std::chrono::steady_clock::time_point::min)();
|
|
674
682
|
};
|
|
675
683
|
|
|
676
684
|
struct Response {
|
|
@@ -736,7 +744,8 @@ public:
|
|
|
736
744
|
virtual ~Stream() = default;
|
|
737
745
|
|
|
738
746
|
virtual bool is_readable() const = 0;
|
|
739
|
-
virtual bool
|
|
747
|
+
virtual bool wait_readable() const = 0;
|
|
748
|
+
virtual bool wait_writable() const = 0;
|
|
740
749
|
|
|
741
750
|
virtual ssize_t read(char *ptr, size_t size) = 0;
|
|
742
751
|
virtual ssize_t write(const char *ptr, size_t size) = 0;
|
|
@@ -879,7 +888,7 @@ public:
|
|
|
879
888
|
* Captures parameters in request path and stores them in Request::path_params
|
|
880
889
|
*
|
|
881
890
|
* Capture name is a substring of a pattern from : to /.
|
|
882
|
-
* The rest of the pattern is matched
|
|
891
|
+
* The rest of the pattern is matched against the request path directly
|
|
883
892
|
* Parameters are captured starting from the next character after
|
|
884
893
|
* the end of the last matched static pattern fragment until the next /.
|
|
885
894
|
*
|
|
@@ -1109,7 +1118,7 @@ private:
|
|
|
1109
1118
|
virtual bool process_and_close_socket(socket_t sock);
|
|
1110
1119
|
|
|
1111
1120
|
std::atomic<bool> is_running_{false};
|
|
1112
|
-
std::atomic<bool>
|
|
1121
|
+
std::atomic<bool> is_decommissioned{false};
|
|
1113
1122
|
|
|
1114
1123
|
struct MountPointEntry {
|
|
1115
1124
|
std::string mount_point;
|
|
@@ -1483,7 +1492,8 @@ public:
|
|
|
1483
1492
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
1484
1493
|
void enable_server_certificate_verification(bool enabled);
|
|
1485
1494
|
void enable_server_hostname_verification(bool enabled);
|
|
1486
|
-
void set_server_certificate_verifier(
|
|
1495
|
+
void set_server_certificate_verifier(
|
|
1496
|
+
std::function<SSLVerifierResponse(SSL *ssl)> verifier);
|
|
1487
1497
|
#endif
|
|
1488
1498
|
|
|
1489
1499
|
void set_logger(Logger logger);
|
|
@@ -1600,7 +1610,7 @@ protected:
|
|
|
1600
1610
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
1601
1611
|
bool server_certificate_verification_ = true;
|
|
1602
1612
|
bool server_hostname_verification_ = true;
|
|
1603
|
-
std::function<
|
|
1613
|
+
std::function<SSLVerifierResponse(SSL *ssl)> server_certificate_verifier_;
|
|
1604
1614
|
#endif
|
|
1605
1615
|
|
|
1606
1616
|
Logger logger_;
|
|
@@ -1913,7 +1923,8 @@ public:
|
|
|
1913
1923
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
1914
1924
|
void enable_server_certificate_verification(bool enabled);
|
|
1915
1925
|
void enable_server_hostname_verification(bool enabled);
|
|
1916
|
-
void set_server_certificate_verifier(
|
|
1926
|
+
void set_server_certificate_verifier(
|
|
1927
|
+
std::function<SSLVerifierResponse(SSL *ssl)> verifier);
|
|
1917
1928
|
#endif
|
|
1918
1929
|
|
|
1919
1930
|
void set_logger(Logger logger);
|
|
@@ -2046,6 +2057,10 @@ inline void duration_to_sec_and_usec(const T &duration, U callback) {
|
|
|
2046
2057
|
callback(static_cast<time_t>(sec), static_cast<time_t>(usec));
|
|
2047
2058
|
}
|
|
2048
2059
|
|
|
2060
|
+
template <size_t N> inline constexpr size_t str_len(const char (&)[N]) {
|
|
2061
|
+
return N - 1;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2049
2064
|
inline bool is_numeric(const std::string &str) {
|
|
2050
2065
|
return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
|
|
2051
2066
|
}
|
|
@@ -2205,9 +2220,9 @@ inline const char *status_message(int status) {
|
|
|
2205
2220
|
|
|
2206
2221
|
inline std::string get_bearer_token_auth(const Request &req) {
|
|
2207
2222
|
if (req.has_header("Authorization")) {
|
|
2208
|
-
|
|
2223
|
+
constexpr auto bearer_header_prefix_len = detail::str_len("Bearer ");
|
|
2209
2224
|
return req.get_header_value("Authorization")
|
|
2210
|
-
.substr(
|
|
2225
|
+
.substr(bearer_header_prefix_len);
|
|
2211
2226
|
}
|
|
2212
2227
|
return "";
|
|
2213
2228
|
}
|
|
@@ -2382,8 +2397,6 @@ std::string encode_query_param(const std::string &value);
|
|
|
2382
2397
|
|
|
2383
2398
|
std::string decode_url(const std::string &s, bool convert_plus_to_space);
|
|
2384
2399
|
|
|
2385
|
-
void read_file(const std::string &path, std::string &out);
|
|
2386
|
-
|
|
2387
2400
|
std::string trim_copy(const std::string &s);
|
|
2388
2401
|
|
|
2389
2402
|
void divide(
|
|
@@ -2439,7 +2452,7 @@ ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags);
|
|
|
2439
2452
|
|
|
2440
2453
|
ssize_t read_socket(socket_t sock, void *ptr, size_t size, int flags);
|
|
2441
2454
|
|
|
2442
|
-
enum class EncodingType { None = 0, Gzip, Brotli };
|
|
2455
|
+
enum class EncodingType { None = 0, Gzip, Brotli, Zstd };
|
|
2443
2456
|
|
|
2444
2457
|
EncodingType encoding_type(const Request &req, const Response &res);
|
|
2445
2458
|
|
|
@@ -2449,7 +2462,8 @@ public:
|
|
|
2449
2462
|
~BufferStream() override = default;
|
|
2450
2463
|
|
|
2451
2464
|
bool is_readable() const override;
|
|
2452
|
-
bool
|
|
2465
|
+
bool wait_readable() const override;
|
|
2466
|
+
bool wait_writable() const override;
|
|
2453
2467
|
ssize_t read(char *ptr, size_t size) override;
|
|
2454
2468
|
ssize_t write(const char *ptr, size_t size) override;
|
|
2455
2469
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
@@ -2551,6 +2565,34 @@ private:
|
|
|
2551
2565
|
};
|
|
2552
2566
|
#endif
|
|
2553
2567
|
|
|
2568
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
2569
|
+
class zstd_compressor : public compressor {
|
|
2570
|
+
public:
|
|
2571
|
+
zstd_compressor();
|
|
2572
|
+
~zstd_compressor();
|
|
2573
|
+
|
|
2574
|
+
bool compress(const char *data, size_t data_length, bool last,
|
|
2575
|
+
Callback callback) override;
|
|
2576
|
+
|
|
2577
|
+
private:
|
|
2578
|
+
ZSTD_CCtx *ctx_ = nullptr;
|
|
2579
|
+
};
|
|
2580
|
+
|
|
2581
|
+
class zstd_decompressor : public decompressor {
|
|
2582
|
+
public:
|
|
2583
|
+
zstd_decompressor();
|
|
2584
|
+
~zstd_decompressor();
|
|
2585
|
+
|
|
2586
|
+
bool is_valid() const override;
|
|
2587
|
+
|
|
2588
|
+
bool decompress(const char *data, size_t data_length,
|
|
2589
|
+
Callback callback) override;
|
|
2590
|
+
|
|
2591
|
+
private:
|
|
2592
|
+
ZSTD_DCtx *ctx_ = nullptr;
|
|
2593
|
+
};
|
|
2594
|
+
#endif
|
|
2595
|
+
|
|
2554
2596
|
// NOTE: until the read size reaches `fixed_buffer_size`, use `fixed_buffer`
|
|
2555
2597
|
// to store data. The call can set memory on stack for performance.
|
|
2556
2598
|
class stream_line_reader {
|
|
@@ -2569,7 +2611,7 @@ private:
|
|
|
2569
2611
|
char *fixed_buffer_;
|
|
2570
2612
|
const size_t fixed_buffer_size_;
|
|
2571
2613
|
size_t fixed_buffer_used_size_ = 0;
|
|
2572
|
-
std::string
|
|
2614
|
+
std::string growable_buffer_;
|
|
2573
2615
|
};
|
|
2574
2616
|
|
|
2575
2617
|
class mmap {
|
|
@@ -2910,18 +2952,9 @@ inline std::string decode_url(const std::string &s,
|
|
|
2910
2952
|
return result;
|
|
2911
2953
|
}
|
|
2912
2954
|
|
|
2913
|
-
inline void read_file(const std::string &path, std::string &out) {
|
|
2914
|
-
std::ifstream fs(path, std::ios_base::binary);
|
|
2915
|
-
fs.seekg(0, std::ios_base::end);
|
|
2916
|
-
auto size = fs.tellg();
|
|
2917
|
-
fs.seekg(0);
|
|
2918
|
-
out.resize(static_cast<size_t>(size));
|
|
2919
|
-
fs.read(&out[0], static_cast<std::streamsize>(size));
|
|
2920
|
-
}
|
|
2921
|
-
|
|
2922
2955
|
inline std::string file_extension(const std::string &path) {
|
|
2923
2956
|
std::smatch m;
|
|
2924
|
-
|
|
2957
|
+
thread_local auto re = std::regex("\\.([a-zA-Z0-9]+)$");
|
|
2925
2958
|
if (std::regex_search(path, m, re)) { return m[1].str(); }
|
|
2926
2959
|
return std::string();
|
|
2927
2960
|
}
|
|
@@ -3005,18 +3038,18 @@ inline stream_line_reader::stream_line_reader(Stream &strm, char *fixed_buffer,
|
|
|
3005
3038
|
fixed_buffer_size_(fixed_buffer_size) {}
|
|
3006
3039
|
|
|
3007
3040
|
inline const char *stream_line_reader::ptr() const {
|
|
3008
|
-
if (
|
|
3041
|
+
if (growable_buffer_.empty()) {
|
|
3009
3042
|
return fixed_buffer_;
|
|
3010
3043
|
} else {
|
|
3011
|
-
return
|
|
3044
|
+
return growable_buffer_.data();
|
|
3012
3045
|
}
|
|
3013
3046
|
}
|
|
3014
3047
|
|
|
3015
3048
|
inline size_t stream_line_reader::size() const {
|
|
3016
|
-
if (
|
|
3049
|
+
if (growable_buffer_.empty()) {
|
|
3017
3050
|
return fixed_buffer_used_size_;
|
|
3018
3051
|
} else {
|
|
3019
|
-
return
|
|
3052
|
+
return growable_buffer_.size();
|
|
3020
3053
|
}
|
|
3021
3054
|
}
|
|
3022
3055
|
|
|
@@ -3027,7 +3060,7 @@ inline bool stream_line_reader::end_with_crlf() const {
|
|
|
3027
3060
|
|
|
3028
3061
|
inline bool stream_line_reader::getline() {
|
|
3029
3062
|
fixed_buffer_used_size_ = 0;
|
|
3030
|
-
|
|
3063
|
+
growable_buffer_.clear();
|
|
3031
3064
|
|
|
3032
3065
|
#ifndef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
|
|
3033
3066
|
char prev_byte = 0;
|
|
@@ -3065,11 +3098,11 @@ inline void stream_line_reader::append(char c) {
|
|
|
3065
3098
|
fixed_buffer_[fixed_buffer_used_size_++] = c;
|
|
3066
3099
|
fixed_buffer_[fixed_buffer_used_size_] = '\0';
|
|
3067
3100
|
} else {
|
|
3068
|
-
if (
|
|
3101
|
+
if (growable_buffer_.empty()) {
|
|
3069
3102
|
assert(fixed_buffer_[fixed_buffer_used_size_] == '\0');
|
|
3070
|
-
|
|
3103
|
+
growable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
|
|
3071
3104
|
}
|
|
3072
|
-
|
|
3105
|
+
growable_buffer_ += c;
|
|
3073
3106
|
}
|
|
3074
3107
|
}
|
|
3075
3108
|
|
|
@@ -3246,35 +3279,23 @@ inline ssize_t send_socket(socket_t sock, const void *ptr, size_t size,
|
|
|
3246
3279
|
});
|
|
3247
3280
|
}
|
|
3248
3281
|
|
|
3282
|
+
inline int poll_wrapper(struct pollfd *fds, nfds_t nfds, int timeout) {
|
|
3283
|
+
#ifdef _WIN32
|
|
3284
|
+
return ::WSAPoll(fds, nfds, timeout);
|
|
3285
|
+
#else
|
|
3286
|
+
return ::poll(fds, nfds, timeout);
|
|
3287
|
+
#endif
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3249
3290
|
template <bool Read>
|
|
3250
3291
|
inline ssize_t select_impl(socket_t sock, time_t sec, time_t usec) {
|
|
3251
|
-
#ifdef CPPHTTPLIB_USE_POLL
|
|
3252
3292
|
struct pollfd pfd;
|
|
3253
3293
|
pfd.fd = sock;
|
|
3254
3294
|
pfd.events = (Read ? POLLIN : POLLOUT);
|
|
3255
3295
|
|
|
3256
3296
|
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
|
3257
3297
|
|
|
3258
|
-
return handle_EINTR([&]() { return
|
|
3259
|
-
#else
|
|
3260
|
-
#ifndef _WIN32
|
|
3261
|
-
if (sock >= FD_SETSIZE) { return -1; }
|
|
3262
|
-
#endif
|
|
3263
|
-
|
|
3264
|
-
fd_set fds, *rfds, *wfds;
|
|
3265
|
-
FD_ZERO(&fds);
|
|
3266
|
-
FD_SET(sock, &fds);
|
|
3267
|
-
rfds = (Read ? &fds : nullptr);
|
|
3268
|
-
wfds = (Read ? nullptr : &fds);
|
|
3269
|
-
|
|
3270
|
-
timeval tv;
|
|
3271
|
-
tv.tv_sec = static_cast<long>(sec);
|
|
3272
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);
|
|
3273
|
-
|
|
3274
|
-
return handle_EINTR([&]() {
|
|
3275
|
-
return select(static_cast<int>(sock + 1), rfds, wfds, nullptr, &tv);
|
|
3276
|
-
});
|
|
3277
|
-
#endif
|
|
3298
|
+
return handle_EINTR([&]() { return poll_wrapper(&pfd, 1, timeout); });
|
|
3278
3299
|
}
|
|
3279
3300
|
|
|
3280
3301
|
inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) {
|
|
@@ -3287,14 +3308,14 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
|
|
|
3287
3308
|
|
|
3288
3309
|
inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
|
|
3289
3310
|
time_t usec) {
|
|
3290
|
-
#ifdef CPPHTTPLIB_USE_POLL
|
|
3291
3311
|
struct pollfd pfd_read;
|
|
3292
3312
|
pfd_read.fd = sock;
|
|
3293
3313
|
pfd_read.events = POLLIN | POLLOUT;
|
|
3294
3314
|
|
|
3295
3315
|
auto timeout = static_cast<int>(sec * 1000 + usec / 1000);
|
|
3296
3316
|
|
|
3297
|
-
auto poll_res =
|
|
3317
|
+
auto poll_res =
|
|
3318
|
+
handle_EINTR([&]() { return poll_wrapper(&pfd_read, 1, timeout); });
|
|
3298
3319
|
|
|
3299
3320
|
if (poll_res == 0) { return Error::ConnectionTimeout; }
|
|
3300
3321
|
|
|
@@ -3308,38 +3329,6 @@ inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
|
|
|
3308
3329
|
}
|
|
3309
3330
|
|
|
3310
3331
|
return Error::Connection;
|
|
3311
|
-
#else
|
|
3312
|
-
#ifndef _WIN32
|
|
3313
|
-
if (sock >= FD_SETSIZE) { return Error::Connection; }
|
|
3314
|
-
#endif
|
|
3315
|
-
|
|
3316
|
-
fd_set fdsr;
|
|
3317
|
-
FD_ZERO(&fdsr);
|
|
3318
|
-
FD_SET(sock, &fdsr);
|
|
3319
|
-
|
|
3320
|
-
auto fdsw = fdsr;
|
|
3321
|
-
auto fdse = fdsr;
|
|
3322
|
-
|
|
3323
|
-
timeval tv;
|
|
3324
|
-
tv.tv_sec = static_cast<long>(sec);
|
|
3325
|
-
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(usec);
|
|
3326
|
-
|
|
3327
|
-
auto ret = handle_EINTR([&]() {
|
|
3328
|
-
return select(static_cast<int>(sock + 1), &fdsr, &fdsw, &fdse, &tv);
|
|
3329
|
-
});
|
|
3330
|
-
|
|
3331
|
-
if (ret == 0) { return Error::ConnectionTimeout; }
|
|
3332
|
-
|
|
3333
|
-
if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) {
|
|
3334
|
-
auto error = 0;
|
|
3335
|
-
socklen_t len = sizeof(error);
|
|
3336
|
-
auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR,
|
|
3337
|
-
reinterpret_cast<char *>(&error), &len);
|
|
3338
|
-
auto successful = res >= 0 && !error;
|
|
3339
|
-
return successful ? Error::Success : Error::Connection;
|
|
3340
|
-
}
|
|
3341
|
-
return Error::Connection;
|
|
3342
|
-
#endif
|
|
3343
3332
|
}
|
|
3344
3333
|
|
|
3345
3334
|
inline bool is_socket_alive(socket_t sock) {
|
|
@@ -3359,11 +3348,12 @@ public:
|
|
|
3359
3348
|
time_t write_timeout_sec, time_t write_timeout_usec,
|
|
3360
3349
|
time_t max_timeout_msec = 0,
|
|
3361
3350
|
std::chrono::time_point<std::chrono::steady_clock> start_time =
|
|
3362
|
-
std::chrono::steady_clock::time_point::min());
|
|
3351
|
+
(std::chrono::steady_clock::time_point::min)());
|
|
3363
3352
|
~SocketStream() override;
|
|
3364
3353
|
|
|
3365
3354
|
bool is_readable() const override;
|
|
3366
|
-
bool
|
|
3355
|
+
bool wait_readable() const override;
|
|
3356
|
+
bool wait_writable() const override;
|
|
3367
3357
|
ssize_t read(char *ptr, size_t size) override;
|
|
3368
3358
|
ssize_t write(const char *ptr, size_t size) override;
|
|
3369
3359
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
@@ -3378,7 +3368,7 @@ private:
|
|
|
3378
3368
|
time_t write_timeout_sec_;
|
|
3379
3369
|
time_t write_timeout_usec_;
|
|
3380
3370
|
time_t max_timeout_msec_;
|
|
3381
|
-
const std::chrono::time_point<std::chrono::steady_clock>
|
|
3371
|
+
const std::chrono::time_point<std::chrono::steady_clock> start_time_;
|
|
3382
3372
|
|
|
3383
3373
|
std::vector<char> read_buff_;
|
|
3384
3374
|
size_t read_buff_off_ = 0;
|
|
@@ -3395,11 +3385,12 @@ public:
|
|
|
3395
3385
|
time_t read_timeout_usec, time_t write_timeout_sec,
|
|
3396
3386
|
time_t write_timeout_usec, time_t max_timeout_msec = 0,
|
|
3397
3387
|
std::chrono::time_point<std::chrono::steady_clock> start_time =
|
|
3398
|
-
std::chrono::steady_clock::time_point::min());
|
|
3388
|
+
(std::chrono::steady_clock::time_point::min)());
|
|
3399
3389
|
~SSLSocketStream() override;
|
|
3400
3390
|
|
|
3401
3391
|
bool is_readable() const override;
|
|
3402
|
-
bool
|
|
3392
|
+
bool wait_readable() const override;
|
|
3393
|
+
bool wait_writable() const override;
|
|
3403
3394
|
ssize_t read(char *ptr, size_t size) override;
|
|
3404
3395
|
ssize_t write(const char *ptr, size_t size) override;
|
|
3405
3396
|
void get_remote_ip_and_port(std::string &ip, int &port) const override;
|
|
@@ -3415,7 +3406,7 @@ private:
|
|
|
3415
3406
|
time_t write_timeout_sec_;
|
|
3416
3407
|
time_t write_timeout_usec_;
|
|
3417
3408
|
time_t max_timeout_msec_;
|
|
3418
|
-
const std::chrono::time_point<std::chrono::steady_clock>
|
|
3409
|
+
const std::chrono::time_point<std::chrono::steady_clock> start_time_;
|
|
3419
3410
|
};
|
|
3420
3411
|
#endif
|
|
3421
3412
|
|
|
@@ -3550,7 +3541,6 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
|
|
3550
3541
|
hints.ai_flags = socket_flags;
|
|
3551
3542
|
}
|
|
3552
3543
|
|
|
3553
|
-
#ifndef _WIN32
|
|
3554
3544
|
if (hints.ai_family == AF_UNIX) {
|
|
3555
3545
|
const auto addrlen = host.length();
|
|
3556
3546
|
if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; }
|
|
@@ -3574,11 +3564,19 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
|
|
3574
3564
|
sizeof(addr) - sizeof(addr.sun_path) + addrlen);
|
|
3575
3565
|
|
|
3576
3566
|
#ifndef SOCK_CLOEXEC
|
|
3567
|
+
#ifndef _WIN32
|
|
3577
3568
|
fcntl(sock, F_SETFD, FD_CLOEXEC);
|
|
3569
|
+
#endif
|
|
3578
3570
|
#endif
|
|
3579
3571
|
|
|
3580
3572
|
if (socket_options) { socket_options(sock); }
|
|
3581
3573
|
|
|
3574
|
+
#ifdef _WIN32
|
|
3575
|
+
// Setting SO_REUSEADDR seems not to work well with AF_UNIX on windows, so
|
|
3576
|
+
// remove the option.
|
|
3577
|
+
detail::set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 0);
|
|
3578
|
+
#endif
|
|
3579
|
+
|
|
3582
3580
|
bool dummy;
|
|
3583
3581
|
if (!bind_or_connect(sock, hints, dummy)) {
|
|
3584
3582
|
close_socket(sock);
|
|
@@ -3587,7 +3585,6 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
|
|
|
3587
3585
|
}
|
|
3588
3586
|
return sock;
|
|
3589
3587
|
}
|
|
3590
|
-
#endif
|
|
3591
3588
|
|
|
3592
3589
|
auto service = std::to_string(port);
|
|
3593
3590
|
|
|
@@ -3993,6 +3990,12 @@ inline EncodingType encoding_type(const Request &req, const Response &res) {
|
|
|
3993
3990
|
if (ret) { return EncodingType::Gzip; }
|
|
3994
3991
|
#endif
|
|
3995
3992
|
|
|
3993
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
3994
|
+
// TODO: 'Accept-Encoding' has zstd, not zstd;q=0
|
|
3995
|
+
ret = s.find("zstd") != std::string::npos;
|
|
3996
|
+
if (ret) { return EncodingType::Zstd; }
|
|
3997
|
+
#endif
|
|
3998
|
+
|
|
3996
3999
|
return EncodingType::None;
|
|
3997
4000
|
}
|
|
3998
4001
|
|
|
@@ -4201,6 +4204,61 @@ inline bool brotli_decompressor::decompress(const char *data,
|
|
|
4201
4204
|
}
|
|
4202
4205
|
#endif
|
|
4203
4206
|
|
|
4207
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
4208
|
+
inline zstd_compressor::zstd_compressor() {
|
|
4209
|
+
ctx_ = ZSTD_createCCtx();
|
|
4210
|
+
ZSTD_CCtx_setParameter(ctx_, ZSTD_c_compressionLevel, ZSTD_fast);
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
inline zstd_compressor::~zstd_compressor() { ZSTD_freeCCtx(ctx_); }
|
|
4214
|
+
|
|
4215
|
+
inline bool zstd_compressor::compress(const char *data, size_t data_length,
|
|
4216
|
+
bool last, Callback callback) {
|
|
4217
|
+
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
|
4218
|
+
|
|
4219
|
+
ZSTD_EndDirective mode = last ? ZSTD_e_end : ZSTD_e_continue;
|
|
4220
|
+
ZSTD_inBuffer input = {data, data_length, 0};
|
|
4221
|
+
|
|
4222
|
+
bool finished;
|
|
4223
|
+
do {
|
|
4224
|
+
ZSTD_outBuffer output = {buff.data(), CPPHTTPLIB_COMPRESSION_BUFSIZ, 0};
|
|
4225
|
+
size_t const remaining = ZSTD_compressStream2(ctx_, &output, &input, mode);
|
|
4226
|
+
|
|
4227
|
+
if (ZSTD_isError(remaining)) { return false; }
|
|
4228
|
+
|
|
4229
|
+
if (!callback(buff.data(), output.pos)) { return false; }
|
|
4230
|
+
|
|
4231
|
+
finished = last ? (remaining == 0) : (input.pos == input.size);
|
|
4232
|
+
|
|
4233
|
+
} while (!finished);
|
|
4234
|
+
|
|
4235
|
+
return true;
|
|
4236
|
+
}
|
|
4237
|
+
|
|
4238
|
+
inline zstd_decompressor::zstd_decompressor() { ctx_ = ZSTD_createDCtx(); }
|
|
4239
|
+
|
|
4240
|
+
inline zstd_decompressor::~zstd_decompressor() { ZSTD_freeDCtx(ctx_); }
|
|
4241
|
+
|
|
4242
|
+
inline bool zstd_decompressor::is_valid() const { return ctx_ != nullptr; }
|
|
4243
|
+
|
|
4244
|
+
inline bool zstd_decompressor::decompress(const char *data, size_t data_length,
|
|
4245
|
+
Callback callback) {
|
|
4246
|
+
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
|
4247
|
+
ZSTD_inBuffer input = {data, data_length, 0};
|
|
4248
|
+
|
|
4249
|
+
while (input.pos < input.size) {
|
|
4250
|
+
ZSTD_outBuffer output = {buff.data(), CPPHTTPLIB_COMPRESSION_BUFSIZ, 0};
|
|
4251
|
+
size_t const remaining = ZSTD_decompressStream(ctx_, &output, &input);
|
|
4252
|
+
|
|
4253
|
+
if (ZSTD_isError(remaining)) { return false; }
|
|
4254
|
+
|
|
4255
|
+
if (!callback(buff.data(), output.pos)) { return false; }
|
|
4256
|
+
}
|
|
4257
|
+
|
|
4258
|
+
return true;
|
|
4259
|
+
}
|
|
4260
|
+
#endif
|
|
4261
|
+
|
|
4204
4262
|
inline bool has_header(const Headers &headers, const std::string &key) {
|
|
4205
4263
|
return headers.find(key) != headers.end();
|
|
4206
4264
|
}
|
|
@@ -4227,6 +4285,9 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
|
|
|
4227
4285
|
p++;
|
|
4228
4286
|
}
|
|
4229
4287
|
|
|
4288
|
+
auto name = std::string(beg, p);
|
|
4289
|
+
if (!detail::fields::is_field_name(name)) { return false; }
|
|
4290
|
+
|
|
4230
4291
|
if (p == end) { return false; }
|
|
4231
4292
|
|
|
4232
4293
|
auto key_end = p;
|
|
@@ -4242,10 +4303,6 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
|
|
|
4242
4303
|
if (!key_len) { return false; }
|
|
4243
4304
|
|
|
4244
4305
|
auto key = std::string(beg, key_end);
|
|
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
4306
|
auto val = std::string(p, end);
|
|
4250
4307
|
|
|
4251
4308
|
if (!detail::fields::is_field_value(val)) { return false; }
|
|
@@ -4341,7 +4398,8 @@ inline bool read_content_without_length(Stream &strm,
|
|
|
4341
4398
|
uint64_t r = 0;
|
|
4342
4399
|
for (;;) {
|
|
4343
4400
|
auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
|
|
4344
|
-
if (n
|
|
4401
|
+
if (n == 0) { return true; }
|
|
4402
|
+
if (n < 0) { return false; }
|
|
4345
4403
|
|
|
4346
4404
|
if (!out(buf, static_cast<size_t>(n), r, 0)) { return false; }
|
|
4347
4405
|
r += static_cast<uint64_t>(n);
|
|
@@ -4384,7 +4442,7 @@ inline bool read_content_chunked(Stream &strm, T &x,
|
|
|
4384
4442
|
|
|
4385
4443
|
assert(chunk_len == 0);
|
|
4386
4444
|
|
|
4387
|
-
// NOTE: In RFC 9112, '7.1 Chunked Transfer Coding'
|
|
4445
|
+
// NOTE: In RFC 9112, '7.1 Chunked Transfer Coding' mentions "The chunked
|
|
4388
4446
|
// transfer coding is complete when a chunk with a chunk-size of zero is
|
|
4389
4447
|
// received, possibly followed by a trailer section, and finally terminated by
|
|
4390
4448
|
// an empty line". https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1
|
|
@@ -4394,8 +4452,8 @@ inline bool read_content_chunked(Stream &strm, T &x,
|
|
|
4394
4452
|
// to be ok whether the final CRLF exists or not in the chunked data.
|
|
4395
4453
|
// https://www.rfc-editor.org/rfc/rfc9112.html#section-7.1.3
|
|
4396
4454
|
//
|
|
4397
|
-
// According to the reference code in RFC 9112, cpp-
|
|
4398
|
-
//
|
|
4455
|
+
// According to the reference code in RFC 9112, cpp-httplib now allows
|
|
4456
|
+
// chunked transfer coding data without the final CRLF.
|
|
4399
4457
|
if (!line_reader.getline()) { return true; }
|
|
4400
4458
|
|
|
4401
4459
|
while (strcmp(line_reader.ptr(), "\r\n") != 0) {
|
|
@@ -4442,6 +4500,13 @@ bool prepare_content_receiver(T &x, int &status,
|
|
|
4442
4500
|
#else
|
|
4443
4501
|
status = StatusCode::UnsupportedMediaType_415;
|
|
4444
4502
|
return false;
|
|
4503
|
+
#endif
|
|
4504
|
+
} else if (encoding == "zstd") {
|
|
4505
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
4506
|
+
decompressor = detail::make_unique<zstd_decompressor>();
|
|
4507
|
+
#else
|
|
4508
|
+
status = StatusCode::UnsupportedMediaType_415;
|
|
4509
|
+
return false;
|
|
4445
4510
|
#endif
|
|
4446
4511
|
}
|
|
4447
4512
|
|
|
@@ -4565,7 +4630,7 @@ inline bool write_content(Stream &strm, const ContentProvider &content_provider,
|
|
|
4565
4630
|
|
|
4566
4631
|
data_sink.write = [&](const char *d, size_t l) -> bool {
|
|
4567
4632
|
if (ok) {
|
|
4568
|
-
if (
|
|
4633
|
+
if (write_data(strm, d, l)) {
|
|
4569
4634
|
offset += l;
|
|
4570
4635
|
} else {
|
|
4571
4636
|
ok = false;
|
|
@@ -4574,10 +4639,10 @@ inline bool write_content(Stream &strm, const ContentProvider &content_provider,
|
|
|
4574
4639
|
return ok;
|
|
4575
4640
|
};
|
|
4576
4641
|
|
|
4577
|
-
data_sink.is_writable = [&]() -> bool { return strm.
|
|
4642
|
+
data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
|
|
4578
4643
|
|
|
4579
4644
|
while (offset < end_offset && !is_shutting_down()) {
|
|
4580
|
-
if (!strm.
|
|
4645
|
+
if (!strm.wait_writable()) {
|
|
4581
4646
|
error = Error::Write;
|
|
4582
4647
|
return false;
|
|
4583
4648
|
} else if (!content_provider(offset, end_offset - offset, data_sink)) {
|
|
@@ -4615,17 +4680,17 @@ write_content_without_length(Stream &strm,
|
|
|
4615
4680
|
data_sink.write = [&](const char *d, size_t l) -> bool {
|
|
4616
4681
|
if (ok) {
|
|
4617
4682
|
offset += l;
|
|
4618
|
-
if (!
|
|
4683
|
+
if (!write_data(strm, d, l)) { ok = false; }
|
|
4619
4684
|
}
|
|
4620
4685
|
return ok;
|
|
4621
4686
|
};
|
|
4622
4687
|
|
|
4623
|
-
data_sink.is_writable = [&]() -> bool { return strm.
|
|
4688
|
+
data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
|
|
4624
4689
|
|
|
4625
4690
|
data_sink.done = [&](void) { data_available = false; };
|
|
4626
4691
|
|
|
4627
4692
|
while (data_available && !is_shutting_down()) {
|
|
4628
|
-
if (!strm.
|
|
4693
|
+
if (!strm.wait_writable()) {
|
|
4629
4694
|
return false;
|
|
4630
4695
|
} else if (!content_provider(offset, 0, data_sink)) {
|
|
4631
4696
|
return false;
|
|
@@ -4660,10 +4725,7 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
|
|
|
4660
4725
|
// Emit chunked response header and footer for each chunk
|
|
4661
4726
|
auto chunk =
|
|
4662
4727
|
from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
|
|
4663
|
-
if (!strm.
|
|
4664
|
-
!write_data(strm, chunk.data(), chunk.size())) {
|
|
4665
|
-
ok = false;
|
|
4666
|
-
}
|
|
4728
|
+
if (!write_data(strm, chunk.data(), chunk.size())) { ok = false; }
|
|
4667
4729
|
}
|
|
4668
4730
|
} else {
|
|
4669
4731
|
ok = false;
|
|
@@ -4672,7 +4734,7 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
|
|
|
4672
4734
|
return ok;
|
|
4673
4735
|
};
|
|
4674
4736
|
|
|
4675
|
-
data_sink.is_writable = [&]() -> bool { return strm.
|
|
4737
|
+
data_sink.is_writable = [&]() -> bool { return strm.wait_writable(); };
|
|
4676
4738
|
|
|
4677
4739
|
auto done_with_trailer = [&](const Headers *trailer) {
|
|
4678
4740
|
if (!ok) { return; }
|
|
@@ -4692,17 +4754,14 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
|
|
|
4692
4754
|
if (!payload.empty()) {
|
|
4693
4755
|
// Emit chunked response header and footer for each chunk
|
|
4694
4756
|
auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n";
|
|
4695
|
-
if (!strm.
|
|
4696
|
-
!write_data(strm, chunk.data(), chunk.size())) {
|
|
4757
|
+
if (!write_data(strm, chunk.data(), chunk.size())) {
|
|
4697
4758
|
ok = false;
|
|
4698
4759
|
return;
|
|
4699
4760
|
}
|
|
4700
4761
|
}
|
|
4701
4762
|
|
|
4702
|
-
|
|
4703
|
-
if (!write_data(strm, done_marker
|
|
4704
|
-
ok = false;
|
|
4705
|
-
}
|
|
4763
|
+
constexpr const char done_marker[] = "0\r\n";
|
|
4764
|
+
if (!write_data(strm, done_marker, str_len(done_marker))) { ok = false; }
|
|
4706
4765
|
|
|
4707
4766
|
// Trailer
|
|
4708
4767
|
if (trailer) {
|
|
@@ -4714,8 +4773,8 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
|
|
|
4714
4773
|
}
|
|
4715
4774
|
}
|
|
4716
4775
|
|
|
4717
|
-
|
|
4718
|
-
if (!write_data(strm, crlf
|
|
4776
|
+
constexpr const char crlf[] = "\r\n";
|
|
4777
|
+
if (!write_data(strm, crlf, str_len(crlf))) { ok = false; }
|
|
4719
4778
|
};
|
|
4720
4779
|
|
|
4721
4780
|
data_sink.done = [&](void) { done_with_trailer(nullptr); };
|
|
@@ -4725,7 +4784,7 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
|
|
|
4725
4784
|
};
|
|
4726
4785
|
|
|
4727
4786
|
while (data_available && !is_shutting_down()) {
|
|
4728
|
-
if (!strm.
|
|
4787
|
+
if (!strm.wait_writable()) {
|
|
4729
4788
|
error = Error::Write;
|
|
4730
4789
|
return false;
|
|
4731
4790
|
} else if (!content_provider(offset, 0, data_sink)) {
|
|
@@ -4957,13 +5016,13 @@ public:
|
|
|
4957
5016
|
return false;
|
|
4958
5017
|
}
|
|
4959
5018
|
|
|
4960
|
-
|
|
5019
|
+
constexpr const char header_content_type[] = "Content-Type:";
|
|
4961
5020
|
|
|
4962
5021
|
if (start_with_case_ignore(header, header_content_type)) {
|
|
4963
5022
|
file_.content_type =
|
|
4964
|
-
trim_copy(header.substr(header_content_type
|
|
5023
|
+
trim_copy(header.substr(str_len(header_content_type)));
|
|
4965
5024
|
} else {
|
|
4966
|
-
|
|
5025
|
+
thread_local const std::regex re_content_disposition(
|
|
4967
5026
|
R"~(^Content-Disposition:\s*form-data;\s*(.*)$)~",
|
|
4968
5027
|
std::regex_constants::icase);
|
|
4969
5028
|
|
|
@@ -4985,8 +5044,8 @@ public:
|
|
|
4985
5044
|
|
|
4986
5045
|
it = params.find("filename*");
|
|
4987
5046
|
if (it != params.end()) {
|
|
4988
|
-
// Only allow UTF-8
|
|
4989
|
-
|
|
5047
|
+
// Only allow UTF-8 encoding...
|
|
5048
|
+
thread_local const std::regex re_rfc5987_encoding(
|
|
4990
5049
|
R"~(^UTF-8''(.+?)$)~", std::regex_constants::icase);
|
|
4991
5050
|
|
|
4992
5051
|
std::smatch m2;
|
|
@@ -5058,10 +5117,10 @@ private:
|
|
|
5058
5117
|
file_.content_type.clear();
|
|
5059
5118
|
}
|
|
5060
5119
|
|
|
5061
|
-
bool start_with_case_ignore(const std::string &a,
|
|
5062
|
-
|
|
5063
|
-
if (a.size() <
|
|
5064
|
-
for (size_t i = 0; i <
|
|
5120
|
+
bool start_with_case_ignore(const std::string &a, const char *b) const {
|
|
5121
|
+
const auto b_len = strlen(b);
|
|
5122
|
+
if (a.size() < b_len) { return false; }
|
|
5123
|
+
for (size_t i = 0; i < b_len; i++) {
|
|
5065
5124
|
if (case_ignore::to_lower(a[i]) != case_ignore::to_lower(b[i])) {
|
|
5066
5125
|
return false;
|
|
5067
5126
|
}
|
|
@@ -5148,19 +5207,18 @@ private:
|
|
|
5148
5207
|
};
|
|
5149
5208
|
|
|
5150
5209
|
inline std::string random_string(size_t length) {
|
|
5151
|
-
|
|
5210
|
+
constexpr const char data[] =
|
|
5152
5211
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
5153
5212
|
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
static std::mt19937 engine(seed_sequence);
|
|
5213
|
+
thread_local auto engine([]() {
|
|
5214
|
+
// std::random_device might actually be deterministic on some
|
|
5215
|
+
// platforms, but due to lack of support in the c++ standard library,
|
|
5216
|
+
// doing better requires either some ugly hacks or breaking portability.
|
|
5217
|
+
std::random_device seed_gen;
|
|
5218
|
+
// Request 128 bits of entropy for initialization
|
|
5219
|
+
std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()};
|
|
5220
|
+
return std::mt19937(seed_sequence);
|
|
5221
|
+
}());
|
|
5164
5222
|
|
|
5165
5223
|
std::string result;
|
|
5166
5224
|
for (size_t i = 0; i < length; i++) {
|
|
@@ -5232,7 +5290,7 @@ serialize_multipart_formdata(const MultipartFormDataItems &items,
|
|
|
5232
5290
|
|
|
5233
5291
|
inline bool range_error(Request &req, Response &res) {
|
|
5234
5292
|
if (!req.ranges.empty() && 200 <= res.status && res.status < 300) {
|
|
5235
|
-
ssize_t
|
|
5293
|
+
ssize_t content_len = static_cast<ssize_t>(
|
|
5236
5294
|
res.content_length_ ? res.content_length_ : res.body.size());
|
|
5237
5295
|
|
|
5238
5296
|
ssize_t prev_first_pos = -1;
|
|
@@ -5252,12 +5310,12 @@ inline bool range_error(Request &req, Response &res) {
|
|
|
5252
5310
|
|
|
5253
5311
|
if (first_pos == -1 && last_pos == -1) {
|
|
5254
5312
|
first_pos = 0;
|
|
5255
|
-
last_pos =
|
|
5313
|
+
last_pos = content_len;
|
|
5256
5314
|
}
|
|
5257
5315
|
|
|
5258
5316
|
if (first_pos == -1) {
|
|
5259
|
-
first_pos =
|
|
5260
|
-
last_pos =
|
|
5317
|
+
first_pos = content_len - last_pos;
|
|
5318
|
+
last_pos = content_len - 1;
|
|
5261
5319
|
}
|
|
5262
5320
|
|
|
5263
5321
|
// NOTE: RFC-9110 '14.1.2. Byte Ranges':
|
|
@@ -5269,13 +5327,13 @@ inline bool range_error(Request &req, Response &res) {
|
|
|
5269
5327
|
// with a value that is one less than the current length of the selected
|
|
5270
5328
|
// representation).
|
|
5271
5329
|
// https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
|
|
5272
|
-
if (last_pos == -1 || last_pos >=
|
|
5273
|
-
last_pos =
|
|
5330
|
+
if (last_pos == -1 || last_pos >= content_len) {
|
|
5331
|
+
last_pos = content_len - 1;
|
|
5274
5332
|
}
|
|
5275
5333
|
|
|
5276
5334
|
// Range must be within content length
|
|
5277
5335
|
if (!(0 <= first_pos && first_pos <= last_pos &&
|
|
5278
|
-
last_pos <=
|
|
5336
|
+
last_pos <= content_len - 1)) {
|
|
5279
5337
|
return true;
|
|
5280
5338
|
}
|
|
5281
5339
|
|
|
@@ -5674,7 +5732,8 @@ inline bool parse_www_authenticate(const Response &res,
|
|
|
5674
5732
|
bool is_proxy) {
|
|
5675
5733
|
auto auth_key = is_proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
|
|
5676
5734
|
if (res.has_header(auth_key)) {
|
|
5677
|
-
|
|
5735
|
+
thread_local auto re =
|
|
5736
|
+
std::regex(R"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~");
|
|
5678
5737
|
auto s = res.get_header_value(auth_key);
|
|
5679
5738
|
auto pos = s.find(' ');
|
|
5680
5739
|
if (pos != std::string::npos) {
|
|
@@ -5758,7 +5817,7 @@ inline void hosted_at(const std::string &hostname,
|
|
|
5758
5817
|
inline std::string append_query_params(const std::string &path,
|
|
5759
5818
|
const Params ¶ms) {
|
|
5760
5819
|
std::string path_with_query = path;
|
|
5761
|
-
const
|
|
5820
|
+
thread_local const std::regex re("[^?]+\\?.*");
|
|
5762
5821
|
auto delm = std::regex_match(path, re) ? '&' : '?';
|
|
5763
5822
|
path_with_query += delm + detail::params_to_query_str(params);
|
|
5764
5823
|
return path_with_query;
|
|
@@ -5987,14 +6046,14 @@ inline ssize_t Stream::write(const std::string &s) {
|
|
|
5987
6046
|
|
|
5988
6047
|
namespace detail {
|
|
5989
6048
|
|
|
5990
|
-
inline void calc_actual_timeout(time_t max_timeout_msec,
|
|
5991
|
-
time_t
|
|
5992
|
-
time_t
|
|
6049
|
+
inline void calc_actual_timeout(time_t max_timeout_msec, time_t duration_msec,
|
|
6050
|
+
time_t timeout_sec, time_t timeout_usec,
|
|
6051
|
+
time_t &actual_timeout_sec,
|
|
5993
6052
|
time_t &actual_timeout_usec) {
|
|
5994
6053
|
auto timeout_msec = (timeout_sec * 1000) + (timeout_usec / 1000);
|
|
5995
6054
|
|
|
5996
6055
|
auto actual_timeout_msec =
|
|
5997
|
-
std::min(max_timeout_msec - duration_msec, timeout_msec);
|
|
6056
|
+
(std::min)(max_timeout_msec - duration_msec, timeout_msec);
|
|
5998
6057
|
|
|
5999
6058
|
actual_timeout_sec = actual_timeout_msec / 1000;
|
|
6000
6059
|
actual_timeout_usec = (actual_timeout_msec % 1000) * 1000;
|
|
@@ -6010,12 +6069,16 @@ inline SocketStream::SocketStream(
|
|
|
6010
6069
|
read_timeout_usec_(read_timeout_usec),
|
|
6011
6070
|
write_timeout_sec_(write_timeout_sec),
|
|
6012
6071
|
write_timeout_usec_(write_timeout_usec),
|
|
6013
|
-
max_timeout_msec_(max_timeout_msec),
|
|
6072
|
+
max_timeout_msec_(max_timeout_msec), start_time_(start_time),
|
|
6014
6073
|
read_buff_(read_buff_size_, 0) {}
|
|
6015
6074
|
|
|
6016
6075
|
inline SocketStream::~SocketStream() = default;
|
|
6017
6076
|
|
|
6018
6077
|
inline bool SocketStream::is_readable() const {
|
|
6078
|
+
return read_buff_off_ < read_buff_content_size_;
|
|
6079
|
+
}
|
|
6080
|
+
|
|
6081
|
+
inline bool SocketStream::wait_readable() const {
|
|
6019
6082
|
if (max_timeout_msec_ <= 0) {
|
|
6020
6083
|
return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
|
|
6021
6084
|
}
|
|
@@ -6028,7 +6091,7 @@ inline bool SocketStream::is_readable() const {
|
|
|
6028
6091
|
return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
|
|
6029
6092
|
}
|
|
6030
6093
|
|
|
6031
|
-
inline bool SocketStream::
|
|
6094
|
+
inline bool SocketStream::wait_writable() const {
|
|
6032
6095
|
return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
|
|
6033
6096
|
is_socket_alive(sock_);
|
|
6034
6097
|
}
|
|
@@ -6055,7 +6118,7 @@ inline ssize_t SocketStream::read(char *ptr, size_t size) {
|
|
|
6055
6118
|
}
|
|
6056
6119
|
}
|
|
6057
6120
|
|
|
6058
|
-
if (!
|
|
6121
|
+
if (!wait_readable()) { return -1; }
|
|
6059
6122
|
|
|
6060
6123
|
read_buff_off_ = 0;
|
|
6061
6124
|
read_buff_content_size_ = 0;
|
|
@@ -6080,7 +6143,7 @@ inline ssize_t SocketStream::read(char *ptr, size_t size) {
|
|
|
6080
6143
|
}
|
|
6081
6144
|
|
|
6082
6145
|
inline ssize_t SocketStream::write(const char *ptr, size_t size) {
|
|
6083
|
-
if (!
|
|
6146
|
+
if (!wait_writable()) { return -1; }
|
|
6084
6147
|
|
|
6085
6148
|
#if defined(_WIN32) && !defined(_WIN64)
|
|
6086
6149
|
size =
|
|
@@ -6104,14 +6167,16 @@ inline socket_t SocketStream::socket() const { return sock_; }
|
|
|
6104
6167
|
|
|
6105
6168
|
inline time_t SocketStream::duration() const {
|
|
6106
6169
|
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
6107
|
-
std::chrono::steady_clock::now() -
|
|
6170
|
+
std::chrono::steady_clock::now() - start_time_)
|
|
6108
6171
|
.count();
|
|
6109
6172
|
}
|
|
6110
6173
|
|
|
6111
6174
|
// Buffer stream implementation
|
|
6112
6175
|
inline bool BufferStream::is_readable() const { return true; }
|
|
6113
6176
|
|
|
6114
|
-
inline bool BufferStream::
|
|
6177
|
+
inline bool BufferStream::wait_readable() const { return true; }
|
|
6178
|
+
|
|
6179
|
+
inline bool BufferStream::wait_writable() const { return true; }
|
|
6115
6180
|
|
|
6116
6181
|
inline ssize_t BufferStream::read(char *ptr, size_t size) {
|
|
6117
6182
|
#if defined(_MSC_VER) && _MSC_VER < 1910
|
|
@@ -6141,7 +6206,7 @@ inline time_t BufferStream::duration() const { return 0; }
|
|
|
6141
6206
|
inline const std::string &BufferStream::get_buffer() const { return buffer; }
|
|
6142
6207
|
|
|
6143
6208
|
inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
|
|
6144
|
-
|
|
6209
|
+
constexpr const char marker[] = "/:";
|
|
6145
6210
|
|
|
6146
6211
|
// One past the last ending position of a path param substring
|
|
6147
6212
|
std::size_t last_param_end = 0;
|
|
@@ -6162,7 +6227,7 @@ inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
|
|
|
6162
6227
|
static_fragments_.push_back(
|
|
6163
6228
|
pattern.substr(last_param_end, marker_pos - last_param_end + 1));
|
|
6164
6229
|
|
|
6165
|
-
const auto param_name_start = marker_pos +
|
|
6230
|
+
const auto param_name_start = marker_pos + str_len(marker);
|
|
6166
6231
|
|
|
6167
6232
|
auto sep_pos = pattern.find(separator, param_name_start);
|
|
6168
6233
|
if (sep_pos == std::string::npos) { sep_pos = pattern.length(); }
|
|
@@ -6469,12 +6534,12 @@ inline Server &Server::set_payload_max_length(size_t length) {
|
|
|
6469
6534
|
inline bool Server::bind_to_port(const std::string &host, int port,
|
|
6470
6535
|
int socket_flags) {
|
|
6471
6536
|
auto ret = bind_internal(host, port, socket_flags);
|
|
6472
|
-
if (ret == -1) {
|
|
6537
|
+
if (ret == -1) { is_decommissioned = true; }
|
|
6473
6538
|
return ret >= 0;
|
|
6474
6539
|
}
|
|
6475
6540
|
inline int Server::bind_to_any_port(const std::string &host, int socket_flags) {
|
|
6476
6541
|
auto ret = bind_internal(host, 0, socket_flags);
|
|
6477
|
-
if (ret == -1) {
|
|
6542
|
+
if (ret == -1) { is_decommissioned = true; }
|
|
6478
6543
|
return ret;
|
|
6479
6544
|
}
|
|
6480
6545
|
|
|
@@ -6488,7 +6553,7 @@ inline bool Server::listen(const std::string &host, int port,
|
|
|
6488
6553
|
inline bool Server::is_running() const { return is_running_; }
|
|
6489
6554
|
|
|
6490
6555
|
inline void Server::wait_until_ready() const {
|
|
6491
|
-
while (!is_running_ && !
|
|
6556
|
+
while (!is_running_ && !is_decommissioned) {
|
|
6492
6557
|
std::this_thread::sleep_for(std::chrono::milliseconds{1});
|
|
6493
6558
|
}
|
|
6494
6559
|
}
|
|
@@ -6500,10 +6565,10 @@ inline void Server::stop() {
|
|
|
6500
6565
|
detail::shutdown_socket(sock);
|
|
6501
6566
|
detail::close_socket(sock);
|
|
6502
6567
|
}
|
|
6503
|
-
|
|
6568
|
+
is_decommissioned = false;
|
|
6504
6569
|
}
|
|
6505
6570
|
|
|
6506
|
-
inline void Server::decommission() {
|
|
6571
|
+
inline void Server::decommission() { is_decommissioned = true; }
|
|
6507
6572
|
|
|
6508
6573
|
inline bool Server::parse_request_line(const char *s, Request &req) const {
|
|
6509
6574
|
auto len = strlen(s);
|
|
@@ -6526,7 +6591,7 @@ inline bool Server::parse_request_line(const char *s, Request &req) const {
|
|
|
6526
6591
|
if (count != 3) { return false; }
|
|
6527
6592
|
}
|
|
6528
6593
|
|
|
6529
|
-
|
|
6594
|
+
thread_local const std::set<std::string> methods{
|
|
6530
6595
|
"GET", "HEAD", "POST", "PUT", "DELETE",
|
|
6531
6596
|
"CONNECT", "OPTIONS", "TRACE", "PATCH", "PRI"};
|
|
6532
6597
|
|
|
@@ -6680,6 +6745,10 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
|
|
|
6680
6745
|
} else if (type == detail::EncodingType::Brotli) {
|
|
6681
6746
|
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
|
6682
6747
|
compressor = detail::make_unique<detail::brotli_compressor>();
|
|
6748
|
+
#endif
|
|
6749
|
+
} else if (type == detail::EncodingType::Zstd) {
|
|
6750
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
6751
|
+
compressor = detail::make_unique<detail::zstd_compressor>();
|
|
6683
6752
|
#endif
|
|
6684
6753
|
} else {
|
|
6685
6754
|
compressor = detail::make_unique<detail::nocompressor>();
|
|
@@ -6862,7 +6931,7 @@ Server::create_server_socket(const std::string &host, int port,
|
|
|
6862
6931
|
|
|
6863
6932
|
inline int Server::bind_internal(const std::string &host, int port,
|
|
6864
6933
|
int socket_flags) {
|
|
6865
|
-
if (
|
|
6934
|
+
if (is_decommissioned) { return -1; }
|
|
6866
6935
|
|
|
6867
6936
|
if (!is_valid()) { return -1; }
|
|
6868
6937
|
|
|
@@ -6889,7 +6958,7 @@ inline int Server::bind_internal(const std::string &host, int port,
|
|
|
6889
6958
|
}
|
|
6890
6959
|
|
|
6891
6960
|
inline bool Server::listen_internal() {
|
|
6892
|
-
if (
|
|
6961
|
+
if (is_decommissioned) { return false; }
|
|
6893
6962
|
|
|
6894
6963
|
auto ret = true;
|
|
6895
6964
|
is_running_ = true;
|
|
@@ -6913,7 +6982,7 @@ inline bool Server::listen_internal() {
|
|
|
6913
6982
|
#endif
|
|
6914
6983
|
|
|
6915
6984
|
#if defined _WIN32
|
|
6916
|
-
// sockets
|
|
6985
|
+
// sockets connected via WASAccept inherit flags NO_HANDLE_INHERIT,
|
|
6917
6986
|
// OVERLAPPED
|
|
6918
6987
|
socket_t sock = WSAAccept(svr_sock_, nullptr, nullptr, nullptr, 0);
|
|
6919
6988
|
#elif defined SOCK_CLOEXEC
|
|
@@ -6955,7 +7024,7 @@ inline bool Server::listen_internal() {
|
|
|
6955
7024
|
task_queue->shutdown();
|
|
6956
7025
|
}
|
|
6957
7026
|
|
|
6958
|
-
|
|
7027
|
+
is_decommissioned = !ret;
|
|
6959
7028
|
return ret;
|
|
6960
7029
|
}
|
|
6961
7030
|
|
|
@@ -7095,6 +7164,8 @@ inline void Server::apply_ranges(const Request &req, Response &res,
|
|
|
7095
7164
|
res.set_header("Content-Encoding", "gzip");
|
|
7096
7165
|
} else if (type == detail::EncodingType::Brotli) {
|
|
7097
7166
|
res.set_header("Content-Encoding", "br");
|
|
7167
|
+
} else if (type == detail::EncodingType::Zstd) {
|
|
7168
|
+
res.set_header("Content-Encoding", "zstd");
|
|
7098
7169
|
}
|
|
7099
7170
|
}
|
|
7100
7171
|
}
|
|
@@ -7134,6 +7205,11 @@ inline void Server::apply_ranges(const Request &req, Response &res,
|
|
|
7134
7205
|
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
|
7135
7206
|
compressor = detail::make_unique<detail::brotli_compressor>();
|
|
7136
7207
|
content_encoding = "br";
|
|
7208
|
+
#endif
|
|
7209
|
+
} else if (type == detail::EncodingType::Zstd) {
|
|
7210
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
7211
|
+
compressor = detail::make_unique<detail::zstd_compressor>();
|
|
7212
|
+
content_encoding = "zstd";
|
|
7137
7213
|
#endif
|
|
7138
7214
|
}
|
|
7139
7215
|
|
|
@@ -7189,20 +7265,6 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|
|
7189
7265
|
res.version = "HTTP/1.1";
|
|
7190
7266
|
res.headers = default_headers_;
|
|
7191
7267
|
|
|
7192
|
-
#ifdef _WIN32
|
|
7193
|
-
// TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL).
|
|
7194
|
-
#else
|
|
7195
|
-
#ifndef CPPHTTPLIB_USE_POLL
|
|
7196
|
-
// Socket file descriptor exceeded FD_SETSIZE...
|
|
7197
|
-
if (strm.socket() >= FD_SETSIZE) {
|
|
7198
|
-
Headers dummy;
|
|
7199
|
-
detail::read_headers(strm, dummy);
|
|
7200
|
-
res.status = StatusCode::InternalServerError_500;
|
|
7201
|
-
return write_response(strm, close_connection, req, res);
|
|
7202
|
-
}
|
|
7203
|
-
#endif
|
|
7204
|
-
#endif
|
|
7205
|
-
|
|
7206
7268
|
// Request line and headers
|
|
7207
7269
|
if (!parse_request_line(line_reader.ptr(), req) ||
|
|
7208
7270
|
!detail::read_headers(strm, req.headers)) {
|
|
@@ -7394,6 +7456,16 @@ inline ClientImpl::ClientImpl(const std::string &host, int port,
|
|
|
7394
7456
|
client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
|
|
7395
7457
|
|
|
7396
7458
|
inline ClientImpl::~ClientImpl() {
|
|
7459
|
+
// Wait until all the requests in flight are handled.
|
|
7460
|
+
size_t retry_count = 10;
|
|
7461
|
+
while (retry_count-- > 0) {
|
|
7462
|
+
{
|
|
7463
|
+
std::lock_guard<std::mutex> guard(socket_mutex_);
|
|
7464
|
+
if (socket_requests_in_flight_ == 0) { break; }
|
|
7465
|
+
}
|
|
7466
|
+
std::this_thread::sleep_for(std::chrono::milliseconds{1});
|
|
7467
|
+
}
|
|
7468
|
+
|
|
7397
7469
|
std::lock_guard<std::mutex> guard(socket_mutex_);
|
|
7398
7470
|
shutdown_socket(socket_);
|
|
7399
7471
|
close_socket(socket_);
|
|
@@ -7519,9 +7591,9 @@ inline bool ClientImpl::read_response_line(Stream &strm, const Request &req,
|
|
|
7519
7591
|
if (!line_reader.getline()) { return false; }
|
|
7520
7592
|
|
|
7521
7593
|
#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
|
|
7522
|
-
const
|
|
7594
|
+
thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n");
|
|
7523
7595
|
#else
|
|
7524
|
-
const
|
|
7596
|
+
thread_local const std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n");
|
|
7525
7597
|
#endif
|
|
7526
7598
|
|
|
7527
7599
|
std::cmatch m;
|
|
@@ -7577,7 +7649,7 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
7577
7649
|
#endif
|
|
7578
7650
|
|
|
7579
7651
|
if (!is_alive) {
|
|
7580
|
-
// Attempt to avoid sigpipe by shutting down
|
|
7652
|
+
// Attempt to avoid sigpipe by shutting down non-gracefully if it seems
|
|
7581
7653
|
// like the other side has already closed the connection Also, there
|
|
7582
7654
|
// cannot be any requests in flight from other threads since we locked
|
|
7583
7655
|
// request_mutex_, so safe to close everything immediately
|
|
@@ -7753,7 +7825,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
|
|
|
7753
7825
|
auto location = res.get_header_value("location");
|
|
7754
7826
|
if (location.empty()) { return false; }
|
|
7755
7827
|
|
|
7756
|
-
const
|
|
7828
|
+
thread_local const std::regex re(
|
|
7757
7829
|
R"((?:(https?):)?(?://(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)");
|
|
7758
7830
|
|
|
7759
7831
|
std::smatch m;
|
|
@@ -7862,6 +7934,10 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
|
|
7862
7934
|
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
|
|
7863
7935
|
if (!accept_encoding.empty()) { accept_encoding += ", "; }
|
|
7864
7936
|
accept_encoding += "gzip, deflate";
|
|
7937
|
+
#endif
|
|
7938
|
+
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
|
|
7939
|
+
if (!accept_encoding.empty()) { accept_encoding += ", "; }
|
|
7940
|
+
accept_encoding += "zstd";
|
|
7865
7941
|
#endif
|
|
7866
7942
|
req.set_header("Accept-Encoding", accept_encoding);
|
|
7867
7943
|
}
|
|
@@ -8213,8 +8289,7 @@ inline bool ClientImpl::process_socket(
|
|
|
8213
8289
|
std::function<bool(Stream &strm)> callback) {
|
|
8214
8290
|
return detail::process_client_socket(
|
|
8215
8291
|
socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
|
|
8216
|
-
write_timeout_usec_, max_timeout_msec_, start_time,
|
|
8217
|
-
std::move(callback));
|
|
8292
|
+
write_timeout_usec_, max_timeout_msec_, start_time, std::move(callback));
|
|
8218
8293
|
}
|
|
8219
8294
|
|
|
8220
8295
|
inline bool ClientImpl::is_ssl() const { return false; }
|
|
@@ -9009,7 +9084,7 @@ inline void ClientImpl::enable_server_hostname_verification(bool enabled) {
|
|
|
9009
9084
|
}
|
|
9010
9085
|
|
|
9011
9086
|
inline void ClientImpl::set_server_certificate_verifier(
|
|
9012
|
-
std::function<
|
|
9087
|
+
std::function<SSLVerifierResponse(SSL *ssl)> verifier) {
|
|
9013
9088
|
server_certificate_verifier_ = verifier;
|
|
9014
9089
|
}
|
|
9015
9090
|
#endif
|
|
@@ -9062,18 +9137,13 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
|
|
|
9062
9137
|
// Note that it is not always possible to avoid SIGPIPE, this is merely a
|
|
9063
9138
|
// best-efforts.
|
|
9064
9139
|
if (shutdown_gracefully) {
|
|
9065
|
-
#ifdef _WIN32
|
|
9066
9140
|
(void)(sock);
|
|
9067
|
-
SSL_shutdown(
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
while (ret == 0) {
|
|
9073
|
-
std::this_thread::sleep_for(std::chrono::milliseconds{100});
|
|
9074
|
-
ret = SSL_shutdown(ssl);
|
|
9141
|
+
// SSL_shutdown() returns 0 on first call (indicating close_notify alert
|
|
9142
|
+
// sent) and 1 on subsequent call (indicating close_notify alert received)
|
|
9143
|
+
if (SSL_shutdown(ssl) == 0) {
|
|
9144
|
+
// Expected to return 1, but even if it doesn't, we free ssl
|
|
9145
|
+
SSL_shutdown(ssl);
|
|
9075
9146
|
}
|
|
9076
|
-
#endif
|
|
9077
9147
|
}
|
|
9078
9148
|
|
|
9079
9149
|
std::lock_guard<std::mutex> guard(ctx_mutex);
|
|
@@ -9124,19 +9194,11 @@ inline bool process_client_socket_ssl(
|
|
|
9124
9194
|
time_t max_timeout_msec,
|
|
9125
9195
|
std::chrono::time_point<std::chrono::steady_clock> start_time, T callback) {
|
|
9126
9196
|
SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
|
|
9127
|
-
write_timeout_sec, write_timeout_usec,
|
|
9128
|
-
|
|
9197
|
+
write_timeout_sec, write_timeout_usec, max_timeout_msec,
|
|
9198
|
+
start_time);
|
|
9129
9199
|
return callback(strm);
|
|
9130
9200
|
}
|
|
9131
9201
|
|
|
9132
|
-
class SSLInit {
|
|
9133
|
-
public:
|
|
9134
|
-
SSLInit() {
|
|
9135
|
-
OPENSSL_init_ssl(
|
|
9136
|
-
OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
|
9137
|
-
}
|
|
9138
|
-
};
|
|
9139
|
-
|
|
9140
9202
|
// SSL socket stream implementation
|
|
9141
9203
|
inline SSLSocketStream::SSLSocketStream(
|
|
9142
9204
|
socket_t sock, SSL *ssl, time_t read_timeout_sec, time_t read_timeout_usec,
|
|
@@ -9147,13 +9209,17 @@ inline SSLSocketStream::SSLSocketStream(
|
|
|
9147
9209
|
read_timeout_usec_(read_timeout_usec),
|
|
9148
9210
|
write_timeout_sec_(write_timeout_sec),
|
|
9149
9211
|
write_timeout_usec_(write_timeout_usec),
|
|
9150
|
-
max_timeout_msec_(max_timeout_msec),
|
|
9212
|
+
max_timeout_msec_(max_timeout_msec), start_time_(start_time) {
|
|
9151
9213
|
SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
|
|
9152
9214
|
}
|
|
9153
9215
|
|
|
9154
9216
|
inline SSLSocketStream::~SSLSocketStream() = default;
|
|
9155
9217
|
|
|
9156
9218
|
inline bool SSLSocketStream::is_readable() const {
|
|
9219
|
+
return SSL_pending(ssl_) > 0;
|
|
9220
|
+
}
|
|
9221
|
+
|
|
9222
|
+
inline bool SSLSocketStream::wait_readable() const {
|
|
9157
9223
|
if (max_timeout_msec_ <= 0) {
|
|
9158
9224
|
return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
|
|
9159
9225
|
}
|
|
@@ -9166,7 +9232,7 @@ inline bool SSLSocketStream::is_readable() const {
|
|
|
9166
9232
|
return select_read(sock_, read_timeout_sec, read_timeout_usec) > 0;
|
|
9167
9233
|
}
|
|
9168
9234
|
|
|
9169
|
-
inline bool SSLSocketStream::
|
|
9235
|
+
inline bool SSLSocketStream::wait_writable() const {
|
|
9170
9236
|
return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
|
|
9171
9237
|
is_socket_alive(sock_) && !is_ssl_peer_could_be_closed(ssl_, sock_);
|
|
9172
9238
|
}
|
|
@@ -9174,7 +9240,7 @@ inline bool SSLSocketStream::is_writable() const {
|
|
|
9174
9240
|
inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
|
|
9175
9241
|
if (SSL_pending(ssl_) > 0) {
|
|
9176
9242
|
return SSL_read(ssl_, ptr, static_cast<int>(size));
|
|
9177
|
-
} else if (
|
|
9243
|
+
} else if (wait_readable()) {
|
|
9178
9244
|
auto ret = SSL_read(ssl_, ptr, static_cast<int>(size));
|
|
9179
9245
|
if (ret < 0) {
|
|
9180
9246
|
auto err = SSL_get_error(ssl_, ret);
|
|
@@ -9188,7 +9254,7 @@ inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
|
|
|
9188
9254
|
#endif
|
|
9189
9255
|
if (SSL_pending(ssl_) > 0) {
|
|
9190
9256
|
return SSL_read(ssl_, ptr, static_cast<int>(size));
|
|
9191
|
-
} else if (
|
|
9257
|
+
} else if (wait_readable()) {
|
|
9192
9258
|
std::this_thread::sleep_for(std::chrono::microseconds{10});
|
|
9193
9259
|
ret = SSL_read(ssl_, ptr, static_cast<int>(size));
|
|
9194
9260
|
if (ret >= 0) { return ret; }
|
|
@@ -9205,7 +9271,7 @@ inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
|
|
|
9205
9271
|
}
|
|
9206
9272
|
|
|
9207
9273
|
inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
|
|
9208
|
-
if (
|
|
9274
|
+
if (wait_writable()) {
|
|
9209
9275
|
auto handle_size = static_cast<int>(
|
|
9210
9276
|
std::min<size_t>(size, (std::numeric_limits<int>::max)()));
|
|
9211
9277
|
|
|
@@ -9220,7 +9286,7 @@ inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
|
|
|
9220
9286
|
#else
|
|
9221
9287
|
while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) {
|
|
9222
9288
|
#endif
|
|
9223
|
-
if (
|
|
9289
|
+
if (wait_writable()) {
|
|
9224
9290
|
std::this_thread::sleep_for(std::chrono::microseconds{10});
|
|
9225
9291
|
ret = SSL_write(ssl_, ptr, static_cast<int>(handle_size));
|
|
9226
9292
|
if (ret >= 0) { return ret; }
|
|
@@ -9249,12 +9315,10 @@ inline socket_t SSLSocketStream::socket() const { return sock_; }
|
|
|
9249
9315
|
|
|
9250
9316
|
inline time_t SSLSocketStream::duration() const {
|
|
9251
9317
|
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
9252
|
-
std::chrono::steady_clock::now() -
|
|
9318
|
+
std::chrono::steady_clock::now() - start_time_)
|
|
9253
9319
|
.count();
|
|
9254
9320
|
}
|
|
9255
9321
|
|
|
9256
|
-
static SSLInit sslinit_;
|
|
9257
|
-
|
|
9258
9322
|
} // namespace detail
|
|
9259
9323
|
|
|
9260
9324
|
// SSL HTTP server implementation
|
|
@@ -9623,12 +9687,18 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
|
9623
9687
|
}
|
|
9624
9688
|
|
|
9625
9689
|
if (server_certificate_verification_) {
|
|
9690
|
+
auto verification_status = SSLVerifierResponse::NoDecisionMade;
|
|
9691
|
+
|
|
9626
9692
|
if (server_certificate_verifier_) {
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9693
|
+
verification_status = server_certificate_verifier_(ssl2);
|
|
9694
|
+
}
|
|
9695
|
+
|
|
9696
|
+
if (verification_status == SSLVerifierResponse::CertificateRejected) {
|
|
9697
|
+
error = Error::SSLServerVerification;
|
|
9698
|
+
return false;
|
|
9699
|
+
}
|
|
9700
|
+
|
|
9701
|
+
if (verification_status == SSLVerifierResponse::NoDecisionMade) {
|
|
9632
9702
|
verify_result_ = SSL_get_verify_result(ssl2);
|
|
9633
9703
|
|
|
9634
9704
|
if (verify_result_ != X509_V_OK) {
|
|
@@ -9740,8 +9810,8 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const {
|
|
|
9740
9810
|
|
|
9741
9811
|
auto type = GEN_DNS;
|
|
9742
9812
|
|
|
9743
|
-
struct in6_addr addr6{};
|
|
9744
|
-
struct in_addr addr{};
|
|
9813
|
+
struct in6_addr addr6 = {};
|
|
9814
|
+
struct in_addr addr = {};
|
|
9745
9815
|
size_t addr_len = 0;
|
|
9746
9816
|
|
|
9747
9817
|
#ifndef __MINGW32__
|
|
@@ -10389,7 +10459,7 @@ inline void Client::enable_server_hostname_verification(bool enabled) {
|
|
|
10389
10459
|
}
|
|
10390
10460
|
|
|
10391
10461
|
inline void Client::set_server_certificate_verifier(
|
|
10392
|
-
std::function<
|
|
10462
|
+
std::function<SSLVerifierResponse(SSL *ssl)> verifier) {
|
|
10393
10463
|
cli_->set_server_certificate_verifier(verifier);
|
|
10394
10464
|
}
|
|
10395
10465
|
#endif
|
|
@@ -10433,8 +10503,4 @@ inline SSL_CTX *Client::ssl_context() const {
|
|
|
10433
10503
|
|
|
10434
10504
|
} // namespace httplib
|
|
10435
10505
|
|
|
10436
|
-
#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL)
|
|
10437
|
-
#undef poll
|
|
10438
|
-
#endif
|
|
10439
|
-
|
|
10440
10506
|
#endif // CPPHTTPLIB_HTTPLIB_H
|