mirror of
https://github.com/openssl/openssl.git
synced 2025-02-23 14:42:15 +08:00
QUIC PORT: Allow errors to be tracked at port level
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22674)
This commit is contained in:
parent
f12ea1f1e0
commit
4df4add22d
@ -133,6 +133,12 @@ void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit);
|
|||||||
/* Returns 1 if the port is running/healthy, 0 if it has failed. */
|
/* Returns 1 if the port is running/healthy, 0 if it has failed. */
|
||||||
int ossl_quic_port_is_running(const QUIC_PORT *port);
|
int ossl_quic_port_is_running(const QUIC_PORT *port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restores port-level error to the error stack. To be called only if
|
||||||
|
* the port is no longer running.
|
||||||
|
*/
|
||||||
|
void ossl_quic_port_restore_err_state(const QUIC_PORT *port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Events
|
* Events
|
||||||
* ======
|
* ======
|
||||||
@ -140,9 +146,11 @@ int ossl_quic_port_is_running(const QUIC_PORT *port);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Called if a permanent network error occurs. Terminates all channels
|
* Called if a permanent network error occurs. Terminates all channels
|
||||||
* immediately.
|
* immediately. triggering_ch is an optional argument designating
|
||||||
|
* a channel which encountered the network error.
|
||||||
*/
|
*/
|
||||||
void ossl_quic_port_raise_net_error(QUIC_PORT *port);
|
void ossl_quic_port_raise_net_error(QUIC_PORT *port,
|
||||||
|
QUIC_CHANNEL *triggering_ch);
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -2310,7 +2310,7 @@ static int ch_tx(QUIC_CHANNEL *ch)
|
|||||||
case QTX_FLUSH_NET_RES_PERMANENT_FAIL:
|
case QTX_FLUSH_NET_RES_PERMANENT_FAIL:
|
||||||
default:
|
default:
|
||||||
/* Permanent underlying network BIO, start terminating. */
|
/* Permanent underlying network BIO, start terminating. */
|
||||||
ossl_quic_port_raise_net_error(ch->port);
|
ossl_quic_port_raise_net_error(ch->port, ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2927,13 +2927,14 @@ void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch)
|
|||||||
{
|
{
|
||||||
QUIC_TERMINATE_CAUSE tcause = {0};
|
QUIC_TERMINATE_CAUSE tcause = {0};
|
||||||
|
|
||||||
|
if (ch->net_error)
|
||||||
|
return;
|
||||||
|
|
||||||
ch->net_error = 1;
|
ch->net_error = 1;
|
||||||
|
|
||||||
ERR_raise_data(ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR,
|
|
||||||
"connection terminated due to network error");
|
|
||||||
ch_save_err_state(ch);
|
|
||||||
|
|
||||||
tcause.error_code = QUIC_ERR_INTERNAL_ERROR;
|
tcause.error_code = QUIC_ERR_INTERNAL_ERROR;
|
||||||
|
tcause.reason = "network BIO I/O error";
|
||||||
|
tcause.reason_len = strlen(tcause.reason);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip Terminating state and go directly to Terminated, no point trying to
|
* Skip Terminating state and go directly to Terminated, no point trying to
|
||||||
@ -2952,7 +2953,10 @@ void ossl_quic_channel_restore_err_state(QUIC_CHANNEL *ch)
|
|||||||
if (ch == NULL)
|
if (ch == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSSL_ERR_STATE_restore(ch->err_state);
|
if (!ossl_quic_port_is_running(ch->port))
|
||||||
|
ossl_quic_port_restore_err_state(ch->port);
|
||||||
|
else
|
||||||
|
OSSL_ERR_STATE_restore(ch->err_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
|
void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
|
||||||
|
@ -70,6 +70,9 @@ static int port_init(QUIC_PORT *port)
|
|||||||
if (port->channel_ctx == NULL)
|
if (port->channel_ctx == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
if ((port->err_state = OSSL_ERR_STATE_new()) == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL,
|
if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL,
|
||||||
/*Short CID Len=*/rx_short_dcid_len,
|
/*Short CID Len=*/rx_short_dcid_len,
|
||||||
get_time, port)) == NULL)
|
get_time, port)) == NULL)
|
||||||
@ -108,6 +111,9 @@ static void port_cleanup(QUIC_PORT *port)
|
|||||||
|
|
||||||
ossl_quic_lcidm_free(port->lcidm);
|
ossl_quic_lcidm_free(port->lcidm);
|
||||||
port->lcidm = NULL;
|
port->lcidm = NULL;
|
||||||
|
|
||||||
|
OSSL_ERR_STATE_free(port->err_state);
|
||||||
|
port->err_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void port_transition_failed(QUIC_PORT *port)
|
static void port_transition_failed(QUIC_PORT *port)
|
||||||
@ -341,7 +347,8 @@ static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
|
|||||||
|
|
||||||
if (!port->inhibit_tick) {
|
if (!port->inhibit_tick) {
|
||||||
/* Handle any incoming data from network. */
|
/* Handle any incoming data from network. */
|
||||||
port_rx_pre(port);
|
if (ossl_quic_port_is_running(port))
|
||||||
|
port_rx_pre(port);
|
||||||
|
|
||||||
/* Iterate through all channels and service them. */
|
/* Iterate through all channels and service them. */
|
||||||
LIST_FOREACH(ch, ch, &port->channel_list) {
|
LIST_FOREACH(ch, ch, &port->channel_list) {
|
||||||
@ -370,7 +377,7 @@ static void port_rx_pre(QUIC_PORT *port)
|
|||||||
* Terminated state as there is no point trying to send CONNECTION_CLOSE
|
* Terminated state as there is no point trying to send CONNECTION_CLOSE
|
||||||
* frames if the network BIO is not operating correctly.
|
* frames if the network BIO is not operating correctly.
|
||||||
*/
|
*/
|
||||||
ossl_quic_port_raise_net_error(port);
|
ossl_quic_port_raise_net_error(port, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -538,12 +545,35 @@ void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit)
|
|||||||
port->inhibit_tick = (inhibit != 0);
|
port->inhibit_tick = (inhibit != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ossl_quic_port_raise_net_error(QUIC_PORT *port)
|
void ossl_quic_port_raise_net_error(QUIC_PORT *port,
|
||||||
|
QUIC_CHANNEL *triggering_ch)
|
||||||
{
|
{
|
||||||
QUIC_CHANNEL *ch;
|
QUIC_CHANNEL *ch;
|
||||||
|
|
||||||
|
if (!ossl_quic_port_is_running(port))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Immediately capture any triggering error on the error stack, with a
|
||||||
|
* cover error.
|
||||||
|
*/
|
||||||
|
ERR_raise_data(ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR,
|
||||||
|
"port failed due to network BIO I/O error");
|
||||||
|
OSSL_ERR_STATE_save(port->err_state);
|
||||||
|
|
||||||
port_transition_failed(port);
|
port_transition_failed(port);
|
||||||
|
|
||||||
|
/* Give the triggering channel (if any) the first notification. */
|
||||||
|
if (triggering_ch != NULL)
|
||||||
|
ossl_quic_channel_raise_net_error(triggering_ch);
|
||||||
|
|
||||||
LIST_FOREACH(ch, ch, &port->channel_list)
|
LIST_FOREACH(ch, ch, &port->channel_list)
|
||||||
ossl_quic_channel_raise_net_error(ch);
|
if (ch != triggering_ch)
|
||||||
|
ossl_quic_channel_raise_net_error(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ossl_quic_port_restore_err_state(const QUIC_PORT *port)
|
||||||
|
{
|
||||||
|
ERR_clear_error();
|
||||||
|
OSSL_ERR_STATE_restore(port->err_state);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,9 @@ struct quic_port_st {
|
|||||||
/* SRTM used for incoming packet routing by SRT. */
|
/* SRTM used for incoming packet routing by SRT. */
|
||||||
QUIC_SRTM *srtm;
|
QUIC_SRTM *srtm;
|
||||||
|
|
||||||
|
/* Port-level permanent errors (causing failure state) are stored here. */
|
||||||
|
ERR_STATE *err_state;
|
||||||
|
|
||||||
/* DCID length used for incoming short header packets. */
|
/* DCID length used for incoming short header packets. */
|
||||||
unsigned char rx_short_dcid_len;
|
unsigned char rx_short_dcid_len;
|
||||||
/* For clients, CID length used for outgoing Initial packets. */
|
/* For clients, CID length used for outgoing Initial packets. */
|
||||||
|
Loading…
Reference in New Issue
Block a user