1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-24 04:01:07 +03:00
Files
mvfst/quic/server/handshake/test/ServerTransportParametersTest.cpp
Aman Sharma 56c0231b9d Implement direct encap transport parameter negotiation + Fix build errors
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
2025-07-07 20:04:24 -07:00

239 lines
8.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 <algorithm>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <quic/QuicConstants.h>
#include <quic/common/test/TestUtils.h>
#include <quic/fizz/server/handshake/FizzServerQuicHandshakeContext.h>
#include <quic/server/handshake/ServerTransportParametersExtension.h>
#include <fizz/protocol/test/TestUtil.h>
using namespace fizz;
using namespace fizz::test;
namespace quic::test {
static ClientHello getClientHello(QuicVersion version) {
auto chlo = TestMessages::clientHello();
ClientTransportParameters clientParams;
auto paramResult =
encodeIntegerParameter(static_cast<TransportParameterId>(0xffff), 0xffff);
CHECK(!paramResult.hasError()) << "Failed to encode integer parameter";
clientParams.parameters.emplace_back(std::move(paramResult.value()));
chlo.extensions.push_back(encodeExtension(clientParams, version));
return chlo;
}
TEST(ServerTransportParametersTest, TestGetExtensions) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::MVFST,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createZeroLength(),
conn);
auto extensions = ext.getExtensions(getClientHello(QuicVersion::MVFST));
EXPECT_EQ(extensions.size(), 1);
auto serverParams = getServerExtension(extensions, QuicVersion::MVFST);
EXPECT_TRUE(serverParams.has_value());
}
TEST(ServerTransportParametersTest, TestGetExtensionsMissingClientParams) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::MVFST,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createZeroLength(),
conn);
EXPECT_THROW(ext.getExtensions(TestMessages::clientHello()), FizzException);
}
TEST(ServerTransportParametersTest, TestQuicV1RejectDraftExtensionNumber) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::QUIC_V1,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createZeroLength(),
conn);
EXPECT_THROW(
ext.getExtensions(getClientHello(QuicVersion::MVFST)), FizzException);
EXPECT_NO_THROW(ext.getExtensions(getClientHello(QuicVersion::QUIC_V1)));
}
TEST(ServerTransportParametersTest, TestQuicV1RejectDuplicateExtensions) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::QUIC_V1,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xfb, 0xfa, 0xf9, 0xf8}),
conn);
auto chlo = getClientHello(QuicVersion::QUIC_V1);
ClientTransportParameters duplicateClientParams;
auto paramResult =
encodeIntegerParameter(static_cast<TransportParameterId>(0xffff), 0xffff);
CHECK(!paramResult.hasError()) << "Failed to encode integer parameter";
duplicateClientParams.parameters.emplace_back(std::move(paramResult.value()));
chlo.extensions.push_back(
encodeExtension(duplicateClientParams, QuicVersion::QUIC_V1));
EXPECT_THROW(ext.getExtensions(chlo), FizzException);
}
TEST(ServerTransportParametersTest, TestQuicV1Fields) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::QUIC_V1,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xfb, 0xfa, 0xf9, 0xf8}),
conn);
auto extensions = ext.getExtensions(getClientHello(QuicVersion::QUIC_V1));
EXPECT_EQ(extensions.size(), 1);
auto serverParams = getServerExtension(extensions, QuicVersion::QUIC_V1);
EXPECT_TRUE(serverParams.has_value());
auto quicTransportParams = serverParams.value().parameters;
auto hasInitialSourceCid = std::any_of(
quicTransportParams.cbegin(),
quicTransportParams.cend(),
[](const TransportParameter& p) {
return p.parameter ==
TransportParameterId::initial_source_connection_id;
});
EXPECT_TRUE(hasInitialSourceCid);
auto hasOriginalDestCid = std::any_of(
quicTransportParams.cbegin(),
quicTransportParams.cend(),
[](const TransportParameter& p) {
return p.parameter ==
TransportParameterId::original_destination_connection_id;
});
EXPECT_TRUE(hasOriginalDestCid);
}
TEST(ServerTransportParametersTest, TestMvfstFields) {
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ServerTransportParametersExtension ext(
QuicVersion::MVFST,
kDefaultConnectionFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
kDefaultStreamFlowControlWindow,
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::max(),
/*disableMigration=*/true,
kDefaultIdleTimeout,
kDefaultAckDelayExponent,
kDefaultUDPSendPacketLen,
generateStatelessResetToken(),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xff, 0xfe, 0xfd, 0xfc}),
ConnectionId::createAndMaybeCrash(
std::vector<uint8_t>{0xfb, 0xfa, 0xf9, 0xf8}),
conn);
auto extensions = ext.getExtensions(getClientHello(QuicVersion::MVFST));
EXPECT_EQ(extensions.size(), 1);
auto serverParams = getServerExtension(extensions, QuicVersion::MVFST);
EXPECT_TRUE(serverParams.has_value());
auto quicTransportParams = serverParams.value().parameters;
auto hasInitialSourceCid = std::any_of(
quicTransportParams.cbegin(),
quicTransportParams.cend(),
[](const TransportParameter& p) {
return p.parameter ==
TransportParameterId::initial_source_connection_id;
});
EXPECT_FALSE(hasInitialSourceCid);
auto hasOriginalDestCid = std::any_of(
quicTransportParams.cbegin(),
quicTransportParams.cend(),
[](const TransportParameter& p) {
return p.parameter ==
TransportParameterId::original_destination_connection_id;
});
EXPECT_FALSE(hasOriginalDestCid);
}
} // namespace quic::test