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 | |
parent | 8b5278942be94b5764b93c0633ea4162685264ac (diff) | |
download | openssl-new-228940168529ba7c10b86934849b19818f79f74e.tar.gz |
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)
-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, |