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 22 matching lines...) Expand all Loading... |
33 } | 33 } |
34 | 34 |
35 } // namespace | 35 } // namespace |
36 | 36 |
37 SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {} | 37 SpdyAltSvcWireFormat::AlternativeService::AlternativeService() {} |
38 | 38 |
39 SpdyAltSvcWireFormat::AlternativeService::AlternativeService( | 39 SpdyAltSvcWireFormat::AlternativeService::AlternativeService( |
40 const std::string& protocol_id, | 40 const std::string& protocol_id, |
41 const std::string& host, | 41 const std::string& host, |
42 uint16 port, | 42 uint16 port, |
43 uint16 version, | |
44 uint32 max_age, | 43 uint32 max_age, |
45 double probability) | 44 double probability, |
| 45 VersionVector version) |
46 : protocol_id(protocol_id), | 46 : protocol_id(protocol_id), |
47 host(host), | 47 host(host), |
48 port(port), | 48 port(port), |
49 version(version), | |
50 max_age(max_age), | 49 max_age(max_age), |
51 probability(probability) {} | 50 probability(probability), |
| 51 version(version) {} |
| 52 |
| 53 SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() {} |
52 | 54 |
53 // static | 55 // static |
54 bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( | 56 bool SpdyAltSvcWireFormat::ParseHeaderFieldValue( |
55 StringPiece value, | 57 StringPiece value, |
56 AlternativeServiceVector* altsvc_vector) { | 58 AlternativeServiceVector* altsvc_vector) { |
57 // Empty value is invalid according to the specification. | 59 // Empty value is invalid according to the specification. |
58 if (value.empty()) { | 60 if (value.empty()) { |
59 return false; | 61 return false; |
60 } | 62 } |
61 altsvc_vector->clear(); | 63 altsvc_vector->clear(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 return false; | 100 return false; |
99 } | 101 } |
100 DCHECK_EQ('"', *c); | 102 DCHECK_EQ('"', *c); |
101 std::string host; | 103 std::string host; |
102 uint16 port; | 104 uint16 port; |
103 if (!ParseAltAuthority(alt_authority_begin, c, &host, &port)) { | 105 if (!ParseAltAuthority(alt_authority_begin, c, &host, &port)) { |
104 return false; | 106 return false; |
105 } | 107 } |
106 ++c; | 108 ++c; |
107 // Parse parameters. | 109 // Parse parameters. |
108 uint16 version = 0; | |
109 uint32 max_age = 86400; | 110 uint32 max_age = 86400; |
110 double probability = 1.0; | 111 double probability = 1.0; |
| 112 VersionVector version; |
111 StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); | 113 StringPiece::const_iterator parameters_end = std::find(c, value.end(), ','); |
112 while (c != parameters_end) { | 114 while (c != parameters_end) { |
113 SkipWhiteSpace(&c, parameters_end); | 115 SkipWhiteSpace(&c, parameters_end); |
114 if (c == parameters_end) { | 116 if (c == parameters_end) { |
115 break; | 117 break; |
116 } | 118 } |
117 if (*c != ';') { | 119 if (*c != ';') { |
118 return false; | 120 return false; |
119 } | 121 } |
120 ++c; | 122 ++c; |
(...skipping 10 matching lines...) Expand all Loading... |
131 return false; | 133 return false; |
132 } | 134 } |
133 ++c; | 135 ++c; |
134 SkipWhiteSpace(&c, parameters_end); | 136 SkipWhiteSpace(&c, parameters_end); |
135 StringPiece::const_iterator parameter_value_begin = c; | 137 StringPiece::const_iterator parameter_value_begin = c; |
136 for (; c != parameters_end && *c != ';' && *c != ' ' && *c != '\t'; ++c) { | 138 for (; c != parameters_end && *c != ';' && *c != ' ' && *c != '\t'; ++c) { |
137 } | 139 } |
138 if (c == parameter_value_begin) { | 140 if (c == parameter_value_begin) { |
139 return false; | 141 return false; |
140 } | 142 } |
141 if (parameter_name.compare("v") == 0) { | 143 if (parameter_name.compare("ma") == 0) { |
142 if (!ParsePositiveInteger16(parameter_value_begin, c, &version)) { | |
143 return false; | |
144 } | |
145 } else if (parameter_name.compare("ma") == 0) { | |
146 if (!ParsePositiveInteger32(parameter_value_begin, c, &max_age)) { | 144 if (!ParsePositiveInteger32(parameter_value_begin, c, &max_age)) { |
147 return false; | 145 return false; |
148 } | 146 } |
149 } else if (parameter_name.compare("p") == 0) { | 147 } else if (parameter_name.compare("p") == 0) { |
150 // Probability value is enclosed in quotation marks. | 148 // Probability value is enclosed in quotation marks. |
151 if (*parameter_value_begin != '"' || *(c - 1) != '"') { | 149 if (*parameter_value_begin != '"' || *(c - 1) != '"') { |
152 return false; | 150 return false; |
153 } | 151 } |
154 if (!ParseProbability(parameter_value_begin + 1, c - 1, &probability)) { | 152 if (!ParseProbability(parameter_value_begin + 1, c - 1, &probability)) { |
155 return false; | 153 return false; |
156 } | 154 } |
| 155 } else if (parameter_name.compare("v") == 0) { |
| 156 // Version is a comma separated list of positive integers enclosed in |
| 157 // quotation marks. Since it can contain commas, which are not |
| 158 // delineating alternative service entries, |parameters_end| and |c| can |
| 159 // be invalid. |
| 160 if (*parameter_value_begin != '"') { |
| 161 return false; |
| 162 } |
| 163 c = std::find(parameter_value_begin + 1, value.end(), '"'); |
| 164 if (c == value.end()) { |
| 165 return false; |
| 166 } |
| 167 ++c; |
| 168 parameters_end = std::find(c, value.end(), ','); |
| 169 StringPiece::const_iterator v_begin = parameter_value_begin + 1; |
| 170 while (v_begin < c) { |
| 171 StringPiece::const_iterator v_end = v_begin; |
| 172 while (v_end < c - 1 && *v_end != ',') { |
| 173 ++v_end; |
| 174 } |
| 175 uint16 v; |
| 176 if (!ParsePositiveInteger16(v_begin, v_end, &v)) { |
| 177 return false; |
| 178 } |
| 179 version.push_back(v); |
| 180 v_begin = v_end + 1; |
| 181 if (v_begin == c - 1) { |
| 182 // List ends in comma. |
| 183 return false; |
| 184 } |
| 185 } |
157 } | 186 } |
158 } | 187 } |
159 altsvc_vector->push_back(AlternativeService(protocol_id, host, port, | 188 altsvc_vector->push_back(AlternativeService(protocol_id, host, port, |
160 version, max_age, probability)); | 189 max_age, probability, version)); |
161 for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { | 190 for (; c != value.end() && (*c == ' ' || *c == '\t' || *c == ','); ++c) { |
162 } | 191 } |
163 } | 192 } |
164 return true; | 193 return true; |
165 } | 194 } |
166 | 195 |
167 // static | 196 // static |
168 std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | 197 std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue( |
169 const AlternativeServiceVector& altsvc_vector) { | 198 const AlternativeServiceVector& altsvc_vector) { |
170 if (altsvc_vector.empty()) { | 199 if (altsvc_vector.empty()) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 } | 239 } |
211 value.push_back('='); | 240 value.push_back('='); |
212 value.push_back('"'); | 241 value.push_back('"'); |
213 for (char c : altsvc.host) { | 242 for (char c : altsvc.host) { |
214 if (c == '"' || c == '\\') { | 243 if (c == '"' || c == '\\') { |
215 value.push_back('\\'); | 244 value.push_back('\\'); |
216 } | 245 } |
217 value.push_back(c); | 246 value.push_back(c); |
218 } | 247 } |
219 base::StringAppendF(&value, ":%d\"", altsvc.port); | 248 base::StringAppendF(&value, ":%d\"", altsvc.port); |
220 if (altsvc.version != 0) { | |
221 base::StringAppendF(&value, "; v=%d", altsvc.version); | |
222 } | |
223 if (altsvc.max_age != 86400) { | 249 if (altsvc.max_age != 86400) { |
224 base::StringAppendF(&value, "; ma=%d", altsvc.max_age); | 250 base::StringAppendF(&value, "; ma=%d", altsvc.max_age); |
225 } | 251 } |
226 if (altsvc.probability != 1.0) { | 252 if (altsvc.probability != 1.0) { |
227 base::StringAppendF(&value, "; p=\"%.2f\"", altsvc.probability); | 253 base::StringAppendF(&value, "; p=\"%.2f\"", altsvc.probability); |
228 } | 254 } |
| 255 if (!altsvc.version.empty()) { |
| 256 value.append("; v=\""); |
| 257 for (VersionVector::const_iterator it = altsvc.version.begin(); |
| 258 it != altsvc.version.end(); ++it) { |
| 259 if (it != altsvc.version.begin()) { |
| 260 value.append(","); |
| 261 } |
| 262 base::StringAppendF(&value, "%d", *it); |
| 263 } |
| 264 value.append("\""); |
| 265 } |
229 } | 266 } |
230 return value; | 267 return value; |
231 } | 268 } |
232 | 269 |
233 // static | 270 // static |
234 void SpdyAltSvcWireFormat::SkipWhiteSpace(StringPiece::const_iterator* c, | 271 void SpdyAltSvcWireFormat::SkipWhiteSpace(StringPiece::const_iterator* c, |
235 StringPiece::const_iterator end) { | 272 StringPiece::const_iterator end) { |
236 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { | 273 for (; *c != end && (**c == ' ' || **c == '\t'); ++*c) { |
237 } | 274 } |
238 } | 275 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 ++c; | 384 ++c; |
348 double place_value = 0.1; | 385 double place_value = 0.1; |
349 for (; c != end && isdigit(*c); ++c) { | 386 for (; c != end && isdigit(*c); ++c) { |
350 *probability += place_value * (*c - '0'); | 387 *probability += place_value * (*c - '0'); |
351 place_value *= 0.1; | 388 place_value *= 0.1; |
352 } | 389 } |
353 return (c == end && *probability <= 1.0); | 390 return (c == end && *probability <= 1.0); |
354 } | 391 } |
355 | 392 |
356 } // namespace net | 393 } // namespace net |
OLD | NEW |