Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Side by Side Diff: net/spdy/spdy_alt_svc_wire_format.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_alt_svc_wire_format.h ('k') | net/spdy/spdy_alt_svc_wire_format_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/spdy/spdy_alt_svc_wire_format.h"
6
7 #include <algorithm>
8 #include <cctype>
9 #include <limits>
10
11 #include "base/logging.h"
12 #include "net/spdy/platform/api/spdy_string_utils.h"
13
14 namespace net {
15
16 namespace {
17
18 template <class T>
19 bool ParsePositiveIntegerImpl(SpdyStringPiece::const_iterator c,
20 SpdyStringPiece::const_iterator end,
21 T* value) {
22 *value = 0;
23 for (; c != end && std::isdigit(*c); ++c) {
24 if (*value > std::numeric_limits<T>::max() / 10) {
25 return false;
26 }
27 *value *= 10;
28 if (*value > std::numeric_limits<T>::max() - (*c - '0')) {
29 return false;
30 }
31 *value += *c - '0';
32 }
33 return (c == end && *value > 0);
34 }
35
36 } // namespace
37
38 SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {}
39
40 SpdyAltSvcWireFormat::AlternativeService::AlternativeService(
41 const SpdyString& protocol_id,
42 const SpdyString& host,
43 uint16_t port,
44 uint32_t max_age,
45 VersionVector version)
46 : protocol_id(protocol_id),
47 host(host),
48 port(port),
49 max_age(max_age),
50 version(version) {}
51
52 SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {}
53
54 SpdyAltSvcWireFormat::AlternativeService::AlternativeService(
55 const AlternativeService& other) = default;
56
57 // static
58 bool SpdyAltSvcWireFormat::ParseHeaderFieldValue(
59 SpdyStringPiece value,
60 AlternativeServiceVector* altsvc_vector) {
61 // Empty value is invalid according to the specification.
62 if (value.empty()) {
63 return false;
64 }
65 altsvc_vector->clear();
66 if (value == SpdyStringPiece("clear")) {
67 return true;
68 }
69 SpdyStringPiece::const_iterator c = value.begin();
70 while (c != value.end()) {
71 // Parse protocol-id.
72 SpdyStringPiece::const_iterator percent_encoded_protocol_id_end =
73 std::find(c, value.end(), '=');
74 SpdyString protocol_id;
75 if (percent_encoded_protocol_id_end == c ||
76 !PercentDecode(c, percent_encoded_protocol_id_end, &protocol_id)) {
77 return false;
78 }
79 c = percent_encoded_protocol_id_end;
80 if (c == value.end()) {
81 return false;
82 }
83 // Parse alt-authority.
84 DCHECK_EQ('=', *c);
85 ++c;
86 if (c == value.end() || *c != '"') {
87 return false;
88 }
89 ++c;
90 SpdyStringPiece::const_iterator alt_authority_begin = c;
91 for (; c != value.end() && *c != '"'; ++c) {
92 // Decode backslash encoding.
93 if (*c != '\\') {
94 continue;
95 }
96 ++c;
97 if (c == value.end()) {
98 return false;
99 }
100 }
101 if (c == alt_authority_begin || c == value.end()) {
102 return false;
103 }
104 DCHECK_EQ('"', *c);
105 SpdyString host;
106 uint16_t port;
107 if (!ParseAltAuthority(alt_authority_begin, c, &host, &port)) {
108 return false;
109 }
110 ++c;
111 // Parse parameters.
112 uint32_t max_age = 86400;
113 VersionVector version;
114 SpdyStringPiece::const_iterator parameters_end =
115 std::find(c, value.end(), ',');
116 while (c != parameters_end) {
117 SkipWhiteSpace(&c, parameters_end);
118 if (c == parameters_end) {
119 break;
120 }
121 if (*c != ';') {
122 return false;
123 }
124 ++c;
125 SkipWhiteSpace(&c, parameters_end);
126 if (c == parameters_end) {
127 break;
128 }
129 SpdyString parameter_name;
130 for (; c != parameters_end && *c != '=' && *c != ' ' && *c != '\t'; ++c) {
131 parameter_name.push_back(tolower(*c));
132 }
133 SkipWhiteSpace(&c, parameters_end);
134 if (c == parameters_end || *c != '=') {
135 return false;
136 }
137 ++c;
138 SkipWhiteSpace(&c, parameters_end);
139 SpdyStringPiece::const_iterator parameter_value_begin = c;
140 for (; c != parameters_end && *c != ';' && *c != ' ' && *c != '\t'; ++c) {
141 }
142 if (c == parameter_value_begin) {
143 return false;
144 }
145 if (parameter_name.compare("ma") == 0) {
146 if (!ParsePositiveInteger32(parameter_value_begin, c, &max_age)) {
147 return false;
148 }
149 } else if (parameter_name.compare("v") == 0) {
150 // Version is a comma separated list of positive integers enclosed in
151 // quotation marks. Since it can contain commas, which are not
152 // delineating alternative service entries, |parameters_end| and |c| can
153 // be invalid.
154 if (*parameter_value_begin != '"') {
155 return false;
156 }
157 c = std::find(parameter_value_begin + 1, value.end(), '"');
158 if (c == value.end()) {
159 return false;
160 }
161 ++c;
162 parameters_end = std::find(c, value.end(), ',');
163 SpdyStringPiece::const_iterator v_begin = parameter_value_begin + 1;
164 while (v_begin < c) {
165 SpdyStringPiece::const_iterator v_end = v_begin;
166 while (v_end < c - 1 && *v_end != ',') {
167 ++v_end;
168 }
169 uint16_t v;
170 if (!ParsePositiveInteger16(v_begin, v_end, &v)) {
171 return false;
172 }
173 version.push_back(v);
174 v_begin = v_end + 1;
175 if (v_begin == c - 1) {
176 // List ends in comma.
177 return false;
178 }
179 }
180 }
181 }
182 altsvc_vector->emplace_back(protocol_id, host, port, max_age, version);
183 for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) {
184 }
185 }
186 return true;
187 }
188
189 // static
190 SpdyString SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
191 const AlternativeServiceVector& altsvc_vector) {
192 if (altsvc_vector.empty()) {
193 return SpdyString("clear");
194 }
195 const char kNibbleToHex[] = "0123456789ABCDEF";
196 SpdyString value;
197 for (const AlternativeService& altsvc : altsvc_vector) {
198 if (!value.empty()) {
199 value.push_back(',');
200 }
201 // Percent escape protocol id according to
202 // http://tools.ietf.org/html/rfc7230#section-3.2.6.
203 for (char c : altsvc.protocol_id) {
204 if (isalnum(c)) {
205 value.push_back(c);
206 continue;
207 }
208 switch (c) {
209 case '!':
210 case '#':
211 case '$':
212 case '&':
213 case '\'':
214 case '*':
215 case '+':
216 case '-':
217 case '.':
218 case '^':
219 case '_':
220 case '`':
221 case '|':
222 case '~':
223 value.push_back(c);
224 break;
225 default:
226 value.push_back('%');
227 // Network byte order is big-endian.
228 value.push_back(kNibbleToHex[c >> 4]);
229 value.push_back(kNibbleToHex[c & 0x0f]);
230 break;
231 }
232 }
233 value.push_back('=');
234 value.push_back('"');
235 for (char c : altsvc.host) {
236 if (c == '"' || c == '\\') {
237 value.push_back('\\');
238 }
239 value.push_back(c);
240 }
241 SpdyStringAppendF(&value, ":%d\"", altsvc.port);
242 if (altsvc.max_age != 86400) {
243 SpdyStringAppendF(&value, "; ma=%d", altsvc.max_age);
244 }
245 if (!altsvc.version.empty()) {
246 value.append("; v=\"");
247 for (VersionVector::const_iterator it = altsvc.version.begin();
248 it != altsvc.version.end(); ++it) {
249 if (it != altsvc.version.begin()) {
250 value.append(",");
251 }
252 SpdyStringAppendF(&value, "%d", *it);
253 }
254 value.append("\"");
255 }
256 }
257 return value;
258 }
259
260 // static
261 void SpdyAltSvcWireFormat::SkipWhiteSpace(SpdyStringPiece::const_iterator* c,
262 SpdyStringPiece::const_iterator end) {
263 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) {
264 }
265 }
266
267 // static
268 bool SpdyAltSvcWireFormat::PercentDecode(SpdyStringPiece::const_iterator c,
269 SpdyStringPiece::const_iterator end,
270 SpdyString* output) {
271 output->clear();
272 for (; c != end; ++c) {
273 if (*c != '%') {
274 output->push_back(*c);
275 continue;
276 }
277 DCHECK_EQ('%', *c);
278 ++c;
279 if (c == end || !std::isxdigit(*c)) {
280 return false;
281 }
282 // Network byte order is big-endian.
283 char decoded = SpdyHexDigitToInt(*c) << 4;
284 ++c;
285 if (c == end || !std::isxdigit(*c)) {
286 return false;
287 }
288 decoded += SpdyHexDigitToInt(*c);
289 output->push_back(decoded);
290 }
291 return true;
292 }
293
294 // static
295 bool SpdyAltSvcWireFormat::ParseAltAuthority(
296 SpdyStringPiece::const_iterator c,
297 SpdyStringPiece::const_iterator end,
298 SpdyString* host,
299 uint16_t* port) {
300 host->clear();
301 if (c == end) {
302 return false;
303 }
304 if (*c == '[') {
305 for (; c != end && *c != ']'; ++c) {
306 if (*c == '"') {
307 // Port is mandatory.
308 return false;
309 }
310 host->push_back(*c);
311 }
312 if (c == end) {
313 return false;
314 }
315 DCHECK_EQ(']', *c);
316 host->push_back(*c);
317 ++c;
318 } else {
319 for (; c != end && *c != ':'; ++c) {
320 if (*c == '"') {
321 // Port is mandatory.
322 return false;
323 }
324 if (*c == '\\') {
325 ++c;
326 if (c == end) {
327 return false;
328 }
329 }
330 host->push_back(*c);
331 }
332 }
333 if (c == end || *c != ':') {
334 return false;
335 }
336 DCHECK_EQ(':', *c);
337 ++c;
338 return ParsePositiveInteger16(c, end, port);
339 }
340
341 // static
342 bool SpdyAltSvcWireFormat::ParsePositiveInteger16(
343 SpdyStringPiece::const_iterator c,
344 SpdyStringPiece::const_iterator end,
345 uint16_t* value) {
346 return ParsePositiveIntegerImpl<uint16_t>(c, end, value);
347 }
348
349 // static
350 bool SpdyAltSvcWireFormat::ParsePositiveInteger32(
351 SpdyStringPiece::const_iterator c,
352 SpdyStringPiece::const_iterator end,
353 uint32_t* value) {
354 return ParsePositiveIntegerImpl<uint32_t>(c, end, value);
355 }
356
357 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_alt_svc_wire_format.h ('k') | net/spdy/spdy_alt_svc_wire_format_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698