Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
kcenon::network::protocols::quic::connection Class Reference

QUIC connection state machine (RFC 9000 Section 5) More...

#include <connection.h>

Collaboration diagram for kcenon::network::protocols::quic::connection:
Collaboration graph

Public Member Functions

 connection (bool is_server, const connection_id &initial_dcid)
 Construct a connection.
 
 ~connection ()
 
 connection (const connection &)=delete
 
auto operator= (const connection &) -> connection &=delete
 
 connection (connection &&)=delete
 
auto operator= (connection &&) -> connection &=delete
 
auto state () const noexcept -> connection_state
 Get current connection state.
 
auto handshake_state () const noexcept -> enum handshake_state
 Get current handshake state.
 
auto is_established () const noexcept -> bool
 Check if connection is established (handshake complete)
 
auto is_draining () const noexcept -> bool
 Check if connection is draining or closing.
 
auto is_closed () const noexcept -> bool
 Check if connection is closed.
 
auto is_server () const noexcept -> bool
 Check if this is a server-side connection.
 
auto local_cid () const -> const connection_id &
 Get local Connection ID.
 
auto remote_cid () const -> const connection_id &
 Get remote Connection ID.
 
auto initial_dcid () const -> const connection_id &
 Get initial Destination Connection ID (for key derivation)
 
auto add_local_cid (const connection_id &cid, uint64_t sequence) -> VoidResult
 Add a new local Connection ID.
 
auto retire_cid (uint64_t sequence) -> VoidResult
 Retire a Connection ID.
 
auto peer_cid_manager () -> connection_id_manager &
 Get the peer connection ID manager.
 
auto peer_cid_manager () const -> const connection_id_manager &
 Get the peer connection ID manager (const)
 
auto active_peer_cid () const -> const connection_id &
 Get the currently active peer connection ID.
 
auto rotate_peer_cid () -> VoidResult
 Rotate to a new peer connection ID.
 
void set_local_params (const transport_parameters &params)
 Set local transport parameters.
 
void set_remote_params (const transport_parameters &params)
 Set remote transport parameters.
 
auto local_params () const -> const transport_parameters &
 Get local transport parameters.
 
auto remote_params () const -> const transport_parameters &
 Get remote transport parameters.
 
auto start_handshake (const std::string &server_name) -> Result< std::vector< uint8_t > >
 Start the handshake (client only)
 
auto init_server_handshake (const std::string &cert_file, const std::string &key_file) -> VoidResult
 Initialize server handshake.
 
auto receive_packet (std::span< const uint8_t > data) -> VoidResult
 Receive and process a packet.
 
auto generate_packets () -> std::vector< std::vector< uint8_t > >
 Generate packets to send.
 
auto has_pending_data () const -> bool
 Check if there are packets to send.
 
auto streams () -> stream_manager &
 Get the stream manager.
 
auto streams () const -> const stream_manager &
 Get the stream manager (const)
 
auto flow_control () -> flow_controller &
 Get the connection-level flow controller.
 
auto flow_control () const -> const flow_controller &
 Get the connection-level flow controller (const)
 
auto close (uint64_t error_code, const std::string &reason="") -> VoidResult
 Close the connection.
 
auto close_application (uint64_t error_code, const std::string &reason="") -> VoidResult
 Close connection due to application error.
 
auto close_error_code () const -> std::optional< uint64_t >
 Get the close error code (if connection was closed)
 
auto close_reason () const -> const std::string &
 Get the close reason (if connection was closed)
 
auto next_timeout () const -> std::optional< std::chrono::steady_clock::time_point >
 Get the next timeout deadline.
 
void on_timeout ()
 Handle timeout event.
 
auto idle_deadline () const -> std::chrono::steady_clock::time_point
 Get idle timeout deadline.
 
auto crypto () -> quic_crypto &
 Get crypto handler.
 
auto crypto () const -> const quic_crypto &
 Get crypto handler (const)
 
auto path_mtu () const noexcept -> size_t
 Get current path MTU.
 
void enable_pmtud ()
 Enable Path MTU Discovery.
 
void disable_pmtud ()
 Disable Path MTU Discovery.
 
auto pmtud_enabled () const noexcept -> bool
 Check if PMTUD is enabled.
 
auto pmtud () -> pmtud_controller &
 Get the PMTUD controller.
 
auto pmtud () const -> const pmtud_controller &
 Get the PMTUD controller (const)
 
auto bytes_sent () const noexcept -> uint64_t
 Get total bytes sent.
 
auto bytes_received () const noexcept -> uint64_t
 Get total bytes received.
 
auto packets_sent () const noexcept -> uint64_t
 Get packets sent count.
 
auto packets_received () const noexcept -> uint64_t
 Get packets received count.
 

Private Member Functions

auto process_long_header_packet (const long_header &hdr, std::span< const uint8_t > payload) -> VoidResult
 Process a long header packet.
 
auto process_short_header_packet (const short_header &hdr, std::span< const uint8_t > payload) -> VoidResult
 Process a short header packet.
 
auto process_frames (std::span< const uint8_t > payload, encryption_level level) -> VoidResult
 Process frames from a decrypted packet.
 
auto handle_frame (const frame &frame, encryption_level level) -> VoidResult
 Handle a specific frame.
 
auto build_packet (encryption_level level) -> std::vector< uint8_t >
 Build a packet at the given encryption level.
 
auto get_pn_space (encryption_level level) -> packet_number_space &
 Get packet number space for an encryption level.
 
auto get_pn_space (encryption_level level) const -> const packet_number_space &
 
void update_state ()
 Update connection state based on handshake progress.
 
void reset_idle_timer ()
 Reset idle timer.
 
void enter_draining ()
 Transition to draining state.
 
void enter_closing ()
 Transition to closing state.
 
void apply_remote_params ()
 Apply remote transport parameters.
 
auto generate_ack_frame (const packet_number_space &space) -> std::optional< ack_frame >
 Generate ACK frame for a packet number space.
 
void handle_loss_detection_result (const loss_detection_result &result)
 Handle loss detection result (RFC 9002)
 
void generate_probe_packets ()
 Generate probe packets for PTO (RFC 9002 Section 6.2.4) Sends one or two ack-eliciting packets to probe for acknowledgment.
 
void queue_frames_for_retransmission (const sent_packet &lost_packet)
 Queue frames from lost packet for retransmission.
 
auto to_sent_packet (const sent_packet_info &info) const -> sent_packet
 Convert sent_packet_info to sent_packet for loss detector.
 

Private Attributes

bool is_server_
 
connection_state state_ {connection_state::idle}
 
connection_id local_cid_
 
connection_id remote_cid_
 
connection_id initial_dcid_
 
std::vector< std::pair< uint64_t, connection_id > > local_cids_
 
uint64_t next_cid_sequence_ {1}
 
connection_id_manager peer_cid_manager_
 
transport_parameters local_params_
 
transport_parameters remote_params_
 
quic_crypto crypto_
 
stream_manager stream_mgr_
 
flow_controller flow_ctrl_
 
rtt_estimator rtt_estimator_
 
loss_detector loss_detector_
 
congestion_controller congestion_controller_
 
pmtud_controller pmtud_controller_
 
packet_number_space initial_space_
 
packet_number_space handshake_space_
 
packet_number_space app_space_
 
std::deque< std::vector< uint8_t > > pending_crypto_initial_
 
std::deque< std::vector< uint8_t > > pending_crypto_handshake_
 
std::deque< std::vector< uint8_t > > pending_crypto_app_
 
bool pending_ack_initial_ {false}
 
bool pending_ack_handshake_ {false}
 
bool pending_ack_app_ {false}
 
std::deque< framepending_frames_
 
bool close_sent_ {false}
 
bool close_received_ {false}
 
std::optional< uint64_t > close_error_code_
 
std::string close_reason_
 
bool application_close_ {false}
 
std::chrono::steady_clock::time_point idle_deadline_
 
std::chrono::steady_clock::time_point pto_deadline_
 
std::chrono::steady_clock::time_point drain_deadline_
 
uint64_t bytes_sent_ {0}
 
uint64_t bytes_received_ {0}
 
uint64_t packets_sent_ {0}
 
uint64_t packets_received_ {0}
 

Detailed Description

QUIC connection state machine (RFC 9000 Section 5)

Manages the complete lifecycle of a QUIC connection including:

  • TLS handshake via QUIC-TLS integration
  • Packet number spaces (Initial, Handshake, Application)
  • Transport parameters negotiation
  • Stream management
  • Flow control
  • Connection termination

Definition at line 157 of file connection.h.

Constructor & Destructor Documentation

◆ connection() [1/3]

kcenon::network::protocols::quic::connection::connection ( bool is_server,
const connection_id & initial_dcid )

Construct a connection.

Parameters
is_serverTrue for server-side, false for client-side
initial_dcidInitial Destination Connection ID

Definition at line 63 of file connection.cpp.

66 , peer_cid_manager_(8) // Default active_connection_id_limit
68 , flow_ctrl_(1048576) // 1MB default
70{
71 // Generate local connection ID
73 local_cids_.emplace_back(0, local_cid_);
74
75 // For client: remote CID is the initial DCID
76 // For server: remote CID will be set when we receive client's SCID
77 if (!is_server)
78 {
81 }
82
83 // Initialize default transport parameters
84 if (is_server)
85 {
87 }
88 else
89 {
91 }
92
93 // Set initial source connection ID
95
96 // Initialize idle timer
98}
void set_initial_peer_cid(const connection_id &cid)
Set the initial peer connection ID (from Initial packet)
static auto generate(size_t length=8) -> connection_id
Generate a random connection ID.
auto initial_dcid() const -> const connection_id &
Get initial Destination Connection ID (for key derivation)
Definition connection.h:239
auto is_server() const noexcept -> bool
Check if this is a server-side connection.
Definition connection.h:220
std::vector< std::pair< uint64_t, connection_id > > local_cids_
Definition connection.h:546
auto make_default_client_params() -> transport_parameters
Create default client transport parameters.
auto make_default_server_params() -> transport_parameters
Create default server transport parameters.
std::optional< connection_id > initial_source_connection_id
Initial Source Connection ID.

References kcenon::network::protocols::quic::connection_id::generate(), initial_dcid(), kcenon::network::protocols::quic::transport_parameters::initial_source_connection_id, is_server(), local_cid_, local_cids_, local_params_, kcenon::network::protocols::quic::make_default_client_params(), kcenon::network::protocols::quic::make_default_server_params(), peer_cid_manager_, remote_cid_, reset_idle_timer(), and kcenon::network::protocols::quic::connection_id_manager::set_initial_peer_cid().

Here is the call graph for this function:

◆ ~connection()

kcenon::network::protocols::quic::connection::~connection ( )
default

◆ connection() [2/3]

kcenon::network::protocols::quic::connection::connection ( const connection & )
delete

◆ connection() [3/3]

kcenon::network::protocols::quic::connection::connection ( connection && )
delete

Member Function Documentation

◆ active_peer_cid()

auto kcenon::network::protocols::quic::connection::active_peer_cid ( ) const -> const connection_id&
nodiscard

Get the currently active peer connection ID.

This returns the peer CID that should be used in outgoing packets. It may differ from remote_cid() if CID rotation has occurred.

Definition at line 1540 of file connection.cpp.

