| 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 <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 } | 29 } |
| 30 *value += *c - '0'; | 30 *value += *c - '0'; |
| 31 } | 31 } |
| 32 return (c == end && *value > 0); | 32 return (c == end && *value > 0); |
| 33 } | 33 } |
| 34 | 34 |
| 35 } // namespace | 35 } // namespace |
| 36 | 36 |
| 37 // static | 37 // static |
| 38 bool SpdyAltSvcWireFormat::ParseHeaderFieldValue(StringPiece value, | 38 bool SpdyAltSvcWireFormat::ParseHeaderFieldValue(StringPiece value, |
| 39 std::string* protocol_id, | 39 AlternativeService* altsvc) { |
| 40 std::string* host, | 40 altsvc->max_age = 86400; |
| 41 uint16* port, | 41 altsvc->p = 1.0; |
| 42 uint32* max_age, | |
| 43 double* p) { | |
| 44 *max_age = 86400; | |
| 45 *p = 1.0; | |
| 46 | 42 |
| 47 StringPiece::const_iterator c = value.begin(); | 43 StringPiece::const_iterator c = value.begin(); |
| 48 StringPiece::const_iterator percent_encoded_protocol_id_end = | 44 StringPiece::const_iterator percent_encoded_protocol_id_end = |
| 49 std::find(c, value.end(), '='); | 45 std::find(c, value.end(), '='); |
| 50 if (percent_encoded_protocol_id_end == c || | 46 if (percent_encoded_protocol_id_end == c || |
| 51 !PercentDecode(c, percent_encoded_protocol_id_end, protocol_id)) { | 47 !PercentDecode(c, percent_encoded_protocol_id_end, |
| 48 &(altsvc->protocol_id))) { |
| 52 return false; | 49 return false; |
| 53 } | 50 } |
| 54 c = percent_encoded_protocol_id_end; | 51 c = percent_encoded_protocol_id_end; |
| 55 if (c == value.end()) { | 52 if (c == value.end()) { |
| 56 return false; | 53 return false; |
| 57 } | 54 } |
| 58 DCHECK_EQ('=', *c); | 55 DCHECK_EQ('=', *c); |
| 59 ++c; | 56 ++c; |
| 60 if (c == value.end() || *c != '"') { | 57 if (c == value.end() || *c != '"') { |
| 61 return false; | 58 return false; |
| 62 } | 59 } |
| 63 ++c; | 60 ++c; |
| 64 StringPiece::const_iterator alt_authority_begin = c; | 61 StringPiece::const_iterator alt_authority_begin = c; |
| 65 for (; c != value.end() && *c != '"'; ++c) { | 62 for (; c != value.end() && *c != '"'; ++c) { |
| 66 // Decode backslash encoding. | 63 // Decode backslash encoding. |
| 67 if (*c != '\\') { | 64 if (*c != '\\') { |
| 68 continue; | 65 continue; |
| 69 } | 66 } |
| 70 ++c; | 67 ++c; |
| 71 if (c == value.end()) { | 68 if (c == value.end()) { |
| 72 return false; | 69 return false; |
| 73 } | 70 } |
| 74 } | 71 } |
| 75 if (c == alt_authority_begin || c == value.end()) { | 72 if (c == alt_authority_begin || c == value.end()) { |
| 76 return false; | 73 return false; |
| 77 } | 74 } |
| 78 DCHECK_EQ('"', *c); | 75 DCHECK_EQ('"', *c); |
| 79 if (!ParseAltAuthority(alt_authority_begin, c, host, port)) { | 76 if (!ParseAltAuthority(alt_authority_begin, c, &(altsvc->host), |
| 77 &(altsvc->port))) { |
| 80 return false; | 78 return false; |
| 81 } | 79 } |
| 82 ++c; | 80 ++c; |
| 83 StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); | 81 StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); |
| 84 while (c != parameters_end) { | 82 while (c != parameters_end) { |
| 85 SkipWhiteSpace(&c, parameters_end); | 83 SkipWhiteSpace(&c, parameters_end); |
| 86 if (c == parameters_end) { | 84 if (c == parameters_end) { |
| 87 return true; | 85 return true; |
| 88 } | 86 } |
| 89 if (*c != ';') { | 87 if (*c != ';') { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 104 } | 102 } |
| 105 ++c; | 103 ++c; |
| 106 SkipWhiteSpace(&c, parameters_end); | 104 SkipWhiteSpace(&c, parameters_end); |
| 107 StringPiece::const_iterator parameter_value_begin = c; | 105 StringPiece::const_iterator parameter_value_begin = c; |
| 108 for (; c != parameters_end && *c != ';' && *c != ' ' && *c != '\t'; ++c) { | 106 for (; c != parameters_end && *c != ';' && *c != ' ' && *c != '\t'; ++c) { |
| 109 } | 107 } |
| 110 if (c == parameter_value_begin) { | 108 if (c == parameter_value_begin) { |
| 111 return false; | 109 return false; |
| 112 } | 110 } |
| 113 if (parameter_name.compare("ma") == 0) { | 111 if (parameter_name.compare("ma") == 0) { |
| 114 if (!ParsePositiveInteger32(parameter_value_begin, c, max_age)) { | 112 if (!ParsePositiveInteger32(parameter_value_begin, c, |
| 113 &(altsvc->max_age))) { |
| 115 return false; | 114 return false; |
| 116 } | 115 } |
| 117 } else if (parameter_name.compare("p") == 0) { | 116 } else if (parameter_name.compare("p") == 0) { |
| 118 if (!ParseProbability(parameter_value_begin, c, p)) { | 117 if (!ParseProbability(parameter_value_begin, c, &(altsvc->p))) { |
| 119 return false; | 118 return false; |
| 120 } | 119 } |
| 121 } | 120 } |
| 122 SkipWhiteSpace(&c, parameters_end); | 121 SkipWhiteSpace(&c, parameters_end); |
| 123 } | 122 } |
| 124 // TODO(bnc): Parse additional alternative services delimited by ','. | 123 // TODO(bnc): Parse additional alternative services delimited by ','. |
| 125 return true; | 124 return true; |
| 126 } | 125 } |
| 127 | 126 |
| 128 // static | 127 // static |
| 129 std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | 128 std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
| 130 const std::string& protocol_id, | 129 const AlternativeService& altsvc) { |
| 131 const std::string& host, | |
| 132 uint16 port, | |
| 133 uint32 max_age, | |
| 134 double p) { | |
| 135 const char kNibbleToHex[] = "0123456789ABCDEF"; | 130 const char kNibbleToHex[] = "0123456789ABCDEF"; |
| 136 std::string value; | 131 std::string value; |
| 137 // Percent escape protocol id according to | 132 // Percent escape protocol id according to |
| 138 // http://tools.ietf.org/html/rfc7230#section-3.2.6. | 133 // http://tools.ietf.org/html/rfc7230#section-3.2.6. |
| 139 for (char c : protocol_id) { | 134 for (char c : altsvc.protocol_id) { |
| 140 if (isalnum(c)) { | 135 if (isalnum(c)) { |
| 141 value.push_back(c); | 136 value.push_back(c); |
| 142 continue; | 137 continue; |
| 143 } | 138 } |
| 144 switch (c) { | 139 switch (c) { |
| 145 case '!': | 140 case '!': |
| 146 case '#': | 141 case '#': |
| 147 case '$': | 142 case '$': |
| 148 case '&': | 143 case '&': |
| 149 case '\'': | 144 case '\'': |
| (...skipping 11 matching lines...) Expand all Loading... |
| 161 default: | 156 default: |
| 162 value.push_back('%'); | 157 value.push_back('%'); |
| 163 // Network byte order is big-endian. | 158 // Network byte order is big-endian. |
| 164 value.push_back(kNibbleToHex[c >> 4]); | 159 value.push_back(kNibbleToHex[c >> 4]); |
| 165 value.push_back(kNibbleToHex[c & 0x0f]); | 160 value.push_back(kNibbleToHex[c & 0x0f]); |
| 166 break; | 161 break; |
| 167 } | 162 } |
| 168 } | 163 } |
| 169 value.push_back('='); | 164 value.push_back('='); |
| 170 value.push_back('"'); | 165 value.push_back('"'); |
| 171 for (char c : host) { | 166 for (char c : altsvc.host) { |
| 172 if (c == '"' || c == '\\') { | 167 if (c == '"' || c == '\\') { |
| 173 value.push_back('\\'); | 168 value.push_back('\\'); |
| 174 } | 169 } |
| 175 value.push_back(c); | 170 value.push_back(c); |
| 176 } | 171 } |
| 177 base::StringAppendF(&value, ":%d\"", port); | 172 base::StringAppendF(&value, ":%d\"", altsvc.port); |
| 178 if (max_age != 86400) { | 173 if (altsvc.max_age != 86400) { |
| 179 base::StringAppendF(&value, "; ma=%d", max_age); | 174 base::StringAppendF(&value, "; ma=%d", altsvc.max_age); |
| 180 } | 175 } |
| 181 if (p != 1.0) { | 176 if (altsvc.p != 1.0) { |
| 182 base::StringAppendF(&value, "; p=%.2f", p); | 177 base::StringAppendF(&value, "; p=%.2f", altsvc.p); |
| 183 } | 178 } |
| 184 return value; | 179 return value; |
| 185 } | 180 } |
| 186 | 181 |
| 187 // static | 182 // static |
| 188 void SpdyAltSvcWireFormat::SkipWhiteSpace(StringPiece::const_iterator* c, | 183 void SpdyAltSvcWireFormat::SkipWhiteSpace(StringPiece::const_iterator* c, |
| 189 StringPiece::const_iterator end) { | 184 StringPiece::const_iterator end) { |
| 190 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { | 185 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { |
| 191 } | 186 } |
| 192 } | 187 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 ++c; | 296 ++c; |
| 302 double place_value = 0.1; | 297 double place_value = 0.1; |
| 303 for (; c != end && isdigit(*c); ++c) { | 298 for (; c != end && isdigit(*c); ++c) { |
| 304 *p += place_value * (*c - '0'); | 299 *p += place_value * (*c - '0'); |
| 305 place_value *= 0.1; | 300 place_value *= 0.1; |
| 306 } | 301 } |
| 307 return (c == end && *p <= 1.0); | 302 return (c == end && *p <= 1.0); |
| 308 } | 303 } |
| 309 | 304 |
| 310 } // namespace net | 305 } // namespace net |
| OLD | NEW |