mirror of
https://github.com/openssl/openssl.git
synced 2024-12-09 05:51:54 +08:00
Enable QUIC test server to find out the termination reason
We enable querying of the termination reason which is useful for tests. Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20030)
This commit is contained in:
parent
ce3106baba
commit
149a8e6c0a
@ -64,6 +64,34 @@ typedef struct quic_channel_args_st {
|
||||
|
||||
typedef struct quic_channel_st QUIC_CHANNEL;
|
||||
|
||||
/* Represents the cause for a connection's termination. */
|
||||
typedef struct quic_terminate_cause_st {
|
||||
/*
|
||||
* If we are in a TERMINATING or TERMINATED state, this is the error code
|
||||
* associated with the error. This field is valid iff we are in the
|
||||
* TERMINATING or TERMINATED states.
|
||||
*/
|
||||
uint64_t error_code;
|
||||
|
||||
/*
|
||||
* If terminate_app is set and this is nonzero, this is the frame type which
|
||||
* caused the connection to be terminated.
|
||||
*/
|
||||
uint64_t frame_type;
|
||||
|
||||
/* Is this error code in the transport (0) or application (1) space? */
|
||||
unsigned int app : 1;
|
||||
|
||||
/*
|
||||
* If set, the cause of the termination is a received CONNECTION_CLOSE
|
||||
* frame. Otherwise, we decided to terminate ourselves and sent a
|
||||
* CONNECTION_CLOSE frame (regardless of whether the peer later also sends
|
||||
* one).
|
||||
*/
|
||||
unsigned int remote : 1;
|
||||
} QUIC_TERMINATE_CAUSE;
|
||||
|
||||
|
||||
/*
|
||||
* Create a new QUIC channel using the given arguments. The argument structure
|
||||
* does not need to remain allocated. Returns NULL on failure.
|
||||
@ -158,9 +186,12 @@ QUIC_STREAM *ossl_quic_channel_get_stream_by_id(QUIC_CHANNEL *ch,
|
||||
uint64_t stream_id);
|
||||
|
||||
/* Returns 1 if channel is terminating or terminated. */
|
||||
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause);
|
||||
int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause);
|
||||
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause);
|
||||
int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
# include <openssl/ssl.h>
|
||||
# include "internal/quic_stream.h"
|
||||
# include "internal/quic_channel.h"
|
||||
|
||||
# ifndef OPENSSL_NO_QUIC
|
||||
|
||||
@ -54,8 +55,12 @@ int ossl_quic_tserver_tick(QUIC_TSERVER *srv);
|
||||
int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv);
|
||||
|
||||
/* Returns 1 if the server is in any terminating or terminated state */
|
||||
int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv);
|
||||
int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv,
|
||||
QUIC_TERMINATE_CAUSE *cause);
|
||||
|
||||
/* Returns 1 if the server is in a terminated state */
|
||||
int ossl_quic_tserver_is_terminated(QUIC_TSERVER *srv,
|
||||
QUIC_TERMINATE_CAUSE *cause);
|
||||
/*
|
||||
* Attempts to read from stream 0. Writes the number of bytes read to
|
||||
* *bytes_read and returns 1 on success. If no bytes are available, 0 is written
|
||||
|
@ -398,21 +398,34 @@ int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch)
|
||||
return ch != NULL && ch->state == QUIC_CHANNEL_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch)
|
||||
int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause)
|
||||
{
|
||||
return ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING
|
||||
|| ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING;
|
||||
if (ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING
|
||||
|| ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING) {
|
||||
if (cause != NULL)
|
||||
*cause = ch->terminate_cause;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch)
|
||||
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause)
|
||||
{
|
||||
return ch->state == QUIC_CHANNEL_STATE_TERMINATED;
|
||||
if (ch->state == QUIC_CHANNEL_STATE_TERMINATED) {
|
||||
if (cause != NULL)
|
||||
*cause = ch->terminate_cause;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch)
|
||||
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch,
|
||||
QUIC_TERMINATE_CAUSE *cause)
|
||||
{
|
||||
return ossl_quic_channel_is_terminating(ch)
|
||||
|| ossl_quic_channel_is_terminated(ch);
|
||||
return ossl_quic_channel_is_terminating(ch, cause)
|
||||
|| ossl_quic_channel_is_terminated(ch, cause);
|
||||
}
|
||||
|
||||
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch)
|
||||
@ -1191,7 +1204,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
|
||||
*/
|
||||
|
||||
/* If we are in the TERMINATED state, there is nothing to do. */
|
||||
if (ossl_quic_channel_is_terminated(ch)) {
|
||||
if (ossl_quic_channel_is_terminated(ch, NULL)) {
|
||||
res->net_read_desired = 0;
|
||||
res->net_write_desired = 0;
|
||||
res->tick_deadline = ossl_time_infinite();
|
||||
@ -1202,7 +1215,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
|
||||
* If we are in the TERMINATING state, check if the terminating timer has
|
||||
* expired.
|
||||
*/
|
||||
if (ossl_quic_channel_is_terminating(ch)) {
|
||||
if (ossl_quic_channel_is_terminating(ch, NULL)) {
|
||||
now = ossl_time_now();
|
||||
|
||||
if (ossl_time_compare(now, ch->terminate_deadline) >= 0) {
|
||||
@ -1273,11 +1286,11 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg)
|
||||
* errors in ch_rx_pre() or ch_tx() may have caused us to transition to the
|
||||
* Terminated state.
|
||||
*/
|
||||
res->net_read_desired = !ossl_quic_channel_is_terminated(ch);
|
||||
res->net_read_desired = !ossl_quic_channel_is_terminated(ch, NULL);
|
||||
|
||||
/* We want to write to the network if we have any in our queue. */
|
||||
res->net_write_desired
|
||||
= (!ossl_quic_channel_is_terminated(ch)
|
||||
= (!ossl_quic_channel_is_terminated(ch, NULL)
|
||||
&& ossl_qtx_get_queue_len_datagrams(ch->qtx) > 0);
|
||||
}
|
||||
|
||||
@ -1581,7 +1594,7 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
|
||||
OSSL_TIME deadline;
|
||||
uint32_t pn_space;
|
||||
|
||||
if (ossl_quic_channel_is_terminated(ch))
|
||||
if (ossl_quic_channel_is_terminated(ch, NULL))
|
||||
return ossl_time_infinite();
|
||||
|
||||
deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);
|
||||
@ -1599,7 +1612,7 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
|
||||
ch->cc_method->get_next_credit_time(ch->cc_data));
|
||||
|
||||
/* Is the terminating timer armed? */
|
||||
if (ossl_quic_channel_is_terminating(ch))
|
||||
if (ossl_quic_channel_is_terminating(ch, NULL))
|
||||
deadline = ossl_time_min(deadline,
|
||||
ch->terminate_deadline);
|
||||
else if (!ossl_time_is_infinite(ch->idle_deadline))
|
||||
@ -1729,7 +1742,7 @@ void ossl_quic_channel_local_close(QUIC_CHANNEL *ch, uint64_t app_error_code)
|
||||
{
|
||||
QUIC_TERMINATE_CAUSE tcause = {0};
|
||||
|
||||
if (ossl_quic_channel_is_term_any(ch))
|
||||
if (ossl_quic_channel_is_term_any(ch, NULL))
|
||||
return;
|
||||
|
||||
tcause.app = 1;
|
||||
|
@ -5,33 +5,6 @@
|
||||
|
||||
# ifndef OPENSSL_NO_QUIC
|
||||
|
||||
/* Represents the cause for a connection's termination. */
|
||||
typedef struct quic_terminate_cause_st {
|
||||
/*
|
||||
* If we are in a TERMINATING or TERMINATED state, this is the error code
|
||||
* associated with the error. This field is valid iff we are in the
|
||||
* TERMINATING or TERMINATED states.
|
||||
*/
|
||||
uint64_t error_code;
|
||||
|
||||
/*
|
||||
* If terminate_app is set and this is nonzero, this is the frame type which
|
||||
* caused the connection to be terminated.
|
||||
*/
|
||||
uint64_t frame_type;
|
||||
|
||||
/* Is this error code in the transport (0) or application (1) space? */
|
||||
unsigned int app : 1;
|
||||
|
||||
/*
|
||||
* If set, the cause of the termination is a received CONNECTION_CLOSE
|
||||
* frame. Otherwise, we decided to terminate ourselves and sent a
|
||||
* CONNECTION_CLOSE frame (regardless of whether the peer later also sends
|
||||
* one).
|
||||
*/
|
||||
unsigned int remote : 1;
|
||||
} QUIC_TERMINATE_CAUSE;
|
||||
|
||||
/*
|
||||
* QUIC Channel Structure
|
||||
* ======================
|
||||
|
@ -646,7 +646,7 @@ int ossl_quic_do_handshake(QUIC_CONNECTION *qc)
|
||||
/* Handshake already completed. */
|
||||
return 1;
|
||||
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch))
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch, NULL))
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
|
||||
if (BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) {
|
||||
@ -1012,7 +1012,7 @@ int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
|
||||
if (!expect_quic_conn(qc))
|
||||
return 0;
|
||||
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch))
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch, NULL))
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
|
||||
/*
|
||||
@ -1133,7 +1133,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
|
||||
if (!expect_quic_conn(qc))
|
||||
return 0;
|
||||
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch))
|
||||
if (qc->ch != NULL && ossl_quic_channel_is_term_any(qc->ch, NULL))
|
||||
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
|
||||
|
||||
/* If we haven't finished the handshake, try to advance it. */
|
||||
|
@ -148,9 +148,17 @@ int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
|
||||
}
|
||||
|
||||
/* Returns 1 if the server is in any terminating or terminated state */
|
||||
int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv)
|
||||
int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv,
|
||||
QUIC_TERMINATE_CAUSE *cause)
|
||||
{
|
||||
return ossl_quic_channel_is_term_any(srv->ch);
|
||||
return ossl_quic_channel_is_term_any(srv->ch, cause);
|
||||
}
|
||||
|
||||
/* Returns 1 if the server is in a terminated state */
|
||||
int ossl_quic_tserver_is_terminated(QUIC_TSERVER *srv,
|
||||
QUIC_TERMINATE_CAUSE *cause)
|
||||
{
|
||||
return ossl_quic_channel_is_terminated(srv->ch, cause);
|
||||
}
|
||||
|
||||
int ossl_quic_tserver_read(QUIC_TSERVER *srv,
|
||||
|
@ -144,7 +144,7 @@ int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
|
||||
SSL_tick(clientssl);
|
||||
if (!servererr) {
|
||||
ossl_quic_tserver_tick(qtserv);
|
||||
servererr = ossl_quic_tserver_is_term_any(qtserv);
|
||||
servererr = ossl_quic_tserver_is_term_any(qtserv, NULL);
|
||||
if (!servererr && !rets)
|
||||
rets = ossl_quic_tserver_is_connected(qtserv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user