1541{
1542 // If peer CID manager has CIDs, use the active one
1544 {
1546 }
1547 // Fall back to remote_cid_ for backward compatibility
1548 return remote_cid_;
1549}
auto peer_cid_count() const -> size_t
Get the current number of peer CIDs (including retired)
auto get_active_peer_cid() const -> const connection_id &
Get the currently active peer connection ID.

References kcenon::network::protocols::quic::connection_id_manager::get_active_peer_cid(), kcenon::network::protocols::quic::connection_id_manager::peer_cid_count(), peer_cid_manager_, and remote_cid_.

Here is the call graph for this function:

◆ add_local_cid()

auto kcenon::network::protocols::quic::connection::add_local_cid ( const connection_id & cid,
uint64_t sequence ) -> VoidResult
nodiscard

Add a new local Connection ID.

Parameters
cidConnection ID to add
sequenceSequence number for this CID
Returns
Success or error

Definition at line 108 of file connection.cpp.

110{
111 // Check for duplicates
112 for (const auto& [seq, existing_cid] : local_cids_)
113 {
114 if (seq == sequence)
115 {
117 "Duplicate connection ID sequence",
118 "connection");
119 }
120 }
121
122 local_cids_.emplace_back(sequence, cid);
123 return ok();
124}
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
VoidResult ok()

References kcenon::network::error_void(), kcenon::network::ok(), and kcenon::network::protocols::quic::connection_error::protocol_violation.

Here is the call graph for this function:

◆ apply_remote_params()

void kcenon::network::protocols::quic::connection::apply_remote_params ( )
private

Apply remote transport parameters.

Definition at line 170 of file connection.cpp.

