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