| 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 |