winsock: move SO_SNDBUF update into cf-socket

- Move the code that updates the SO_SNDBUF size for Windows to
  cf_socket_send.

Prior to this change the code was in readwrite_upload but the socket
filter is the more appropriate place because it applies to all sends.

Background:

For Windows users SO_SNDBUF (the total per-socket buffer size reserved
by Winsock for sends) is updated dynamically by libcurl during the
transfer. This is because Windows does not do it automatically for
non-blocking sockets and without it the performance of large transfers
may suffer.

Closes https://github.com/curl/curl/pull/13763
This commit is contained in:
Stefan Eissing 2024-05-24 10:09:32 +02:00 committed by Jay Satiro
parent 2b52fe4115
commit 0b520e1250
3 changed files with 33 additions and 44 deletions

View File

@ -395,8 +395,26 @@ void Curl_sndbufset(curl_socket_t sockfd)
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
} }
#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
#endif #endif
static void win_update_buffer_size(curl_socket_t sockfd)
{
int result;
ULONG ideal;
DWORD ideallen;
result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
&ideal, sizeof(ideal), &ideallen, 0, 0);
if(result == 0) {
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
(const char *)&ideal, sizeof(ideal));
}
}
#endif /* USE_WINSOCK */
#ifndef CURL_DISABLE_BINDLOCAL #ifndef CURL_DISABLE_BINDLOCAL
static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd, int af, unsigned int scope) curl_socket_t sockfd, int af, unsigned int scope)
@ -770,6 +788,9 @@ struct cf_socket_ctx {
struct curltime started_at; /* when socket was created */ struct curltime started_at; /* when socket was created */
struct curltime connected_at; /* when socket connected/got first byte */ struct curltime connected_at; /* when socket connected/got first byte */
struct curltime first_byte_at; /* when first byte was recvd */ struct curltime first_byte_at; /* when first byte was recvd */
#ifdef USE_WINSOCK
struct curltime last_sndbuf_update; /* last update of sendbuf */
#endif
int error; /* errno of last failure or 0 */ int error; /* errno of last failure or 0 */
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
int wblock_percent; /* percent of writes doing EAGAIN */ int wblock_percent; /* percent of writes doing EAGAIN */
@ -1336,6 +1357,16 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
} }
} }
#if defined(USE_WINSOCK)
if(!*err) {
struct curltime n = Curl_now();
if(Curl_timediff(n, ctx->last_sndbuf_update) > 1000) {
win_update_buffer_size(ctx->sock);
ctx->last_sndbuf_update = n;
}
}
#endif
CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, err=%d", CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, err=%d",
orig_len, (int)nwritten, *err); orig_len, (int)nwritten, *err);
cf->conn->sock[cf->sockindex] = fdsave; cf->conn->sock[cf->sockindex] = fdsave;

View File

@ -320,34 +320,11 @@ out:
return result; return result;
} }
#if defined(_WIN32) && defined(USE_WINSOCK)
#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
#endif
static void win_update_buffer_size(curl_socket_t sockfd)
{
int result;
ULONG ideal;
DWORD ideallen;
result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
&ideal, sizeof(ideal), &ideallen, 0, 0);
if(result == 0) {
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
(const char *)&ideal, sizeof(ideal));
}
}
#else
#define win_update_buffer_size(x)
#endif
/* /*
* Send data to upload to the server, when the socket is writable. * Send data to upload to the server, when the socket is writable.
*/ */
static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat) static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat)
{ {
CURLcode result = CURLE_OK;
if((data->req.keepon & KEEP_SEND_PAUSE)) if((data->req.keepon & KEEP_SEND_PAUSE))
return CURLE_OK; return CURLE_OK;
@ -358,23 +335,9 @@ static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat)
if(!Curl_req_done_sending(data)) { if(!Curl_req_done_sending(data)) {
*didwhat |= KEEP_SEND; *didwhat |= KEEP_SEND;
result = Curl_req_send_more(data); return Curl_req_send_more(data);
if(result)
return result;
#if defined(_WIN32) && defined(USE_WINSOCK)
/* FIXME: this looks like it would fit better into cf-socket.c
* but then I do not know enough Windows to say... */
{
struct curltime n = Curl_now();
if(Curl_timediff(n, data->conn->last_sndbuf_update) > 1000) {
win_update_buffer_size(data->conn->writesockfd);
data->conn->last_sndbuf_update = n;
} }
} return CURLE_OK;
#endif
}
return result;
} }
static int select_bits_paused(struct Curl_easy *data, int select_bits) static int select_bits_paused(struct Curl_easy *data, int select_bits)

View File

@ -908,11 +908,6 @@ struct connectdata {
CtxtHandle *sslContext; CtxtHandle *sslContext;
#endif #endif
#if defined(_WIN32) && defined(USE_WINSOCK)
struct curltime last_sndbuf_update; /* last time readwrite_upload called
win_update_buffer_size */
#endif
#ifdef USE_GSASL #ifdef USE_GSASL
struct gsasldata gsasl; struct gsasldata gsasl;
#endif #endif