QUIC PORT: Fix BIO_dgram usage under Winsock due to bind requirement

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22674)
This commit is contained in:
Hugo Landau 2023-11-09 15:30:15 +00:00
parent ff3a26b24f
commit 3051339887
3 changed files with 27 additions and 0 deletions

View File

@ -2255,6 +2255,7 @@ static int ch_tx(QUIC_CHANNEL *ch)
res = ossl_quic_tx_packetiser_generate(ch->txp, &status);
if (status.sent_pkt > 0) {
ch->have_sent_any_pkt = 1; /* Packet(s) were sent */
ch->port->have_sent_any_pkt = 1;
/*
* RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when

View File

@ -323,6 +323,7 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls)
ch = port_make_channel(port, tls, /*is_server=*/1);
port->tserver_ch = ch;
port->is_server = 1;
return ch;
}
@ -365,6 +366,25 @@ static void port_rx_pre(QUIC_PORT *port)
{
int ret;
/*
* Originally, this check (don't RX before we have sent anything if we are
* not a server, because there can't be anything) was just intended as a
* minor optimisation. However, it is actually required on Windows, and
* removing this check will cause Windows to break.
*
* The reason is that under Win32, recvfrom() does not work on a UDP socket
* which has not had bind() called (???). However, calling sendto() will
* automatically bind an unbound UDP socket. Therefore, if we call a Winsock
* recv-type function before calling a Winsock send-type function, that call
* will fail with WSAEINVAL, which we will regard as a permanent network
* error.
*
* Therefore, this check is essential as we do not require our API users to
* bind a socket first when using the API in client mode.
*/
if (!port->is_server && !port->have_sent_any_pkt)
return;
/*
* Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams
* to the appropriate QRX instances.

View File

@ -87,6 +87,12 @@ struct quic_port_st {
/* Inhibit tick for testing purposes? */
unsigned int inhibit_tick : 1;
/* Has this port sent any packet of any kind yet? */
unsigned int have_sent_any_pkt : 1;
/* Does this port allow incoming connections? */
unsigned int is_server : 1;
};
# endif