xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_tag.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2016 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_tag.h"
6 
7 #include <algorithm>
8 #include <string>
9 
10 #include "absl/base/macros.h"
11 #include "absl/strings/ascii.h"
12 #include "absl/strings/escaping.h"
13 #include "absl/strings/str_split.h"
14 #include "quiche/quic/platform/api/quic_flag_utils.h"
15 #include "quiche/quic/platform/api/quic_flags.h"
16 #include "quiche/common/quiche_text_utils.h"
17 
18 namespace quic {
19 
FindMutualQuicTag(const QuicTagVector & our_tags,const QuicTagVector & their_tags,QuicTag * out_result,size_t * out_index)20 bool FindMutualQuicTag(const QuicTagVector& our_tags,
21                        const QuicTagVector& their_tags, QuicTag* out_result,
22                        size_t* out_index) {
23   const size_t num_our_tags = our_tags.size();
24   const size_t num_their_tags = their_tags.size();
25   for (size_t i = 0; i < num_our_tags; i++) {
26     for (size_t j = 0; j < num_their_tags; j++) {
27       if (our_tags[i] == their_tags[j]) {
28         *out_result = our_tags[i];
29         if (out_index != nullptr) {
30           *out_index = j;
31         }
32         return true;
33       }
34     }
35   }
36 
37   return false;
38 }
39 
QuicTagToString(QuicTag tag)40 std::string QuicTagToString(QuicTag tag) {
41   if (tag == 0) {
42     return "0";
43   }
44   char chars[sizeof tag];
45   bool ascii = true;
46   const QuicTag orig_tag = tag;
47 
48   for (size_t i = 0; i < ABSL_ARRAYSIZE(chars); i++) {
49     chars[i] = static_cast<char>(tag);
50     if ((chars[i] == 0 || chars[i] == '\xff') &&
51         i == ABSL_ARRAYSIZE(chars) - 1) {
52       chars[i] = ' ';
53     }
54     if (!absl::ascii_isprint(static_cast<unsigned char>(chars[i]))) {
55       ascii = false;
56       break;
57     }
58     tag >>= 8;
59   }
60 
61   if (ascii) {
62     return std::string(chars, sizeof(chars));
63   }
64 
65   return absl::BytesToHexString(absl::string_view(
66       reinterpret_cast<const char*>(&orig_tag), sizeof(orig_tag)));
67 }
68 
MakeQuicTag(uint8_t a,uint8_t b,uint8_t c,uint8_t d)69 uint32_t MakeQuicTag(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
70   return static_cast<uint32_t>(a) | static_cast<uint32_t>(b) << 8 |
71          static_cast<uint32_t>(c) << 16 | static_cast<uint32_t>(d) << 24;
72 }
73 
ContainsQuicTag(const QuicTagVector & tag_vector,QuicTag tag)74 bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) {
75   return std::find(tag_vector.begin(), tag_vector.end(), tag) !=
76          tag_vector.end();
77 }
78 
ParseQuicTag(absl::string_view tag_string)79 QuicTag ParseQuicTag(absl::string_view tag_string) {
80   quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&tag_string);
81   std::string tag_bytes;
82   if (tag_string.length() == 8) {
83     tag_bytes = absl::HexStringToBytes(tag_string);
84     tag_string = tag_bytes;
85   }
86   QuicTag tag = 0;
87   // Iterate over every character from right to left.
88   for (auto it = tag_string.rbegin(); it != tag_string.rend(); ++it) {
89     // The cast here is required on platforms where char is signed.
90     unsigned char token_char = static_cast<unsigned char>(*it);
91     tag <<= 8;
92     tag |= token_char;
93   }
94   return tag;
95 }
96 
ParseQuicTagVector(absl::string_view tags_string)97 QuicTagVector ParseQuicTagVector(absl::string_view tags_string) {
98   QuicTagVector tag_vector;
99   quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&tags_string);
100   if (!tags_string.empty()) {
101     std::vector<absl::string_view> tag_strings =
102         absl::StrSplit(tags_string, ',');
103     for (absl::string_view tag_string : tag_strings) {
104       tag_vector.push_back(ParseQuicTag(tag_string));
105     }
106   }
107   return tag_vector;
108 }
109 
110 }  // namespace quic
111