summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-01-09 15:44:42 +0000
committerHugo Landau <hlandau@openssl.org>2023-01-13 13:20:37 +0000
commit0550829f53fe74f884e382ec0ec323342f77d181 (patch)
tree0deefdcccc9dfc45ce41e56ed6b49359eb321222 /ssl
parent66eab5e08e3a5c7026a3468915ef2e42a43a1479 (diff)
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.c41
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)