Skip to content

Commit fa9a481

Browse files
committed
Support legacy relay SUBSCRIBE_UPDATE
1 parent 75c2e6f commit fa9a481

2 files changed

Lines changed: 107 additions & 1 deletion

File tree

src/transport/moqt_session.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,62 @@ bool apply_subscribe_update(SubscribeMessage& subscribe, const SubscribeUpdateMe
385385
return true;
386386
}
387387

388+
bool decode_legacy_subscribe_update_message(std::span<const std::uint8_t> bytes,
389+
const std::map<std::string, PublishedTrack>& tracks_by_name,
390+
const std::map<std::uint64_t, SubscribeMessage>& pending_subscriptions,
391+
SubscribeUpdateMessage& message) {
392+
std::size_t offset = 0;
393+
std::uint64_t message_type = 0;
394+
if (!decode_varint(bytes, offset, message_type) || message_type != 0x02 || offset + 2 > bytes.size()) {
395+
return false;
396+
}
397+
398+
const std::size_t payload_length =
399+
(static_cast<std::size_t>(bytes[offset]) << 8) | static_cast<std::size_t>(bytes[offset + 1]);
400+
offset += 2;
401+
if (offset + payload_length != bytes.size() || payload_length != 7) {
402+
return false;
403+
}
404+
405+
std::size_t payload_offset = offset;
406+
std::uint64_t track_alias = 0;
407+
std::uint64_t start_group_id = 0;
408+
std::uint64_t start_object_id = 0;
409+
if (!decode_varint(bytes, payload_offset, track_alias) ||
410+
!decode_varint(bytes, payload_offset, start_group_id) ||
411+
!decode_varint(bytes, payload_offset, start_object_id) ||
412+
payload_offset + 4 != bytes.size()) {
413+
return false;
414+
}
415+
416+
const std::uint8_t subscriber_priority = bytes[payload_offset++];
417+
const std::uint8_t group_order = bytes[payload_offset++];
418+
const std::uint8_t parameter_or_filter = bytes[payload_offset++];
419+
const std::uint8_t forward = bytes[payload_offset++];
420+
if (group_order > 2 || forward > 1) {
421+
return false;
422+
}
423+
static_cast<void>(parameter_or_filter);
424+
425+
for (const auto& [request_id, subscribe] : pending_subscriptions) {
426+
const auto track_it = tracks_by_name.find(subscribe.track_name);
427+
if (track_it == tracks_by_name.end() || track_it->second.alias != track_alias) {
428+
continue;
429+
}
430+
431+
message.request_id = 0;
432+
message.subscription_request_id = request_id;
433+
message.start_group_id = static_cast<std::size_t>(start_group_id);
434+
message.start_object_id = static_cast<std::size_t>(start_object_id);
435+
message.end_group_plus_one = subscribe.filter_type == 0x04 ? (subscribe.end_group_id + 1) : 0;
436+
message.subscriber_priority = subscriber_priority;
437+
message.forward = forward;
438+
return true;
439+
}
440+
441+
return false;
442+
}
443+
388444
TransportStatus serve_subscriptions(PublisherTransport& transport,
389445
std::uint64_t control_stream_id,
390446
const openmoq::publisher::PublishPlan& plan,
@@ -425,7 +481,11 @@ TransportStatus serve_subscriptions(PublisherTransport& transport,
425481

426482
if (message_type == 0x02) {
427483
SubscribeUpdateMessage subscribe_update;
428-
if (!decode_subscribe_update_message(message_bytes, subscribe_update)) {
484+
if (!decode_subscribe_update_message(message_bytes, subscribe_update) &&
485+
!decode_legacy_subscribe_update_message(message_bytes,
486+
tracks_by_name,
487+
pending_subscriptions,
488+
subscribe_update)) {
429489
return TransportStatus::failure("received invalid SUBSCRIBE_UPDATE");
430490
}
431491
auto pending_it = pending_subscriptions.find(subscribe_update.subscription_request_id);

tests/moqt_session_test.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,23 @@ std::vector<std::uint8_t> encode_subscribe_update_message(std::uint64_t request_
213213
return message;
214214
}
215215

216+
std::vector<std::uint8_t> encode_legacy_subscribe_update_message(std::uint64_t track_alias) {
217+
std::vector<std::uint8_t> payload = encode_varint(track_alias);
218+
const std::vector<std::uint8_t> start_group = encode_varint(0);
219+
const std::vector<std::uint8_t> start_object = encode_varint(0);
220+
payload.insert(payload.end(), start_group.begin(), start_group.end());
221+
payload.insert(payload.end(), start_object.begin(), start_object.end());
222+
payload.push_back(0x80);
223+
payload.push_back(0x01);
224+
payload.push_back(0x10);
225+
payload.push_back(0x01);
226+
227+
std::vector<std::uint8_t> message = encode_varint(0x02);
228+
append_be16(message, static_cast<std::uint16_t>(payload.size()));
229+
message.insert(message.end(), payload.begin(), payload.end());
230+
return message;
231+
}
232+
216233
std::vector<std::uint8_t> encode_publish_ok_message(DraftVersion draft,
217234
std::uint64_t request_id,
218235
std::uint8_t forward = 1) {
@@ -571,6 +588,35 @@ int main() {
571588
}
572589
}
573590

591+
{
592+
MockTransport transport;
593+
transport.reads[0].push_back(encode_server_setup_message({
594+
.draft = DraftVersion::kDraft14,
595+
.max_request_id = 8,
596+
}));
597+
std::vector<std::uint8_t> interleaved_control = encode_publish_namespace_ok_message(DraftVersion::kDraft14, 0);
598+
const auto catalog_publish_ok = encode_publish_ok_message(DraftVersion::kDraft14, 2, 0);
599+
interleaved_control.insert(interleaved_control.end(), catalog_publish_ok.begin(), catalog_publish_ok.end());
600+
const auto catalog_subscribe = encode_subscribe_message(6, kTestTrackNamespace, "catalog", 0);
601+
interleaved_control.insert(interleaved_control.end(), catalog_subscribe.begin(), catalog_subscribe.end());
602+
const auto catalog_subscribe_update = encode_legacy_subscribe_update_message(0);
603+
interleaved_control.insert(interleaved_control.end(),
604+
catalog_subscribe_update.begin(),
605+
catalog_subscribe_update.end());
606+
const auto media_publish_ok = encode_publish_ok_message(DraftVersion::kDraft14, 4, 1);
607+
interleaved_control.insert(interleaved_control.end(), media_publish_ok.begin(), media_publish_ok.end());
608+
transport.reads[0].push_back(interleaved_control);
609+
MoqtSession session(transport, std::string(kTestTrackNamespace), true);
610+
611+
auto status = session.connect(endpoint, tls);
612+
ok &= expect(status.ok, "expected legacy update session connect to succeed");
613+
614+
const PublishPlan materialized =
615+
materialize_publish_plan(make_span_backed_plan(DraftVersion::kDraft14), source_bytes);
616+
status = session.publish(materialized);
617+
ok &= expect(status.ok, "expected publish to succeed with legacy alias-based SUBSCRIBE_UPDATE");
618+
}
619+
574620
{
575621
MockTransport transport;
576622
transport.reads[0].push_back(encode_server_setup_message({

0 commit comments

Comments
 (0)