Skip to content

Commit c589b34

Browse files
martindukecopybara-github
authored andcommitted
Change MOQT key-value pair lists to have diff-encoded keys.
(Part of draft-16 update) PiperOrigin-RevId: 853808195
1 parent a8b5dbc commit c589b34

File tree

6 files changed

+84
-91
lines changed

6 files changed

+84
-91
lines changed

quiche/quic/moqt/moqt_framer.cc

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,28 +82,34 @@ class WireKeyValuePairList {
8282

8383
size_t GetLengthOnWire() {
8484
size_t total = WireVarInt62(list_.size()).GetLengthOnWire();
85+
uint64_t last_key = 0;
8586
list_.ForEach(
8687
[&](uint64_t key, uint64_t value) {
87-
total += WireKeyVarIntPair(key, value).GetLengthOnWire();
88+
total += WireKeyVarIntPair(key - last_key, value).GetLengthOnWire();
89+
last_key = key;
8890
return true;
8991
},
9092
[&](uint64_t key, absl::string_view value) {
91-
total += WireKeyStringPair(key, value).GetLengthOnWire();
93+
total += WireKeyStringPair(key - last_key, value).GetLengthOnWire();
94+
last_key = key;
9295
return true;
9396
});
9497
return total;
9598
}
9699
absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
97100
WireVarInt62(list_.size()).SerializeIntoWriter(writer);
101+
uint64_t last_key = 0;
98102
list_.ForEach(
99103
[&](uint64_t key, uint64_t value) {
100-
absl::Status status =
101-
WireKeyVarIntPair(key, value).SerializeIntoWriter(writer);
104+
absl::Status status = WireKeyVarIntPair(key - last_key, value)
105+
.SerializeIntoWriter(writer);
106+
last_key = key;
102107
return quiche::IsWriterStatusOk(status);
103108
},
104109
[&](uint64_t key, absl::string_view value) {
105-
absl::Status status =
106-
WireKeyStringPair(key, value).SerializeIntoWriter(writer);
110+
absl::Status status = WireKeyStringPair(key - last_key, value)
111+
.SerializeIntoWriter(writer);
112+
last_key = key;
107113
return quiche::IsWriterStatusOk(status);
108114
});
109115
return absl::OkStatus();
@@ -250,7 +256,7 @@ void VersionSpecificParametersToKeyValuePairList(
250256
Serialize(WireVarInt62(AuthTokenAliasType::kUseValue),
251257
WireVarInt62(it.type), WireBytes(it.token));
252258
out.insert(VersionSpecificParameter::kAuthorizationToken,
253-
std::string(parameter_value.AsStringView()));
259+
parameter_value.AsStringView());
254260
}
255261
if (!parameters.delivery_timeout.IsInfinite()) {
256262
out.insert(

quiche/quic/moqt/moqt_messages.cc

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <cstdint>
1010
#include <string>
1111
#include <utility>
12+
#include <variant>
1213
#include <vector>
1314

1415
#include "absl/algorithm/container.h"
@@ -23,34 +24,21 @@
2324

2425
namespace moqt {
2526

26-
void KeyValuePairList::insert(uint64_t key, absl::string_view value) {
27-
if (key % 2 == 0) {
27+
void KeyValuePairList::insert(uint64_t key,
28+
std::variant<uint64_t, absl::string_view> value) {
29+
if (key % 2 == 0 && std::holds_alternative<absl::string_view>(value)) {
2830
QUICHE_BUG(key_value_pair_string_is_even) << "Key value pair of wrong type";
2931
return;
3032
}
31-
string_map_.emplace(key, value);
32-
}
33-
34-
void KeyValuePairList::insert(uint64_t key, uint64_t value) {
35-
if (key % 2 == 1) {
33+
if (key % 2 == 1 && std::holds_alternative<uint64_t>(value)) {
3634
QUICHE_BUG(key_value_pair_int_is_odd) << "Key value pair of wrong type";
3735
return;
3836
}
39-
integer_map_.emplace(key, value);
40-
}
41-
42-
size_t KeyValuePairList::count(uint64_t key) const {
43-
if (key % 2 == 0) {
44-
return integer_map_.count(key);
45-
}
46-
return string_map_.count(key);
47-
}
48-
49-
bool KeyValuePairList::contains(uint64_t key) const {
50-
if (key % 2 == 0) {
51-
return integer_map_.contains(key);
37+
if (key % 2 == 1) {
38+
map_.emplace(key, std::string(std::get<absl::string_view>(value)));
39+
} else {
40+
map_.emplace(key, std::get<uint64_t>(value));
5241
}
53-
return string_map_.contains(key);
5442
}
5543

5644
std::vector<uint64_t> KeyValuePairList::GetIntegers(uint64_t key) const {
@@ -59,9 +47,9 @@ std::vector<uint64_t> KeyValuePairList::GetIntegers(uint64_t key) const {
5947
return {};
6048
}
6149
std::vector<uint64_t> result;
62-
auto [range_start, range_end] = integer_map_.equal_range(key);
50+
auto [range_start, range_end] = map_.equal_range(key);
6351
for (auto& it = range_start; it != range_end; ++it) {
64-
result.push_back(it->second);
52+
result.push_back(std::get<uint64_t>(it->second));
6553
}
6654
return result;
6755
}
@@ -73,9 +61,9 @@ std::vector<absl::string_view> KeyValuePairList::GetStrings(
7361
return {};
7462
}
7563
std::vector<absl::string_view> result;
76-
auto [range_start, range_end] = string_map_.equal_range(key);
64+
auto [range_start, range_end] = map_.equal_range(key);
7765
for (auto& it = range_start; it != range_end; ++it) {
78-
result.push_back(it->second);
66+
result.push_back(std::get<std::string>(it->second));
7967
}
8068
return result;
8169
}

quiche/quic/moqt/moqt_messages.h

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -463,50 +463,49 @@ H AbslHashValue(H h, const Location& m) {
463463
// This class does not interpret the semantic meaning of the keys and values,
464464
// although it does accept various uint64_t-based enums to reduce the burden of
465465
// casting on the caller.
466+
// Keys must be ordered.
466467
class KeyValuePairList {
467468
public:
468469
KeyValuePairList() = default;
469-
size_t size() const { return integer_map_.size() + string_map_.size(); }
470-
void insert(VersionSpecificParameter key, uint64_t value) {
471-
insert(static_cast<uint64_t>(key), value);
472-
}
473-
void insert(SetupParameter key, uint64_t value) {
474-
insert(static_cast<uint64_t>(key), value);
475-
}
476-
void insert(VersionSpecificParameter key, absl::string_view value) {
470+
size_t size() const { return map_.size(); }
471+
472+
void insert(VersionSpecificParameter key,
473+
std::variant<uint64_t, absl::string_view> value) {
477474
insert(static_cast<uint64_t>(key), value);
478475
}
479-
void insert(SetupParameter key, absl::string_view value) {
476+
void insert(SetupParameter key,
477+
std::variant<uint64_t, absl::string_view> value) {
480478
insert(static_cast<uint64_t>(key), value);
481479
}
482-
void insert(uint64_t key, absl::string_view value);
483-
void insert(uint64_t key, uint64_t value);
480+
void insert(uint64_t key, std::variant<uint64_t, absl::string_view> value);
481+
484482
size_t count(VersionSpecificParameter key) const {
485-
return count(static_cast<uint64_t>(key));
483+
return map_.count(static_cast<uint64_t>(key));
486484
}
487485
size_t count(SetupParameter key) const {
488-
return count(static_cast<uint64_t>(key));
486+
return map_.count(static_cast<uint64_t>(key));
489487
}
488+
490489
bool contains(VersionSpecificParameter key) const {
491-
return contains(static_cast<uint64_t>(key));
490+
return map_.contains(static_cast<uint64_t>(key));
492491
}
493492
bool contains(SetupParameter key) const {
494-
return contains(static_cast<uint64_t>(key));
493+
return map_.contains(static_cast<uint64_t>(key));
495494
}
495+
496496
// If either of these callbacks returns false, ForEach will return early.
497497
using IntCallback = quiche::UnretainedCallback<bool(uint64_t, uint64_t)>;
498498
using StringCallback =
499499
quiche::UnretainedCallback<bool(uint64_t, absl::string_view)>;
500500
// Iterates through the whole list, and executes int_callback for each integer
501501
// value and string_callback for each string value.
502502
bool ForEach(IntCallback int_callback, StringCallback string_callback) const {
503-
for (const auto& [key, value] : integer_map_) {
504-
if (!int_callback(key, value)) {
505-
return false;
506-
}
507-
}
508-
for (const auto& [key, value] : string_map_) {
509-
if (!string_callback(key, value)) {
503+
for (const auto& [key, value] : map_) {
504+
if (std::holds_alternative<uint64_t>(value)) {
505+
if (!int_callback(key, std::get<uint64_t>(value))) {
506+
return false;
507+
}
508+
} else if (!string_callback(key, std::get<std::string>(value))) {
510509
return false;
511510
}
512511
}
@@ -525,18 +524,13 @@ class KeyValuePairList {
525524
std::vector<absl::string_view> GetStrings(SetupParameter key) const {
526525
return GetStrings(static_cast<uint64_t>(key));
527526
}
528-
void clear() {
529-
integer_map_.clear();
530-
string_map_.clear();
531-
}
527+
528+
void clear() { map_.clear(); }
532529

533530
private:
534-
size_t count(uint64_t key) const;
535-
bool contains(uint64_t key) const;
536531
std::vector<uint64_t> GetIntegers(uint64_t key) const;
537532
std::vector<absl::string_view> GetStrings(uint64_t key) const;
538-
absl::btree_multimap<uint64_t, uint64_t> integer_map_;
539-
absl::btree_multimap<uint64_t, std::string> string_map_;
533+
absl::btree_multimap<uint64_t, std::variant<uint64_t, std::string>> map_;
540534
};
541535

542536
// TODO(martinduke): Collapse both Setup messages into MoqtSessionParameters.

quiche/quic/moqt/moqt_parser.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,13 @@ bool ParseKeyValuePairList(quic::QuicDataReader& reader,
106106
if (!reader.ReadVarInt62(&num_params)) {
107107
return false;
108108
}
109+
uint64_t type = 0;
109110
for (uint64_t i = 0; i < num_params; ++i) {
110-
uint64_t type;
111-
if (!reader.ReadVarInt62(&type)) {
111+
uint64_t type_diff;
112+
if (!reader.ReadVarInt62(&type_diff)) {
112113
return false;
113114
}
115+
type += type_diff;
114116
if (type % 2 == 1) {
115117
absl::string_view bytes;
116118
if (!reader.ReadStringPieceVarInt62(&bytes)) {

quiche/quic/moqt/moqt_parser_test.cc

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,8 @@ TEST_F(MoqtMessageSpecificTest, ClientSetupMaxRequestIdAppearsTwice) {
494494
0x20, 0x00, 0x0d, 0x02, 0x01, 0x02, // versions
495495
0x03, // 3 params
496496
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
497-
0x02, 0x32, // max_request_id = 50
498-
0x02, 0x32, // max_request_id = 50
497+
0x01, 0x32, // max_request_id = 50
498+
0x00, 0x32, // max_request_id = 50
499499
};
500500
stream.Receive(absl::string_view(setup, sizeof(setup)), false);
501501
parser.ReadAndDispatchMessages();
@@ -512,8 +512,8 @@ TEST_F(MoqtMessageSpecificTest, ClientSetupAuthorizationTokenTagRegister) {
512512
0x20, 0x00, 0x13, 0x02, 0x01, 0x02, // versions
513513
0x03, // 3 params
514514
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
515-
0x02, 0x32, // max_request_id = 50
516-
0x03, 0x06, 0x01, 0x10, 0x00, 0x62, 0x61, 0x72, // REGISTER 0x01
515+
0x01, 0x32, // max_request_id = 50
516+
0x01, 0x06, 0x01, 0x10, 0x00, 0x62, 0x61, 0x72, // REGISTER 0x01
517517
};
518518
stream.Receive(absl::string_view(setup, sizeof(setup)), false);
519519
parser.ReadAndDispatchMessages();
@@ -562,7 +562,7 @@ TEST_F(MoqtMessageSpecificTest, SetupPathAppearsTwice) {
562562
0x20, 0x00, 0x0e, 0x02, 0x01, 0x02, // versions = 1, 2
563563
0x02, // 2 params
564564
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
565-
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
565+
0x00, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
566566
};
567567
stream.Receive(absl::string_view(setup, sizeof(setup)), false);
568568
parser.ReadAndDispatchMessages();
@@ -626,8 +626,8 @@ TEST_F(MoqtMessageSpecificTest, ServerSetupMaxRequestIdAppearsTwice) {
626626
0x20, 0x00, 0x0d, 0x02, 0x01, 0x02, // versions = 1, 2
627627
0x03, // 4 params
628628
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
629-
0x02, 0x32, // max_request_id = 50
630-
0x02, 0x32, // max_request_id = 50
629+
0x01, 0x32, // max_request_id = 50
630+
0x00, 0x32, // max_request_id = 50
631631
};
632632
stream.Receive(absl::string_view(setup, sizeof(setup)), false);
633633
parser.ReadAndDispatchMessages();
@@ -659,7 +659,7 @@ TEST_F(MoqtMessageSpecificTest, ServerSetupMalformedAuthority) {
659659
0x20, 0x00, 0x0e, 0x02, 0x01, 0x02, // versions = 1, 2
660660
0x02, // 2 params
661661
0x01, 0x03, 0x66, 0x6f, 0x6f, // path = "foo"
662-
0x05, 0x03, 0x66, 0x5c, 0x6f, // authority = "f\o"
662+
0x04, 0x03, 0x66, 0x5c, 0x6f, // authority = "f\o"
663663
};
664664
stream.Receive(absl::string_view(setup, sizeof(setup)), false);
665665
parser.ReadAndDispatchMessages();
@@ -679,7 +679,7 @@ TEST_F(MoqtMessageSpecificTest, UnknownParameterTwiceIsOk) {
679679
0x02, // filter_type = kLatestObject
680680
0x02, // two params
681681
0x1f, 0x03, 0x62, 0x61, 0x72, // 0x1f = "bar"
682-
0x1f, 0x03, 0x62, 0x61, 0x72, // 0x1f = "bar"
682+
0x00, 0x03, 0x62, 0x61, 0x72, // 0x1f = "bar"
683683
};
684684
stream.Receive(absl::string_view(subscribe, sizeof(subscribe)), false);
685685
parser.ReadAndDispatchMessages();
@@ -697,7 +697,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeDeliveryTimeoutTwice) {
697697
0x02, // filter_type = kLatestObject
698698
0x02, // two params
699699
0x02, 0x67, 0x10, // delivery_timeout = 10000
700-
0x02, 0x67, 0x10, // delivery_timeout = 10000
700+
0x00, 0x67, 0x10, // delivery_timeout = 10000
701701
};
702702
stream.Receive(absl::string_view(subscribe, sizeof(subscribe)), false);
703703
parser.ReadAndDispatchMessages();
@@ -717,7 +717,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeMaxCacheDurationTwice) {
717717
0x02, // filter_type = kLatestObject
718718
0x02, // two params
719719
0x04, 0x67, 0x10, // max_cache_duration = 10000
720-
0x04, 0x67, 0x10, // max_cache_duration = 10000
720+
0x00, 0x67, 0x10, // max_cache_duration = 10000
721721
};
722722
stream.Receive(absl::string_view(subscribe, sizeof(subscribe)), false);
723723
parser.ReadAndDispatchMessages();
@@ -852,7 +852,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeInvalidGroupOrder) {
852852
0x02,
853853
0x67,
854854
0x10, // delivery_timeout = 10000 ms
855-
0x03,
855+
0x01,
856856
0x05,
857857
0x03,
858858
0x00,
@@ -896,7 +896,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeInvalidForward) {
896896
0x02,
897897
0x67,
898898
0x10, // delivery_timeout = 10000 ms
899-
0x03,
899+
0x01,
900900
0x05,
901901
0x03,
902902
0x00,
@@ -940,7 +940,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeInvalidFilter) {
940940
0x02,
941941
0x67,
942942
0x10, // delivery_timeout = 10000 ms
943-
0x03,
943+
0x01,
944944
0x05,
945945
0x03,
946946
0x00,
@@ -964,7 +964,7 @@ TEST_F(MoqtMessageSpecificTest, SubscribeOkHasAuthorizationToken) {
964964
0x0c, 0x14, // largest_group_id = 12, largest_object_id = 20,
965965
0x02, // 2 parameters
966966
0x02, 0x67, 0x10, // delivery_timeout = 10000
967-
0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_token = "bar"
967+
0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_token = "bar"
968968
};
969969
stream.Receive(absl::string_view(subscribe_ok, sizeof(subscribe_ok)), false);
970970
parser.ReadAndDispatchMessages();
@@ -982,7 +982,7 @@ TEST_F(MoqtMessageSpecificTest, PublishNamespaceAuthorizationTokenTwice) {
982982
0x6f, 0x6f, // track_namespace = "foo"
983983
0x02, // 2 params
984984
0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization = "bar"
985-
0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization = "bar"
985+
0x00, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization = "bar"
986986
};
987987
stream.Receive(
988988
absl::string_view(publish_namespace, sizeof(publish_namespace)), false);
@@ -997,8 +997,8 @@ TEST_F(MoqtMessageSpecificTest, PublishNamespaceHasDeliveryTimeout) {
997997
0x06, 0x00, 0x11, 0x02, 0x01, 0x03, 0x66,
998998
0x6f, 0x6f, // track_namespace = "foo"
999999
0x02, // 2 params
1000-
0x03, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_info = "bar"
10011000
0x02, 0x67, 0x10, // delivery_timeout = 10000
1001+
0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72, // authorization_info = "bar"
10021002
};
10031003
stream.Receive(
10041004
absl::string_view(publish_namespace, sizeof(publish_namespace)), false);

0 commit comments

Comments
 (0)