summaryrefslogtreecommitdiff
path: root/ssl/quic/quic_tserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/quic/quic_tserver.c')
-rw-r--r--ssl/quic/quic_tserver.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
index 17b70eb3a5..46d39c9d90 100644
--- a/ssl/quic/quic_tserver.c
+++ b/ssl/quic/quic_tserver.c
@@ -252,11 +252,42 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv,
int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id)
{
QUIC_STREAM *qs;
+ unsigned char buf[1];
+ size_t bytes_read = 0;
+ int is_fin = 0;
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
stream_id);
- return qs != NULL && qs->recv_fin_retired;
+ if (qs == NULL || qs->rstream == NULL)
+ return 0;
+
+ if (qs->recv_fin_retired)
+ return 1;
+
+ /*
+ * If we do not have recv_fin_retired, it is possible we should still return
+ * 1 if there is a lone FIN (but no more data) remaining to be retired from
+ * the RSTREAM, for example because ossl_quic_tserver_read() has not been
+ * called since the FIN was received.
+ */
+ if (!ossl_quic_rstream_peek(qs->rstream, buf, sizeof(buf),
+ &bytes_read, &is_fin))
+ return 0;
+
+ if (is_fin && bytes_read == 0) {
+ /* If we have a FIN awaiting retirement and no data before it... */
+ /* Let RSTREAM know we've consumed this FIN. */
+ ossl_quic_rstream_read(qs->rstream, buf, sizeof(buf),
+ &bytes_read, &is_fin); /* best effort */
+ assert(is_fin && bytes_read == 0);
+
+ qs->recv_fin_retired = 1;
+ ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);
+ return 1;
+ }
+
+ return 0;
}
int ossl_quic_tserver_write(QUIC_TSERVER *srv,