171{
172 // Apply to flow control
174
175 // Apply to stream manager
178
179 // Apply to peer CID manager
181
182 // Update idle timeout
184 {
185 auto timeout = std::min(local_params_.max_idle_timeout,
187 if (timeout > 0)
188 {
189 idle_deadline_ = std::chrono::steady_clock::now() +
190 std::chrono::milliseconds(timeout);
191 }
192 }
193}
void set_active_cid_limit(uint64_t limit)
Set the active connection ID limit.
std::chrono::steady_clock::time_point idle_deadline_
Definition connection.h:593
void update_send_limit(uint64_t max_data)
Update the send limit (from peer's MAX_DATA)
void set_peer_max_streams_uni(uint64_t max)
Set maximum unidirectional streams peer can initiate.
void set_peer_max_streams_bidi(uint64_t max)
Set maximum bidirectional streams peer can initiate.
uint64_t max_idle_timeout
Maximum idle timeout in milliseconds (0 = disabled)
uint64_t initial_max_data
Initial maximum data for connection (default: 0)
uint64_t initial_max_streams_uni
Initial maximum unidirectional streams.
uint64_t initial_max_streams_bidi
Initial maximum bidirectional streams.
uint64_t active_connection_id_limit
Maximum number of connection IDs from the peer.

References kcenon::network::protocols::quic::transport_parameters::active_connection_id_limit, flow_ctrl_, idle_deadline_, kcenon::network::protocols::quic::transport_parameters::initial_max_data, kcenon::network::protocols::quic::transport_parameters::initial_max_streams_bidi, kcenon::network::protocols::quic::transport_parameters::initial_max_streams_uni, local_params_, kcenon::network::protocols::quic::transport_parameters::max_idle_timeout, peer_cid_manager_, remote_params_, kcenon::network::protocols::quic::connection_id_manager::set_active_cid_limit(), kcenon::network::protocols::quic::stream_manager::set_peer_max_streams_bidi(), kcenon::network::protocols::quic::stream_manager::set_peer_max_streams_uni(), stream_mgr_, and kcenon::network::protocols::quic::flow_controller::update_send_limit().

Referenced by set_remote_params().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_packet()

auto kcenon::network::protocols::quic::connection::build_packet ( encryption_level level) -> std::vector<uint8_t>
nodiscardprivate

Build a packet at the given encryption level.

Definition at line 846 of file connection.cpp.

847{
848 std::vector<uint8_t> packet;
849
850 // Get keys for this level
851 auto keys_result = crypto_.get_write_keys(level);
852 if (keys_result.is_err())
853 {
854 return packet;
855 }
856
857 auto& space = get_pn_space(level);
858 uint64_t pn = space.next_pn++;
859
860 // Build header
861 std::vector<uint8_t> header;
862 switch (level)
863 {
866 remote_cid_, local_cid_, {}, pn);
867 break;
871 break;
875 break;
876 default:
877 return packet;
878 }
879
880 // Build payload with frames
881 std::vector<uint8_t> payload;
882
883 // Add ACK frame if needed
884 if (space.ack_needed)
885 {
886 auto ack = generate_ack_frame(space);
887 if (ack)
888 {
889 auto encoded = frame_builder::build_ack(*ack);
890 payload.insert(payload.end(), encoded.begin(), encoded.end());
891 space.ack_needed = false;
892 }
893 }
894
895 // Add CRYPTO frames
896 std::deque<std::vector<uint8_t>>* crypto_queue = nullptr;
897 switch (level)
898 {
900 crypto_queue = &pending_crypto_initial_;
901 break;
903 crypto_queue = &pending_crypto_handshake_;
904 break;
905 default:
906 crypto_queue = &pending_crypto_app_;
907 break;
908 }
909
910 uint64_t crypto_offset = 0;
911 while (!crypto_queue->empty())
912 {
913 auto& data = crypto_queue->front();
914 crypto_frame cf;
915 cf.offset = crypto_offset;
916 cf.data = std::move(data);
917 crypto_offset += cf.data.size();
918
919 auto encoded = frame_builder::build_crypto(cf);
920 payload.insert(payload.end(), encoded.begin(), encoded.end());
921 crypto_queue->pop_front();
922 }
923
924 // Add HANDSHAKE_DONE for server
927 {
928 handshake_done_frame hd;
929 auto encoded = frame_builder::build(hd);
930 payload.insert(payload.end(), encoded.begin(), encoded.end());
931 }
932
933 // Add CONNECTION_CLOSE if closing
934 if (close_sent_)
935 {
936 connection_close_frame ccf;
937 ccf.error_code = close_error_code_.value_or(0);
938 ccf.reason_phrase = close_reason_;
939 ccf.is_application_error = application_close_;
940 auto encoded = frame_builder::build(ccf);
941 payload.insert(payload.end(), encoded.begin(), encoded.end());
942 }
943
944 // Add RETIRE_CONNECTION_ID frames for application level
946 {
947 auto retire_frames = peer_cid_manager_.get_pending_retire_frames();
948 for (const auto& rf : retire_frames)
949 {
950 auto encoded = frame_builder::build(rf);
951 payload.insert(payload.end(), encoded.begin(), encoded.end());
952 }
953 if (!retire_frames.empty())
954 {
956 }
957 }
958
959 // Add pending frames (e.g., PING from PTO probing)
960 if (!close_sent_)
961 {
962 while (!pending_frames_.empty())
963 {
964 const auto& f = pending_frames_.front();
965 auto encoded = frame_builder::build(f);
966 payload.insert(payload.end(), encoded.begin(), encoded.end());
967 pending_frames_.pop_front();
968 }
969 }
970
971 // Add stream data frames for application level
973 {
975 for (auto* s : streams)
976 {
977 if (auto sf = s->next_stream_frame(1200))
978 {
979 auto encoded = frame_builder::build_stream(*sf);
980 payload.insert(payload.end(), encoded.begin(), encoded.end());
981 }
982 }
983 }
984
985 if (payload.empty())
986 {
987 return packet;
988 }
989
990 // Add padding for Initial packets to meet minimum size
991 if (level == encryption_level::initial)
992 {
993 size_t min_size = 1200;
994 size_t current_size = header.size() + payload.size() + 16; // +16 for AEAD tag
995 if (current_size < min_size)
996 {
997 auto encoded = frame_builder::build_padding(min_size - current_size);
998 payload.insert(payload.end(), encoded.begin(), encoded.end());
999 }
1000 }
1001
1002 // Encrypt and protect the packet
1003 auto protect_result = packet_protection::protect(
1004 keys_result.value(),
1005 std::span<const uint8_t>(header.data(), header.size()),
1006 std::span<const uint8_t>(payload.data(), payload.size()),
1007 pn);
1008
1009 if (protect_result.is_err())
1010 {
1011 return {};
1012 }
1013
1014 packet = std::move(protect_result.value());
1015
1016 // Track sent packet for local state
1017 sent_packet_info info;
1018 info.packet_number = pn;
1019 info.sent_time = std::chrono::steady_clock::now();
1020 info.sent_bytes = packet.size();
1021 info.ack_eliciting = !payload.empty();
1022 info.in_flight = true;
1023 info.level = level;
1024 // Note: frames are not stored here as the current implementation
1025 // doesn't track individual frames in build_packet.
1026 // For full retransmission support, frames would need to be collected
1027 // during packet building and stored here.
1028
1029 // Notify loss detector about sent packet (RFC 9002)
1030 sent_packet sent_pkt;
1031 sent_pkt.packet_number = info.packet_number;
1032 sent_pkt.sent_time = info.sent_time;
1033 sent_pkt.sent_bytes = info.sent_bytes;
1034 sent_pkt.ack_eliciting = info.ack_eliciting;
1035 sent_pkt.in_flight = info.in_flight;
1036 sent_pkt.level = info.level;
1038
1039 // Notify congestion controller about sent packet
1040 if (info.in_flight)
1041 {
1043 }
1044
1045 space.sent_packets[pn] = std::move(info);
1046
1047 bytes_sent_ += packet.size();
1048 packets_sent_++;
1049
1050 return packet;
1051}
auto on_packet_sent(size_t bytes) -> void
Record bytes sent.
auto get_pending_retire_frames() -> std::vector< retire_connection_id_frame >
Get pending RETIRE_CONNECTION_ID frames to send.
void clear_pending_retire_frames()
Clear the pending retire frames queue.
std::deque< std::vector< uint8_t > > pending_crypto_app_
Definition connection.h:575
std::deque< std::vector< uint8_t > > pending_crypto_initial_
Definition connection.h:573
auto get_pn_space(encryption_level level) -> packet_number_space &
Get packet number space for an encryption level.
auto generate_ack_frame(const packet_number_space &space) -> std::optional< ack_frame >
Generate ACK frame for a packet number space.
std::optional< uint64_t > close_error_code_
Definition connection.h:588
std::deque< std::vector< uint8_t > > pending_crypto_handshake_
Definition connection.h:574
auto streams() -> stream_manager &
Get the stream manager.
Definition connection.h:371
static auto build_stream(const stream_frame &f, bool include_length=true) -> std::vector< uint8_t >
Build STREAM frame.
Definition frame.cpp:1035
static auto build_ack(const ack_frame &f) -> std::vector< uint8_t >
Build ACK frame.
Definition frame.cpp:950
static auto build_padding(size_t count=1) -> std::vector< uint8_t >
Build PADDING frame.
Definition frame.cpp:940
static auto build_crypto(const crypto_frame &f) -> std::vector< uint8_t >
Build CRYPTO frame.
Definition frame.cpp:1015
static auto build(const frame &f) -> std::vector< uint8_t >
Build any frame from variant.
Definition frame.cpp:891
auto on_packet_sent(const sent_packet &packet) -> void
Record a sent packet.
static auto build_handshake(const connection_id &dest_cid, const connection_id &src_cid, uint64_t packet_number, uint32_t version=quic_version::version_1) -> std::vector< uint8_t >
Build a Handshake packet header.
Definition packet.cpp:467
static auto build_short(const connection_id &dest_cid, uint64_t packet_number, bool key_phase=false, bool spin_bit=false) -> std::vector< uint8_t >
Build a Short Header (1-RTT) packet.
Definition packet.cpp:578
static auto build_initial(const connection_id &dest_cid, const connection_id &src_cid, const std::vector< uint8_t > &token, uint64_t packet_number, uint32_t version=quic_version::version_1) -> std::vector< uint8_t >
Build an Initial packet header.
Definition packet.cpp:423
static auto protect(const quic_keys &keys, std::span< const uint8_t > header, std::span< const uint8_t > payload, uint64_t packet_number) -> Result< std::vector< uint8_t > >
Protect (encrypt) a QUIC packet.
Definition crypto.cpp:425
auto get_write_keys(encryption_level level) const -> Result< quic_keys >
Get write keys for an encryption level.
Definition crypto.cpp:1013
auto key_phase() const noexcept -> uint8_t
Get current key phase (for key updates)
Definition crypto.cpp:1137
auto streams_with_pending_data() -> std::vector< stream * >
Get streams with pending data to send.
@ connected
Handshake complete, can send/receive data.
@ application
1-RTT application data encryption
@ initial
Initial encryption (derived from DCID)

References kcenon::network::protocols::quic::ack, kcenon::network::protocols::quic::sent_packet::ack_eliciting, kcenon::network::protocols::quic::application, kcenon::network::protocols::quic::frame_builder::build(), kcenon::network::protocols::quic::frame_builder::build_ack(), kcenon::network::protocols::quic::frame_builder::build_crypto(), kcenon::network::protocols::quic::packet_builder::build_handshake(), kcenon::network::protocols::quic::packet_builder::build_initial(), kcenon::network::protocols::quic::frame_builder::build_padding(), kcenon::network::protocols::quic::packet_builder::build_short(), kcenon::network::protocols::quic::frame_builder::build_stream(), kcenon::network::protocols::quic::complete, kcenon::network::protocols::quic::connected, kcenon::network::protocols::quic::crypto_frame::data, kcenon::network::protocols::quic::connection_close_frame::error_code, kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::sent_packet::in_flight, kcenon::network::protocols::quic::initial, kcenon::network::protocols::quic::connection_close_frame::is_application_error, kcenon::network::protocols::quic::sent_packet::level, kcenon::network::protocols::quic::crypto_frame::offset, kcenon::network::protocols::quic::sent_packet::packet_number, kcenon::network::protocols::quic::packet_protection::protect(), kcenon::network::protocols::quic::connection_close_frame::reason_phrase, kcenon::network::protocols::quic::sent_packet::sent_bytes, and kcenon::network::protocols::quic::sent_packet::sent_time.

Here is the call graph for this function:

◆ bytes_received()

auto kcenon::network::protocols::quic::connection::bytes_received ( ) const -> uint64_t
inlinenodiscardnoexcept

Get total bytes received.

Definition at line 518 of file connection.h.

References bytes_received_.

◆ bytes_sent()

auto kcenon::network::protocols::quic::connection::bytes_sent ( ) const -> uint64_t
inlinenodiscardnoexcept

Get total bytes sent.

Definition at line 513 of file connection.h.

513{ return bytes_sent_; }

References bytes_sent_.

◆ close()

auto kcenon::network::protocols::quic::connection::close ( uint64_t error_code,
const std::string & reason = "" ) -> VoidResult
nodiscard

Close the connection.

Parameters
error_codeError code (0 for normal close)
reasonOptional reason phrase
Returns
Success or error

Definition at line 1137 of file connection.cpp.

1138{
1139 auto span = tracing::is_tracing_enabled()
1140 ? std::make_optional(tracing::trace_context::create_span("quic.connection.close"))
1141 : std::nullopt;
1142 if (span)
1143 {
1144 span->set_attribute("quic.close.error_code", static_cast<int64_t>(error_code))
1145 .set_attribute("quic.close.reason", reason)
1146 .set_attribute("quic.close.type", "transport")
1147 .set_attribute("quic.role", is_server_ ? "server" : "client");
1148 }
1149
1150 // Already closing or closed - don't update error state
1151 if (is_closed() || is_draining())
1152 {
1153 if (span)
1154 {
1155 span->set_attribute("quic.close.already_closing", true);
1156 }
1157 return ok();
1158 }
1159
1161 close_reason_ = reason;
1162 close_sent_ = true;
1163 application_close_ = false;
1164 enter_closing();
1165
1166 if (span)
1167 {
1168 span->set_attribute("quic.state", "closing");
1169 }
1170
1171 return ok();
1172}
auto is_draining() const noexcept -> bool
Check if connection is draining or closing.
Definition connection.h:203
void enter_closing()
Transition to closing state.
auto is_closed() const noexcept -> bool
Check if connection is closed.
Definition connection.h:212
static auto create_span(std::string_view name) -> span
Create a new root span with a new trace context.
error_code
HTTP/2 error codes (RFC 7540 Section 7)
Definition frame.h:471
auto is_tracing_enabled() -> bool
Check if tracing is enabled.

References kcenon::network::tracing::trace_context::create_span(), kcenon::network::tracing::is_tracing_enabled(), and kcenon::network::ok().

Here is the call graph for this function:

◆ close_application()

auto kcenon::network::protocols::quic::connection::close_application ( uint64_t error_code,
const std::string & reason = "" ) -> VoidResult
nodiscard

Close connection due to application error.

Parameters
error_codeApplication-level error code
reasonOptional reason phrase
Returns
Success or error

Definition at line 1174 of file connection.cpp.

1176{
1177 auto span = tracing::is_tracing_enabled()
1178 ? std::make_optional(tracing::trace_context::create_span("quic.connection.close_application"))
1179 : std::nullopt;
1180 if (span)
1181 {
1182 span->set_attribute("quic.close.error_code", static_cast<int64_t>(error_code))
1183 .set_attribute("quic.close.reason", reason)
1184 .set_attribute("quic.close.type", "application")
1185 .set_attribute("quic.role", is_server_ ? "server" : "client");
1186 }
1187
1188 // Already closing or closed - don't update error state
1189 if (is_closed() || is_draining())
1190 {
1191 if (span)
1192 {
1193 span->set_attribute("quic.close.already_closing", true);
1194 }
1195 return ok();
1196 }
1197
1199 close_reason_ = reason;
1200 close_sent_ = true;
1201 application_close_ = true;
1202 enter_closing();
1203
1204 if (span)
1205 {
1206 span->set_attribute("quic.state", "closing");
1207 }
1208
1209 return ok();
1210}

References kcenon::network::tracing::trace_context::create_span(), kcenon::network::tracing::is_tracing_enabled(), and kcenon::network::ok().

Here is the call graph for this function:

◆ close_error_code()

auto kcenon::network::protocols::quic::connection::close_error_code ( ) const -> std::optional<uint64_t>
inlinenodiscard

Get the close error code (if connection was closed)

Definition at line 417 of file connection.h.

418 {
419 return close_error_code_;
420 }

References close_error_code_.

◆ close_reason()

auto kcenon::network::protocols::quic::connection::close_reason ( ) const -> const std::string&
inlinenodiscard

Get the close reason (if connection was closed)

Definition at line 425 of file connection.h.

425{ return close_reason_; }

References close_reason_.

◆ crypto() [1/2]

auto kcenon::network::protocols::quic::connection::crypto ( ) -> quic_crypto&
inlinenodiscard

Get crypto handler.

Definition at line 458 of file connection.h.

458{ return crypto_; }

References crypto_.

◆ crypto() [2/2]

auto kcenon::network::protocols::quic::connection::crypto ( ) const -> const quic_crypto&
inlinenodiscard

Get crypto handler (const)

Definition at line 463 of file connection.h.

463{ return crypto_; }

References crypto_.

◆ disable_pmtud()

void kcenon::network::protocols::quic::connection::disable_pmtud ( )

Disable Path MTU Discovery.

Stops PMTUD probing and reverts to minimum MTU (1200 bytes).

Definition at line 1572 of file connection.cpp.

1573{
1575 // Reset congestion controller to minimum MTU
1577}
auto set_max_datagram_size(size_t size) -> void
Set max datagram size.
auto min_mtu() const noexcept -> size_t
Get minimum MTU.

References congestion_controller_, kcenon::network::protocols::quic::pmtud_controller::disable(), kcenon::network::protocols::quic::pmtud_controller::min_mtu(), pmtud_controller_, and kcenon::network::protocols::quic::congestion_controller::set_max_datagram_size().

Here is the call graph for this function:

◆ enable_pmtud()

void kcenon::network::protocols::quic::connection::enable_pmtud ( )

Enable Path MTU Discovery.

Starts PMTUD probing to discover the maximum MTU on the path. Uses DPLPMTUD algorithm as specified in RFC 8899.

Definition at line 1565 of file connection.cpp.

1566{
1568 // Update congestion controller with current MTU
1570}
void enable()
Enable PMTUD and start probing.
auto current_mtu() const noexcept -> size_t
Get current validated MTU.

References congestion_controller_, kcenon::network::protocols::quic::pmtud_controller::current_mtu(), kcenon::network::protocols::quic::pmtud_controller::enable(), pmtud_controller_, and kcenon::network::protocols::quic::congestion_controller::set_max_datagram_size().

Here is the call graph for this function:

◆ enter_closing()

void kcenon::network::protocols::quic::connection::enter_closing ( )
private

Transition to closing state.

Definition at line 1212 of file connection.cpp.

1213{
1215 {
1216 return;
1217 }
1218
1220
1221 // Set drain timer (3 * PTO)
1222 auto pto = std::chrono::milliseconds(100); // Simplified PTO
1223 drain_deadline_ = std::chrono::steady_clock::now() + 3 * pto;
1224}
std::chrono::steady_clock::time_point drain_deadline_
Definition connection.h:595
@ closing
CONNECTION_CLOSE sent, waiting for timeout.
@ draining
CONNECTION_CLOSE received, draining period.

References kcenon::network::protocols::quic::closing, drain_deadline_, kcenon::network::protocols::quic::draining, and state_.

◆ enter_draining()

void kcenon::network::protocols::quic::connection::enter_draining ( )
private

Transition to draining state.

Definition at line 1226 of file connection.cpp.

1227{
1229 {
1230 return;
1231 }
1232
1234
1235 // Set drain timer (3 * PTO)
1236 auto pto = std::chrono::milliseconds(100);
1237 drain_deadline_ = std::chrono::steady_clock::now() + 3 * pto;
1238}

References kcenon::network::protocols::quic::closed, drain_deadline_, kcenon::network::protocols::quic::draining, and state_.

◆ flow_control() [1/2]

auto kcenon::network::protocols::quic::connection::flow_control ( ) -> flow_controller&
inlinenodiscard

Get the connection-level flow controller.

Definition at line 385 of file connection.h.

385{ return flow_ctrl_; }

References flow_ctrl_.

◆ flow_control() [2/2]

auto kcenon::network::protocols::quic::connection::flow_control ( ) const -> const flow_controller&
inlinenodiscard

Get the connection-level flow controller (const)

Definition at line 390 of file connection.h.

390{ return flow_ctrl_; }

References flow_ctrl_.

◆ generate_ack_frame()

auto kcenon::network::protocols::quic::connection::generate_ack_frame ( const packet_number_space & space) -> std::optional<ack_frame>
nodiscardprivate

Generate ACK frame for a packet number space.

Definition at line 1315 of file connection.cpp.

1317{
1318 if (space.largest_received == 0 && !space.ack_needed)
1319 {
1320 return std::nullopt;
1321 }
1322
1323 ack_frame ack;
1324 ack.largest_acknowledged = space.largest_received;
1325 ack.ack_delay = std::chrono::duration_cast<std::chrono::microseconds>(
1326 std::chrono::steady_clock::now() - space.largest_received_time)
1327 .count();
1328 // Simplified: ACK all packets from 0 to largest_received
1329 // The first ACK range is implicit (largest_acknowledged to largest_acknowledged - first_ack_range_length)
1330 // For simplicity, we don't add any additional ranges
1331
1332 return ack;
1333}

References kcenon::network::protocols::quic::ack, and kcenon::network::protocols::quic::ack_frame::largest_acknowledged.

◆ generate_packets()

auto kcenon::network::protocols::quic::connection::generate_packets ( ) -> std::vector<std::vector<uint8_t>>
nodiscard

Generate packets to send.

Returns
Vector of packets (may be coalesced for handshake)

Definition at line 780 of file connection.cpp.

781{
782 std::vector<std::vector<uint8_t>> packets;
783
784 if (is_closed())
785 {
786 return packets;
787 }
788
789 // Generate close packet if closing
791 {
793 if (!pkt.empty())
794 {
795 packets.push_back(std::move(pkt));
796 }
797 return packets;
798 }
799
800 // Generate Initial packets if needed
802 {
804 if (!pkt.empty())
805 {
806 packets.push_back(std::move(pkt));
807 pending_ack_initial_ = false;
808 }
809 }
810
811 // Generate Handshake packets if needed
813 {
815 if (!pkt.empty())
816 {
817 packets.push_back(std::move(pkt));
819 }
820 }
821
822 // Generate 1-RTT packets if connected
824 {
825 // Send HANDSHAKE_DONE (server only, once)
826 if (is_server_ && hs_state_ == handshake_state::complete)
827 {
828 // Will be included in next packet
829 }
830
831 // Generate application data packets
833 {
835 if (!pkt.empty())
836 {
837 packets.push_back(std::move(pkt));
838 pending_ack_app_ = false;
839 }
840 }
841 }
842
843 return packets;
844}
auto has_pending_data() const -> bool
Check if there are packets to send.
auto build_packet(encryption_level level) -> std::vector< uint8_t >
Build a packet at the given encryption level.

References kcenon::network::protocols::quic::application, kcenon::network::protocols::quic::complete, kcenon::network::protocols::quic::connected, kcenon::network::protocols::quic::handshake, and kcenon::network::protocols::quic::initial.

◆ generate_probe_packets()

void kcenon::network::protocols::quic::connection::generate_probe_packets ( )
private

Generate probe packets for PTO (RFC 9002 Section 6.2.4) Sends one or two ack-eliciting packets to probe for acknowledgment.

Definition at line 1384 of file connection.cpp.

1385{
1386 // RFC 9002 Section 6.2.4: When PTO expires, send one or two ack-eliciting packets.
1387 // Probe packets must be ack-eliciting.
1388
1389 // Determine which encryption level to use for probes
1390 // Priority: Application > Handshake > Initial (use the highest available)
1392
1394 {
1395 probe_level = encryption_level::application;
1396 }
1398 {
1399 probe_level = encryption_level::handshake;
1400 }
1401
1402 // Generate a PING frame as an ack-eliciting probe
1403 // PING frames are the simplest ack-eliciting frames
1404 pending_frames_.emplace_back(ping_frame{});
1405
1406 // Mark that we need to send packets
1407 switch (probe_level)
1408 {
1410 // For initial space, we might need to retransmit crypto data
1411 if (!pending_crypto_initial_.empty())
1412 {
1413 // Crypto data will be sent as probe
1414 break;
1415 }
1416 // Queue a PING frame
1417 break;
1418
1420 if (!pending_crypto_handshake_.empty())
1421 {
1422 break;
1423 }
1424 break;
1425
1428 // Application level: PING is sufficient
1429 break;
1430 }
1431}
encryption_level
QUIC encryption levels (RFC 9001 Section 4)
Definition keys.h:54

References kcenon::network::protocols::quic::application, crypto_, kcenon::network::protocols::quic::quic_crypto::get_write_keys(), kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::initial, pending_crypto_handshake_, pending_crypto_initial_, pending_frames_, and kcenon::network::protocols::quic::zero_rtt.

Referenced by handle_loss_detection_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_pn_space() [1/2]

auto kcenon::network::protocols::quic::connection::get_pn_space ( encryption_level level) -> packet_number_space&
nodiscardprivate

Get packet number space for an encryption level.

Definition at line 1087 of file connection.cpp.

1088{
1089 switch (level)
1090 {
1093 return initial_space_;
1095 return handshake_space_;
1096 default:
1097 return app_space_;
1098 }
1099}

References kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::initial, and kcenon::network::protocols::quic::zero_rtt.

◆ get_pn_space() [2/2]

auto kcenon::network::protocols::quic::connection::get_pn_space ( encryption_level level) const -> const packet_number_space&
nodiscardprivate

Definition at line 1101 of file connection.cpp.

1103{
1104 switch (level)
1105 {
1108 return initial_space_;
1110 return handshake_space_;
1111 default:
1112 return app_space_;
1113 }
1114}

References kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::initial, and kcenon::network::protocols::quic::zero_rtt.

◆ handle_frame()

auto kcenon::network::protocols::quic::connection::handle_frame ( const frame & frame,
encryption_level level ) -> VoidResult
nodiscardprivate

Handle a specific frame.

Definition at line 550 of file connection.cpp.

552{
553 return std::visit(
554 [this, level](const auto& f) -> VoidResult
555 {
556 using T = std::decay_t<decltype(f)>;
557
558 if constexpr (std::is_same_v<T, padding_frame>)
559 {
560 // Padding is ignored
561 return ok();
562 }
563 else if constexpr (std::is_same_v<T, ping_frame>)
564 {
565 // Ping just elicits an ACK (already handled)
566 return ok();
567 }
568 else if constexpr (std::is_same_v<T, ack_frame>)
569 {
570 // Process ACK using loss detector (RFC 9002)
571 auto recv_time = std::chrono::steady_clock::now();
572 auto result = loss_detector_.on_ack_received(f, level, recv_time);
573
574 // Handle loss detection result
576
577 // Reset PTO count on receiving acknowledgment
579
580 // Update handshake confirmation for loss detector
582 {
584 }
585
586 // Also update our local packet number space tracking
587 auto& space = get_pn_space(level);
588 if (f.largest_acknowledged > space.largest_acked)
589 {
590 space.largest_acked = f.largest_acknowledged;
591 }
592
593 // Remove acknowledged packets from local tracking
594 for (auto it = space.sent_packets.begin();
595 it != space.sent_packets.end();)
596 {
597 if (it->first <= f.largest_acknowledged)
598 {
599 it = space.sent_packets.erase(it);
600 }
601 else
602 {
603 ++it;
604 }
605 }
606 return ok();
607 }
608 else if constexpr (std::is_same_v<T, crypto_frame>)
609 {
610 // Process CRYPTO frame
611 auto result = crypto_.process_crypto_data(level,
612 std::span<const uint8_t>(f.data.data(), f.data.size()));
613 if (result.is_err())
614 {
616 "Failed to process crypto data",
617 "connection",
618 result.error().message);
619 }
620
621 // Store response crypto data
622 if (!result.value().empty())
623 {
624 switch (level)
625 {
627 pending_crypto_initial_.push_back(std::move(result.value()));
628 break;
630 pending_crypto_handshake_.push_back(std::move(result.value()));
631 break;
632 default:
633 pending_crypto_app_.push_back(std::move(result.value()));
634 break;
635 }
636 }
637
638 return ok();
639 }
640 else if constexpr (std::is_same_v<T, stream_frame>)
641 {
642 // Get or create stream
643 auto stream_result = stream_mgr_.get_or_create_stream(f.stream_id);
644 if (stream_result.is_err())
645 {
647 "Failed to get stream",
648 "connection",
649 stream_result.error().message);
650 }
651
652 // Deliver data
653 auto recv_result = stream_result.value()->receive_data(
654 f.offset,
655 std::span<const uint8_t>(f.data.data(), f.data.size()),
656 f.fin);
657 if (recv_result.is_err())
658 {
659 return recv_result;
660 }
661
662 // Update connection-level flow control
663 auto recv_flow = flow_ctrl_.record_received(f.data.size());
664 if (recv_flow.is_err())
665 {
666 return recv_flow;
667 }
668 return ok();
669 }
670 else if constexpr (std::is_same_v<T, max_data_frame>)
671 {
672 flow_ctrl_.update_send_limit(f.maximum_data);
673 return ok();
674 }
675 else if constexpr (std::is_same_v<T, max_stream_data_frame>)
676 {
677 auto* s = stream_mgr_.get_stream(f.stream_id);
678 if (s)
679 {
680 s->set_max_send_data(f.maximum_stream_data);
681 }
682 return ok();
683 }
684 else if constexpr (std::is_same_v<T, max_streams_frame>)
685 {
686 if (f.bidirectional)
687 {
688 stream_mgr_.set_peer_max_streams_bidi(f.maximum_streams);
689 }
690 else
691 {
692 stream_mgr_.set_peer_max_streams_uni(f.maximum_streams);
693 }
694 return ok();
695 }
696 else if constexpr (std::is_same_v<T, connection_close_frame>)
697 {
698 close_error_code_ = f.error_code;
699 close_reason_ = f.reason_phrase;
700 close_received_ = true;
701 application_close_ = f.is_application_error;
703 return ok();
704 }
705 else if constexpr (std::is_same_v<T, handshake_done_frame>)
706 {
707 if (!is_server_)
708 {
709 hs_state_ = handshake_state::complete;
711 }
712 return ok();
713 }
714 else if constexpr (std::is_same_v<T, reset_stream_frame>)
715 {
716 auto* s = stream_mgr_.get_stream(f.stream_id);
717 if (s)
718 {
719 return s->receive_reset(f.application_error_code, f.final_size);
720 }
721 return ok();
722 }
723 else if constexpr (std::is_same_v<T, stop_sending_frame>)
724 {
725 auto* s = stream_mgr_.get_stream(f.stream_id);
726 if (s)
727 {
728 return s->receive_stop_sending(f.application_error_code);
729 }
730 return ok();
731 }
732 else if constexpr (std::is_same_v<T, new_connection_id_frame>)
733 {
734 // RFC 9000 Section 19.15: Process NEW_CONNECTION_ID frame
735 // Store the new peer connection ID with its metadata
736 connection_id cid(std::span<const uint8_t>(
737 f.connection_id.data(), f.connection_id.size()));
738
739 auto result = peer_cid_manager_.add_peer_cid(
740 cid,
741 f.sequence_number,
742 f.retire_prior_to,
743 f.stateless_reset_token);
744
745 if (result.is_err())
746 {
748 "Failed to process NEW_CONNECTION_ID",
749 "connection",
750 result.error().message);
751 }
752 return ok();
753 }
754 else if constexpr (std::is_same_v<T, retire_connection_id_frame>)
755 {
756 return retire_cid(f.sequence_number);
757 }
758 else if constexpr (std::is_same_v<T, data_blocked_frame> ||
759 std::is_same_v<T, stream_data_blocked_frame> ||
760 std::is_same_v<T, streams_blocked_frame> ||
761 std::is_same_v<T, path_challenge_frame> ||
762 std::is_same_v<T, path_response_frame> ||
763 std::is_same_v<T, new_token_frame>)
764 {
765 // These frames are acknowledged but may not require action
766 return ok();
767 }
768 else
769 {
770 return ok();
771 }
772 },
773 frm);
774}
auto add_peer_cid(const connection_id &cid, uint64_t sequence, uint64_t retire_prior_to, const std::array< uint8_t, 16 > &reset_token) -> VoidResult
Add a new peer connection ID from NEW_CONNECTION_ID frame.
void enter_draining()
Transition to draining state.
auto retire_cid(uint64_t sequence) -> VoidResult
Retire a Connection ID.
void handle_loss_detection_result(const loss_detection_result &result)
Handle loss detection result (RFC 9002)
auto record_received(uint64_t bytes) -> VoidResult
Record received data.
auto set_handshake_confirmed(bool confirmed) noexcept -> void
Set handshake confirmed status.
auto reset_pto_count() noexcept -> void
Reset PTO count to zero.
auto on_ack_received(const ack_frame &ack, encryption_level level, std::chrono::steady_clock::time_point recv_time) -> loss_detection_result
Process received ACK frame (RFC 9002 Section 6)
auto process_crypto_data(encryption_level level, std::span< const uint8_t > data) -> Result< std::vector< uint8_t > >
Process incoming CRYPTO frame data.
Definition crypto.cpp:912
auto is_handshake_complete() const noexcept -> bool
Check if the handshake is complete.
Definition crypto.cpp:1003
auto get_stream(uint64_t stream_id) -> stream *
Get a stream by ID.
auto get_or_create_stream(uint64_t stream_id) -> Result< stream * >
Get or create a stream for a peer-initiated stream ID.
Result< std::monostate > VoidResult

