diff options
-rw-r--r-- | include/internal/quic_tserver.h | 2 | ||||
-rw-r--r-- | ssl/quic/quic_tserver.c | 33 |
2 files changed, 33 insertions, 2 deletions
diff --git a/include/internal/quic_tserver.h b/include/internal/quic_tserver.h index 89879b01b7..662b1c0979 100644 --- a/include/internal/quic_tserver.h +++ b/include/internal/quic_tserver.h @@ -98,7 +98,7 @@ int ossl_quic_tserver_read(QUIC_TSERVER *srv, int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id); /* - * Attempts to write to stream 0. Writes the number of bytes consumed to + * Attempts to write to the given stream. Writes the number of bytes consumed to * *bytes_written and returns 1 on success. If there is no space currently * available to write any bytes, 0 is written to *consumed and 1 is returned * (this is considered a success case). 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, |