From 8929428316cec371b7b621708f19f6d74652e9c2 Mon Sep 17 00:00:00 2001 From: Evgeny Kotkov Date: Thu, 20 Oct 2022 05:53:45 +0000 Subject: Revert r1902312, r1904699 in preparation for a slightly different change. Shortlog: - r1902312: apr_socket_sendv: WIN32: Limit the number of WSABUFs allocated for a single call. - r1904699: apr_socket_sendv: WIN32: Follow up to r1902312: Avoid short writes. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1904714 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_network_io.h | 6 ---- network_io/win32/sendrecv.c | 88 ++++++++++++++------------------------------- 2 files changed, 26 insertions(+), 68 deletions(-) diff --git a/include/apr_network_io.h b/include/apr_network_io.h index e37b95297..b3536d802 100644 --- a/include/apr_network_io.h +++ b/include/apr_network_io.h @@ -574,12 +574,6 @@ APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, * socket option. * The number of bytes actually sent is stored in argument 4. * - * This function does not provide full-write and/or atomicity guarantees - * if the underlying system call does not either. Some systems (like Windows) - * guarantee both for a single system call but this call does not allow for - * as much data as an iovec vector can contain; in this case apr_socket_sendv() - * can issue multiple system calls thus favoring full-write over atomicity. - * * It is possible for both bytes to be sent and an error to be returned. * * APR_EINTR is never returned. diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c index c04d27e29..20d802042 100644 --- a/network_io/win32/sendrecv.c +++ b/network_io/win32/sendrecv.c @@ -20,7 +20,6 @@ #include "apr_network_io.h" #include "apr_lib.h" #include "apr_arch_file_io.h" -#include #if APR_HAVE_TIME_H #include #endif @@ -35,14 +34,7 @@ * than 8193 bytes. */ #define MAX_SEGMENT_SIZE 65536 - -/* Maximum number of WSABUF allocated for a single apr_socket_sendv() */ #define WSABUF_ON_STACK 50 -#if APR_SIZEOF_VOIDP < 8 -#define WSABUF_ON_HEAP (APR_DWORD_MAX / sizeof(WSABUF)) -#else -#define WSABUF_ON_HEAP (APR_DWORD_MAX) -#endif APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len) @@ -99,32 +91,18 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, apr_status_t rc = APR_SUCCESS; apr_ssize_t rv; apr_size_t cur_len; - apr_size_t cur_pos = 0; - apr_size_t total_len = 0; - apr_size_t nvec = 0; - int i; + apr_int32_t nvec = 0; + int i, j = 0; + DWORD dwBytes = 0; WSABUF *pWsaBuf; - *nbytes = 0; /* until further notice */ - for (i = 0; i < in_vec; i++) { cur_len = vec[i].iov_len; - if (!cur_len) { - continue; - } - if (cur_len > APR_SIZE_MAX - total_len) { - /* max total_len can take */ - return APR_EINVAL; - } - total_len += cur_len; nvec++; - } - if (!nvec) { - return (in_vec >= 0) ? APR_SUCCESS : APR_EINVAL; - } - if (nvec > WSABUF_ON_HEAP) { - /* max malloc() and/or WSASend() can take */ - nvec = WSABUF_ON_HEAP; + while (cur_len > APR_DWORD_MAX) { + nvec++; + cur_len -= APR_DWORD_MAX; + } } pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec)) @@ -132,48 +110,34 @@ APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, if (!pWsaBuf) return APR_ENOMEM; - for (i = 0; total_len > 0;) { - DWORD nbuf = 0, nsend = 0, nsent = 0; - + for (i = 0; i < in_vec; i++) { + char * base = vec[i].iov_base; + cur_len = vec[i].iov_len; + do { - assert(i < in_vec); - cur_len = vec[i].iov_len - cur_pos; - if (!cur_len) { - assert(cur_pos == 0); - i++; - continue; - } - pWsaBuf[nbuf].buf = (char *)vec[i].iov_base + cur_pos; - if (cur_len > APR_DWORD_MAX - nsend) { - cur_len = APR_DWORD_MAX - nsend; - cur_pos += cur_len; + if (cur_len > APR_DWORD_MAX) { + pWsaBuf[j].buf = base; + pWsaBuf[j].len = APR_DWORD_MAX; + cur_len -= APR_DWORD_MAX; + base += APR_DWORD_MAX; } else { - cur_pos = 0; - i++; + pWsaBuf[j].buf = base; + pWsaBuf[j].len = (DWORD)cur_len; + cur_len = 0; } - nsend += cur_len; - pWsaBuf[nbuf++].len = (DWORD)cur_len; - } while (nbuf < nvec && nsend < total_len && nsend < APR_DWORD_MAX); + j++; - rv = WSASend(sock->socketdes, pWsaBuf, nbuf, &nsent, 0, NULL, NULL); - if (rv == SOCKET_ERROR) { - rc = apr_get_netos_error(); - break; - } - *nbytes += nsent; - if (nsent < nsend) { - /* Stop on short/partial write (nonblocking supposedly, but anyway - * we don't guarantee full write if the system does not either). - */ - break; - } - total_len -= nsent; + } while (cur_len > 0); + } + rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL); + if (rv == SOCKET_ERROR) { + rc = apr_get_netos_error(); } - if (nvec > WSABUF_ON_STACK) free(pWsaBuf); + *nbytes = dwBytes; return rc; } -- cgit v1.2.1