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