From 0b520e125081096f174788cc599d49b19796e6d8 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Fri, 24 May 2024 10:09:32 +0200 Subject: [PATCH] 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 --- lib/cf-socket.c | 31 +++++++++++++++++++++++++++++++ lib/transfer.c | 41 ++--------------------------------------- lib/urldata.h | 5 ----- 3 files changed, 33 insertions(+), 44 deletions(-) diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 3e87889f9c..b5edaff717 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -395,8 +395,26 @@ void Curl_sndbufset(curl_socket_t sockfd) 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 +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 static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, 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 connected_at; /* when socket connected/got first byte */ 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 */ #ifdef DEBUGBUILD 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", orig_len, (int)nwritten, *err); cf->conn->sock[cf->sockindex] = fdsave; diff --git a/lib/transfer.c b/lib/transfer.c index b0783581cc..cbd91d0e27 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -320,34 +320,11 @@ out: 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. */ static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat) { - CURLcode result = CURLE_OK; - if((data->req.keepon & KEEP_SEND_PAUSE)) return CURLE_OK; @@ -358,23 +335,9 @@ static CURLcode readwrite_upload(struct Curl_easy *data, int *didwhat) if(!Curl_req_done_sending(data)) { *didwhat |= KEEP_SEND; - result = 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; - } - } -#endif + return Curl_req_send_more(data); } - return result; + return CURLE_OK; } static int select_bits_paused(struct Curl_easy *data, int select_bits) diff --git a/lib/urldata.h b/lib/urldata.h index 48844d2707..f55ba5027d 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -908,11 +908,6 @@ struct connectdata { CtxtHandle *sslContext; #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 struct gsasldata gsasl; #endif -- 2.47.2