Skip to content

Commit 51963b7

Browse files
afrindmeta-codesync[bot]
authored andcommitted
Unify ClientSetup/ServerSetup into Setup
Summary: MOQT draft-15+ negotiates version via ALPN rather than in the setup messages themselves, making the `supportedVersions` vector in ClientSetup and `selectedVersion` in ServerSetup redundant for modern drafts. Draft-14 (legacy/moq-00) is the only pre-ALPN version we support. This change unifies `ClientSetup` and `ServerSetup` into a single `Setup` struct (aliases kept for compat), removing the version fields from the structs and moving version handling into the framer/codec layer. Key changes: - Add `Setup` struct; alias `ClientSetup`/`ServerSetup` to it - Framer: `writeClientSetup`/`writeServerSetup` take an explicit version param; write version on wire only in legacy mode (draft < 15), with XCHECK_EQ that version is draft-14 - Framer: `parseClientSetup` in legacy mode requires draft-14 in the client's version array (VERSION_NEGOTIATION_FAILED if absent); `parseServerSetup` in legacy mode validates server selected draft-14 - Session: `setup(Setup)` replaces `setup(ClientSetup)`; version initialized from ALPN or hardcoded to draft-14 for legacy - Remove `shouldSendAuthorityParam()` and `shouldIncludeMoqtImplementationParam()` helpers; inline their logic - mlog: unify `MOQTClientSetupMessage`/`MOQTServerSetupMessage` into `MOQTSetupMessage`; log version alongside setup params - Tests: add framer helpers (`makeLegacyClientSetupFrame`, `makeLegacyServerSetupFrame`, `skipFrameHeader`) and version validation tests Reviewed By: sharmafb Differential Revision: D95678227 fbshipit-source-id: 48c4f15ff0ed14533a405b15f83727835373a1dc
1 parent 38593c3 commit 51963b7

21 files changed

Lines changed: 316 additions & 389 deletions

moxygen/MoQClientBase.cpp

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,6 @@
1313
#include <utility>
1414

