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
ch = port_make_channel(port, tls, /*is_server=*/1);
port->tserver_ch = ch;
+ port->is_server = 1;
return ch;
}
{
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.
/* 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