diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-04-18 19:30:56 +0100 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-05-12 14:47:13 +0100 |
commit | 228940168529ba7c10b86934849b19818f79f74e (patch) | |
tree | d5a0b1d9572b5bc43567dc7c4efa3847c56ca795 /ssl | |
parent | 8b5278942be94b5764b93c0633ea4162685264ac (diff) |
QUIC TSERVER: Handle FINs correctly if ossl_quic_tserver_read is not called first
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20765)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/quic/quic_tserver.c | 33 |
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, |