1515
namespace moxygen {
16-
/*static*/
17-
bool MoQClientBase::shouldSendAuthorityParam(
18-
const std::vector<uint64_t>& supportedVersions) {
19-
for (const auto& version : supportedVersions) {
20-
if (getDraftMajorVersion(version) >= 14) {
21-
return true;
22-
}
23-
}
24-
return false;
25-
}
2616

2717
folly::coro::Task<void> MoQClientBase::setupMoQSession(
2818
std::chrono::milliseconds connect_timeout,
@@ -91,7 +81,7 @@ folly::coro::Task<void> MoQClientBase::setupMoQSession(
9181
}
9282
}
9383

94-
folly::coro::Task<ServerSetup> MoQClientBase::completeSetupMoQSession(
84+
folly::coro::Task<Setup> MoQClientBase::completeSetupMoQSession(
9585
proxygen::WebTransport* wt,
9686
const std::optional<std::string>& pathParam,
9787
std::shared_ptr<Publisher> publishHandler,
@@ -116,21 +106,21 @@ folly::coro::Task<ServerSetup> MoQClientBase::completeSetupMoQSession(
116106
moqSession_->start();
117107
ClientSetup clientSetup = getClientSetup(pathParam);
118108
if (logger_) {
119-
logger_->logClientSetup(clientSetup);
109+
logger_->logClientSetup(
110+
clientSetup,
111+
moqSession_->getNegotiatedVersion().value_or(kVersionDraft14));
120112
}
121113
return moqSession_->setup(clientSetup);
122114
}
123115

124-
ClientSetup MoQClientBase::getClientSetup(
125-
const std::optional<std::string>& path) {
116+
Setup MoQClientBase::getClientSetup(const std::optional<std::string>& path) {
126117
// Setup MoQSession parameters
127118
// TODO: maybe let the caller set max subscribes. Any client that publishes
128119
// via relay needs to support subscribes.
129120
const uint32_t kDefaultMaxRequestID = 100;
130121
const uint32_t kMaxAuthTokenCacheSize = 1024;
131122

132-
const auto& legacyVersions = getSupportedLegacyVersions();
133-
ClientSetup clientSetup{.supportedVersions = legacyVersions};
123+
Setup clientSetup;
134124
clientSetup.params.insertParam(Parameter(
135125
folly::to_underlying(SetupKey::MAX_REQUEST_ID), kDefaultMaxRequestID));
136126
clientSetup.params.insertParam(Parameter(
@@ -142,18 +132,16 @@ ClientSetup MoQClientBase::getClientSetup(
142132
SetupParameter(folly::to_underlying(SetupKey::PATH), *path));
143133
}
144134

145-
if (shouldSendAuthorityParam(clientSetup.supportedVersions)) {
146-
// Add AUTHORITY parameter for Direct QUIC with moqt:// scheme only
147-
if (path.has_value() && url_.getScheme() == "moqt") {
148-
// Extract authority from URI as per RFC 3986
149-
std::string authority = url_.getHost();
150-
if (url_.getPort() != 0 && url_.getPort() != 443) {
151-
authority += ":" + std::to_string(url_.getPort());
152-
}
153-
154-
clientSetup.params.insertParam(
155-
SetupParameter(folly::to_underlying(SetupKey::AUTHORITY), authority));
135+
// Add AUTHORITY parameter for Direct QUIC with moqt:// scheme only
136+
if (path.has_value() && url_.getScheme() == "moqt") {
137+
// Extract authority from URI as per RFC 3986
138+
std::string authority = url_.getHost();
139+
if (url_.getPort() != 0 && url_.getPort() != 443) {
140+
authority += ":" + std::to_string(url_.getPort());
156141
}
142+
143+
clientSetup.params.insertParam(
144+
SetupParameter(folly::to_underlying(SetupKey::AUTHORITY), authority));
157145
}
158146

159147
return clientSetup;

moxygen/MoQClientBase.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ class MoQClientBase : public proxygen::WebTransportHandler {
8686
std::shared_ptr<MLogger> logger_ = nullptr;
8787

8888
protected:
89-
static bool shouldSendAuthorityParam(
90-
const std::vector<uint64_t>& supportedVersions);
9189
virtual folly::coro::Task<std::shared_ptr<quic::QuicClientTransport>>
9290
connectQuic(
9391
folly::SocketAddress connectAddr,
@@ -101,12 +99,12 @@ class MoQClientBase : public proxygen::WebTransportHandler {
10199

102100
static SessionFactory defaultSessionFactory();
103101

104-
folly::coro::Task<ServerSetup> completeSetupMoQSession(
102+
folly::coro::Task<Setup> completeSetupMoQSession(
105103
proxygen::WebTransport* wt,
106104
const std::optional<std::string>& pathParam,
107105
std::shared_ptr<Publisher> publishHandler,
108106
std::shared_ptr<Subscriber> subscribeHandler);
109-
ClientSetup getClientSetup(const std::optional<std::string>& path);
107+
Setup getClientSetup(const std::optional<std::string>& path);
110108

111109
void onSessionEnd(folly::Optional<uint32_t>) noexcept override;
112110
void onSessionDrain() noexcept override;

moxygen/MoQCodec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class MoQControlCodec : public MoQCodec {
7171
~ControlCallback() override = default;
7272

7373
virtual void onFrame(FrameType) {}
74-
virtual void onClientSetup(ClientSetup) {}
75-
virtual void onServerSetup(ServerSetup) {}
74+
virtual void onClientSetup(Setup) {}
75+
virtual void onServerSetup(Setup) {}
7676
virtual void onSubscribe(SubscribeRequest) {}
7777
virtual void onRequestUpdate(RequestUpdate) {}
7878
virtual void onSubscribeOk(SubscribeOk) {}

moxygen/MoQFramer.cpp

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,10 @@ folly::Expected<folly::Unit, ErrorCode> parseParams(
627627
return folly::unit;
628628
}
629629

630-
folly::Expected<ClientSetup, ErrorCode> MoQFrameParser::parseClientSetup(
630+
folly::Expected<Setup, ErrorCode> MoQFrameParser::parseClientSetup(
631631
folly::io::Cursor& cursor,
632632
size_t length) noexcept {
633-
ClientSetup clientSetup;
633+
Setup clientSetup;
634634
uint64_t serializationVersion = kVersionDraft14;
635635

636636
// Only parse version array when version is not initialized, i.e. alpn did not
@@ -642,20 +642,22 @@ folly::Expected<ClientSetup, ErrorCode> MoQFrameParser::parseClientSetup(
642642
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
643643
}
644644
length -= numVersions->second;
645+
bool foundDraft14 = false;
645646
for (auto i = 0ul; i < numVersions->first; i++) {
646647
auto version = quic::follyutils::decodeQuicInteger(cursor, length);
647648
if (!version) {
648649
XLOG(DBG4) << "parseClientSetup: UNDERFLOW on version";
649650
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
650651
}
651652
length -= version->second;
652-
if (!isSupportedVersion(version->first)) {
653-
XLOG(WARN) << "Peer advertised unsupported version " << version->first
654-
<< ", supported versions are: "
655-
<< getSupportedVersionsString();
656-
continue;
653+
if (getDraftMajorVersion(version->first) == 14) {
654+
foundDraft14 = true;
657655
}
658-
clientSetup.supportedVersions.push_back(version->first);
656+
}
657+
if (!foundDraft14) {
658+
XLOG(ERR) << "Draft-14 not found in ClientSetup version array"
659+
" (legacy mode only supports draft-14)";
660+
return folly::makeUnexpected(ErrorCode::VERSION_NEGOTIATION_FAILED);
659661
}
660662
} else {
661663
XLOG(DBG3)
@@ -688,10 +690,11 @@ folly::Expected<ClientSetup, ErrorCode> MoQFrameParser::parseClientSetup(
688690
return clientSetup;
689691
}
690692

691-
folly::Expected<ServerSetup, ErrorCode> MoQFrameParser::parseServerSetup(
693+
folly::Expected<Setup, ErrorCode> MoQFrameParser::parseServerSetup(
692694
folly::io::Cursor& cursor,
693695
size_t length) noexcept {
694-
ServerSetup serverSetup;
696+
Setup serverSetup;
697+
uint64_t serializationVersion = kVersionDraft14;
695698

696699
// Only parse version when version is not initialized, i.e. alpn did not
697700
// happen, or when version is initialized but is < 15 (in tests)
@@ -702,16 +705,17 @@ folly::Expected<ServerSetup, ErrorCode> MoQFrameParser::parseServerSetup(
702705
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
703706
}
704707
length -= version->second;
705-
if (!isSupportedVersion(version->first)) {
706-
XLOG(WARN) << "Peer advertised unsupported version " << version->first
707-
<< ", supported versions are: "
708-
<< getSupportedVersionsString();
709-
return folly::makeUnexpected(ErrorCode::PROTOCOL_VIOLATION);
708+
if (getDraftMajorVersion(version->first) != 14) {
709+
XLOG(ERR) << "Server selected version draft-"
710+
<< getDraftMajorVersion(version->first)
711+
<< " but we only offer draft-14 in legacy mode";
712+
return folly::makeUnexpected(ErrorCode::VERSION_NEGOTIATION_FAILED);
710713
}
711-
serverSetup.selectedVersion = version->first;
714+
serializationVersion = version->first;
712715
} else {
713716
XLOG(DBG3)
714717
<< "Skipped parsing version from wire for alpn ServerSetup message";
718+
serializationVersion = *version_;
715719
}
716720

717721
auto numParams = quic::follyutils::decodeQuicInteger(cursor, length);
@@ -724,7 +728,7 @@ folly::Expected<ServerSetup, ErrorCode> MoQFrameParser::parseServerSetup(
724728
auto res = parseParams(
725729
cursor,
726730
length,
727-
version_ ? *version_ : serverSetup.selectedVersion,
731+
serializationVersion,
728732
numParams->first,
729733
serverSetup.params,
730734
requestSpecificParams,
@@ -3500,7 +3504,7 @@ bool includeSetupParam(uint64_t version, SetupKey key) {
35003504

35013505
WriteResult writeClientSetup(
35023506
folly::IOBufQueue& writeBuf,
3503-
const ClientSetup& clientSetup,
3507+
const Setup& clientSetup,
35043508
uint64_t version) noexcept {
35053509
size_t size = 0;
35063510
bool error = false;
@@ -3509,17 +3513,12 @@ WriteResult writeClientSetup(
35093513
auto sizePtr = writeFrameHeader(writeBuf, frameType, error);
35103514

35113515
if (getDraftMajorVersion(version) < 15) {
3512-
// Check that all versions are supported
3513-
for (auto ver : clientSetup.supportedVersions) {
3514-
XCHECK(isSupportedVersion(ver))
3515-
<< "Version " << ver << " is not supported. Supported versions are: "
3516-
<< getSupportedVersionsString();
3517-
}
3518-
// Only write version array in non-alpn mode
3519-
writeVarint(writeBuf, clientSetup.supportedVersions.size(), size, error);
3520-
for (auto ver : clientSetup.supportedVersions) {
3521-
writeVarint(writeBuf, ver, size, error);
3522-
}
3516+
XCHECK_EQ(getDraftMajorVersion(version), 14u)
3517+
<< "Legacy mode only supports draft-14, got draft-"
3518+
<< getDraftMajorVersion(version);
3519+
// Only write version array in non-alpn mode, hardcode draft-14
3520+
writeVarint(writeBuf, 1, size, error);
3521+
writeVarint(writeBuf, kVersionDraft14, size, error);
35233522
} else {
35243523
XLOG(DBG3)
35253524
<< "Skipped writing versions to wire for alpn ClientSetup message";
@@ -3563,7 +3562,7 @@ WriteResult writeClientSetup(
35633562

35643563
WriteResult writeServerSetup(
35653564
folly::IOBufQueue& writeBuf,
3566-
const ServerSetup& serverSetup,
3565+
const Setup& serverSetup,
35673566
uint64_t version) noexcept {
35683567
size_t size = 0;
35693568
bool error = false;
@@ -3573,20 +3572,19 @@ WriteResult writeServerSetup(
35733572

35743573
// Only write selected version in non-alpn mode
35753574
if (getDraftMajorVersion(version) < 15) {
3576-
XCHECK(isSupportedVersion(serverSetup.selectedVersion))
3577-
<< "Supported version " << serverSetup.selectedVersion
3578-
<< ") is not supported. Supported versions are: "
3579-
<< getSupportedVersionsString();
3580-
writeVarint(writeBuf, serverSetup.selectedVersion, size, error);
3575+
XCHECK_EQ(getDraftMajorVersion(version), 14u)
3576+
<< "Legacy mode only supports draft-14, got draft-"
3577+
<< getDraftMajorVersion(version);
3578+
writeVarint(writeBuf, kVersionDraft14, size, error);
35813579
} else {
35823580
XLOG(DBG3)
3583-
<< "Skipped writing version to wire for alpn ClientSetup message";
3581+
<< "Skipped writing version to wire for alpn ServerSetup message";
35843582
}
35853583

35863584
// Collect params that should be included
35873585
std::vector<Parameter> filteredParams;
35883586
for (const auto& param : serverSetup.params) {
3589-
if (includeSetupParam(serverSetup.selectedVersion, SetupKey(param.key))) {
3587+
if (includeSetupParam(version, SetupKey(param.key))) {
35903588
filteredParams.push_back(param);
35913589
}
35923590
}

moxygen/MoQFramer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ class MoQFrameParser {
111111
T value;
112112
size_t bytesConsumed;
113113
};
114-
folly::Expected<ClientSetup, ErrorCode> parseClientSetup(
114+
folly::Expected<Setup, ErrorCode> parseClientSetup(
115115
folly::io::Cursor& cursor,
116116
size_t length) noexcept;
117117

118-
folly::Expected<ServerSetup, ErrorCode> parseServerSetup(
118+
folly::Expected<Setup, ErrorCode> parseServerSetup(
119119
folly::io::Cursor& cursor,
120120
size_t length) noexcept;
121121

@@ -435,12 +435,12 @@ TrackRequestParameter getAuthParam(
435435

436436
WriteResult writeClientSetup(
437437
folly::IOBufQueue& writeBuf,
438-
const ClientSetup& clientSetup,
438+
const Setup& clientSetup,
439439
uint64_t version) noexcept;
440440

441441
WriteResult writeServerSetup(
442442
folly::IOBufQueue& writeBuf,
443-
const ServerSetup& serverSetup,
443+
const Setup& serverSetup,
444444
uint64_t version) noexcept;
445445

446446
// writeClientSetup and writeServerSetup are the only two functions that

moxygen/MoQServerBase.cpp

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,54 +46,26 @@ folly::coro::Task<void> MoQServerBase::handleClientSession(
4646
terminateClientSession(std::move(clientSession));
4747
}
4848

49-
folly::Try<ServerSetup> MoQServerBase::onClientSetup(
50-
ClientSetup setup,
49+
folly::Try<Setup> MoQServerBase::onClientSetup(
50+
Setup setup,
5151
const std::shared_ptr<MoQSession>& session) {
5252
XLOG(DBG1) << "MoQServerBase::ClientSetup";
5353

54-
uint64_t negotiatedVersion = 0;
55-
56-
// Check if version was negotiated via ALPN first (takes precedence)
54+
// Version is either negotiated via ALPN or defaults to draft-14
5755
auto sessionVersion = session->getNegotiatedVersion();
5856
if (sessionVersion) {
59-
// ALPN mode: use the ALPN-negotiated version
60-
negotiatedVersion = *sessionVersion;
6157
XLOG(DBG1)
6258
<< "MoQServerBase::ClientSetup: Using ALPN-negotiated version: moqt-"
63-
<< getDraftMajorVersion(negotiatedVersion);
64-
} else if (!setup.supportedVersions.empty()) {
65-
// Legacy mode: negotiate from version array in CLIENT_SETUP
66-
// Iterate over supported versions and set the highest version within the
67-
// range
68-
uint64_t highestVersion = 0;
69-
for (const auto& version : setup.supportedVersions) {
70-
if (getDraftMajorVersion(version) >= 15) {
71-
XLOG(WARN) << "MoQServerBase::ClientSetup: Skiping version " << version
72-
<< " (which needs alpn negotiation), to attempt fallback.";
73-
continue;
74-
}
75-
if (isSupportedVersion(version)) {
76-
highestVersion = std::max(highestVersion, version);
77-
}
78-
}
79-
if (highestVersion == 0) {
80-
std::string errorMessage = folly::to<std::string>(
81-
"The only supported versions in client_setup are ",
82-
getSupportedVersionsString());
83-
return folly::Try<ServerSetup>(std::runtime_error(errorMessage));
84-
}
85-
negotiatedVersion = highestVersion;
59+
<< getDraftMajorVersion(*sessionVersion);
8660
} else {
87-
// No version available from either ALPN or CLIENT_SETUP
88-
return folly::Try<ServerSetup>(
89-
std::runtime_error("No version negotiated via ALPN or CLIENT_SETUP"));
61+
XLOG(DBG1) << "MoQServerBase::ClientSetup: No ALPN, using draft-14";
9062
}
9163

9264
// TODO: Make the default MAX_REQUEST_ID configurable and
9365
// take in the value from ClientSetup
9466
static constexpr size_t kDefaultMaxRequestID = 100;
9567
static constexpr size_t kMaxAuthTokenCacheSize = 1024;
96-
ServerSetup serverSetup{.selectedVersion = negotiatedVersion};
68+
Setup serverSetup;
9769
serverSetup.params.insertParam(
9870
Parameter{
9971
folly::to_underlying(SetupKey::MAX_REQUEST_ID),
@@ -105,15 +77,16 @@ folly::Try<ServerSetup> MoQServerBase::onClientSetup(
10577

10678
// Log Server Setup
10779
if (auto logger = session->getLogger()) {
108-
logger->logServerSetup(serverSetup);
80+
logger->logServerSetup(
81+
serverSetup, sessionVersion.value_or(kVersionDraft14));
10982
}
11083

111-
return folly::Try<ServerSetup>(serverSetup);
84+
return folly::Try<Setup>(serverSetup);
11285
}
11386

11487
folly::Expected<folly::Unit, SessionCloseErrorCode>
11588
MoQServerBase::validateAuthority(
116-
const ClientSetup& setup,
89+
const Setup& setup,
11790
uint64_t negotiatedVersion,
11891
std::shared_ptr<MoQSession>) {
11992
if (getDraftMajorVersion(negotiatedVersion) >= 14) {

moxygen/MoQServerBase.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ class MoQServerBase : public MoQSession::ServerSetupCallback {
5959
void setMLoggerFactory(std::shared_ptr<MLoggerFactory> factory);
6060

6161
// ServerSetupCallback overrides
62-
folly::Try<ServerSetup> onClientSetup(
63-
ClientSetup clientSetup,
62+
folly::Try<Setup> onClientSetup(
63+
Setup clientSetup,
6464
const std::shared_ptr<MoQSession>& session) override;
6565

6666
folly::Expected<folly::Unit, SessionCloseErrorCode> validateAuthority(
67-
const ClientSetup& clientSetup,
67+
const Setup& clientSetup,
6868
uint64_t negotiatedVersion,
6969
std::shared_ptr<MoQSession> session) override;
7070

0 commit comments

Comments
 (0)