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 |