=back
+=head1 WINDOWS APPLICATION NOTES
+
+QUIC protocol uses UDP sockets. The recvfrom() function on Windows may fail
+with C<WSAECONNRESET> error causing OpenSSL QUIC stack to enter permanent
+error, which prevents further communication over QUIC protocol. Applications
+should disable SIO_UDP_CONNRESET and SIO_UDP_NETRESET error notification
+on UDP sockets they pass to OpenSSL QUIC stack. More details can be found here:
+https://learn.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#sio_udp_connreset-opcode-setting-i-t3
+
+OpenSSL attempts to always disable SIO_UDP_CONNRESET and SIO_UDP_NETRESET
+on UDP sockets it receives from application, but no error is reported back
+if the respective C<WSAIoctl()> calls fail. Robust application should set those
+options itself so it can handle error notifications from C<WSAIoctl()> properly.
+
=head1 SEE ALSO
L<SSL_handle_events(3)>, L<SSL_get_event_timeout(3)>,
#include "internal/thread_arch.h"
#include <assert.h>
+#if defined(OPENSSL_SYS_WINDOWS)
+#include <winsock2.h>
+#include <mstcpip.h>
+#include <mswsock.h>
+#endif
+
/*
* Core I/O Reactor Framework
* ==========================
}
}
+#if defined(OPENSSL_SYS_WINDOWS)
+/*
+ * On Windows recvfrom() may return WSAECONNRESET when destination port
+ * used in preceding call to sendto() is no longer reachable. The reset
+ * error received from UDP socket takes the whole port down. This behavior
+ * must be suppressed for QUIC protocol so QUIC applications may rely on
+ * QUIC protocol itself to detect network failures.
+ */
+static void rtor_configure_winsock(BIO_POLL_DESCRIPTOR *bpd)
+{
+ BOOL bNewBehavior = FALSE;
+ DWORD dwBytesReturned = 0;
+
+ if (bpd->type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) {
+ WSAIoctl(bpd->value.fd, SIO_UDP_CONNRESET, &bNewBehavior,
+ sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL);
+ WSAIoctl(bpd->value.fd, SIO_UDP_NETRESET, &bNewBehavior,
+ sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL);
+ }
+}
+#endif
+
void ossl_quic_reactor_set_poll_r(QUIC_REACTOR *rtor, const BIO_POLL_DESCRIPTOR *r)
{
if (r == NULL)
else
rtor->poll_r = *r;
+#if defined(OPENSSL_SYS_WINDOWS)
+ rtor_configure_winsock(&rtor->poll_r);
+#endif
+
rtor->can_poll_r
= ossl_quic_reactor_can_support_poll_descriptor(rtor, &rtor->poll_r);
}
else
rtor->poll_w = *w;
+#if defined(OPENSSL_SYS_WINDOWS)
+ rtor_configure_winsock(&rtor->poll_w);
+#endif
+
rtor->can_poll_w
= ossl_quic_reactor_can_support_poll_descriptor(rtor, &rtor->poll_w);
}