diff --git a/include/lsquic.h b/include/lsquic.h index ea477544f..d3f31adb2 100644 --- a/include/lsquic.h +++ b/include/lsquic.h @@ -221,6 +221,16 @@ struct lsquic_stream_if { * just one direction in IETF QUIC. */ void (*on_reset) (lsquic_stream_t *s, lsquic_stream_ctx_t *h, int how); + /** + * Optional callback is called when a CONNECTION_CLOSE frame is received. + * This allows the application to log low-level diagnostic information about + * errors received with the CONNECTION_CLOSE frame. If app_error is -1 then + * it is considered unknown if this is an app_error or not. + */ +#define LSQUIC_SUPPORTS_CONNCLOSEFRAME_CALLBACK + void (*on_conncloseframe_received)(lsquic_conn_t *c, + int app_error, uint64_t error_code, + const char *reason, int reason_len); }; struct ssl_ctx_st; diff --git a/src/liblsquic/lsquic_full_conn.c b/src/liblsquic/lsquic_full_conn.c index dae1b67a8..acafaab1f 100644 --- a/src/liblsquic/lsquic_full_conn.c +++ b/src/liblsquic/lsquic_full_conn.c @@ -2098,6 +2098,9 @@ process_connection_close_frame (struct full_conn *conn, lsquic_packet_in_t *pack (int) reason_len, (const char *) p + reason_off); LSQ_INFO("Received CONNECTION_CLOSE frame (code: %"PRIu64"; reason: %.*s)", error_code, (int) reason_len, (const char *) p + reason_off); + if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_conncloseframe_received) + conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_conncloseframe_received( + &conn->fc_conn, -1, error_code, (const char *) p + reason_off, reason_len); conn->fc_flags |= FC_RECV_CLOSE; if (!(conn->fc_flags & FC_CLOSING)) { diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index f53d3bdf9..ebd702d92 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -5960,6 +5960,9 @@ process_connection_close_frame (struct ietf_full_conn *conn, LSQ_INFO("Received CONNECTION_CLOSE frame (%s-level code: %"PRIu64"; " "reason: %.*s)", app_error ? "application" : "transport", error_code, (int) reason_len, (const char *) p + reason_off); + if (conn->ifc_enpub->enp_stream_if->on_conncloseframe_received) + conn->ifc_enpub->enp_stream_if->on_conncloseframe_received( + &conn->ifc_conn, app_error, error_code, (const char *) p + reason_off, reason_len); conn->ifc_flags |= IFC_RECV_CLOSE; if (!(conn->ifc_flags & IFC_CLOSING)) {