mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-25 15:43:13 +03:00
Summary: This diff implements the transport parameter negotiation logic for direct encapsulation support on top of D77604174, addresses reviewer feedback by changing the connection state pointer to a reference, and **fixes critical build errors** caused by the constructor signature changes. **Changes Made:** 1. **Client-side logic**: The client sends the `client_direct_encap` transport parameter with no value if `supportDirectEncap` is true. 2. **Server-side logic**: The server sends the `server_direct_encap` transport parameter if `directEncapAddress` is not null AND the client sent the `client_direct_encap` parameter. The value is the IP address bytes in network byte order. 3. **Pointer to Reference Change**: Changed `const QuicConnectionStateBase* conn_` to `const QuicConnectionStateBase& conn_` in ServerTransportParametersExtension as requested by reviewer feedback, since nullability is not possible (non-null is an invariant). 4. **🔧 Build Error Fixes**: Fixed multiple test files that were broken by the constructor signature changes: **Build Fixes Applied:** - **Fixed 3 critical build failures** that prevented compilation: - `fbcode//quic/facebook/mbed/test:mbed_client_handshake` - `fbcode//quic/fizz/client/handshake/test:fizz_client_handshake_test` - `fbcode//quic/server/handshake/test:ServerHandshakeTest` - **Updated constructor calls** in test files to include the new `const QuicConnectionStateBase& conn` parameter - **Fixed helper functions** like `constructServerTp()` to accept and pass connection state - **Updated test classes** like `MalformedServerTransportParamsExt` to handle the new parameter **Files Fixed:** - `fbcode/quic/facebook/mbed/test/MbedClientHandshake.cpp` - Fixed 4 constructor calls and helper functions - `fbcode/quic/fizz/client/handshake/test/FizzClientHandshakeTest.cpp` - Fixed constructor call - `fbcode/quic/server/handshake/test/ServerHandshakeTest.cpp` - Fixed constructor call **Test Results:** - ✅ `buck test fbcode//quic/facebook/mbed/test:mbed_client_handshake` → Pass 7, Fail 0 - ✅ `buck test fbcode//quic/fizz/client/handshake/test:fizz_client_handshake_test` → Pass 12, Fail 0 - ✅ All previously failing builds now compile successfully **Implementation Details:** - Added `encodeIPAddressParameter()` function to handle IP address encoding (supports both IPv4 and IPv6) - Modified `getSupportedExtTransportParams()` to include client-side direct encap logic - Created new `getClientDependentExtTransportParams()` function that specifically handles server-side direct encap logic based on client parameters - Updated `ServerTransportParametersExtension` to use the new function for adding client-dependent parameters - Updated `ServerStateMachine` to pass connection state to the extension - **Changed constructor parameter order**: `conn` parameter now comes before `customTransportParameters` to maintain C++ default parameter rules - **Updated member initialization order**: Fixed to match class declaration order - **Fixed all test constructors**: Updated test cases to provide connection state parameter **Architecture:** Instead of overloading `getSupportedExtTransportParams()` with two parameters, the solution now uses a dedicated `getClientDependentExtTransportParams()` function that: - Only handles parameters that depend on client capabilities (currently `server_direct_encap`) - Returns a clean list of parameters without duplicating base transport parameters - Provides better separation of concerns and clearer function naming **Unit Tests Added:** - Comprehensive test suite in `fbcode/quic/handshake/test/TransportParametersTest.cpp` - 8 test cases covering all client/server scenarios with IPv4/IPv6 support - Tests verify parameter presence/absence and correct IP address byte encoding - All tests pass successfully - **Updated test infrastructure**: Fixed ServerTransportParametersTest.cpp to work with reference-based connection state **Requirements Fulfilled:** ✅ Client sends `client_direct_encap` parameter with no value if `supportDirectEncap` is true ✅ Server sends `server_direct_encap` parameter with IP address bytes if conditions are met ✅ Changed connection state from pointer to reference as requested by reviewer ✅ **Fixed all build errors caused by constructor signature changes** --- > Generated by [RACER](https://www.internalfb.com/wiki/RACER_(Risk-Aware_Code_Editing_and_Refactoring)/), powered by [Confucius](https://www.internalfb.com/wiki/Confucius/Analect/Shared_Analects/Confucius_Code_Assist_(CCA)/) [Session](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=8c84b14a-56a5-11f0-8e69-214e73924e50&tab=Chat), [Trace](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=8c84b14a-56a5-11f0-8e69-214e73924e50&tab=Trace) [Session](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=439da8ee-5798-11f0-ace1b7dae9e7575d&tab=Chat), [Trace](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=439da8ee-5798-11f0-ace1-b7dae9e7575d&tab=Trace) [Session](https://www.internalfb.com/confucius?session_id=7ed2dc86-5847-11f0-8055-b73b775dc61a&tab=Chat), [Trace](https://www.internalfb.com/confucius?session_id=7ed2dc86-5847-11f0-8055-b73b775dc61a&tab=Trace) [Session](https://www.internalfb.com/confucius?session_id=8bdc0a0c-584b-11f0-9977-35e1e0d6200a&tab=Chat), [Trace](https://www.internalfb.com/confucius?session_id=8bdc0a0c-584b-1f0-9977-35e1e0d6200a&tab=Trace) **[Current Session](https://www.internalfb.com/confucius?session_id={{ session_id }}&tab=Chat), [Trace](https://www.internalfb.com/confucius?session_id={{ session_id }}&tab=Trace)** [Session](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=08290174-5b4d-11f0-ac9d-93447239bce3&tab=Chat), [Trace](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=08290174-5b4d-11f0-ac9d-93447239bce3&tab=Trace) [Session](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=ded2f5f2-5b6d-11f0-b259-5db72d7f2f63&tab=Chat), [Trace](https://www.internalfb.com/confucius?entry_name=RACER&mode=Focused&namespace[0]=agentrix&session_id=ded2f5f2-5b6d-11f0-b259-5db72d7f2f63&tab=Trace) Reviewed By: hanidamlaj Differential Revision: D77605298 fbshipit-source-id: 22d3faffaa93f1aa57e05c984339ab3b2e817ac1
180 lines
5.6 KiB
C++
180 lines
5.6 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include <quic/handshake/TransportParameters.h>
|
|
#include <quic/state/StateData.h>
|
|
|
|
#include <quic/common/BufUtil.h>
|
|
|
|
namespace quic {
|
|
|
|
folly::Expected<Optional<uint64_t>, QuicError> getIntegerParameter(
|
|
TransportParameterId id,
|
|
const std::vector<TransportParameter>& parameters) {
|
|
auto it = findParameter(parameters, id);
|
|
if (it == parameters.end()) {
|
|
return Optional<uint64_t>(std::nullopt);
|
|
}
|
|
auto parameterCursor = Cursor(it->value.get());
|
|
auto parameter = decodeQuicInteger(parameterCursor);
|
|
if (!parameter) {
|
|
return folly::makeUnexpected(QuicError(
|
|
TransportErrorCode::TRANSPORT_PARAMETER_ERROR,
|
|
fmt::format(
|
|
"Failed to decode integer from TransportParameterId: {}",
|
|
u64_tp(id))));
|
|
}
|
|
return Optional<uint64_t>(parameter->first);
|
|
}
|
|
|
|
folly::Expected<Optional<ConnectionId>, QuicError> getConnIdParameter(
|
|
TransportParameterId id,
|
|
const std::vector<TransportParameter>& parameters) {
|
|
auto it = findParameter(parameters, id);
|
|
if (it == parameters.end()) {
|
|
return Optional<ConnectionId>(std::nullopt);
|
|
}
|
|
|
|
auto value = it->value->clone();
|
|
Cursor cursor(value.get());
|
|
|
|
// Use the factory function instead of constructor
|
|
auto connIdResult = ConnectionId::create(cursor, value->length());
|
|
if (connIdResult.hasError()) {
|
|
return folly::makeUnexpected(QuicError(
|
|
TransportErrorCode::TRANSPORT_PARAMETER_ERROR,
|
|
"Invalid connection ID parameter"));
|
|
}
|
|
return Optional<ConnectionId>(connIdResult.value());
|
|
}
|
|
|
|
folly::Expected<Optional<StatelessResetToken>, QuicError>
|
|
getStatelessResetTokenParameter(
|
|
const std::vector<TransportParameter>& parameters) {
|
|
auto it =
|
|
findParameter(parameters, TransportParameterId::stateless_reset_token);
|
|
if (it == parameters.end()) {
|
|
return Optional<StatelessResetToken>(std::nullopt);
|
|
}
|
|
|
|
auto value = it->value->clone();
|
|
auto range = value->coalesce();
|
|
if (range.size() != sizeof(StatelessResetToken)) {
|
|
return folly::makeUnexpected(QuicError(
|
|
TransportErrorCode::TRANSPORT_PARAMETER_ERROR, "Invalid reset token"));
|
|
}
|
|
StatelessResetToken token;
|
|
memcpy(token.data(), range.data(), range.size());
|
|
return Optional<StatelessResetToken>(token);
|
|
}
|
|
|
|
folly::Expected<TransportParameter, QuicError> encodeIntegerParameter(
|
|
TransportParameterId id,
|
|
uint64_t value) {
|
|
BufPtr data = BufHelpers::create(8);
|
|
BufAppender appender(data.get(), 8);
|
|
auto encoded = encodeQuicInteger(
|
|
value, [appender = std::move(appender)](auto val) mutable {
|
|
appender.writeBE(val);
|
|
});
|
|
if (!encoded) {
|
|
return folly::makeUnexpected(QuicError(
|
|
TransportErrorCode::TRANSPORT_PARAMETER_ERROR,
|
|
"Invalid integer parameter"));
|
|
}
|
|
return TransportParameter{id, std::move(data)};
|
|
}
|
|
|
|
TransportParameter encodeIPAddressParameter(
|
|
TransportParameterId id,
|
|
const folly::IPAddress& addr) {
|
|
return {id, BufHelpers::copyBuffer(addr.bytes(), addr.byteCount())};
|
|
}
|
|
|
|
std::vector<TransportParameter> getSupportedExtTransportParams(
|
|
const QuicConnectionStateBase& conn) {
|
|
using TpId = TransportParameterId;
|
|
const auto& ts = conn.transportSettings;
|
|
|
|
std::vector<TransportParameter> customTps;
|
|
customTps.reserve(7);
|
|
|
|
if (ts.datagramConfig.enabled) {
|
|
auto result = encodeIntegerParameter(
|
|
TransportParameterId::max_datagram_frame_size,
|
|
conn.datagramState.maxReadFrameSize);
|
|
if (!result.hasError()) {
|
|
customTps.push_back(result.value());
|
|
}
|
|
}
|
|
|
|
if (ts.advertisedMaxStreamGroups > 0) {
|
|
auto result = encodeIntegerParameter(
|
|
TpId::stream_groups_enabled, ts.advertisedMaxStreamGroups);
|
|
if (!result.hasError()) {
|
|
customTps.push_back(result.value());
|
|
}
|
|
}
|
|
|
|
auto ackTimestampsResult = encodeIntegerParameter(
|
|
TpId::ack_receive_timestamps_enabled,
|
|
ts.maybeAckReceiveTimestampsConfigSentToPeer.has_value() ? 1 : 0);
|
|
if (!ackTimestampsResult.hasError()) {
|
|
customTps.push_back(ackTimestampsResult.value());
|
|
}
|
|
|
|
if (ts.maybeAckReceiveTimestampsConfigSentToPeer.has_value()) {
|
|
auto maxTimestampsResult = encodeIntegerParameter(
|
|
TpId::max_receive_timestamps_per_ack,
|
|
ts.maybeAckReceiveTimestampsConfigSentToPeer
|
|
->maxReceiveTimestampsPerAck);
|
|
if (!maxTimestampsResult.hasError()) {
|
|
customTps.push_back(maxTimestampsResult.value());
|
|
}
|
|
|
|
auto exponentResult = encodeIntegerParameter(
|
|
TpId::receive_timestamps_exponent,
|
|
ts.maybeAckReceiveTimestampsConfigSentToPeer
|
|
->receiveTimestampsExponent);
|
|
if (!exponentResult.hasError()) {
|
|
customTps.push_back(exponentResult.value());
|
|
}
|
|
}
|
|
|
|
if (ts.minAckDelay) {
|
|
auto minAckDelayResult = encodeIntegerParameter(
|
|
TpId::min_ack_delay, ts.minAckDelay.value().count());
|
|
if (!minAckDelayResult.hasError()) {
|
|
customTps.push_back(minAckDelayResult.value());
|
|
}
|
|
}
|
|
|
|
if (ts.advertisedKnobFrameSupport) {
|
|
auto knobFrameResult =
|
|
encodeIntegerParameter(TpId::knob_frames_supported, 1);
|
|
if (!knobFrameResult.hasError()) {
|
|
customTps.push_back(knobFrameResult.value());
|
|
}
|
|
}
|
|
|
|
if (ts.advertisedReliableResetStreamSupport) {
|
|
customTps.push_back(encodeEmptyParameter(TpId::reliable_stream_reset));
|
|
}
|
|
|
|
if (ts.advertisedExtendedAckFeatures) {
|
|
auto extendedAckResult = encodeIntegerParameter(
|
|
TpId::extended_ack_features, ts.advertisedExtendedAckFeatures);
|
|
if (!extendedAckResult.hasError()) {
|
|
customTps.push_back(extendedAckResult.value());
|
|
}
|
|
}
|
|
|
|
return customTps;
|
|
}
|
|
|
|
} // namespace quic
|