References kcenon::network::protocols::quic::complete, kcenon::network::protocols::quic::connected, kcenon::network::error_void(), kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::connection_error::handshake_failed, kcenon::network::protocols::quic::initial, kcenon::network::ok(), and kcenon::network::protocols::quic::connection_error::protocol_violation.

Here is the call graph for this function:

◆ handle_loss_detection_result()

void kcenon::network::protocols::quic::connection::handle_loss_detection_result ( const loss_detection_result & result)
private

Handle loss detection result (RFC 9002)

Parameters
resultLoss detection result from timeout or ACK processing

Definition at line 1339 of file connection.cpp.

1340{
1341 switch (result.event)
1342 {
1344 // PTO timeout: generate probe packets (RFC 9002 Section 6.2.4)
1346 break;
1347
1349 // Handle lost packets: queue frames for retransmission and update congestion control
1350 for (const auto& lost : result.lost_packets)
1351 {
1354 }
1355 break;
1356
1358 // No action needed
1359 break;
1360 }
1361
1362 // Process acknowledged packets for congestion control
1363 auto ack_time = std::chrono::steady_clock::now();
1364 for (const auto& acked : result.acked_packets)
1365 {
1366 congestion_controller_.on_packet_acked(acked, ack_time);
1367 }
1368
1369 // Handle ECN congestion signal (RFC 9002 Section 7.1)
1370 if (result.ecn_signal == ecn_result::congestion_signal)
1371 {
1372 // ECN-CE marks indicate congestion without packet loss
1373 // Trigger congestion response using the sent time of the triggering packet
1374 congestion_controller_.on_ecn_congestion(result.ecn_congestion_sent_time);
1375 }
1376 else if (result.ecn_signal == ecn_result::ecn_failure)
1377 {
1378 // ECN validation failed - disable ECN for this connection
1379 // The ecn_tracker in loss_detector already handles this internally
1380 // No additional action needed here
1381 }
1382}
auto on_packet_acked(const sent_packet &packet, std::chrono::steady_clock::time_point ack_time) -> void
Handle packet acknowledgment (RFC 9002 Section 7.3)
auto on_packet_lost(const sent_packet &packet) -> void
Handle packet loss (RFC 9002 Section 7.3.2)
auto on_ecn_congestion(std::chrono::steady_clock::time_point sent_time) -> void
Handle ECN congestion signal (RFC 9002 Section 7.1)
void generate_probe_packets()
Generate probe packets for PTO (RFC 9002 Section 6.2.4) Sends one or two ack-eliciting packets to pro...
void queue_frames_for_retransmission(const sent_packet &lost_packet)
Queue frames from lost packet for retransmission.
@ ecn_failure
ECN validation failed, should disable ECN.
@ congestion_signal
ECN-CE increased (congestion experienced)

