QUIC CONFORMANCE/APL: Handle FIN/reset retirement correctly
authorHugo Landau <hlandau@openssl.org>
Tue, 6 Jun 2023 15:25:12 +0000 (16:25 +0100)
committerPauli <pauli@openssl.org>
Sun, 16 Jul 2023 22:17:58 +0000 (08:17 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21135)

ssl/quic/quic_impl.c
ssl/quic/quic_rx_depack.c

index 544e21e5a7c7ed77c06272bf5cbfc32c548aa492..8efdcb0f131baad04792dbb2b872c070c3cdda74 100644 (file)
@@ -2050,6 +2050,7 @@ QUIC_NEEDS_LOCK
 static int quic_validate_for_read(QUIC_XSO *xso, int *err, int *eos)
 {
     *eos = 0;
+    QUIC_STREAM_MAP *qsm;
 
     if (xso == NULL || xso->stream == NULL) {
         *err = ERR_R_INTERNAL_ERROR;
@@ -2072,6 +2073,10 @@ static int quic_validate_for_read(QUIC_XSO *xso, int *err, int *eos)
         return 0;
 
     case QUIC_RSTREAM_STATE_RESET_RECVD:
+        qsm = ossl_quic_channel_get_qsm(xso->conn->ch);
+        ossl_quic_stream_map_notify_app_read_reset_recv_part(qsm, xso->stream);
+
+        /* FALLTHROUGH */
     case QUIC_RSTREAM_STATE_RESET_READ:
         *err = SSL_R_STREAM_RESET;
         return 0;
@@ -2095,11 +2100,6 @@ static int quic_read_actual(QCTX *ctx,
             return QUIC_RAISE_NON_NORMAL_ERROR(ctx, err, NULL);
     }
 
-    /* If the receive part of the stream is over, issue EOF. */
-    if (stream->recv_fin_retired)
-        /* XXX TODO REMOVE */
-        return QUIC_RAISE_NORMAL_ERROR(ctx, SSL_ERROR_ZERO_RETURN);
-
     if (peek) {
         if (!ossl_quic_rstream_peek(stream->rstream, buf, buf_len,
                                     bytes_read, &is_fin))
@@ -2128,8 +2128,11 @@ static int quic_read_actual(QCTX *ctx,
                 return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
         }
 
-        if (is_fin)
-            stream->recv_fin_retired = 1;
+        if (is_fin && !peek) {
+            QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(ctx->qc->ch);
+
+            ossl_quic_stream_map_notify_totally_read(qsm, ctx->xso->stream);
+        }
 
         if (*bytes_read > 0)
             ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(qc->ch),
index 58d2fc459631a48038f6d5f6c2a10bb04bec229f..71f47705f34e52452b4926718b6bedadd0ed540e 100644 (file)
@@ -463,6 +463,8 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
     OSSL_QUIC_FRAME_STREAM frame_data;
     QUIC_STREAM *stream;
     uint64_t fce;
+    size_t rs_avail;
+    int rs_fin = 0;
 
     *datalen = 0;
 
@@ -567,6 +569,16 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
                                       frame_data.is_fin))
         return 0;
 
+    /*
+     * rs_fin will be 1 only if we can read all data up to and including the FIN
+     * without any gaps before it; this implies we have received all data.
+     */
+    if (!ossl_quic_rstream_available(stream->rstream, &rs_avail, &rs_fin))
+        return 0;
+
+    if (rs_fin)
+        ossl_quic_stream_map_notify_totally_received(&ch->qsm, stream);
+
     *datalen = frame_data.len;
 
     return 1;