multi: stop sending empty HTTP/3 UDP datagrams on Windows

- Limit the 0-sized send procedure that is used to reset a SOCKET's
  FD_WRITE to TCP sockets only.

Prior to this change the reset was used on UDP sockets as well, but
unlike TCP sockets a 0-sized send actually sends out a datagram.

Assisted-by: Marc Hörsken

Ref: https://github.com/curl/curl/pull/9203

Fixes https://github.com/curl/curl/issues/9086
Closes https://github.com/curl/curl/pull/10430
This commit is contained in:
Jay Satiro 2023-02-07 03:14:34 -05:00
parent 7ce140ba97
commit f438ce099b

View File

@ -1110,6 +1110,22 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
return CURLM_OK;
}
#ifdef USE_WINSOCK
/* Reset FD_WRITE for TCP sockets. Nothing is actually sent. UDP sockets can't
* be reset this way because an empty datagram would be sent. #9203
*
* "On Windows the internal state of FD_WRITE as returned from
* WSAEnumNetworkEvents is only reset after successful send()."
*/
static void reset_socket_fdwrite(curl_socket_t s)
{
int t;
int l = (int)sizeof(t);
if(!getsockopt(s, SOL_SOCKET, SO_TYPE, (char *)&t, &l) && t == SOCK_STREAM)
send(s, NULL, 0, 0);
}
#endif
#define NUM_POLLS_ON_STACK 10
static CURLMcode multi_wait(struct Curl_multi *multi,
@ -1231,7 +1247,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
s = sockbunch[i];
#ifdef USE_WINSOCK
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
send(s, NULL, 0, 0); /* reset FD_WRITE */
reset_socket_fdwrite(s);
#endif
ufds[nfds].fd = s;
ufds[nfds].events = POLLOUT;
@ -1265,7 +1281,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
mask |= FD_OOB;
if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
reset_socket_fdwrite(extra_fds[i].fd);
}
if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
if(ufds_malloc)