@@ -1671,6 +1671,10 @@ bool parse_range_header(const std::string &s, Ranges &ranges);
1671
1671
1672
1672
int close_socket (socket_t sock);
1673
1673
1674
+ ssize_t send_socket (socket_t sock, const void *ptr, size_t size, int flags);
1675
+
1676
+ ssize_t read_socket (socket_t sock, void *ptr, size_t size, int flags);
1677
+
1674
1678
enum class EncodingType { None = 0 , Gzip, Brotli };
1675
1679
1676
1680
EncodingType encoding_type (const Request &req, const Response &res);
@@ -2189,6 +2193,34 @@ template <typename T> inline ssize_t handle_EINTR(T fn) {
2189
2193
return res;
2190
2194
}
2191
2195
2196
+ inline ssize_t read_socket (socket_t sock, void *ptr, size_t size, int flags) {
2197
+ return handle_EINTR ([&]() {
2198
+ return recv (sock,
2199
+ #ifdef _WIN32
2200
+ static_cast <char *>(ptr),
2201
+ static_cast <int >(size),
2202
+ #else
2203
+ ptr,
2204
+ size,
2205
+ #endif
2206
+ flags);
2207
+ });
2208
+ }
2209
+
2210
+ inline ssize_t send_socket (socket_t sock, const void *ptr, size_t size, int flags) {
2211
+ return handle_EINTR ([&]() {
2212
+ return send (sock,
2213
+ #ifdef _WIN32
2214
+ static_cast <const char *>(ptr),
2215
+ static_cast <int >(size),
2216
+ #else
2217
+ ptr,
2218
+ size,
2219
+ #endif
2220
+ flags);
2221
+ });
2222
+ }
2223
+
2192
2224
inline ssize_t select_read (socket_t sock, time_t sec, time_t usec) {
2193
2225
#ifdef CPPHTTPLIB_USE_POLL
2194
2226
struct pollfd pfd_read;
@@ -2313,6 +2345,12 @@ class SocketStream : public Stream {
2313
2345
time_t read_timeout_usec_;
2314
2346
time_t write_timeout_sec_;
2315
2347
time_t write_timeout_usec_;
2348
+
2349
+ std::vector<char > read_buff_;
2350
+ size_t read_buff_off_ = 0 ;
2351
+ size_t read_buff_content_size_ = 0 ;
2352
+
2353
+ static const size_t read_buff_size_ = 1024 * 4 ;
2316
2354
};
2317
2355
2318
2356
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -4368,7 +4406,8 @@ inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec,
4368
4406
: sock_(sock), read_timeout_sec_(read_timeout_sec),
4369
4407
read_timeout_usec_(read_timeout_usec),
4370
4408
write_timeout_sec_(write_timeout_sec),
4371
- write_timeout_usec_(write_timeout_usec) {}
4409
+ write_timeout_usec_(write_timeout_usec),
4410
+ read_buff_(read_buff_size_, 0 ) {}
4372
4411
4373
4412
inline SocketStream::~SocketStream () {}
4374
4413
@@ -4381,31 +4420,56 @@ inline bool SocketStream::is_writable() const {
4381
4420
}
4382
4421
4383
4422
inline ssize_t SocketStream::read (char *ptr, size_t size) {
4384
- if (!is_readable ()) { return -1 ; }
4385
-
4386
4423
#ifdef _WIN32
4387
- if (size > static_cast <size_t >((std::numeric_limits<int >::max)())) {
4388
- return -1 ;
4389
- }
4390
- return recv (sock_, ptr, static_cast <int >(size), CPPHTTPLIB_RECV_FLAGS);
4424
+ size = std::min (size, static_cast <size_t >((std::numeric_limits<int >::max)()));
4391
4425
#else
4392
- return handle_EINTR (
4393
- [&]() { return recv (sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS); });
4426
+ size = std::min (size, static_cast <size_t >((std::numeric_limits<ssize_t >::max)()));
4394
4427
#endif
4428
+
4429
+ if (read_buff_off_ < read_buff_content_size_) {
4430
+ auto remaining_size = read_buff_content_size_ - read_buff_off_;
4431
+ if (size <= remaining_size) {
4432
+ memcpy (ptr, read_buff_.data () + read_buff_off_, size);
4433
+ read_buff_off_ += size;
4434
+ return static_cast <ssize_t >(size);
4435
+ } else {
4436
+ memcpy (ptr, read_buff_.data () + read_buff_off_, remaining_size);
4437
+ read_buff_off_ += remaining_size;
4438
+ return static_cast <ssize_t >(remaining_size);
4439
+ }
4440
+ }
4441
+
4442
+ if (!is_readable ()) { return -1 ; }
4443
+
4444
+ read_buff_off_ = 0 ;
4445
+ read_buff_content_size_ = 0 ;
4446
+
4447
+ if (size < read_buff_size_) {
4448
+ auto n = read_socket (sock_, read_buff_.data (), read_buff_size_, CPPHTTPLIB_RECV_FLAGS);
4449
+ if (n <= 0 ) {
4450
+ return n;
4451
+ } else if (n <= static_cast <ssize_t >(size)) {
4452
+ memcpy (ptr, read_buff_.data (), static_cast <size_t >(n));
4453
+ return n;
4454
+ } else {
4455
+ memcpy (ptr, read_buff_.data (), size);
4456
+ read_buff_off_ = size;
4457
+ read_buff_content_size_ = static_cast <size_t >(n);
4458
+ return static_cast <ssize_t >(size);
4459
+ }
4460
+ } else {
4461
+ return read_socket (sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS);
4462
+ }
4395
4463
}
4396
4464
4397
4465
inline ssize_t SocketStream::write (const char *ptr, size_t size) {
4398
4466
if (!is_writable ()) { return -1 ; }
4399
4467
4400
4468
#ifdef _WIN32
4401
- if (size > static_cast <size_t >((std::numeric_limits<int >::max)())) {
4402
- return -1 ;
4403
- }
4404
- return send (sock_, ptr, static_cast <int >(size), CPPHTTPLIB_SEND_FLAGS);
4405
- #else
4406
- return handle_EINTR (
4407
- [&]() { return send (sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); });
4469
+ size = std::min (size, static_cast <size_t >((std::numeric_limits<int >::max)()));
4408
4470
#endif
4471
+
4472
+ return send_socket (sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS);
4409
4473
}
4410
4474
4411
4475
inline void SocketStream::get_remote_ip_and_port (std::string &ip,
0 commit comments