diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-01-09 15:44:42 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-01-13 13:20:37 +0000 |
commit | 0550829f53fe74f884e382ec0ec323342f77d181 (patch) | |
tree | 0deefdcccc9dfc45ce41e56ed6b49359eb321222 /ssl | |
parent | 66eab5e08e3a5c7026a3468915ef2e42a43a1479 (diff) | |
download | openssl-new-0550829f53fe74f884e382ec0ec323342f77d181.tar.gz |
QUIC QTX: Handle network errors explicitly
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/quic/quic_record_tx.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/ssl/quic/quic_record_tx.c b/ssl/quic/quic_record_tx.c index 0cea8c13f5..dddb29663c 100644 --- a/ssl/quic/quic_record_tx.c +++ b/ssl/quic/quic_record_tx.c @@ -812,14 +812,18 @@ static void txe_to_msg(TXE *txe, BIO_MSG *msg) #define MAX_MSGS_PER_SEND 32 -void ossl_qtx_flush_net(OSSL_QTX *qtx) +int ossl_qtx_flush_net(OSSL_QTX *qtx) { BIO_MSG msg[MAX_MSGS_PER_SEND]; - size_t wr, i; + size_t wr, i, total_written = 0; TXE *txe; + int res; + + if (ossl_list_txe_head(&qtx->pending) == NULL) + return QTX_FLUSH_NET_RES_OK; /* Nothing to send. */ if (qtx->bio == NULL) - return; + return QTX_FLUSH_NET_RES_PERMANENT_FAIL; for (;;) { for (txe = ossl_list_txe_head(&qtx->pending), i = 0; @@ -829,21 +833,46 @@ void ossl_qtx_flush_net(OSSL_QTX *qtx) if (!i) /* Nothing to send. */ - return; + break; - if (!BIO_sendmmsg(qtx->bio, msg, sizeof(BIO_MSG), i, 0, &wr) || wr == 0) + ERR_set_mark(); + res = BIO_sendmmsg(qtx->bio, msg, sizeof(BIO_MSG), i, 0, &wr); + if (res && wr == 0) { + /* + * Treat 0 messages sent as a transient error and just stop for now. + */ + ERR_clear_last_mark(); + break; + } else if (!res) { /* * We did not get anything, so further calls will probably not * succeed either. */ - break; + if (BIO_err_is_non_fatal(ERR_peek_last_error())) { + /* Transient error, just stop for now, clearing the error. */ + ERR_pop_to_mark(); + break; + } else { + /* Non-transient error, fail and do not clear the error. */ + ERR_clear_last_mark(); + return QTX_FLUSH_NET_RES_PERMANENT_FAIL; + } + } + + ERR_clear_last_mark(); /* * Remove everything which was successfully sent from the pending queue. */ for (i = 0; i < wr; ++i) qtx_pending_to_free(qtx); + + total_written += wr; } + + return total_written > 0 + ? QTX_FLUSH_NET_RES_OK + : QTX_FLUSH_NET_RES_TRANSIENT_FAIL; } int ossl_qtx_pop_net(OSSL_QTX *qtx, BIO_MSG *msg) |