OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "components/network_session_configurator/network_session_configurator.h
" | |
6 | |
7 #include <map> | |
8 #include <unordered_set> | |
9 | |
10 #include "base/metrics/field_trial.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "base/strings/string_piece.h" | |
13 #include "base/strings/string_split.h" | |
14 #include "base/strings/string_util.h" | |
15 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param
s.h" | |
16 #include "components/variations/variations_associated_data.h" | |
17 #include "components/version_info/version_info.h" | |
18 #include "net/http/http_stream_factory.h" | |
19 #include "net/quic/chromium/quic_utils_chromium.h" | |
20 #include "net/quic/core/quic_packets.h" | |
21 #include "net/spdy/core/spdy_protocol.h" | |
22 #include "net/url_request/url_fetcher.h" | |
23 | |
24 namespace { | |
25 | |
26 // Map from name to value for all parameters associate with a field trial. | |
27 using VariationParameters = std::map<std::string, std::string>; | |
28 | |
29 const char kTCPFastOpenFieldTrialName[] = "TCPFastOpen"; | |
30 const char kTCPFastOpenHttpsEnabledGroupName[] = "HttpsEnabled"; | |
31 | |
32 const char kQuicFieldTrialName[] = "QUIC"; | |
33 const char kQuicFieldTrialEnabledGroupName[] = "Enabled"; | |
34 const char kQuicFieldTrialHttpsEnabledGroupName[] = "HttpsEnabled"; | |
35 | |
36 // Field trial for HTTP/2. | |
37 const char kHttp2FieldTrialName[] = "HTTP2"; | |
38 const char kHttp2FieldTrialDisablePrefix[] = "Disable"; | |
39 | |
40 // Returns the value associated with |key| in |params| or "" if the | |
41 // key is not present in the map. | |
42 const std::string& GetVariationParam( | |
43 const std::map<std::string, std::string>& params, | |
44 const std::string& key) { | |
45 std::map<std::string, std::string>::const_iterator it = params.find(key); | |
46 if (it == params.end()) | |
47 return base::EmptyString(); | |
48 | |
49 return it->second; | |
50 } | |
51 | |
52 void ConfigureTCPFastOpenParams(base::StringPiece tfo_trial_group, | |
53 net::HttpNetworkSession::Params* params) { | |
54 if (tfo_trial_group == kTCPFastOpenHttpsEnabledGroupName) | |
55 params->enable_tcp_fast_open_for_ssl = true; | |
56 } | |
57 | |
58 net::SettingsMap GetHttp2Settings( | |
59 const VariationParameters& http2_trial_params) { | |
60 net::SettingsMap http2_settings; | |
61 | |
62 const std::string settings_string = | |
63 GetVariationParam(http2_trial_params, "http2_settings"); | |
64 | |
65 base::StringPairs key_value_pairs; | |
66 if (!base::SplitStringIntoKeyValuePairs(settings_string, ':', ',', | |
67 &key_value_pairs)) { | |
68 return http2_settings; | |
69 } | |
70 | |
71 for (auto key_value : key_value_pairs) { | |
72 uint32_t key; | |
73 if (!base::StringToUint(key_value.first, &key)) | |
74 continue; | |
75 uint32_t value; | |
76 if (!base::StringToUint(key_value.second, &value)) | |
77 continue; | |
78 http2_settings[static_cast<net::SpdySettingsIds>(key)] = value; | |
79 } | |
80 | |
81 return http2_settings; | |
82 } | |
83 | |
84 void ConfigureHttp2Params(base::StringPiece http2_trial_group, | |
85 const VariationParameters& http2_trial_params, | |
86 net::HttpNetworkSession::Params* params) { | |
87 if (http2_trial_group.starts_with(kHttp2FieldTrialDisablePrefix)) { | |
88 params->enable_http2 = false; | |
89 return; | |
90 } | |
91 params->http2_settings = GetHttp2Settings(http2_trial_params); | |
92 } | |
93 | |
94 bool ShouldEnableQuic(base::StringPiece quic_trial_group, | |
95 const VariationParameters& quic_trial_params, | |
96 bool is_quic_force_disabled, | |
97 bool is_quic_force_enabled) { | |
98 if (is_quic_force_disabled) | |
99 return false; | |
100 if (is_quic_force_enabled) | |
101 return true; | |
102 | |
103 return quic_trial_group.starts_with(kQuicFieldTrialEnabledGroupName) || | |
104 quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName) || | |
105 base::LowerCaseEqualsASCII( | |
106 GetVariationParam(quic_trial_params, "enable_quic"), | |
107 "true"); | |
108 } | |
109 | |
110 bool ShouldMarkQuicBrokenWhenNetworkBlackholes( | |
111 const VariationParameters& quic_trial_params) { | |
112 return base::LowerCaseEqualsASCII( | |
113 GetVariationParam(quic_trial_params, | |
114 "mark_quic_broken_when_network_blackholes"), | |
115 "true"); | |
116 } | |
117 | |
118 bool ShouldRetryWithoutAltSvcOnQuicErrors( | |
119 const VariationParameters& quic_trial_params) { | |
120 return base::LowerCaseEqualsASCII( | |
121 GetVariationParam(quic_trial_params, | |
122 "retry_without_alt_svc_on_quic_errors"), | |
123 "true"); | |
124 } | |
125 | |
126 net::QuicTagVector GetQuicConnectionOptions( | |
127 const VariationParameters& quic_trial_params) { | |
128 VariationParameters::const_iterator it = | |
129 quic_trial_params.find("connection_options"); | |
130 if (it == quic_trial_params.end()) { | |
131 return net::QuicTagVector(); | |
132 } | |
133 | |
134 return net::ParseQuicConnectionOptions(it->second); | |
135 } | |
136 | |
137 bool ShouldForceHolBlocking(const VariationParameters& quic_trial_params) { | |
138 return base::LowerCaseEqualsASCII( | |
139 GetVariationParam(quic_trial_params, "force_hol_blocking"), "true"); | |
140 } | |
141 | |
142 bool ShouldQuicCloseSessionsOnIpChange( | |
143 const VariationParameters& quic_trial_params) { | |
144 return base::LowerCaseEqualsASCII( | |
145 GetVariationParam(quic_trial_params, "close_sessions_on_ip_change"), | |
146 "true"); | |
147 } | |
148 | |
149 int GetQuicIdleConnectionTimeoutSeconds( | |
150 const VariationParameters& quic_trial_params) { | |
151 int value; | |
152 if (base::StringToInt(GetVariationParam(quic_trial_params, | |
153 "idle_connection_timeout_seconds"), | |
154 &value)) { | |
155 return value; | |
156 } | |
157 return 0; | |
158 } | |
159 | |
160 int GetQuicReducedPingTimeoutSeconds( | |
161 const VariationParameters& quic_trial_params) { | |
162 int value; | |
163 if (base::StringToInt( | |
164 GetVariationParam(quic_trial_params, "reduced_ping_timeout_seconds"), | |
165 &value)) { | |
166 return value; | |
167 } | |
168 return 0; | |
169 } | |
170 | |
171 int GetQuicPacketReaderYieldAfterDurationMilliseconds( | |
172 const VariationParameters& quic_trial_params) { | |
173 int value; | |
174 if (base::StringToInt( | |
175 GetVariationParam(quic_trial_params, | |
176 "packet_reader_yield_after_duration_milliseconds"), | |
177 &value)) { | |
178 return value; | |
179 } | |
180 return 0; | |
181 } | |
182 | |
183 bool ShouldQuicRaceCertVerification( | |
184 const VariationParameters& quic_trial_params) { | |
185 return base::LowerCaseEqualsASCII( | |
186 GetVariationParam(quic_trial_params, "race_cert_verification"), "true"); | |
187 } | |
188 | |
189 bool ShouldQuicDoNotFragment(const VariationParameters& quic_trial_params) { | |
190 return base::LowerCaseEqualsASCII( | |
191 GetVariationParam(quic_trial_params, "do_not_fragment"), "true"); | |
192 } | |
193 | |
194 bool ShouldQuicEstimateInitialRtt( | |
195 const VariationParameters& quic_trial_params) { | |
196 return base::LowerCaseEqualsASCII( | |
197 GetVariationParam(quic_trial_params, "estimate_initial_rtt"), "true"); | |
198 } | |
199 | |
200 bool ShouldQuicMigrateSessionsOnNetworkChange( | |
201 const VariationParameters& quic_trial_params) { | |
202 return base::LowerCaseEqualsASCII( | |
203 GetVariationParam(quic_trial_params, | |
204 "migrate_sessions_on_network_change"), | |
205 "true"); | |
206 } | |
207 | |
208 bool ShouldQuicMigrateSessionsEarly( | |
209 const VariationParameters& quic_trial_params) { | |
210 return base::LowerCaseEqualsASCII( | |
211 GetVariationParam(quic_trial_params, "migrate_sessions_early"), "true"); | |
212 } | |
213 | |
214 bool ShouldQuicAllowServerMigration( | |
215 const VariationParameters& quic_trial_params) { | |
216 return base::LowerCaseEqualsASCII( | |
217 GetVariationParam(quic_trial_params, | |
218 "allow_server_migration"), | |
219 "true"); | |
220 } | |
221 | |
222 size_t GetQuicMaxPacketLength(const VariationParameters& quic_trial_params) { | |
223 unsigned value; | |
224 if (base::StringToUint( | |
225 GetVariationParam(quic_trial_params, "max_packet_length"), &value)) { | |
226 return value; | |
227 } | |
228 return 0; | |
229 } | |
230 | |
231 net::QuicVersion GetQuicVersion(const VariationParameters& quic_trial_params) { | |
232 return network_session_configurator::ParseQuicVersion( | |
233 GetVariationParam(quic_trial_params, "quic_version")); | |
234 } | |
235 | |
236 bool ShouldEnableServerPushCancelation( | |
237 const VariationParameters& quic_trial_params) { | |
238 return base::LowerCaseEqualsASCII( | |
239 GetVariationParam(quic_trial_params, "enable_server_push_cancellation"), | |
240 "true"); | |
241 } | |
242 | |
243 void ConfigureQuicParams(base::StringPiece quic_trial_group, | |
244 const VariationParameters& quic_trial_params, | |
245 bool is_quic_force_disabled, | |
246 bool is_quic_force_enabled, | |
247 const std::string& quic_user_agent_id, | |
248 net::HttpNetworkSession::Params* params) { | |
249 params->enable_quic = ShouldEnableQuic( | |
250 quic_trial_group, quic_trial_params, is_quic_force_disabled, | |
251 is_quic_force_enabled); | |
252 params->mark_quic_broken_when_network_blackholes = | |
253 ShouldMarkQuicBrokenWhenNetworkBlackholes(quic_trial_params); | |
254 | |
255 params->enable_server_push_cancellation = | |
256 ShouldEnableServerPushCancelation(quic_trial_params); | |
257 | |
258 params->retry_without_alt_svc_on_quic_errors = | |
259 ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params); | |
260 | |
261 if (params->enable_quic) { | |
262 params->quic_force_hol_blocking = ShouldForceHolBlocking(quic_trial_params); | |
263 params->quic_connection_options = | |
264 GetQuicConnectionOptions(quic_trial_params); | |
265 params->quic_close_sessions_on_ip_change = | |
266 ShouldQuicCloseSessionsOnIpChange(quic_trial_params); | |
267 int idle_connection_timeout_seconds = | |
268 GetQuicIdleConnectionTimeoutSeconds(quic_trial_params); | |
269 if (idle_connection_timeout_seconds != 0) { | |
270 params->quic_idle_connection_timeout_seconds = | |
271 idle_connection_timeout_seconds; | |
272 } | |
273 int reduced_ping_timeout_seconds = | |
274 GetQuicReducedPingTimeoutSeconds(quic_trial_params); | |
275 if (reduced_ping_timeout_seconds > 0 && | |
276 reduced_ping_timeout_seconds < net::kPingTimeoutSecs) { | |
277 params->quic_reduced_ping_timeout_seconds = reduced_ping_timeout_seconds; | |
278 } | |
279 int packet_reader_yield_after_duration_milliseconds = | |
280 GetQuicPacketReaderYieldAfterDurationMilliseconds(quic_trial_params); | |
281 if (packet_reader_yield_after_duration_milliseconds != 0) { | |
282 params->quic_packet_reader_yield_after_duration_milliseconds = | |
283 packet_reader_yield_after_duration_milliseconds; | |
284 } | |
285 params->quic_race_cert_verification = | |
286 ShouldQuicRaceCertVerification(quic_trial_params); | |
287 params->quic_do_not_fragment = | |
288 ShouldQuicDoNotFragment(quic_trial_params); | |
289 params->quic_estimate_initial_rtt = | |
290 ShouldQuicEstimateInitialRtt(quic_trial_params); | |
291 params->quic_migrate_sessions_on_network_change = | |
292 ShouldQuicMigrateSessionsOnNetworkChange(quic_trial_params); | |
293 params->quic_migrate_sessions_early = | |
294 ShouldQuicMigrateSessionsEarly(quic_trial_params); | |
295 params->quic_allow_server_migration = | |
296 ShouldQuicAllowServerMigration(quic_trial_params); | |
297 } | |
298 | |
299 size_t max_packet_length = GetQuicMaxPacketLength(quic_trial_params); | |
300 if (max_packet_length != 0) { | |
301 params->quic_max_packet_length = max_packet_length; | |
302 } | |
303 | |
304 params->quic_user_agent_id = quic_user_agent_id; | |
305 | |
306 net::QuicVersion version = GetQuicVersion(quic_trial_params); | |
307 if (version != net::QUIC_VERSION_UNSUPPORTED) { | |
308 net::QuicVersionVector supported_versions; | |
309 supported_versions.push_back(version); | |
310 params->quic_supported_versions = supported_versions; | |
311 } | |
312 } | |
313 | |
314 } // anonymous namespace | |
315 | |
316 namespace network_session_configurator { | |
317 | |
318 net::QuicVersion ParseQuicVersion(const std::string& quic_version) { | |
319 net::QuicVersionVector supported_versions = net::AllSupportedVersions(); | |
320 for (size_t i = 0; i < supported_versions.size(); ++i) { | |
321 net::QuicVersion version = supported_versions[i]; | |
322 if (net::QuicVersionToString(version) == quic_version) { | |
323 return version; | |
324 } | |
325 } | |
326 | |
327 return net::QUIC_VERSION_UNSUPPORTED; | |
328 } | |
329 | |
330 void ParseFieldTrials(bool is_quic_force_disabled, | |
331 bool is_quic_force_enabled, | |
332 const std::string& quic_user_agent_id, | |
333 net::HttpNetworkSession::Params* params) { | |
334 std::string quic_trial_group = | |
335 base::FieldTrialList::FindFullName(kQuicFieldTrialName); | |
336 VariationParameters quic_trial_params; | |
337 if (!variations::GetVariationParams(kQuicFieldTrialName, &quic_trial_params)) | |
338 quic_trial_params.clear(); | |
339 ConfigureQuicParams(quic_trial_group, quic_trial_params, | |
340 is_quic_force_disabled, is_quic_force_enabled, | |
341 quic_user_agent_id, params); | |
342 | |
343 std::string http2_trial_group = | |
344 base::FieldTrialList::FindFullName(kHttp2FieldTrialName); | |
345 VariationParameters http2_trial_params; | |
346 if (!variations::GetVariationParams(kHttp2FieldTrialName, | |
347 &http2_trial_params)) | |
348 http2_trial_params.clear(); | |
349 ConfigureHttp2Params(http2_trial_group, http2_trial_params, params); | |
350 | |
351 const std::string tfo_trial_group = | |
352 base::FieldTrialList::FindFullName(kTCPFastOpenFieldTrialName); | |
353 ConfigureTCPFastOpenParams(tfo_trial_group, params); | |
354 } | |
355 | |
356 } // namespace network_session_configurator | |
OLD | NEW |