References kcenon::network::protocols::quic::loss_detection_result::acked_packets, congestion_controller_, kcenon::network::protocols::quic::congestion_signal, kcenon::network::protocols::quic::loss_detection_result::ecn_congestion_sent_time, kcenon::network::protocols::quic::ecn_failure, kcenon::network::protocols::quic::loss_detection_result::ecn_signal, kcenon::network::protocols::quic::loss_detection_result::event, generate_probe_packets(), kcenon::network::protocols::quic::loss_detection_result::lost_packets, kcenon::network::protocols::quic::none, kcenon::network::protocols::quic::congestion_controller::on_ecn_congestion(), kcenon::network::protocols::quic::congestion_controller::on_packet_acked(), kcenon::network::protocols::quic::congestion_controller::on_packet_lost(), kcenon::network::protocols::quic::packet_lost, kcenon::network::protocols::quic::pto_expired, and queue_frames_for_retransmission().

Referenced by on_timeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handshake_state()

auto kcenon::network::protocols::quic::connection::handshake_state ( ) const -> enum handshake_state
inlinenodiscardnoexcept

Get current handshake state.

Definition at line 187 of file connection.h.

188 {
189 return hs_state_;
190 }

◆ has_pending_data()

auto kcenon::network::protocols::quic::connection::has_pending_data ( ) const -> bool
nodiscard

Check if there are packets to send.

Definition at line 1053 of file connection.cpp.

1054{
1055 if (!pending_crypto_initial_.empty() ||
1056 !pending_crypto_handshake_.empty() ||
1057 !pending_crypto_app_.empty())
1058 {
1059 return true;
1060 }
1061
1063 {
1064 return true;
1065 }
1066
1067 if (close_sent_)
1068 {
1069 return true;
1070 }
1071
1072 // Check for pending frames (e.g., PING from PTO probing)
1073 if (!pending_frames_.empty())
1074 {
1075 return true;
1076 }
1077
1078 // Check for stream data
1079 auto& streams = const_cast<stream_manager&>(stream_mgr_);
1080 return !streams.streams_with_pending_data().empty();
1081}

References close_sent_, pending_ack_app_, pending_ack_handshake_, pending_ack_initial_, pending_crypto_app_, pending_crypto_handshake_, pending_crypto_initial_, pending_frames_, stream_mgr_, streams(), and kcenon::network::protocols::quic::stream_manager::streams_with_pending_data().

Here is the call graph for this function:

◆ idle_deadline()

auto kcenon::network::protocols::quic::connection::idle_deadline ( ) const -> std::chrono::steady_clock::time_point
inlinenodiscard

Get idle timeout deadline.

Definition at line 446 of file connection.h.

447 {
448 return idle_deadline_;
449 }

References idle_deadline_.

◆ init_server_handshake()

auto kcenon::network::protocols::quic::connection::init_server_handshake ( const std::string & cert_file,
const std::string & key_file ) -> VoidResult
nodiscard

Initialize server handshake.

Parameters
cert_filePath to certificate file
key_filePath to private key file
Returns
Success or error

Definition at line 295 of file connection.cpp.

297{
298 auto span = tracing::is_tracing_enabled()
299 ? std::make_optional(tracing::trace_context::create_span("quic.connection.init_server_handshake"))
300 : std::nullopt;
301 if (span)
302 {
303 span->set_attribute("quic.role", "server")
304 .set_attribute("net.transport", "udp")
305 .set_attribute("quic.version", "1");
306 }
307
308 if (!is_server_)
309 {
310 if (span)
311 {
312 span->set_error("Not a server connection");
313 }
315 "Not a server connection",
316 "connection");
317 }
318
319 auto result = crypto_.init_server(cert_file, key_file);
320 if (result.is_err())
321 {
322 if (span)
323 {
324 span->set_error(result.error().message);
325 }
327 "Failed to initialize server crypto",
328 "connection",
329 result.error().message);
330 }
331
332 // Derive initial secrets using the client's DCID
333 auto derive_result = crypto_.derive_initial_secrets(initial_dcid_);
334 if (derive_result.is_err())
335 {
336 if (span)
337 {
338 span->set_error(derive_result.error().message);
339 }
341 "Failed to derive initial secrets",
342 "connection",
343 derive_result.error().message);
344 }
345
347 if (span)
348 {
349 span->set_attribute("quic.state", "handshaking");
350 }
351 return ok();
352}
auto init_server(const std::string &cert_file, const std::string &key_file) -> VoidResult
Initialize as server.
Definition crypto.cpp:827
auto derive_initial_secrets(const connection_id &dest_cid) -> VoidResult
Derive initial secrets from destination connection ID.
Definition crypto.cpp:883

References kcenon::network::tracing::trace_context::create_span(), kcenon::network::error_void(), kcenon::network::protocols::quic::connection_error::handshake_failed, kcenon::network::protocols::quic::handshaking, kcenon::network::protocols::quic::connection_error::invalid_state, kcenon::network::tracing::is_tracing_enabled(), and kcenon::network::ok().

Here is the call graph for this function:

◆ initial_dcid()

auto kcenon::network::protocols::quic::connection::initial_dcid ( ) const -> const connection_id&
inlinenodiscard

Get initial Destination Connection ID (for key derivation)

Definition at line 239 of file connection.h.

239{ return initial_dcid_; }

References initial_dcid_.

Referenced by connection().

Here is the caller graph for this function:

◆ is_closed()

auto kcenon::network::protocols::quic::connection::is_closed ( ) const -> bool
inlinenodiscardnoexcept

Check if connection is closed.

Definition at line 212 of file connection.h.

213 {
215 }

References kcenon::network::protocols::quic::closed, and state_.

Referenced by next_timeout().

Here is the caller graph for this function:

◆ is_draining()

auto kcenon::network::protocols::quic::connection::is_draining ( ) const -> bool
inlinenodiscardnoexcept

Check if connection is draining or closing.

Definition at line 203 of file connection.h.

204 {
207 }

References kcenon::network::protocols::quic::closing, kcenon::network::protocols::quic::draining, and state_.

Referenced by next_timeout(), and on_timeout().

Here is the caller graph for this function:

◆ is_established()

auto kcenon::network::protocols::quic::connection::is_established ( ) const -> bool
inlinenodiscardnoexcept

Check if connection is established (handshake complete)

Definition at line 195 of file connection.h.

196 {
198 }

References kcenon::network::protocols::quic::connected, and state_.

◆ is_server()

auto kcenon::network::protocols::quic::connection::is_server ( ) const -> bool
inlinenodiscardnoexcept

Check if this is a server-side connection.

Definition at line 220 of file connection.h.

220{ return is_server_; }

References is_server_.

Referenced by connection().

Here is the caller graph for this function:

◆ local_cid()

