nquic_conn_metrics (nquic v1.0.0)
View SourcePer-connection bridge between #conn_state{} and nquic_metrics.
Lives at the boundary between the connection state machine and the listener-wide observability primitives so callers do not have to thread the metrics handle through every state transition.
All functions are no-ops when:
- the connection has no
dispatch_table(client-mode conns without a listener), or - the listener was started before the metrics primitives existed and the dispatch has no metrics handle attached, or
- the row has not been opened yet (
metrics_countersisundefined).
Summary
Functions
Add N bytes to the row's lifetime bytes_in counter.
Add N bytes to the row's lifetime bytes_out counter.
Pick the conns_closed_* counter for Reason.
Prefers an explicit close_kind set by the draining entry points; falls
back to inspecting the gen_statem terminate reason. idle_timeout is
preferred over protocol_error even when both apply because the operator
view of an idle close is more useful than the generic transport error.
Bump the listener-wide handshakes_inflight counter on conn-statem
init. Pair with on_terminate/2 or listener_established/1 which
decrement.
Insert the info-table row and prime metrics_counters.
Called from
nquic_conn_events:deliver_protocol_event(listener_established, _) on
the server side after the handshake completes. Decrements
handshakes_inflight as the same call site since the handshake is done.
Record the originating cause for an upcoming draining/terminate
transition. Stored on #conn_state.close_kind for
classify_terminate/2.
Return the nquic_metrics handle reachable from this conn, or undefined.
Bump the appropriate conns_closed_* counter, decrement
handshakes_inflight when the conn died before reaching established,
and remove the info-table row.
Idempotent: missing rows and undefined counters are no-ops.
Pick the DCID used as the info-table key for this connection. Prefers the original DCID (set by the listener when the conn was created) and falls back to the local SCID for client-side conns.
Functions
-spec bytes_in(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}, non_neg_integer()) -> ok.
Add N bytes to the row's lifetime bytes_in counter.
-spec bytes_out(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}, non_neg_integer()) -> ok.
Add N bytes to the row's lifetime bytes_out counter.
-spec classify_terminate(term(), #conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> nquic_metrics:slot().
Pick the conns_closed_* counter for Reason.
Prefers an explicit close_kind set by the draining entry points; falls
back to inspecting the gen_statem terminate reason. idle_timeout is
preferred over protocol_error even when both apply because the operator
view of an idle close is more useful than the generic transport error.
-spec handshake_started(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> ok.
Bump the listener-wide handshakes_inflight counter on conn-statem
init. Pair with on_terminate/2 or listener_established/1 which
decrement.
-spec listener_established(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> #conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}.
Insert the info-table row and prime metrics_counters.
Called from
nquic_conn_events:deliver_protocol_event(listener_established, _) on
the server side after the handshake completes. Decrements
handshakes_inflight as the same call site since the handshake is done.
-spec mark_close(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}, local | peer | idle_timeout | protocol_error) -> #conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}.
Record the originating cause for an upcoming draining/terminate
transition. Stored on #conn_state.close_kind for
classify_terminate/2.
-spec metrics(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> nquic_metrics:t() | undefined.
Return the nquic_metrics handle reachable from this conn, or undefined.
-spec on_terminate(term(), #conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> ok.
Bump the appropriate conns_closed_* counter, decrement
handshakes_inflight when the conn died before reaching established,
and remove the info-table row.
Idempotent: missing rows and undefined counters are no-ops.
-spec row_key(#conn_state{role :: client | server, scid :: nquic:connection_id(), dcid :: nquic:connection_id(), odcid :: nquic:connection_id() | undefined, retry_scid :: nquic:connection_id() | undefined, retry_token :: binary(), version :: non_neg_integer(), version_preference :: [non_neg_integer()], socket :: nquic_socket:t() | undefined, peer :: nquic_socket:sockaddr() | undefined, select_info :: nquic_socket:select_info() | undefined, pn_spaces :: #{nquic_packet:space() => map()}, app_next_pn :: non_neg_integer(), app_largest_received :: integer(), loss_state :: nquic_loss:loss_state() | undefined, dispatch_table :: nquic_dispatch:t() | undefined, listener :: pid() | undefined, connect_waiters :: [gen_server:from()], local_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined}, remote_params :: #transport_params{original_destination_connection_id :: nquic:connection_id() | undefined, max_idle_timeout :: non_neg_integer(), stateless_reset_token :: binary() | undefined, max_udp_payload_size :: pos_integer(), initial_max_data :: non_neg_integer(), initial_max_stream_data_bidi_local :: non_neg_integer(), initial_max_stream_data_bidi_remote :: non_neg_integer(), initial_max_stream_data_uni :: non_neg_integer(), initial_max_streams_bidi :: non_neg_integer(), initial_max_streams_uni :: non_neg_integer(), ack_delay_exponent :: 0..20, max_ack_delay :: non_neg_integer(), disable_active_migration :: boolean(), preferred_address :: nquic_transport:preferred_address() | undefined, active_connection_id_limit :: non_neg_integer(), initial_source_connection_id :: nquic:connection_id() | undefined, retry_source_connection_id :: nquic:connection_id() | undefined, version_information :: nquic_transport:version_information() | undefined, max_datagram_frame_size :: non_neg_integer() | undefined} | undefined, server_packet_processed :: boolean(), owner :: pid() | undefined, owner_mon :: reference() | undefined, deferred_flush_pending :: boolean(), pending_ack_count :: non_neg_integer(), last_idle_ms :: non_neg_integer() | infinity | undefined, last_pto_ms :: non_neg_integer() | cancel | undefined, recv_ecn :: nquic_socket:ecn_mark(), pmtud :: nquic_pmtud:pmtud_state() | undefined, gso_size :: undefined | pos_integer(), max_payload_size :: pos_integer(), server_per_conn_fd :: boolean(), proactive_cids :: boolean(), socket_connected :: boolean(), self_migration_pending :: boolean(), metrics_counters :: nquic_metrics:conn_counters() | undefined, spin_enabled :: boolean(), peer_spin :: 0..1, new_token_enabled :: boolean(), new_token_lifetime :: pos_integer(), qlog :: undefined | nquic_qlog:qlog_state(), close_kind :: undefined | local | peer | idle_timeout | protocol_error, crypto :: #conn_crypto{tls_state :: term(), keys :: #{nquic_packet:space() | rtt0 => map()}, app_send_keys :: map() | undefined, app_recv_keys :: map() | undefined, crypto_buffer :: #{nquic_packet:space() => {non_neg_integer(), binary(), list()}}, cipher :: aes_128_gcm | aes_256_gcm | chacha20_poly1305, cipher_suites :: [aes_128_gcm | aes_256_gcm | chacha20_poly1305] | undefined, key_phase :: boolean(), key_update_pending :: boolean(), client_app_secret :: binary() | undefined, server_app_secret :: binary() | undefined, old_read_keys :: #{key := binary(), iv := binary()} | undefined, zero_rtt_accepted :: boolean(), replay_protection :: module() | undefined, session_ticket :: map() | undefined, resumption_secret :: binary() | undefined, session_cache :: atom() | false | {module, module()} | undefined, token_cache :: atom() | false | {module, module()}, alpn :: [binary()] | undefined, hostname :: string() | binary() | undefined, cert :: binary() | undefined, cert_chain :: [binary()], key :: any() | undefined, verify :: verify_none | verify_peer, cacerts :: [binary()], peer_cert :: binary() | undefined, static_key :: binary() | undefined}, streams_state :: #conn_streams{streams :: #{nquic:stream_id() => #stream_state{stream_id :: nquic:stream_id(), type :: bidi | uni, send_state :: ready | send | data_sent | data_recvd | reset_sent | reset_recvd, send_offset :: non_neg_integer(), send_max_data :: non_neg_integer(), last_stream_data_blocked :: non_neg_integer(), pending_send_data :: [binary()], pending_send_size :: non_neg_integer(), pending_send_fin :: boolean(), recv_state :: recv | size_known | data_recvd | reset_recvd | data_read | reset_read, recv_offset :: non_neg_integer(), recv_max_offset :: non_neg_integer(), recv_window :: non_neg_integer(), recv_buffer :: gb_trees:tree(non_neg_integer(), {binary(), boolean()}), app_buffer :: iodata(), app_buffer_size :: non_neg_integer()}}, next_bidi_stream :: nquic:stream_id() | undefined, next_uni_stream :: nquic:stream_id() | undefined, peer_max_streams_bidi :: non_neg_integer(), peer_max_streams_uni :: non_neg_integer(), local_max_streams_bidi :: non_neg_integer(), local_max_streams_uni :: non_neg_integer(), last_sent_max_streams_bidi :: non_neg_integer(), last_sent_max_streams_uni :: non_neg_integer(), max_peer_bidi_stream_id :: non_neg_integer() | undefined, max_peer_uni_stream_id :: non_neg_integer() | undefined, opened_peer_bidi_count :: non_neg_integer(), opened_peer_uni_count :: non_neg_integer(), closed_peer_bidi_wm :: integer(), closed_peer_uni_wm :: integer(), closed_peer_streams :: #{nquic:stream_id() => true}, recv_waiters :: #{nquic:stream_id() => gen_statem:from()}, accept_stream_waiters :: queue:queue(gen_statem:from()), pending_streams :: queue:queue(nquic:stream_id()), blocked_streams :: #{nquic:stream_id() => true}, pending_send_streams :: #{nquic:stream_id() => true}, send_buffer_high_water :: pos_integer(), send_timeout :: timeout(), send_waiters :: queue:queue(nquic_conn_send_waiters:t())}, flow :: #conn_flow{local_max_data :: non_neg_integer(), remote_max_data :: non_neg_integer(), data_sent :: non_neg_integer(), data_received :: non_neg_integer(), last_data_blocked :: non_neg_integer(), pending_initial_frames :: [nquic_frame:t()], pending_handshake_frames :: [nquic_frame:t()], pending_app_frames :: [nquic_frame:t()], pending_app_pre_encoded :: [{non_neg_integer(), iodata(), nquic_frame:t()}], queued_app_send_bytes :: non_neg_integer()}, path :: #conn_path_mgmt{path_state :: nquic_path:state() | undefined, peer_cids :: #{non_neg_integer() => #{cid := nquic:connection_id(), token := binary()}}, local_cids :: #{non_neg_integer() => nquic:connection_id()}, local_cid_seq :: non_neg_integer(), peer_retire_prior_to :: non_neg_integer(), anti_amp_bytes_received :: non_neg_integer(), anti_amp_bytes_sent :: non_neg_integer(), address_validated :: boolean()}}) -> binary().
Pick the DCID used as the info-table key for this connection. Prefers the original DCID (set by the listener when the conn was created) and falls back to the local SCID for client-side conns.