BIO_POLL_DESCRIPTOR poll_r, poll_w;
OSSL_TIME tick_deadline; /* ossl_time_infinite() if none currently applicable */
- void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg);
+ void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
void *tick_cb_arg;
/*
} QUIC_REACTOR;
void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
- void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg),
+ void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
+ uint32_t flags),
void *tick_cb_arg,
OSSL_TIME initial_tick_deadline);
* Do whatever work can be done, and as much work as can be done. This involves
* e.g. seeing if we can read anything from the network (if we want to), seeing
* if we can write anything to the network (if we want to), etc.
+ *
+ * If the CHANNEL_ONLY flag is set, this indicates that we should only
+ * touch state which is synchronised by the channel mutex.
*/
-int ossl_quic_reactor_tick(QUIC_REACTOR *rtor);
+#define QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY (1U << 0)
+
+int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags);
/*
* Blocking I/O Adaptation Layer
static void ch_rx_pre(QUIC_CHANNEL *ch);
static int ch_rx(QUIC_CHANNEL *ch);
static int ch_tx(QUIC_CHANNEL *ch);
-static void ch_tick(QUIC_TICK_RESULT *res, void *arg);
+static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
static void ch_rx_handle_packet(QUIC_CHANNEL *ch);
static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch);
static int ch_retry(QUIC_CHANNEL *ch,
* at least everything network I/O related. Best effort - not allowed to fail
* "loudly".
*/
-static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
+static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
{
OSSL_TIME now, deadline;
QUIC_CHANNEL *ch = arg;
+ int channel_only = ((flags & QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY) != 0);
/*
* When we tick the QUIC connection, we do everything we need to do
* new outgoing data.
*/
ch->have_new_rx_secret = 0;
- ossl_quic_tls_tick(ch->qtls);
+ if (!channel_only)
+ ossl_quic_tls_tick(ch->qtls);
/*
* If the handshake layer gave us a new secret, we need to do RX again
if (!ossl_quic_tls_tick(ch->qtls))
return 0;
- ossl_quic_reactor_tick(&ch->rtor); /* best effort */
+ ossl_quic_reactor_tick(&ch->rtor, 0); /* best effort */
return 1;
}
return 1;
}
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
quic_unlock(qc);
return 1;
}
if (blocking_mode(qc) && (flags & SSL_SHUTDOWN_FLAG_RAPID) == 0)
block_until_pred(qc, quic_shutdown_wait, qc, 0);
else
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
ret = ossl_quic_channel_is_terminated(qc->ch);
quic_unlock(qc);
return 1;
} else {
/* Try to advance the reactor. */
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
if (ossl_quic_channel_is_handshake_complete(qc->ch))
/* The handshake is now done. */
* plus we should eventually consider Nagle's algorithm.
*/
if (do_tick)
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
}
struct quic_write_again_args {
* Even though we succeeded, tick the reactor here to ensure we are
* handling other aspects of the QUIC connection.
*/
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
ret = 1;
} else if (blocking_mode(qc)) {
/*
* ==========================
*/
void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
- void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg),
+ void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
+ uint32_t flags),
void *tick_cb_arg,
OSSL_TIME initial_tick_deadline)
{
return rtor->tick_deadline;
}
-int ossl_quic_reactor_tick(QUIC_REACTOR *rtor)
+int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags)
{
QUIC_TICK_RESULT res = {0};
* best effort. If something fatal happens with a connection we can report
* it on the next actual application I/O call.
*/
- rtor->tick_cb(&res, rtor->tick_cb_arg);
+ rtor->tick_cb(&res, rtor->tick_cb_arg, flags);
rtor->net_read_desired = res.net_read_desired;
rtor->net_write_desired = res.net_write_desired;
flags &= ~SKIP_FIRST_TICK;
else
/* best effort */
- ossl_quic_reactor_tick(rtor);
+ ossl_quic_reactor_tick(rtor, 0);
if ((res = pred(pred_arg)) != 0)
return res;
if (qta->teardown)
break;
- ossl_quic_reactor_tick(rtor);
+ ossl_quic_reactor_tick(rtor, QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY);
}
CRYPTO_THREAD_unlock(m);
int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
{
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
if (ossl_quic_channel_is_active(srv->ch))
srv->connected = 1;