1 // Copyright 2022 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "quiche/quic/core/quic_stream_priority.h" 6 7 #include "quiche/common/platform/api/quiche_bug_tracker.h" 8 #include "quiche/common/structured_headers.h" 9 10 namespace quic { 11 SerializePriorityFieldValue(HttpStreamPriority priority)12std::string SerializePriorityFieldValue(HttpStreamPriority priority) { 13 quiche::structured_headers::Dictionary dictionary; 14 15 if (priority.urgency != HttpStreamPriority::kDefaultUrgency && 16 priority.urgency >= HttpStreamPriority::kMinimumUrgency && 17 priority.urgency <= HttpStreamPriority::kMaximumUrgency) { 18 dictionary[HttpStreamPriority::kUrgencyKey] = 19 quiche::structured_headers::ParameterizedMember( 20 quiche::structured_headers::Item( 21 static_cast<int64_t>(priority.urgency)), 22 {}); 23 } 24 25 if (priority.incremental != HttpStreamPriority::kDefaultIncremental) { 26 dictionary[HttpStreamPriority::kIncrementalKey] = 27 quiche::structured_headers::ParameterizedMember( 28 quiche::structured_headers::Item(priority.incremental), {}); 29 } 30 31 std::optional<std::string> priority_field_value = 32 quiche::structured_headers::SerializeDictionary(dictionary); 33 if (!priority_field_value.has_value()) { 34 QUICHE_BUG(priority_field_value_serialization_failed); 35 return ""; 36 } 37 38 return *priority_field_value; 39 } 40 ParsePriorityFieldValue(absl::string_view priority_field_value)41std::optional<HttpStreamPriority> ParsePriorityFieldValue( 42 absl::string_view priority_field_value) { 43 std::optional<quiche::structured_headers::Dictionary> parsed_dictionary = 44 quiche::structured_headers::ParseDictionary(priority_field_value); 45 if (!parsed_dictionary.has_value()) { 46 return std::nullopt; 47 } 48 49 uint8_t urgency = HttpStreamPriority::kDefaultUrgency; 50 bool incremental = HttpStreamPriority::kDefaultIncremental; 51 52 for (const auto& [name, value] : *parsed_dictionary) { 53 if (value.member_is_inner_list) { 54 continue; 55 } 56 57 const std::vector<quiche::structured_headers::ParameterizedItem>& member = 58 value.member; 59 if (member.size() != 1) { 60 // If `member_is_inner_list` is false above, 61 // then `member` should have exactly one element. 62 QUICHE_BUG(priority_field_value_parsing_internal_error); 63 continue; 64 } 65 66 const quiche::structured_headers::Item item = member[0].item; 67 if (name == HttpStreamPriority::kUrgencyKey && item.is_integer()) { 68 int parsed_urgency = item.GetInteger(); 69 // Ignore out-of-range values. 70 if (parsed_urgency >= HttpStreamPriority::kMinimumUrgency && 71 parsed_urgency <= HttpStreamPriority::kMaximumUrgency) { 72 urgency = parsed_urgency; 73 } 74 } else if (name == HttpStreamPriority::kIncrementalKey && 75 item.is_boolean()) { 76 incremental = item.GetBoolean(); 77 } 78 } 79 80 return HttpStreamPriority{urgency, incremental}; 81 } 82 83 } // namespace quic 84