OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_alt_svc_wire_format.h" | 5 #include "net/spdy/spdy_alt_svc_wire_format.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cctype> | 8 #include <cctype> |
9 #include <limits> | 9 #include <limits> |
10 #include <string> | |
11 | 10 |
12 #include "base/logging.h" | 11 #include "base/logging.h" |
13 #include "net/spdy/platform/api/spdy_string_utils.h" | 12 #include "net/spdy/platform/api/spdy_string_utils.h" |
14 | 13 |
15 namespace net { | 14 namespace net { |
16 | 15 |
17 namespace { | 16 namespace { |
18 | 17 |
19 template <class T> | 18 template <class T> |
20 bool ParsePositiveIntegerImpl(SpdyStringPiece::const_iterator c, | 19 bool ParsePositiveIntegerImpl(SpdyStringPiece::const_iterator c, |
(...skipping 11 matching lines...) Expand all Loading... |
32 *value += *c - '0'; | 31 *value += *c - '0'; |
33 } | 32 } |
34 return (c == end && *value > 0); | 33 return (c == end && *value > 0); |
35 } | 34 } |
36 | 35 |
37 } // namespace | 36 } // namespace |
38 | 37 |
39 SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {} | 38 SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {} |
40 | 39 |
41 SpdyAltSvcWireFormat::AlternativeService::AlternativeService( | 40 SpdyAltSvcWireFormat::AlternativeService::AlternativeService( |
42 const std::string& protocol_id, | 41 const SpdyString& protocol_id, |
43 const std::string& host, | 42 const SpdyString& host, |
44 uint16_t port, | 43 uint16_t port, |
45 uint32_t max_age, | 44 uint32_t max_age, |
46 VersionVector version) | 45 VersionVector version) |
47 : protocol_id(protocol_id), | 46 : protocol_id(protocol_id), |
48 host(host), | 47 host(host), |
49 port(port), | 48 port(port), |
50 max_age(max_age), | 49 max_age(max_age), |
51 version(version) {} | 50 version(version) {} |
52 | 51 |
53 SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {} | 52 SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {} |
(...skipping 11 matching lines...) Expand all Loading... |
65 } | 64 } |
66 altsvc_vector->clear(); | 65 altsvc_vector->clear(); |
67 if (value == SpdyStringPiece("clear")) { | 66 if (value == SpdyStringPiece("clear")) { |
68 return true; | 67 return true; |
69 } | 68 } |
70 SpdyStringPiece::const_iterator c = value.begin(); | 69 SpdyStringPiece::const_iterator c = value.begin(); |
71 while (c != value.end()) { | 70 while (c != value.end()) { |
72 // Parse protocol-id. | 71 // Parse protocol-id. |
73 SpdyStringPiece::const_iterator percent_encoded_protocol_id_end = | 72 SpdyStringPiece::const_iterator percent_encoded_protocol_id_end = |
74 std::find(c, value.end(), '='); | 73 std::find(c, value.end(), '='); |
75 std::string protocol_id; | 74 SpdyString protocol_id; |
76 if (percent_encoded_protocol_id_end == c || | 75 if (percent_encoded_protocol_id_end == c || |
77 !PercentDecode(c, percent_encoded_protocol_id_end, &protocol_id)) { | 76 !PercentDecode(c, percent_encoded_protocol_id_end, &protocol_id)) { |
78 return false; | 77 return false; |
79 } | 78 } |
80 c = percent_encoded_protocol_id_end; | 79 c = percent_encoded_protocol_id_end; |
81 if (c == value.end()) { | 80 if (c == value.end()) { |
82 return false; | 81 return false; |
83 } | 82 } |
84 // Parse alt-authority. | 83 // Parse alt-authority. |
85 DCHECK_EQ('=', *c); | 84 DCHECK_EQ('=', *c); |
(...skipping 10 matching lines...) Expand all Loading... |
96 } | 95 } |
97 ++c; | 96 ++c; |
98 if (c == value.end()) { | 97 if (c == value.end()) { |
99 return false; | 98 return false; |
100 } | 99 } |
101 } | 100 } |
102 if (c == alt_authority_begin || c == value.end()) { | 101 if (c == alt_authority_begin || c == value.end()) { |
103 return false; | 102 return false; |
104 } | 103 } |
105 DCHECK_EQ('"', *c); | 104 DCHECK_EQ('"', *c); |
106 std::string host; | 105 SpdyString host; |
107 uint16_t port; | 106 uint16_t port; |
108 if (!ParseAltAuthority(alt_authority_begin, c, &host, &port)) { | 107 if (!ParseAltAuthority(alt_authority_begin, c, &host, &port)) { |
109 return false; | 108 return false; |
110 } | 109 } |
111 ++c; | 110 ++c; |
112 // Parse parameters. | 111 // Parse parameters. |
113 uint32_t max_age = 86400; | 112 uint32_t max_age = 86400; |
114 VersionVector version; | 113 VersionVector version; |
115 SpdyStringPiece::const_iterator parameters_end = | 114 SpdyStringPiece::const_iterator parameters_end = |
116 std::find(c, value.end(), ','); | 115 std::find(c, value.end(), ','); |
117 while (c != parameters_end) { | 116 while (c != parameters_end) { |
118 SkipWhiteSpace(&c, parameters_end); | 117 SkipWhiteSpace(&c, parameters_end); |
119 if (c == parameters_end) { | 118 if (c == parameters_end) { |
120 break; | 119 break; |
121 } | 120 } |
122 if (*c != ';') { | 121 if (*c != ';') { |
123 return false; | 122 return false; |
124 } | 123 } |
125 ++c; | 124 ++c; |
126 SkipWhiteSpace(&c, parameters_end); | 125 SkipWhiteSpace(&c, parameters_end); |
127 if (c == parameters_end) { | 126 if (c == parameters_end) { |
128 break; | 127 break; |
129 } | 128 } |
130 std::string parameter_name; | 129 SpdyString parameter_name; |
131 for (; c != parameters_end && *c != '=' && *c != ' ' && *c != '\t'; ++c) { | 130 for (; c != parameters_end && *c != '=' && *c != ' ' && *c != '\t'; ++c) { |
132 parameter_name.push_back(tolower(*c)); | 131 parameter_name.push_back(tolower(*c)); |
133 } | 132 } |
134 SkipWhiteSpace(&c, parameters_end); | 133 SkipWhiteSpace(&c, parameters_end); |
135 if (c == parameters_end || *c != '=') { | 134 if (c == parameters_end || *c != '=') { |
136 return false; | 135 return false; |
137 } | 136 } |
138 ++c; | 137 ++c; |
139 SkipWhiteSpace(&c, parameters_end); | 138 SkipWhiteSpace(&c, parameters_end); |
140 SpdyStringPiece::const_iterator parameter_value_begin = c; | 139 SpdyStringPiece::const_iterator parameter_value_begin = c; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 } | 180 } |
182 } | 181 } |
183 altsvc_vector->emplace_back(protocol_id, host, port, max_age, version); | 182 altsvc_vector->emplace_back(protocol_id, host, port, max_age, version); |
184 for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { | 183 for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { |
185 } | 184 } |
186 } | 185 } |
187 return true; | 186 return true; |
188 } | 187 } |
189 | 188 |
190 // static | 189 // static |
191 std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | 190 SpdyString SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
192 const AlternativeServiceVector& altsvc_vector) { | 191 const AlternativeServiceVector& altsvc_vector) { |
193 if (altsvc_vector.empty()) { | 192 if (altsvc_vector.empty()) { |
194 return std::string("clear"); | 193 return SpdyString("clear"); |
195 } | 194 } |
196 const char kNibbleToHex[] = "0123456789ABCDEF"; | 195 const char kNibbleToHex[] = "0123456789ABCDEF"; |
197 std::string value; | 196 SpdyString value; |
198 for (const AlternativeService& altsvc : altsvc_vector) { | 197 for (const AlternativeService& altsvc : altsvc_vector) { |
199 if (!value.empty()) { | 198 if (!value.empty()) { |
200 value.push_back(','); | 199 value.push_back(','); |
201 } | 200 } |
202 // Percent escape protocol id according to | 201 // Percent escape protocol id according to |
203 // http://tools.ietf.org/html/rfc7230#section-3.2.6. | 202 // http://tools.ietf.org/html/rfc7230#section-3.2.6. |
204 for (char c : altsvc.protocol_id) { | 203 for (char c : altsvc.protocol_id) { |
205 if (isalnum(c)) { | 204 if (isalnum(c)) { |
206 value.push_back(c); | 205 value.push_back(c); |
207 continue; | 206 continue; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 // static | 260 // static |
262 void SpdyAltSvcWireFormat::SkipWhiteSpace(SpdyStringPiece::const_iterator* c, | 261 void SpdyAltSvcWireFormat::SkipWhiteSpace(SpdyStringPiece::const_iterator* c, |
263 SpdyStringPiece::const_iterator end) { | 262 SpdyStringPiece::const_iterator end) { |
264 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { | 263 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { |
265 } | 264 } |
266 } | 265 } |
267 | 266 |
268 // static | 267 // static |
269 bool SpdyAltSvcWireFormat::PercentDecode(SpdyStringPiece::const_iterator c, | 268 bool SpdyAltSvcWireFormat::PercentDecode(SpdyStringPiece::const_iterator c, |
270 SpdyStringPiece::const_iterator end, | 269 SpdyStringPiece::const_iterator end, |
271 std::string* output) { | 270 SpdyString* output) { |
272 output->clear(); | 271 output->clear(); |
273 for (; c != end; ++c) { | 272 for (; c != end; ++c) { |
274 if (*c != '%') { | 273 if (*c != '%') { |
275 output->push_back(*c); | 274 output->push_back(*c); |
276 continue; | 275 continue; |
277 } | 276 } |
278 DCHECK_EQ('%', *c); | 277 DCHECK_EQ('%', *c); |
279 ++c; | 278 ++c; |
280 if (c == end || !std::isxdigit(*c)) { | 279 if (c == end || !std::isxdigit(*c)) { |
281 return false; | 280 return false; |
282 } | 281 } |
283 // Network byte order is big-endian. | 282 // Network byte order is big-endian. |
284 char decoded = SpdyHexDigitToInt(*c) << 4; | 283 char decoded = SpdyHexDigitToInt(*c) << 4; |
285 ++c; | 284 ++c; |
286 if (c == end || !std::isxdigit(*c)) { | 285 if (c == end || !std::isxdigit(*c)) { |
287 return false; | 286 return false; |
288 } | 287 } |
289 decoded += SpdyHexDigitToInt(*c); | 288 decoded += SpdyHexDigitToInt(*c); |
290 output->push_back(decoded); | 289 output->push_back(decoded); |
291 } | 290 } |
292 return true; | 291 return true; |
293 } | 292 } |
294 | 293 |
295 // static | 294 // static |
296 bool SpdyAltSvcWireFormat::ParseAltAuthority( | 295 bool SpdyAltSvcWireFormat::ParseAltAuthority( |
297 SpdyStringPiece::const_iterator c, | 296 SpdyStringPiece::const_iterator c, |
298 SpdyStringPiece::const_iterator end, | 297 SpdyStringPiece::const_iterator end, |
299 std::string* host, | 298 SpdyString* host, |
300 uint16_t* port) { | 299 uint16_t* port) { |
301 host->clear(); | 300 host->clear(); |
302 if (c == end) { | 301 if (c == end) { |
303 return false; | 302 return false; |
304 } | 303 } |
305 if (*c == '[') { | 304 if (*c == '[') { |
306 for (; c != end && *c != ']'; ++c) { | 305 for (; c != end && *c != ']'; ++c) { |
307 if (*c == '"') { | 306 if (*c == '"') { |
308 // Port is mandatory. | 307 // Port is mandatory. |
309 return false; | 308 return false; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 348 |
350 // static | 349 // static |
351 bool SpdyAltSvcWireFormat::ParsePositiveInteger32( | 350 bool SpdyAltSvcWireFormat::ParsePositiveInteger32( |
352 SpdyStringPiece::const_iterator c, | 351 SpdyStringPiece::const_iterator c, |
353 SpdyStringPiece::const_iterator end, | 352 SpdyStringPiece::const_iterator end, |
354 uint32_t* value) { | 353 uint32_t* value) { |
355 return ParsePositiveIntegerImpl<uint32_t>(c, end, value); | 354 return ParsePositiveIntegerImpl<uint32_t>(c, end, value); |
356 } | 355 } |
357 | 356 |
358 } // namespace net | 357 } // namespace net |
OLD | NEW |