From f19a887acbd8f5b3e535437bf326576ae409ef10 Mon Sep 17 00:00:00 2001 From: PA Dev Bot <344001113+pa-devbot@users.noreply.github.com> Date: Mon, 2 Nov 2026 09:55:14 +0000 Subject: [PATCH] Sockets: align the WinSocket backends' send() semantics Two residuals of the cross-backend send() inconsistency: - The WinSocket client returned on the first partial ::send() call (mid-block), while the POSIX and Qt backends keep sending until everything is written, the deadline elapses, or close() cancels the send. It now advances and loops like them; the loop condition re-checks the deadline and the state each iteration, so the cancellation and deadline behavior is unchanged. - The WinSocket server passed the raw payload length to ::send(), which takes an int: a payload larger than 2 GiB wrapped the length negative. It now chunks the send at 1 GiB, the same cap the WinSocket client already uses. --- Common/Cpp/Sockets/ClientSocket_WinSocket.cpp | 6 +++--- Common/Cpp/Sockets/ServerSocket_WinSocket.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Common/Cpp/Sockets/ClientSocket_WinSocket.cpp b/Common/Cpp/Sockets/ClientSocket_WinSocket.cpp index cfc5602942..37f630c19b 100644 --- a/Common/Cpp/Sockets/ClientSocket_WinSocket.cpp +++ b/Common/Cpp/Sockets/ClientSocket_WinSocket.cpp @@ -126,10 +126,10 @@ size_t ClientSocket_WinSocket::send(const void* data, size_t bytes, std::chrono: int current = (int)std::min(bytes, BLOCK_SIZE); int current_sent = ::send(socket, ptr, current, 0); if (current_sent != SOCKET_ERROR){ + // A partial send is not an error: advance and keep looping + // until everything is written or the deadline/state ends + // the send, the same way the POSIX and Qt backends do. sent += current_sent; - if (current_sent != current){ - return sent; - } ptr += current_sent; bytes -= current_sent; continue; diff --git a/Common/Cpp/Sockets/ServerSocket_WinSocket.cpp b/Common/Cpp/Sockets/ServerSocket_WinSocket.cpp index 7779c00122..8f1b1d4d24 100644 --- a/Common/Cpp/Sockets/ServerSocket_WinSocket.cpp +++ b/Common/Cpp/Sockets/ServerSocket_WinSocket.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "Common/Cpp/Concurrency/ThreadPool.h" #include "ServerSocket_WinSocket.h" @@ -191,7 +192,12 @@ size_t ServerSocket_WinSocket::send(const void* data, size_t bytes, std::chrono: return sent; } - int current_sent = ::send(socket, ptr, (int)bytes, 0); + // "::send" takes an "int" length, so chunk the send the same + // way the WinSocket client does; sending a payload larger than + // 2 GiB in one call would wrap the length negative. + constexpr size_t BLOCK_SIZE = (size_t)1 << 30; + const int current = (int)std::min(bytes, BLOCK_SIZE); + int current_sent = ::send(socket, ptr, current, 0); if (current_sent != SOCKET_ERROR){ sent += (size_t)current_sent; ptr += current_sent;