]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: stop sending empty HTTP/3 UDP datagrams on Windows
authorJay Satiro <raysatiro@yahoo.com>
Tue, 7 Feb 2023 08:14:34 +0000 (03:14 -0500)
committerJay Satiro <raysatiro@yahoo.com>
Mon, 13 Feb 2023 08:25:12 +0000 (03:25 -0500)
- 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

lib/multi.c

index 403274814b51fa65028db2bd82a516061052424f..f020a0b64acf159798dc7bbedc87a9b25e3c86f6 100644 (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)