Fix large files transfer on Windows

The maximum number of bytes to write using TransmitFile cannot be
greater than INT_MAX - 1, otherwise the function fails with WSAEINVAL.

https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile

The issue can be reproduced using the http-server-sync example, by
sending a GET request for a file larger than INTMAX.

e.g:
$ curl -v http://127.0.0.1:8080/ubuntu.iso -o ubuntu.iso
*   Trying 127.0.0.1:8080...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET /ubuntu.iso HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.83.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Boost.Beast/330
< Content-Type: application/text
< Content-Length: 3654957056
<
{ [0 bytes data]
* transfer closed with 3654957056 bytes remaining to read
  0 3485M    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Closing connection 0
curl: (18) transfer closed with 3654957056 bytes remaining to read

Signed-off-by: Petre Pircalabu <ppircalabu@bitdefender.com>
This commit is contained in:
Petre Pircalabu
2022-06-01 02:53:10 +03:00
committed by Alan de Freitas
parent d362b68edd
commit 7f6adb91f7

View File

@ -434,7 +434,7 @@ public:
static_cast<boost::winapi::DWORD_>(
(std::min<std::uint64_t>)(
(std::min<std::uint64_t>)(w.body_.last_ - w.pos_, sr_.limit()),
(std::numeric_limits<boost::winapi::DWORD_>::max)()));
(std::numeric_limits<boost::winapi::INT_>::max)() - 1));
net::windows::overlapped_ptr overlapped{
sock_.get_executor(), std::move(*this)};
// Note that we have moved *this, so we cannot access
@ -562,7 +562,7 @@ write_some(
static_cast<boost::winapi::DWORD_>(
(std::min<std::uint64_t>)(
(std::min<std::uint64_t>)(w.body_.last_ - w.pos_, sr.limit()),
(std::numeric_limits<boost::winapi::DWORD_>::max)()));
(std::numeric_limits<boost::winapi::INT_>::max)() - 1));
auto const bSuccess = ::TransmitFile(
sock.native_handle(),
w.body_.file_.native_handle(),