summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-02-21 10:18:58 +0000
committerHugo Landau <hlandau@openssl.org>2023-03-30 11:14:07 +0100
commitfb2245c44b58b41a378eb47422221edd49ba9091 (patch)
tree7e7b828e8f62868f2cb93834b99f0618432a73dd
parentc019e1efe9b5dbb43c52f516e76b3f535158aaae (diff)
QUIC Channel: Add a mutex
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20348)
-rw-r--r--include/internal/quic_channel.h36
-rw-r--r--include/internal/quic_ssl.h1
-rw-r--r--ssl/quic/quic_channel.c20
-rw-r--r--ssl/quic/quic_channel_local.h6
4 files changed, 63 insertions, 0 deletions
diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h
index f08252d1f9..13cd83bff1 100644
--- a/include/internal/quic_channel.h
+++ b/include/internal/quic_channel.h
@@ -47,6 +47,16 @@
* demuxers). Since we only use server-side functionality for dummy test servers
* for now, which only need to handle one connection at a time, this is not
* currently modelled.
+ *
+ * Synchronisation
+ * ---------------
+ *
+ * To support thread assisted mode, QUIC_CHANNEL can be used by multiple
+ * threads. **It is the caller's responsibility to ensure that the QUIC_CHANNEL
+ * is only accessed (whether via its methods or via direct access to its state)
+ * while the QUIC_CHANNEL mutex is held**, except for methods explicitly marked
+ * as not requiring prior locking. See ossl_quic_channel_get_mutex() for more
+ * information. This is an unchecked precondition.
*/
# define QUIC_CHANNEL_STATE_IDLE 0
@@ -198,6 +208,32 @@ QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch);
SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch);
+/*
+ * Retreves the channel mutex, which can be used to synchronise access to
+ * channel functions and internal data. In order to allow locks to be acquired
+ * and released with the correct granularity, it is the caller's responsibility
+ * to ensure this lock is held for write while calling any QUIC_CHANNEL method.
+ *
+ * This method is thread safe and does not require prior locking. It can also be
+ * called while the lock is already held.
+ */
+CRYPTO_RWLOCK *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch);
+
+/*
+ * Locks the channel mutex. It is roughly analagous to locking the mutex
+ * returned by ossl_quic_channel_get_mutex() but might be able to avoid locking
+ * where thread assisted mode is not being used, thus it is recommended that
+ * these methods are used uniformly rather than locking the channel mutex
+ * directly.
+ *
+ * This method is (obviously) thread safe and does not require prior locking. It
+ * must not be called while the lock is already held.
+ */
+int ossl_quic_channel_lock(QUIC_CHANNEL *ch);
+
+/* Unlocks the channel mutex. */
+void ossl_quic_channel_unlock(QUIC_CHANNEL *ch);
+
# endif
#endif
diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h
index 7b89534c22..3cf32e0944 100644
--- a/include/internal/quic_ssl.h
+++ b/include/internal/quic_ssl.h
@@ -46,6 +46,7 @@ void ossl_quic_set_accept_state(QUIC_CONNECTION *qc);
__owur int ossl_quic_has_pending(const QUIC_CONNECTION *qc);
__owur int ossl_quic_tick(QUIC_CONNECTION *qc);
__owur int ossl_quic_get_tick_timeout(QUIC_CONNECTION *qc, struct timeval *tv);
+OSSL_TIME ossl_quic_get_tick_deadline(QUIC_CONNECTION *qc);
__owur int ossl_quic_get_rpoll_descriptor(QUIC_CONNECTION *qc, BIO_POLL_DESCRIPTOR *d);
__owur int ossl_quic_get_wpoll_descriptor(QUIC_CONNECTION *qc, BIO_POLL_DESCRIPTOR *d);
__owur int ossl_quic_get_net_read_desired(QUIC_CONNECTION *qc);
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index 86eed313ab..efe8ca6def 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -115,6 +115,10 @@ static int ch_init(QUIC_CHANNEL *ch)
qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN;
ch->rx_max_udp_payload_size = qtx_args.mdpl;
+ ch->mutex = CRYPTO_THREAD_lock_new();
+ if (ch->mutex == NULL)
+ goto err;
+
ch->qtx = ossl_qtx_new(&qtx_args);
if (ch->qtx == NULL)
goto err;
@@ -318,6 +322,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch)
ossl_qrx_free(ch->qrx);
ossl_quic_demux_free(ch->demux);
OPENSSL_free(ch->local_transport_params);
+ CRYPTO_THREAD_lock_free(ch->mutex);
}
QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args)
@@ -443,6 +448,21 @@ QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch)
return ch->demux;
}
+CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch)
+{
+ return ch->mutex;
+}
+
+int ossl_quic_channel_lock(QUIC_CHANNEL *ch)
+{
+ return ossl_crypto_mutex_lock(ch->mutex);
+}
+
+void ossl_quic_channel_unlock(QUIC_CHANNEL *ch)
+{
+ ossl_crypto_mutex_unlock(ch->mutex);
+}
+
/*
* QUIC Channel: Callbacks from Miscellaneous Subsidiary Components
* ================================================================
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index fa2618bce5..2f63119cef 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -26,6 +26,12 @@ struct quic_channel_st {
const char *propq;
/*
+ * Master synchronisation mutex used for thread assisted mode
+ * synchronisation.
+ */
+ CRYPTO_RWLOCK *mutex;
+
+ /*
* The associated TLS 1.3 connection data. Used to provide the handshake
* layer; its 'network' side is plugged into the crypto stream for each EL
* (other than the 0-RTT EL).