auto kcenon::network::protocols::quic::connection::local_cid ( ) const -> const connection_id&
inlinenodiscard

Get local Connection ID.

Definition at line 229 of file connection.h.

229{ return local_cid_; }

References local_cid_.

◆ local_params()

auto kcenon::network::protocols::quic::connection::local_params ( ) const -> const transport_parameters&
inlinenodiscard

Get local transport parameters.

Definition at line 308 of file connection.h.

309 {
310 return local_params_;
311 }

References local_params_.

◆ next_timeout()

auto kcenon::network::protocols::quic::connection::next_timeout ( ) const -> std::optional<std::chrono::steady_clock::time_point>
nodiscard

Get the next timeout deadline.

Returns
Timeout time point or nullopt if no timer is set

Definition at line 1259 of file connection.cpp.

1261{
1262 if (is_closed())
1263 {
1264 return std::nullopt;
1265 }
1266
1267 if (is_draining())
1268 {
1269 return drain_deadline_;
1270 }
1271
1272 // Return the earliest of idle timeout and loss detection timeout
1273 auto loss_timeout = loss_detector_.next_timeout();
1274 if (loss_timeout.has_value())
1275 {
1276 return std::min(idle_deadline_, *loss_timeout);
1277 }
1278
1279 return idle_deadline_;
1280}
auto next_timeout() const -> std::optional< std::chrono::steady_clock::time_point >
Get the time of the next scheduled timeout.

References drain_deadline_, idle_deadline_, is_closed(), is_draining(), loss_detector_, and kcenon::network::protocols::quic::loss_detector::next_timeout().

Here is the call graph for this function:

◆ on_timeout()

void kcenon::network::protocols::quic::connection::on_timeout ( )

Handle timeout event.

Definition at line 1282 of file connection.cpp.

1283{
1284 auto now = std::chrono::steady_clock::now();
1285
1286 // Check drain timeout
1287 if (is_draining() && now >= drain_deadline_)
1288 {
1290 return;
1291 }
1292
1293 // Check idle timeout
1294 if (now >= idle_deadline_)
1295 {
1297 close_reason_ = "Idle timeout";
1299 return;
1300 }
1301
1302 // Handle PTO timeout for loss detection (RFC 9002 Section 6.2)
1303 auto loss_timeout = loss_detector_.next_timeout();
1304 if (loss_timeout.has_value() && now >= *loss_timeout)
1305 {
1306 auto result = loss_detector_.on_timeout();
1308 }
1309}
auto on_timeout() -> loss_detection_result
Handle timeout expiry (RFC 9002 Section 6.2)

References close_error_code_, close_reason_, kcenon::network::protocols::quic::closed, drain_deadline_, handle_loss_detection_result(), idle_deadline_, is_draining(), loss_detector_, kcenon::network::protocols::quic::loss_detector::next_timeout(), kcenon::network::protocols::quic::loss_detector::on_timeout(), and state_.

Here is the call graph for this function:

◆ operator=() [1/2]

auto kcenon::network::protocols::quic::connection::operator= ( connection && ) -> connection &=delete
delete

◆ operator=() [2/2]

auto kcenon::network::protocols::quic::connection::operator= ( const connection & ) -> connection &=delete
delete

◆ packets_received()

auto kcenon::network::protocols::quic::connection::packets_received ( ) const -> uint64_t
inlinenodiscardnoexcept

Get packets received count.

Definition at line 528 of file connection.h.

529 {
530 return packets_received_;
531 }

References packets_received_.

◆ packets_sent()

auto kcenon::network::protocols::quic::connection::packets_sent ( ) const -> uint64_t
inlinenodiscardnoexcept

Get packets sent count.

Definition at line 523 of file connection.h.

523{ return packets_sent_; }

References packets_sent_.

◆ path_mtu()

auto kcenon::network::protocols::quic::connection::path_mtu ( ) const -> size_t
nodiscardnoexcept

Get current path MTU.

Returns
Current validated MTU for this connection path

Definition at line 1560 of file connection.cpp.

1561{
1563}

References kcenon::network::protocols::quic::pmtud_controller::current_mtu(), and pmtud_controller_.

Here is the call graph for this function:

◆ peer_cid_manager() [1/2]

auto kcenon::network::protocols::quic::connection::peer_cid_manager ( ) -> connection_id_manager&
inlinenodiscard

Get the peer connection ID manager.

Definition at line 260 of file connection.h.

261 {
262 return peer_cid_manager_;
263 }

References peer_cid_manager_.

◆ peer_cid_manager() [2/2]

auto kcenon::network::protocols::quic::connection::peer_cid_manager ( ) const -> const connection_id_manager&
inlinenodiscard

Get the peer connection ID manager (const)

Definition at line 268 of file connection.h.

269 {
270 return peer_cid_manager_;
271 }

References peer_cid_manager_.

◆ pmtud() [1/2]

auto kcenon::network::protocols::quic::connection::pmtud ( ) -> pmtud_controller&
inlinenodiscard

Get the PMTUD controller.

Definition at line 499 of file connection.h.

499{ return pmtud_controller_; }

References pmtud_controller_.

◆ pmtud() [2/2]

auto kcenon::network::protocols::quic::connection::pmtud ( ) const -> const pmtud_controller&
inlinenodiscard

Get the PMTUD controller (const)

Definition at line 504 of file connection.h.

504{ return pmtud_controller_; }

References pmtud_controller_.

◆ pmtud_enabled()

auto kcenon::network::protocols::quic::connection::pmtud_enabled ( ) const -> bool
nodiscardnoexcept

Check if PMTUD is enabled.

Returns
True if PMTUD is enabled

Definition at line 1579 of file connection.cpp.

1580{
1582}
auto is_enabled() const noexcept -> bool
Check if PMTUD is enabled.

References kcenon::network::protocols::quic::pmtud_controller::is_enabled(), and pmtud_controller_.

Here is the call graph for this function:

◆ process_frames()

auto kcenon::network::protocols::quic::connection::process_frames ( std::span< const uint8_t > payload,
encryption_level level ) -> VoidResult
nodiscardprivate

Process frames from a decrypted packet.

Definition at line 523 of file connection.cpp.

525{
526 // Parse all frames in the payload
527 auto frames_result = frame_parser::parse_all(payload);
528 if (frames_result.is_err())
529 {
531 "Failed to parse frames",
532 "connection",
533 frames_result.error().message);
534 }
535
536 // Process each frame
537 for (const auto& f : frames_result.value())
538 {
539 auto result = handle_frame(f, level);
540 if (result.is_err())
541 {
542 return result;
543 }
544 }
545
546 update_state();
547 return ok();
548}
auto handle_frame(const frame &frame, encryption_level level) -> VoidResult
Handle a specific frame.
void update_state()
Update connection state based on handshake progress.
static auto parse_all(std::span< const uint8_t > data) -> Result< std::vector< frame > >
Parse all frames from buffer.
Definition frame.cpp:343

References kcenon::network::error_void(), kcenon::network::ok(), kcenon::network::protocols::quic::frame_parser::parse_all(), and kcenon::network::protocols::quic::connection_error::protocol_violation.

Here is the call graph for this function:

◆ process_long_header_packet()

auto kcenon::network::protocols::quic::connection::process_long_header_packet ( const long_header & hdr,
std::span< const uint8_t > payload ) -> VoidResult
nodiscardprivate

Process a long header packet.

Definition at line 428 of file connection.cpp.

431{
432 encryption_level level;
433 switch (hdr.type())
434 {
438 break;
442 break;
445 break;
447 // Handle Retry packet specially
448 return ok();
449 default:
451 "Unknown packet type",
452 "connection");
453 }
454
455 // Update remote CID if this is first packet from peer
456 if (remote_cid_.length() == 0)
457 {
458 remote_cid_ = hdr.src_conn_id;
460 }
461
462 // Server: set original DCID for transport parameters
464 {
466 }
467
468 // Get keys for this level
469 auto keys_result = crypto_.get_read_keys(level);
470 if (keys_result.is_err())
471 {
472 // Keys not yet available - this might happen during handshake
473 return ok();
474 }
475
476 // Track largest packet number
477 auto& space = get_pn_space(level);
478 if (hdr.packet_number > space.largest_received)
479 {
480 space.largest_received = hdr.packet_number;
481 space.largest_received_time = std::chrono::steady_clock::now();
482 }
483 space.ack_needed = true;
484
485 return process_frames(payload, level);
486}
auto length() const noexcept -> size_t
Get the length of the connection ID.
auto process_frames(std::span< const uint8_t > payload, encryption_level level) -> VoidResult
Process frames from a decrypted packet.
auto get_read_keys(encryption_level level) const -> Result< quic_keys >
Get read keys for an encryption level.
Definition crypto.cpp:1026
std::optional< connection_id > original_destination_connection_id
Original Destination Connection ID (server only)

References kcenon::network::error_void(), kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::initial, kcenon::network::ok(), kcenon::network::protocols::quic::connection_error::protocol_violation, kcenon::network::protocols::quic::retry, and kcenon::network::protocols::quic::zero_rtt.

Here is the call graph for this function:

◆ process_short_header_packet()

auto kcenon::network::protocols::quic::connection::process_short_header_packet ( const short_header & hdr,
std::span< const uint8_t > payload ) -> VoidResult
nodiscardprivate

Process a short header packet.

Definition at line 488 of file connection.cpp.

491{
493 {
494 // Short header packets require completed handshake
496 "Received 1-RTT packet before handshake complete",
497 "connection");
498 }
499
500 pending_ack_app_ = true;
501
502 // Get 1-RTT keys
504 if (keys_result.is_err())
505 {
507 "1-RTT keys not available",
508 "connection");
509 }
510
511 // Track largest packet number
512 auto& space = app_space_;
513 if (hdr.packet_number > space.largest_received)
514 {
515 space.largest_received = hdr.packet_number;
516 space.largest_received_time = std::chrono::steady_clock::now();
517 }
518 space.ack_needed = true;
519
521}

References kcenon::network::protocols::quic::application, kcenon::network::protocols::quic::connected, kcenon::network::error_void(), kcenon::network::protocols::quic::connection_error::handshake_failed, and kcenon::network::protocols::quic::connection_error::not_established.

Here is the call graph for this function:

◆ queue_frames_for_retransmission()

void kcenon::network::protocols::quic::connection::queue_frames_for_retransmission ( const sent_packet & lost_packet)
private

Queue frames from lost packet for retransmission.

Parameters
lost_packetThe packet that was declared lost

Definition at line 1433 of file connection.cpp.

