summaryrefslogtreecommitdiff
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-04-18 19:30:54 +0100
committerHugo Landau <hlandau@openssl.org>2023-05-12 14:47:11 +0100
commit2dbc39deacf9d5850eecef515cbc50331750dd22 (patch)
tree0a484718a8525de642a4d6f26b3fef49d1d38406 /ssl
parentcb5c208bf2e39bf2367b051136c599cff1fc3683 (diff)
downloadopenssl-new-2dbc39deacf9d5850eecef515cbc50331750dd22.tar.gz
QUIC APL: Add stream creation APIs
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20765)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_channel.c29
-rw-r--r--ssl/quic/quic_channel_local.h8
-rw-r--r--ssl/quic/quic_impl.c58
-rw-r--r--ssl/quic/quic_local.h3
4 files changed, 95 insertions, 3 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index 7ef66b234d..8e1d415935 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -2213,3 +2213,32 @@ SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch)
{
return ch->tls;
}
+
+QUIC_STREAM *ossl_quic_channel_new_stream(QUIC_CHANNEL *ch, int is_uni)
+{
+ QUIC_STREAM *qs;
+ int type = 0;
+ uint64_t stream_id, *p_next_ordinal;
+
+ type |= ch->is_server ? QUIC_STREAM_INITIATOR_SERVER
+ : QUIC_STREAM_INITIATOR_CLIENT;
+
+ if (is_uni) {
+ p_next_ordinal = &ch->next_local_stream_ordinal_uni;
+ type |= QUIC_STREAM_DIR_UNI;
+ } else {
+ p_next_ordinal = &ch->next_local_stream_ordinal_bidi;
+ type |= QUIC_STREAM_DIR_BIDI;
+ }
+
+ if (*p_next_ordinal >= ((uint64_t)1) << 62)
+ return NULL;
+
+ stream_id = ((*p_next_ordinal) << 2) | type;
+
+ if ((qs = ossl_quic_stream_map_alloc(&ch->qsm, stream_id, type)) == NULL)
+ return NULL;
+
+ ++*p_next_ordinal;
+ return qs;
+}
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index fbf16a93db..8534ae9835 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -159,6 +159,14 @@ struct quic_channel_st {
/* Maximum active CID limit, as negotiated by transport parameters. */
uint64_t rx_active_conn_id_limit;
+ /*
+ * Used to allocate stream IDs. This is a stream ordinal, i.e., a stream ID
+ * without the low two bits designating type and initiator. Shift and or in
+ * the type bits to convert to a stream ID.
+ */
+ uint64_t next_local_stream_ordinal_bidi;
+ uint64_t next_local_stream_ordinal_uni;
+
/* Valid if we are in the TERMINATING or TERMINATED states. */
QUIC_TERMINATE_CAUSE terminate_cause;
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index c02efed5f8..0dd6576633 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -257,10 +257,16 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
if (!create_channel(qc))
goto err;
+ if ((qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, 0)) == NULL)
+ goto err;
+
return ssl_base;
err:
- SSL_free(qc->tls);
+ if (qc != NULL) {
+ ossl_quic_channel_free(qc->ch);
+ SSL_free(qc->tls);
+ }
OPENSSL_free(qc);
return NULL;
}
@@ -275,8 +281,39 @@ void ossl_quic_free(SSL *s)
if (!expect_quic(s, &ctx))
return;
+ if (ctx.is_stream) {
+ /*
+ * When a QSSO is freed, the XSO is freed immediately, because the XSO
+ * itself only contains API personality layer data. However the
+ * underlying QUIC_STREAM is not freed immediately but is instead marked
+ * as deleted for later collection.
+ */
+
+ quic_lock(ctx.qc);
+
+ assert(ctx.qc->num_xso > 0);
+ --ctx.qc->num_xso;
+
+ ctx.xso->stream->deleted = 1;
+
+ quic_unlock(ctx.qc);
+
+ /* Note: SSL_free calls OPENSSL_free(xso) for us */
+ return;
+ }
+
quic_lock(ctx.qc);
+ /*
+ * Free the default XSO, if any. The QUIC_STREAM is not deleted at this
+ * stage, but is freed during the channel free when the whole QSM is freed.
+ */
+ if (ctx.qc->default_xso != NULL)
+ SSL_free(&ctx.qc->default_xso->ssl);
+
+ /* Ensure we have no remaining XSOs. */
+ assert(ctx.qc->num_xso == 0);
+
if (ctx.qc->is_thread_assisted && ctx.qc->started) {
ossl_quic_thread_assist_wait_stopped(&ctx.qc->thread_assist);
ossl_quic_thread_assist_cleanup(&ctx.qc->thread_assist);
@@ -1047,12 +1084,20 @@ SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags)
{
QCTX ctx;
QUIC_XSO *xso = NULL;
+ int is_uni = ((flags & SSL_STREAM_FLAG_UNI) != 0);
if (!expect_quic_conn_only(s, &ctx))
return NULL;
+ quic_lock(ctx.qc);
+
+ if (ossl_quic_channel_is_term_any(ctx.qc->ch)) {
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
+ goto err;
+ }
+
if ((xso = OPENSSL_zalloc(sizeof(*xso))) == NULL)
- return NULL;
+ goto err;
if (!ossl_ssl_init(&xso->ssl, s->ctx, s->method, SSL_TYPE_QUIC_XSO))
goto err;
@@ -1061,11 +1106,18 @@ SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags)
xso->blocking = ctx.qc->default_blocking;
xso->ssl_mode = ctx.qc->default_ssl_mode;
- xso->stream = NULL; /* TODO XXX ossl_quic_channel_new_stream */
+ xso->stream = ossl_quic_channel_new_stream(ctx.qc->ch, is_uni);
+ if (xso->stream == NULL)
+ goto err;
+
+ ++ctx.qc->num_xso;
+
+ quic_unlock(ctx.qc);
return &xso->ssl;
err:
OPENSSL_free(xso);
+ quic_unlock(ctx.qc);
return NULL;
}
diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h
index 3906a20357..4b9d715c9b 100644
--- a/ssl/quic/quic_local.h
+++ b/ssl/quic/quic_local.h
@@ -138,6 +138,9 @@ struct quic_conn_st {
OSSL_TIME (*override_now_cb)(void *arg);
void *override_now_cb_arg;
+ /* Number of XSOs allocated. Includes the default XSO, if any. */
+ size_t num_xso;
+
/* Have we started? */
unsigned int started : 1;