summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2024-02-09 12:52:49 +0000
committerTomas Mraz <tomas@openssl.org>2024-02-19 10:15:46 +0100
commit965f68f3e94267e0d19e45c2028386906331b051 (patch)
treeaaa0638a184441a0aa806139a6739c3e1cde6d63 /ssl
parent8c13e0851319ac99413044ac83e7e4a66fb23277 (diff)
QUIC APL: Add implementation of SSL_VALUE_EVENT_HANDLING_MODE
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/23535)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_impl.c122
-rw-r--r--ssl/quic/quic_local.h7
2 files changed, 116 insertions, 13 deletions
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index d0dc04bb37..76cd4d13cf 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -40,6 +40,8 @@ static int quic_validate_for_write(QUIC_XSO *xso, int *err);
static int quic_mutation_allowed(QUIC_CONNECTION *qc, int req_active);
static int qc_blocking_mode(const QUIC_CONNECTION *qc);
static int xso_blocking_mode(const QUIC_XSO *xso);
+static void qctx_maybe_autotick(QCTX *ctx);
+static int qctx_should_autotick(QCTX *ctx);
/*
* QUIC Front-End I/O API: Common Utilities
@@ -1270,7 +1272,7 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
goto err;
}
} else {
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(ctx.qc->ch), 0);
+ qctx_maybe_autotick(&ctx);
}
}
@@ -1289,7 +1291,7 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
goto err;
}
} else {
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(ctx.qc->ch), 0);
+ qctx_maybe_autotick(&ctx);
}
if (!ossl_quic_channel_is_term_any(ctx.qc->ch)) {
@@ -1330,7 +1332,7 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
goto err;
}
} else {
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(ctx.qc->ch), 0);
+ qctx_maybe_autotick(&ctx);
}
ret = ossl_quic_channel_is_terminated(ctx.qc->ch);
@@ -1678,7 +1680,7 @@ static int quic_do_handshake(QCTX *ctx)
if (!qc_blocking_mode(qc)) {
/* Try to advance the reactor. */
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
+ qctx_maybe_autotick(ctx);
if (ossl_quic_channel_is_handshake_complete(qc->ch))
/* The handshake is now done. */
@@ -1884,7 +1886,7 @@ static int qc_wait_for_default_xso_for_read(QCTX *ctx)
expect_id | QUIC_STREAM_DIR_UNI);
if (qs == NULL) {
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
+ qctx_maybe_autotick(ctx);
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(qc->ch),
expect_id);
@@ -2404,7 +2406,7 @@ static int quic_write_nonblocking_aon(QCTX *ctx, const void *buf,
}
quic_post_write(xso, actual_written > 0, actual_written == actual_len,
- flags, 1);
+ flags, qctx_should_autotick(ctx));
if (actual_written == actual_len) {
/* We have sent everything. */
@@ -2465,7 +2467,8 @@ static int quic_write_nonblocking_epw(QCTX *ctx, const void *buf, size_t len,
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
}
- quic_post_write(xso, *written > 0, *written == len, flags, 1);
+ quic_post_write(xso, *written > 0, *written == len, flags,
+ qctx_should_autotick(ctx));
return 1;
}
@@ -2553,7 +2556,8 @@ int ossl_quic_write_flags(SSL *s, const void *buf, size_t len,
if (len == 0) {
if ((flags & SSL_WRITE_FLAG_CONCLUDE) != 0)
- quic_post_write(ctx.xso, 0, 1, flags, 1);
+ quic_post_write(ctx.xso, 0, 1, flags,
+ qctx_should_autotick(&ctx));
ret = 1;
goto out;
@@ -2767,7 +2771,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
* 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(ctx.qc->ch), 0);
+ qctx_maybe_autotick(&ctx);
ret = 1;
} else if (xso_blocking_mode(ctx.xso)) {
/*
@@ -2797,7 +2801,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
* We did not get any bytes and are not in blocking mode.
* Tick to see if this delivers any more.
*/
- ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(ctx.qc->ch), 0);
+ qctx_maybe_autotick(&ctx);
/* Try the read again. */
if (!quic_read_actual(&ctx, ctx.xso->stream, buf, len, bytes_read, peek)) {
@@ -2909,7 +2913,7 @@ int ossl_quic_conn_stream_conclude(SSL *s)
}
ossl_quic_sstream_fin(qs->sstream);
- quic_post_write(ctx.xso, 1, 0, 0, 1);
+ quic_post_write(ctx.xso, 1, 0, 0, qctx_should_autotick(&ctx));
quic_unlock(ctx.qc);
return 1;
}
@@ -3295,13 +3299,99 @@ static int qc_get_stream_avail(QCTX *ctx, uint32_t class_,
return ret;
}
+QUIC_NEEDS_LOCK
+static int qctx_should_autotick(QCTX *ctx)
+{
+ int event_handling_mode;
+
+ if (ctx->is_stream) {
+ event_handling_mode = ctx->xso->event_handling_mode;
+ if (event_handling_mode != SSL_VALUE_EVENT_HANDLING_MODE_INHERIT)
+ return event_handling_mode == SSL_VALUE_EVENT_HANDLING_MODE_IMPLICIT;
+ }
+
+ event_handling_mode = ctx->qc->event_handling_mode;
+ if (event_handling_mode == SSL_VALUE_EVENT_HANDLING_MODE_INHERIT)
+ event_handling_mode = SSL_VALUE_EVENT_HANDLING_MODE_IMPLICIT;
+
+ return event_handling_mode == SSL_VALUE_EVENT_HANDLING_MODE_IMPLICIT;
+}
+
+QUIC_NEEDS_LOCK
+static void qctx_maybe_autotick(QCTX *ctx)
+{
+ if (!qctx_should_autotick(ctx))
+ return;
+
+ ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(ctx->qc->ch), 0);
+}
+
+QUIC_TAKES_LOCK
+static int qc_getset_event_handling(QCTX *ctx, uint32_t class_,
+ uint64_t *p_value_out,
+ uint64_t *p_value_in)
+{
+ int ret = 0;
+ uint64_t value_out = 0;
+
+ quic_lock(ctx->qc);
+
+ if (class_ != SSL_VALUE_CLASS_GENERIC) {
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS,
+ NULL);
+ goto err;
+ }
+
+ if (p_value_in != NULL) {
+ switch (*p_value_in) {
+ case SSL_VALUE_EVENT_HANDLING_MODE_INHERIT:
+ case SSL_VALUE_EVENT_HANDLING_MODE_IMPLICIT:
+ case SSL_VALUE_EVENT_HANDLING_MODE_EXPLICIT:
+ break;
+ default:
+ QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT,
+ NULL);
+ goto err;
+ }
+
+ value_out = *p_value_in;
+ if (ctx->is_stream)
+ ctx->xso->event_handling_mode = value_out;
+ else
+ ctx->qc->event_handling_mode = value_out;
+ } else {
+ value_out = ctx->is_stream
+ ? ctx->xso->event_handling_mode
+ : ctx->qc->event_handling_mode;
+ }
+
+ ret = 1;
+err:
+ quic_unlock(ctx->qc);
+ if (ret && p_value_out != NULL)
+ *p_value_out = value_out;
+
+ return ret;
+}
+
+QUIC_NEEDS_LOCK
+static int expect_quic_for_value(SSL *s, QCTX *ctx, uint32_t id)
+{
+ switch (id) {
+ case SSL_VALUE_EVENT_HANDLING_MODE:
+ return expect_quic(s, ctx);
+ default:
+ return expect_quic_conn_only(s, ctx);
+ }
+}
+
QUIC_TAKES_LOCK
int ossl_quic_get_value_uint(SSL *s, uint32_t class_, uint32_t id,
uint64_t *value)
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_for_value(s, &ctx, id))
return 0;
if (value == NULL)
@@ -3321,6 +3411,9 @@ int ossl_quic_get_value_uint(SSL *s, uint32_t class_, uint32_t id,
case SSL_VALUE_QUIC_STREAM_UNI_REMOTE_AVAIL:
return qc_get_stream_avail(&ctx, class_, /*uni=*/1, /*remote=*/1, value);
+ case SSL_VALUE_EVENT_HANDLING_MODE:
+ return qc_getset_event_handling(&ctx, class_, value, NULL);
+
default:
return QUIC_RAISE_NON_NORMAL_ERROR(&ctx,
SSL_R_UNSUPPORTED_CONFIG_VALUE, NULL);
@@ -3335,13 +3428,16 @@ int ossl_quic_set_value_uint(SSL *s, uint32_t class_, uint32_t id,
{
QCTX ctx;
- if (!expect_quic_conn_only(s, &ctx))
+ if (!expect_quic_for_value(s, &ctx, id))
return 0;
switch (id) {
case SSL_VALUE_QUIC_IDLE_TIMEOUT:
return qc_getset_idle_timeout(&ctx, class_, NULL, &value);
+ case SSL_VALUE_EVENT_HANDLING_MODE:
+ return qc_getset_event_handling(&ctx, class_, NULL, &value);
+
default:
return QUIC_RAISE_NON_NORMAL_ERROR(&ctx,
SSL_R_UNSUPPORTED_CONFIG_VALUE, NULL);
diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h
index cd65610cd8..a5376320d8 100644
--- a/ssl/quic/quic_local.h
+++ b/ssl/quic/quic_local.h
@@ -83,6 +83,10 @@ struct quic_xso_st {
*/
/* Is an AON write in progress? */
unsigned int aon_write_in_progress : 1;
+
+ /* Event handling mode. One of SSL_QUIC_VALUE_EVENT_HANDLING. */
+ unsigned int event_handling_mode : 2;
+
/*
* The base buffer pointer the caller passed us for the initial AON write
* call. We use this for validation purposes unless
@@ -217,6 +221,9 @@ struct quic_conn_st {
unsigned int addressed_mode_w : 1;
unsigned int addressed_mode_r : 1;
+ /* Event handling mode. One of SSL_QUIC_VALUE_EVENT_HANDLING. */
+ unsigned int event_handling_mode : 2;
+
/* Default stream type. Defaults to SSL_DEFAULT_STREAM_MODE_AUTO_BIDI. */
uint32_t default_stream_mode;