summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2022-12-13 12:28:54 +0000
committerHugo Landau <hlandau@openssl.org>2023-01-27 14:19:15 +0000
commita9979965bf2b74ca79e4bf3fa13539ab90728eeb (patch)
treec2163a1e1f4c2b19ac4bacf6d2a44dd79c8dfcab /ssl
parentcf06f34727447fad04cbcbce2b8b3f269c1b9307 (diff)
QUIC Front End I/O API: Add support for signalling and detecting end-of-stream
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19897)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/quic/quic_impl.c46
-rw-r--r--ssl/quic/quic_sstream.c11
-rw-r--r--ssl/quic/quic_tserver.c25
-rw-r--r--ssl/ssl_lib.c14
4 files changed, 85 insertions, 11 deletions
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index e869e97ef5..8fe5575813 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -756,6 +756,8 @@ int ossl_quic_accept(SSL *s)
* (BIO/)SSL_read => ossl_quic_read
* (BIO/)SSL_write => ossl_quic_write
* SSL_pending => ossl_quic_pending
+ * SSL_stream_conclude => ossl_quic_conn_stream_conclude
+ *
*/
/* SSL_get_error */
@@ -1053,6 +1055,10 @@ static int quic_read_actual(QUIC_CONNECTION *qc,
{
int is_fin = 0;
+ /* If the receive part of the stream is over, issue EOF. */
+ if (stream->recv_fin_retired)
+ return QUIC_RAISE_NORMAL_ERROR(qc, SSL_ERROR_ZERO_RETURN);
+
if (stream->rstream == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
@@ -1099,9 +1105,11 @@ static int quic_read_again(void *arg)
{
struct quic_read_again_args *args = arg;
- if (!ossl_quic_channel_is_active(args->qc->ch))
+ if (!ossl_quic_channel_is_active(args->qc->ch)) {
/* If connection is torn down due to an error while blocking, stop. */
+ QUIC_RAISE_NON_NORMAL_ERROR(args->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
return -1;
+ }
if (!quic_read_actual(args->qc, args->stream,
args->buf, args->len, args->bytes_read,
@@ -1129,15 +1137,15 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch))
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
- /* If we haven't finished the handshake, try to advance it.*/
+ /* If we haven't finished the handshake, try to advance it. */
if (ossl_quic_do_handshake(qc) < 1)
- return 0;
+ return 0; /* ossl_quic_do_handshake raised error here */
if (qc->stream0 == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
if (!quic_read_actual(qc, qc->stream0, buf, len, bytes_read, peek))
- return 0;
+ return 0; /* quic_read_actual raised error here */
if (*bytes_read > 0) {
/*
@@ -1160,12 +1168,10 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
args.peek = peek;
res = block_until_pred(qc, quic_read_again, &args, 0);
- if (res <= 0) {
- if (!ossl_quic_channel_is_active(qc->ch))
- return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
- else
- return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
- }
+ if (res == 0)
+ return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
+ else if (res < 0)
+ return 0; /* quic_read_again raised error here */
return 1;
} else {
@@ -1208,6 +1214,26 @@ size_t ossl_quic_pending(const SSL *s)
}
/*
+ * SSL_stream_conclude
+ * -------------------
+ */
+int ossl_quic_conn_stream_conclude(QUIC_CONNECTION *qc)
+{
+ QUIC_STREAM *qs = qc->stream0;
+
+ if (qs == NULL || qs->sstream == NULL)
+ return 0;
+
+ if (!ossl_quic_channel_is_active(qc->ch)
+ || ossl_quic_sstream_get_final_size(qs->sstream, NULL))
+ return 1;
+
+ ossl_quic_sstream_fin(qs->sstream);
+ quic_post_write(qc, 1, 1);
+ return 1;
+}
+
+/*
* QUIC Front-End I/O API: SSL_CTX Management
* ==========================================
*/
diff --git a/ssl/quic/quic_sstream.c b/ssl/quic/quic_sstream.c
index a5c4b92823..8dc7002c41 100644
--- a/ssl/quic/quic_sstream.c
+++ b/ssl/quic/quic_sstream.c
@@ -442,6 +442,17 @@ void ossl_quic_sstream_fin(QUIC_SSTREAM *qss)
qss->have_final_size = 1;
}
+int ossl_quic_sstream_get_final_size(QUIC_SSTREAM *qss, uint64_t *final_size)
+{
+ if (!qss->have_final_size)
+ return 0;
+
+ if (final_size != NULL)
+ *final_size = qss->ring_buf.head_offset;
+
+ return 1;
+}
+
int ossl_quic_sstream_append(QUIC_SSTREAM *qss,
const unsigned char *buf,
size_t buf_len,
diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
index 6795d4ec46..5a03aa5327 100644
--- a/ssl/quic/quic_tserver.c
+++ b/ssl/quic/quic_tserver.c
@@ -142,11 +142,14 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv,
size_t buf_len,
size_t *bytes_read)
{
- int is_fin = 0; /* TODO(QUIC): Handle FIN in API */
+ int is_fin = 0;
if (!ossl_quic_channel_is_active(srv->ch))
return 0;
+ if (srv->stream0->recv_fin_retired)
+ return 0;
+
if (!ossl_quic_rstream_read(srv->stream0->rstream, buf, buf_len,
bytes_read, &is_fin))
return 0;
@@ -177,6 +180,11 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv,
return 1;
}
+int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv)
+{
+ return srv->stream0->recv_fin_retired;
+}
+
int ossl_quic_tserver_write(QUIC_TSERVER *srv,
const unsigned char *buf,
size_t buf_len,
@@ -201,3 +209,18 @@ int ossl_quic_tserver_write(QUIC_TSERVER *srv,
ossl_quic_tserver_tick(srv);
return 1;
}
+
+int ossl_quic_tserver_conclude(QUIC_TSERVER *srv)
+{
+ if (!ossl_quic_channel_is_active(srv->ch))
+ return 0;
+
+ if (!ossl_quic_sstream_get_final_size(srv->stream0->sstream, NULL)) {
+ ossl_quic_sstream_fin(srv->stream0->sstream);
+ ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
+ srv->stream0);
+ }
+
+ ossl_quic_tserver_tick(srv);
+ return 1;
+}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index b927e283fe..2549798598 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -7197,3 +7197,17 @@ int SSL_shutdown_ex(SSL *ssl, uint64_t flags,
return SSL_shutdown(ssl);
#endif
}
+
+int SSL_stream_conclude(SSL *ssl, uint64_t flags)
+{
+#ifndef OPENSSL_NO_QUIC
+ QUIC_CONNECTION *qc = QUIC_CONNECTION_FROM_SSL(ssl);
+
+ if (qc == NULL)
+ return 0;
+
+ return ossl_quic_conn_stream_conclude(qc);
+#else
+ return 0;
+#endif
+}