in quic/s2n-quic-transport/src/space/session_context.rs [76:218]
fn on_server_params(
&mut self,
decoder: DecoderBuffer,
) -> Result<
(
InitialFlowControlLimits,
ActiveConnectionIdLimit,
DatagramLimits,
MaxAckDelay,
Option<dc::Version>,
),
transport::Error,
> {
debug_assert!(Config::ENDPOINT_TYPE.is_client());
let (peer_parameters, remaining) =
ServerTransportParameters::decode(decoder).map_err(|_| {
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.4
//# An endpoint SHOULD treat receipt of
//# duplicate transport parameters as a connection error of type
//# TRANSPORT_PARAMETER_ERROR.
transport::Error::TRANSPORT_PARAMETER_ERROR
.with_reason("Invalid transport parameters")
})?;
debug_assert_eq!(remaining.len(), 0);
self.publisher.on_transport_parameters_received(
event::builder::TransportParametersReceived {
transport_parameters: peer_parameters.into_event(),
},
);
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.3
//# An endpoint MUST treat the following as a connection error of type
//# TRANSPORT_PARAMETER_ERROR or PROTOCOL_VIOLATION:
self.validate_initial_source_connection_id(
&peer_parameters.initial_source_connection_id,
self.path_manager
.active_path()
.peer_connection_id
.as_bytes(),
)?;
match (self.retry_cid, peer_parameters.retry_source_connection_id) {
(Some(retry_packet_value), Some(transport_params_value)) => {
if retry_packet_value
.as_bytes()
.ct_eq(transport_params_value.as_bytes())
.not()
.into()
{
return Err(transport::Error::TRANSPORT_PARAMETER_ERROR
.with_reason("retry_source_connection_id mismatch"));
}
}
(Some(_), None) => {
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.3
//# * absence of the retry_source_connection_id transport parameter from
//# the server after receiving a Retry packet,
return Err(transport::Error::TRANSPORT_PARAMETER_ERROR.with_reason(
"retry_source_connection_id transport parameter absent \
after receiving a Retry packet from the server",
));
}
(None, Some(_)) => {
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.3
//# * presence of the retry_source_connection_id transport parameter
//# when no Retry packet was received, or
return Err(transport::Error::TRANSPORT_PARAMETER_ERROR.with_reason(
"retry_source_connection_id transport parameter present \
when no Retry packet was received",
));
}
(None, None) => {}
}
if let Some(peer_value) = peer_parameters.original_destination_connection_id {
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.3
//# The values provided by a peer for these transport parameters MUST
//# match the values that an endpoint used in the Destination and Source
//# Connection ID fields of Initial packets that it sent (and received,
//# for servers). Endpoints MUST validate that received transport
//# parameters match received connection ID values.
if peer_value
.as_bytes()
.ct_eq(self.initial_cid.as_bytes())
.not()
.into()
{
return Err(transport::Error::TRANSPORT_PARAMETER_ERROR
.with_reason("original_destination_connection_id mismatch"));
}
} else {
//= https://www.rfc-editor.org/rfc/rfc9000#section-7.3
//# An endpoint MUST treat the absence of the
//# initial_source_connection_id transport parameter from either endpoint
//# or the absence of the original_destination_connection_id transport
//# parameter from the server as a connection error of type
//# TRANSPORT_PARAMETER_ERROR.
return Err(transport::Error::TRANSPORT_PARAMETER_ERROR
.with_reason("missing original_destination_connection_id"));
}
//= https://www.rfc-editor.org/rfc/rfc9000#section-10.3
//# Servers can also issue a stateless_reset_token transport parameter during the
//# handshake that applies to the connection ID that it selected during
//# the handshake. These exchanges are protected by encryption, so only
//# client and server know their value. Note that clients cannot use the
//# stateless_reset_token transport parameter because their transport
//# parameters do not have confidentiality protection.
if let Some(stateless_reset_token) = peer_parameters.stateless_reset_token {
self.path_manager
.peer_id_registry
.register_initial_stateless_reset_token(stateless_reset_token);
}
// Load the peer's transport parameters into the connection's limits
self.limits.load_peer(&peer_parameters);
let initial_flow_control_limits = peer_parameters.flow_control_limits();
let active_connection_id_limit = peer_parameters.active_connection_id_limit;
let datagram_limits = peer_parameters.datagram_limits();
let dc_version = if Config::DcEndpoint::ENABLED {
peer_parameters
.dc_supported_versions
.selected_version()
.map_err(|_| {
transport::Error::TRANSPORT_PARAMETER_ERROR
.with_reason("invalid dc supported versions")
})?
} else {
None
};
Ok((
initial_flow_control_limits,
active_connection_id_limit,
datagram_limits,
peer_parameters.max_ack_delay,
dc_version,
))
}