• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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/http2/http2_constants.h"
6 
7 #include "absl/strings/str_cat.h"
8 #include "absl/strings/str_format.h"
9 #include "absl/strings/string_view.h"
10 #include "quiche/common/platform/api/quiche_flag_utils.h"
11 #include "quiche/common/platform/api/quiche_flags.h"
12 #include "quiche/common/platform/api/quiche_logging.h"
13 
14 namespace http2 {
15 
Http2FrameTypeToString(Http2FrameType v)16 std::string Http2FrameTypeToString(Http2FrameType v) {
17   switch (v) {
18     case Http2FrameType::DATA:
19       return "DATA";
20     case Http2FrameType::HEADERS:
21       return "HEADERS";
22     case Http2FrameType::PRIORITY:
23       return "PRIORITY";
24     case Http2FrameType::RST_STREAM:
25       return "RST_STREAM";
26     case Http2FrameType::SETTINGS:
27       return "SETTINGS";
28     case Http2FrameType::PUSH_PROMISE:
29       return "PUSH_PROMISE";
30     case Http2FrameType::PING:
31       return "PING";
32     case Http2FrameType::GOAWAY:
33       return "GOAWAY";
34     case Http2FrameType::WINDOW_UPDATE:
35       return "WINDOW_UPDATE";
36     case Http2FrameType::CONTINUATION:
37       return "CONTINUATION";
38     case Http2FrameType::ALTSVC:
39       return "ALTSVC";
40     case Http2FrameType::PRIORITY_UPDATE:
41       return "PRIORITY_UPDATE";
42   }
43   return absl::StrCat("UnknownFrameType(", static_cast<int>(v), ")");
44 }
45 
Http2FrameTypeToString(uint8_t v)46 std::string Http2FrameTypeToString(uint8_t v) {
47   return Http2FrameTypeToString(static_cast<Http2FrameType>(v));
48 }
49 
Http2FrameFlagsToString(Http2FrameType type,uint8_t flags)50 std::string Http2FrameFlagsToString(Http2FrameType type, uint8_t flags) {
51   std::string s;
52   // Closure to append flag name |v| to the std::string |s|,
53   // and to clear |bit| from |flags|.
54   auto append_and_clear = [&s, &flags](absl::string_view v, uint8_t bit) {
55     if (!s.empty()) {
56       s.push_back('|');
57     }
58     absl::StrAppend(&s, v);
59     flags ^= bit;
60   };
61   if (flags & 0x01) {
62     if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS) {
63       append_and_clear("END_STREAM", Http2FrameFlag::END_STREAM);
64     } else if (type == Http2FrameType::SETTINGS ||
65                type == Http2FrameType::PING) {
66       append_and_clear("ACK", Http2FrameFlag::ACK);
67     }
68   }
69   if (flags & 0x04) {
70     if (type == Http2FrameType::HEADERS ||
71         type == Http2FrameType::PUSH_PROMISE ||
72         type == Http2FrameType::CONTINUATION) {
73       append_and_clear("END_HEADERS", Http2FrameFlag::END_HEADERS);
74     }
75   }
76   if (flags & 0x08) {
77     if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
78         type == Http2FrameType::PUSH_PROMISE) {
79       append_and_clear("PADDED", Http2FrameFlag::PADDED);
80     }
81   }
82   if (flags & 0x20) {
83     if (type == Http2FrameType::HEADERS) {
84       append_and_clear("PRIORITY", Http2FrameFlag::PRIORITY);
85     }
86   }
87   if (flags != 0) {
88     append_and_clear(absl::StrFormat("0x%02x", flags), flags);
89   }
90   QUICHE_DCHECK_EQ(0, flags);
91   return s;
92 }
Http2FrameFlagsToString(uint8_t type,uint8_t flags)93 std::string Http2FrameFlagsToString(uint8_t type, uint8_t flags) {
94   return Http2FrameFlagsToString(static_cast<Http2FrameType>(type), flags);
95 }
96 
Http2ErrorCodeToString(uint32_t v)97 std::string Http2ErrorCodeToString(uint32_t v) {
98   switch (v) {
99     case 0x0:
100       return "NO_ERROR";
101     case 0x1:
102       return "PROTOCOL_ERROR";
103     case 0x2:
104       return "INTERNAL_ERROR";
105     case 0x3:
106       return "FLOW_CONTROL_ERROR";
107     case 0x4:
108       return "SETTINGS_TIMEOUT";
109     case 0x5:
110       return "STREAM_CLOSED";
111     case 0x6:
112       return "FRAME_SIZE_ERROR";
113     case 0x7:
114       return "REFUSED_STREAM";
115     case 0x8:
116       return "CANCEL";
117     case 0x9:
118       return "COMPRESSION_ERROR";
119     case 0xa:
120       return "CONNECT_ERROR";
121     case 0xb:
122       return "ENHANCE_YOUR_CALM";
123     case 0xc:
124       return "INADEQUATE_SECURITY";
125     case 0xd:
126       return "HTTP_1_1_REQUIRED";
127   }
128   return absl::StrCat("UnknownErrorCode(0x", absl::Hex(v), ")");
129 }
Http2ErrorCodeToString(Http2ErrorCode v)130 std::string Http2ErrorCodeToString(Http2ErrorCode v) {
131   return Http2ErrorCodeToString(static_cast<uint32_t>(v));
132 }
133 
Http2SettingsParameterToString(uint32_t v)134 std::string Http2SettingsParameterToString(uint32_t v) {
135   switch (v) {
136     case 0x1:
137       return "HEADER_TABLE_SIZE";
138     case 0x2:
139       return "ENABLE_PUSH";
140     case 0x3:
141       return "MAX_CONCURRENT_STREAMS";
142     case 0x4:
143       return "INITIAL_WINDOW_SIZE";
144     case 0x5:
145       return "MAX_FRAME_SIZE";
146     case 0x6:
147       return "MAX_HEADER_LIST_SIZE";
148   }
149   return absl::StrCat("UnknownSettingsParameter(0x", absl::Hex(v), ")");
150 }
Http2SettingsParameterToString(Http2SettingsParameter v)151 std::string Http2SettingsParameterToString(Http2SettingsParameter v) {
152   return Http2SettingsParameterToString(static_cast<uint32_t>(v));
153 }
154 
155 // Invalid HTTP/2 header names according to
156 // https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.2.
157 // TODO(b/78024822): Consider adding "upgrade" to this set.
158 constexpr char const* kHttp2InvalidHeaderNames[] = {
159     "connection",        "host", "keep-alive", "proxy-connection",
160     "transfer-encoding", "",
161 };
162 
163 constexpr char const* kHttp2InvalidHeaderNamesOld[] = {
164     "connection", "host", "keep-alive", "proxy-connection", "transfer-encoding",
165 };
166 
GetInvalidHttp2HeaderSet()167 const InvalidHeaderSet& GetInvalidHttp2HeaderSet() {
168   if (!GetQuicheReloadableFlag(quic, quic_verify_request_headers_2)) {
169     static const auto* invalid_header_set_old =
170         new InvalidHeaderSet(std::begin(http2::kHttp2InvalidHeaderNamesOld),
171                              std::end(http2::kHttp2InvalidHeaderNamesOld));
172     return *invalid_header_set_old;
173   }
174   QUICHE_RELOADABLE_FLAG_COUNT_N(quic_verify_request_headers_2, 3, 3);
175   static const auto* invalid_header_set =
176       new InvalidHeaderSet(std::begin(http2::kHttp2InvalidHeaderNames),
177                            std::end(http2::kHttp2InvalidHeaderNames));
178   return *invalid_header_set;
179 }
180 
181 }  // namespace http2
182