1434{
1435 // Queue frames from the lost packet for retransmission
1436 // Note: Some frames should not be retransmitted (ACK, PADDING)
1437 const auto level = lost_packet.level;
1438
1439 for (const auto& f : lost_packet.frames)
1440 {
1441 std::visit(
1442 [this, level](const auto& frm)
1443 {
1444 using T = std::decay_t<decltype(frm)>;
1445
1446 // Skip non-retransmittable frames
1447 if constexpr (std::is_same_v<T, padding_frame> ||
1448 std::is_same_v<T, ack_frame>)
1449 {
1450 // These frames are not retransmitted
1451 }
1452 else if constexpr (std::is_same_v<T, crypto_frame>)
1453 {
1454 // Crypto frames need to be retransmitted with their data
1455 switch (level)
1456 {
1458 pending_crypto_initial_.push_back(frm.data);
1459 break;
1461 pending_crypto_handshake_.push_back(frm.data);
1462 break;
1465 pending_crypto_app_.push_back(frm.data);
1466 break;
1467 }
1468 }
1469 else if constexpr (std::is_same_v<T, stream_frame>)
1470 {
1471 // Stream data retransmission:
1472 // The stream will naturally resend unacknowledged data
1473 // when next_stream_frame() is called, as the data remains
1474 // in the send buffer until acknowledged via acknowledge_data().
1475 // No explicit action needed here.
1476 (void)frm;
1477 }
1478 else if constexpr (std::is_same_v<T, ping_frame> ||
1479 std::is_same_v<T, new_token_frame> ||
1480 std::is_same_v<T, handshake_done_frame>)
1481 {
1482 // These frames can be retransmitted
1483 pending_frames_.push_back(frm);
1484 }
1485 else if constexpr (std::is_same_v<T, max_data_frame> ||
1486 std::is_same_v<T, max_stream_data_frame> ||
1487 std::is_same_v<T, max_streams_frame> ||
1488 std::is_same_v<T, data_blocked_frame> ||
1489 std::is_same_v<T, stream_data_blocked_frame> ||
1490 std::is_same_v<T, streams_blocked_frame>)
1491 {
1492 // Flow control frames: queue for retransmission
1493 pending_frames_.push_back(frm);
1494 }
1495 else if constexpr (std::is_same_v<T, reset_stream_frame> ||
1496 std::is_same_v<T, stop_sending_frame>)
1497 {
1498 // Stream control frames: queue for retransmission
1499 pending_frames_.push_back(frm);
1500 }
1501 else if constexpr (std::is_same_v<T, new_connection_id_frame> ||
1502 std::is_same_v<T, retire_connection_id_frame>)
1503 {
1504 // Connection ID management: queue for retransmission
1505 pending_frames_.push_back(frm);
1506 }
1507 else if constexpr (std::is_same_v<T, path_challenge_frame> ||
1508 std::is_same_v<T, path_response_frame>)
1509 {
1510 // Path validation: may need fresh challenge, skip retransmission
1511 (void)frm;
1512 }
1513 else if constexpr (std::is_same_v<T, connection_close_frame>)
1514 {
1515 // CONNECTION_CLOSE is handled specially during closing
1516 (void)frm;
1517 }
1518 },
1519 f);
1520 }
1521}

References kcenon::network::protocols::quic::application, kcenon::network::protocols::quic::sent_packet::frames, kcenon::network::protocols::quic::handshake, kcenon::network::protocols::quic::initial, kcenon::network::protocols::quic::sent_packet::level, pending_crypto_app_, pending_crypto_handshake_, pending_crypto_initial_, pending_frames_, and kcenon::network::protocols::quic::zero_rtt.

Referenced by handle_loss_detection_result().

Here is the caller graph for this function:

◆ receive_packet()

auto kcenon::network::protocols::quic::connection::receive_packet ( std::span< const uint8_t > data) -> VoidResult
nodiscard

Receive and process a packet.

Parameters
dataRaw packet data
Returns
Success or error

Definition at line 358 of file connection.cpp.

359{
360 auto span = tracing::is_tracing_enabled()
361 ? std::make_optional(tracing::trace_context::create_span("quic.connection.receive_packet"))
362 : std::nullopt;
363 if (span)
364 {
365 span->set_attribute("quic.packet.size", static_cast<int64_t>(data.size()))
366 .set_attribute("quic.role", is_server_ ? "server" : "client")
367 .set_attribute("quic.state", connection_state_to_string(state_));
368 }
369
370 if (data.empty())
371 {
372 if (span)
373 {
374 span->set_error("Empty packet");
375 }
377 "Empty packet",
378 "connection");
379 }
380
381 if (is_draining() || is_closed())
382 {
383 // In draining/closed state, just count the packet
385 bytes_received_ += data.size();
386 if (span)
387 {
388 span->set_attribute("quic.packet.ignored", true);
389 }
390 return ok();
391 }
392
393 bytes_received_ += data.size();
396
397 // Check header form
399 {
400 auto parse_result = packet_parser::parse_long_header(data);
401 if (parse_result.is_err())
402 {
404 "Failed to parse long header",
405 "connection",
406 parse_result.error().message);
407 }
408
409 auto [header, header_len] = parse_result.value();
410 return process_long_header_packet(header, data.subspan(header_len));
411 }
412 else
413 {
414 auto parse_result = packet_parser::parse_short_header(data, local_cid_.length());
415 if (parse_result.is_err())
416 {
418 "Failed to parse short header",
419 "connection",
420 parse_result.error().message);
421 }
422
423 auto [header, header_len] = parse_result.value();
424 return process_short_header_packet(header, data.subspan(header_len));
425 }
426}
auto process_short_header_packet(const short_header &hdr, std::span< const uint8_t > payload) -> VoidResult
Process a short header packet.
auto process_long_header_packet(const long_header &hdr, std::span< const uint8_t > payload) -> VoidResult
Process a long header packet.
static constexpr auto is_long_header(uint8_t first_byte) noexcept -> bool
Check if a packet has a long header.
Definition packet.h:225
static auto parse_long_header(std::span< const uint8_t > data) -> Result< std::pair< long_header, size_t > >
Parse a long header packet.
Definition packet.cpp:199
static auto parse_short_header(std::span< const uint8_t > data, size_t conn_id_length) -> Result< std::pair< short_header, size_t > >
Parse a short header packet.
Definition packet.cpp:360
auto connection_state_to_string(connection_state state) -> const char *
Convert connection state to string.

References kcenon::network::protocols::quic::connection_state_to_string(), kcenon::network::tracing::trace_context::create_span(), kcenon::network::error_void(), kcenon::network::protocols::quic::packet_parser::is_long_header(), kcenon::network::tracing::is_tracing_enabled(), kcenon::network::ok(), kcenon::network::protocols::quic::packet_parser::parse_long_header(), kcenon::network::protocols::quic::packet_parser::parse_short_header(), and kcenon::network::protocols::quic::connection_error::protocol_violation.

Here is the call graph for this function:

◆ remote_cid()

auto kcenon::network::protocols::quic::connection::remote_cid ( ) const -> const connection_id&
inlinenodiscard

Get remote Connection ID.

Definition at line 234 of file connection.h.

234{ return remote_cid_; }

References remote_cid_.

◆ remote_params()

auto kcenon::network::protocols::quic::connection::remote_params ( ) const -> const transport_parameters&
inlinenodiscard

Get remote transport parameters.

Definition at line 316 of file connection.h.

317 {
318 return remote_params_;
319 }

References remote_params_.

◆ reset_idle_timer()

void kcenon::network::protocols::quic::connection::reset_idle_timer ( )
private

Reset idle timer.

Definition at line 1244 of file connection.cpp.

1245{
1248 {
1249 timeout = std::min(timeout, remote_params_.max_idle_timeout);
1250 }
1251
1252 if (timeout > 0)
1253 {
1254 idle_deadline_ = std::chrono::steady_clock::now() +
1255 std::chrono::milliseconds(timeout);
1256 }
1257}

References idle_deadline_, local_params_, kcenon::network::protocols::quic::transport_parameters::max_idle_timeout, and remote_params_.

Referenced by connection().

Here is the caller graph for this function:

◆ retire_cid()

auto kcenon::network::protocols::quic::connection::retire_cid ( uint64_t sequence) -> VoidResult
nodiscard

Retire a Connection ID.

Parameters
sequenceSequence number of CID to retire
Returns
Success or error

Definition at line 126 of file connection.cpp.

127{
128 auto it = std::find_if(local_cids_.begin(), local_cids_.end(),
129 [sequence](const auto& p) { return p.first == sequence; });
130
131 if (it == local_cids_.end())
132 {
134 "Connection ID not found",
135 "connection");
136 }
137
138 // Don't retire the only remaining CID
139 if (local_cids_.size() <= 1)
140 {
142 "Cannot retire last connection ID",
143 "connection");
144 }
145
146 local_cids_.erase(it);
147 return ok();
148}

References kcenon::network::error_void(), kcenon::network::ok(), and kcenon::network::protocols::quic::connection_error::protocol_violation.

Here is the call graph for this function:

◆ rotate_peer_cid()

auto kcenon::network::protocols::quic::connection::rotate_peer_cid ( ) -> VoidResult
nodiscard

Rotate to a new peer connection ID.

Returns
Success or error if no unused CID is available

Used for path migration or proactive CID rotation.

Definition at line 1551 of file connection.cpp.

1552{
1554}
auto rotate_peer_cid() -> VoidResult
Rotate to a new peer connection ID.

◆ set_local_params()

void kcenon::network::protocols::quic::connection::set_local_params ( const transport_parameters & params)

Set local transport parameters.

Parameters
paramsParameters to advertise to peer

Definition at line 154 of file connection.cpp.

155{
156 local_params_ = params;
158
159 // Apply to subsystems
160 stream_mgr_.set_local_max_streams_bidi(params.initial_max_streams_bidi);
161 stream_mgr_.set_local_max_streams_uni(params.initial_max_streams_uni);
162}
void set_local_max_streams_uni(uint64_t max)
Set our maximum unidirectional streams (advertised to peer)
void set_local_max_streams_bidi(uint64_t max)
Set our maximum bidirectional streams (advertised to peer)

References kcenon::network::protocols::quic::transport_parameters::initial_max_streams_bidi, kcenon::network::protocols::quic::transport_parameters::initial_max_streams_uni, kcenon::network::protocols::quic::transport_parameters::initial_source_connection_id, local_cid_, local_params_, kcenon::network::protocols::quic::stream_manager::set_local_max_streams_bidi(), kcenon::network::protocols::quic::stream_manager::set_local_max_streams_uni(), and stream_mgr_.

Here is the call graph for this function:

◆ set_remote_params()

void kcenon::network::protocols::quic::connection::set_remote_params ( const transport_parameters & params)

Set remote transport parameters.

Parameters
paramsParameters received from peer

Definition at line 164 of file connection.cpp.

165{
166 remote_params_ = params;
168}
void apply_remote_params()
Apply remote transport parameters.

References apply_remote_params(), and remote_params_.

Here is the call graph for this function:

◆ start_handshake()

auto kcenon::network::protocols::quic::connection::start_handshake ( const std::string & server_name) -> Result<std::vector<uint8_t>>
nodiscard

Start the handshake (client only)

Parameters
server_nameServer hostname for SNI
Returns
Initial crypto data to send or error

Definition at line 199 of file connection.cpp.

201{
202 auto span = tracing::is_tracing_enabled()
203 ? std::make_optional(tracing::trace_context::create_span("quic.connection.start_handshake"))
204 : std::nullopt;
205 if (span)
206 {
207 span->set_attribute("quic.role", "client")
208 .set_attribute("quic.server_name", server_name)
209 .set_attribute("net.transport", "udp")
210 .set_attribute("quic.version", "1");
211 }
212
213 if (is_server_)
214 {
215 if (span)
216 {
217 span->set_error("Server cannot start handshake");
218 }
220 "Server cannot start handshake",
221 "connection");
222 }
223
225 {
226 if (span)
227 {
228 span->set_error("Connection already started");
229 }
231 "Connection already started",
232 "connection");
233 }
234
235 // Initialize crypto for client
236 auto init_result = crypto_.init_client(server_name);
237 if (init_result.is_err())
238 {
239 if (span)
240 {
241 span->set_error(init_result.error().message);
242 }
244 "Failed to initialize crypto",
245 "connection",
246 init_result.error().message);
247 }
248
249 // Derive initial secrets
250 auto derive_result = crypto_.derive_initial_secrets(initial_dcid_);
251 if (derive_result.is_err())
252 {
253 if (span)
254 {
255 span->set_error(derive_result.error().message);
256 }
258 "Failed to derive initial secrets",
259 "connection",
260 derive_result.error().message);
261 }
262
263 // Start TLS handshake to get ClientHello
264 auto hs_result = crypto_.start_handshake();
265 if (hs_result.is_err())
266 {
267 if (span)
268 {
269 span->set_error(hs_result.error().message);
270 }
272 "Failed to start TLS handshake",
273 "connection",
274 hs_result.error().message);
275 }
276
277 // Store crypto data for Initial packet
278 if (!hs_result.value().empty())
279 {
280 pending_crypto_initial_.push_back(std::move(hs_result.value()));
281 }
282
283 // Update state
286
287 if (span)
288 {
289 span->set_attribute("quic.state", "handshaking");
290 }
291
292 return ok(std::vector<uint8_t>{});
293}
auto start_handshake() -> Result< std::vector< uint8_t > >
Start the handshake (generate initial CRYPTO data)
Definition crypto.cpp:965
auto init_client(const std::string &server_name) -> VoidResult
Initialize as client.
Definition crypto.cpp:782
@ error
Black hole detected, reset to base.
@ waiting_server_hello
Client waiting for ServerHello.

References kcenon::network::tracing::trace_context::create_span(), kcenon::network::protocols::quic::error, kcenon::network::protocols::quic::connection_error::handshake_failed, kcenon::network::protocols::quic::handshaking, kcenon::network::protocols::quic::idle, kcenon::network::protocols::quic::connection_error::invalid_state, kcenon::network::tracing::is_tracing_enabled(), kcenon::network::message, kcenon::network::ok(), and kcenon::network::protocols::quic::waiting_server_hello.

Here is the call graph for this function:

◆ state()

auto kcenon::network::protocols::quic::connection::state ( ) const -> connection_state
inlinenodiscardnoexcept

Get current connection state.

Definition at line 182 of file connection.h.

182{ return state_; }

References state_.

◆ streams() [1/2]

auto kcenon::network::protocols::quic::connection::streams ( ) -> stream_manager&
inlinenodiscard

Get the stream manager.

Definition at line 371 of file connection.h.

371{ return stream_mgr_; }

References stream_mgr_.

Referenced by has_pending_data().

Here is the caller graph for this function:

◆ streams() [2/2]

auto kcenon::network::protocols::quic::connection::streams ( ) const -> const stream_manager&
inlinenodiscard

Get the stream manager (const)

Definition at line 376 of file connection.h.

376{ return stream_mgr_; }

References stream_mgr_.

◆ to_sent_packet()

auto kcenon::network::protocols::quic::connection::to_sent_packet ( const sent_packet_info & info) const -> sent_packet
nodiscardprivate

Convert sent_packet_info to sent_packet for loss detector.

Definition at line 1523 of file connection.cpp.

1524{
1525 sent_packet pkt;
1526 pkt.packet_number = info.packet_number;
1527 pkt.sent_time = info.sent_time;
1528 pkt.sent_bytes = info.sent_bytes;
1529 pkt.ack_eliciting = info.ack_eliciting;
1530 pkt.in_flight = info.in_flight;
1531 pkt.level = info.level;
1532 pkt.frames = info.frames;
1533 return pkt;
1534}

References kcenon::network::protocols::quic::sent_packet::ack_eliciting, kcenon::network::protocols::quic::sent_packet::frames, kcenon::network::protocols::quic::sent_packet::in_flight, kcenon::network::protocols::quic::sent_packet::level, kcenon::network::protocols::quic::sent_packet::packet_number, kcenon::network::protocols::quic::sent_packet::sent_bytes, and kcenon::network::protocols::quic::sent_packet::sent_time.

◆ update_state()

void kcenon::network::protocols::quic::connection::update_state ( )
private

Update connection state based on handshake progress.

Definition at line 1120 of file connection.cpp.

1121{
1123 {
1124 hs_state_ = handshake_state::complete;
1125 if (is_server_)
1126 {
1128 }
1129 // Client waits for HANDSHAKE_DONE
1130 }
1131}

References kcenon::network::protocols::quic::complete, kcenon::network::protocols::quic::connected, crypto_, kcenon::network::protocols::quic::quic_crypto::is_handshake_complete(), is_server_, and state_.

Here is the call graph for this function:

Member Data Documentation

◆ app_space_

packet_number_space kcenon::network::protocols::quic::connection::app_space_
private

Definition at line 570 of file connection.h.

◆ application_close_

bool kcenon::network::protocols::quic::connection::application_close_ {false}
private

Definition at line 590 of file connection.h.

590{false};

◆ bytes_received_

uint64_t kcenon::network::protocols::quic::connection::bytes_received_ {0}
private

Definition at line 599 of file connection.h.

599{0};

Referenced by bytes_received().

◆ bytes_sent_

uint64_t kcenon::network::protocols::quic::connection::bytes_sent_ {0}
private

Definition at line 598 of file connection.h.

598{0};

Referenced by bytes_sent().

◆ close_error_code_

std::optional<uint64_t> kcenon::network::protocols::quic::connection::close_error_code_
private

Definition at line 588 of file connection.h.

Referenced by close_error_code(), and on_timeout().

◆ close_reason_

std::string kcenon::network::protocols::quic::connection::close_reason_
private

Definition at line 589 of file connection.h.

Referenced by close_reason(), and on_timeout().

◆ close_received_

bool kcenon::network::protocols::quic::connection::close_received_ {false}
private

Definition at line 587 of file connection.h.

587{false};

◆ close_sent_

bool kcenon::network::protocols::quic::connection::close_sent_ {false}
private

Definition at line 586 of file connection.h.

586{false};

Referenced by has_pending_data().

◆ congestion_controller_

congestion_controller kcenon::network::protocols::quic::connection::congestion_controller_
private

Definition at line 562 of file connection.h.

Referenced by disable_pmtud(), enable_pmtud(), and handle_loss_detection_result().

◆ crypto_

quic_crypto kcenon::network::protocols::quic::connection::crypto_
private

Definition at line 555 of file connection.h.

Referenced by crypto(), crypto(), generate_probe_packets(), and update_state().

◆ drain_deadline_

std::chrono::steady_clock::time_point kcenon::network::protocols::quic::connection::drain_deadline_
private

Definition at line 595 of file connection.h.

Referenced by enter_closing(), enter_draining(), next_timeout(), and on_timeout().

◆ flow_ctrl_

flow_controller kcenon::network::protocols::quic::connection::flow_ctrl_
private

Definition at line 557 of file connection.h.

Referenced by apply_remote_params(), flow_control(), and flow_control().

◆ handshake_space_

packet_number_space kcenon::network::protocols::quic::connection::handshake_space_
private

Definition at line 569 of file connection.h.

◆ idle_deadline_

std::chrono::steady_clock::time_point kcenon::network::protocols::quic::connection::idle_deadline_
private

◆ initial_dcid_

connection_id kcenon::network::protocols::quic::connection::initial_dcid_
private

Definition at line 545 of file connection.h.

Referenced by initial_dcid().

◆ initial_space_

packet_number_space kcenon::network::protocols::quic::connection::initial_space_
private

Definition at line 568 of file connection.h.

◆ is_server_

bool kcenon::network::protocols::quic::connection::is_server_
private

Definition at line 538 of file connection.h.

Referenced by is_server(), and update_state().

◆ local_cid_

connection_id kcenon::network::protocols::quic::connection::local_cid_
private

Definition at line 543 of file connection.h.

Referenced by connection(), local_cid(), and set_local_params().

◆ local_cids_

std::vector<std::pair<uint64_t, connection_id> > kcenon::network::protocols::quic::connection::local_cids_
private

Definition at line 546 of file connection.h.

Referenced by connection().

◆ local_params_

transport_parameters kcenon::network::protocols::quic::connection::local_params_
private

◆ loss_detector_

loss_detector kcenon::network::protocols::quic::connection::loss_detector_
private

Definition at line 561 of file connection.h.

Referenced by next_timeout(), and on_timeout().

◆ next_cid_sequence_

uint64_t kcenon::network::protocols::quic::connection::next_cid_sequence_ {1}
private

Definition at line 547 of file connection.h.

547{1};

◆ packets_received_

uint64_t kcenon::network::protocols::quic::connection::packets_received_ {0}
private

Definition at line 601 of file connection.h.

601{0};

Referenced by packets_received().

◆ packets_sent_

uint64_t kcenon::network::protocols::quic::connection::packets_sent_ {0}
private

Definition at line 600 of file connection.h.

600{0};

Referenced by packets_sent().

◆ peer_cid_manager_

connection_id_manager kcenon::network::protocols::quic::connection::peer_cid_manager_
private

◆ pending_ack_app_

bool kcenon::network::protocols::quic::connection::pending_ack_app_ {false}
private

Definition at line 580 of file connection.h.

580{false};

Referenced by has_pending_data().

◆ pending_ack_handshake_

bool kcenon::network::protocols::quic::connection::pending_ack_handshake_ {false}
private

Definition at line 579 of file connection.h.

579{false};

Referenced by has_pending_data().

◆ pending_ack_initial_

bool kcenon::network::protocols::quic::connection::pending_ack_initial_ {false}
private

Definition at line 578 of file connection.h.

578{false};

Referenced by has_pending_data().

◆ pending_crypto_app_

std::deque<std::vector<uint8_t> > kcenon::network::protocols::quic::connection::pending_crypto_app_
private

Definition at line 575 of file connection.h.

Referenced by has_pending_data(), and queue_frames_for_retransmission().

◆ pending_crypto_handshake_

std::deque<std::vector<uint8_t> > kcenon::network::protocols::quic::connection::pending_crypto_handshake_
private

◆ pending_crypto_initial_

std::deque<std::vector<uint8_t> > kcenon::network::protocols::quic::connection::pending_crypto_initial_
private

◆ pending_frames_

std::deque<frame> kcenon::network::protocols::quic::connection::pending_frames_
private

◆ pmtud_controller_

pmtud_controller kcenon::network::protocols::quic::connection::pmtud_controller_
private

Definition at line 565 of file connection.h.

Referenced by disable_pmtud(), enable_pmtud(), path_mtu(), pmtud(), pmtud(), and pmtud_enabled().

◆ pto_deadline_

std::chrono::steady_clock::time_point kcenon::network::protocols::quic::connection::pto_deadline_
private

Definition at line 594 of file connection.h.

◆ remote_cid_

connection_id kcenon::network::protocols::quic::connection::remote_cid_
private

Definition at line 544 of file connection.h.

Referenced by active_peer_cid(), connection(), and remote_cid().

◆ remote_params_

transport_parameters kcenon::network::protocols::quic::connection::remote_params_
private

◆ rtt_estimator_

rtt_estimator kcenon::network::protocols::quic::connection::rtt_estimator_
private

Definition at line 560 of file connection.h.

◆ state_

connection_state kcenon::network::protocols::quic::connection::state_ {connection_state::idle}
private

◆ stream_mgr_

stream_manager kcenon::network::protocols::quic::connection::stream_mgr_
private

The documentation for this class was generated from the following files: