OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/socket/transport_client_socket_pool.h" | 5 #include "net/socket/transport_client_socket_pool.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "net/socket/socket_net_log_params.h" | 24 #include "net/socket/socket_net_log_params.h" |
25 #include "net/socket/tcp_client_socket.h" | 25 #include "net/socket/tcp_client_socket.h" |
26 | 26 |
27 using base::TimeDelta; | 27 using base::TimeDelta; |
28 | 28 |
29 namespace net { | 29 namespace net { |
30 | 30 |
31 // TODO(willchan): Base this off RTT instead of statically setting it. Note we | 31 // TODO(willchan): Base this off RTT instead of statically setting it. Note we |
32 // choose a timeout that is different from the backup connect job timer so they | 32 // choose a timeout that is different from the backup connect job timer so they |
33 // don't synchronize. | 33 // don't synchronize. |
34 const int TransportConnectJob::kIPv6FallbackTimerInMs = 300; | 34 const int TransportConnectJobHelper::kIPv6FallbackTimerInMs = 300; |
35 | 35 |
36 namespace { | 36 namespace { |
37 | 37 |
38 // Returns true iff all addresses in |list| are in the IPv6 family. | 38 // Returns true iff all addresses in |list| are in the IPv6 family. |
39 bool AddressListOnlyContainsIPv6(const AddressList& list) { | 39 bool AddressListOnlyContainsIPv6(const AddressList& list) { |
40 DCHECK(!list.empty()); | 40 DCHECK(!list.empty()); |
41 for (AddressList::const_iterator iter = list.begin(); iter != list.end(); | 41 for (AddressList::const_iterator iter = list.begin(); iter != list.end(); |
42 ++iter) { | 42 ++iter) { |
43 if (iter->GetFamily() != ADDRESS_FAMILY_IPV6) | 43 if (iter->GetFamily() != ADDRESS_FAMILY_IPV6) |
44 return false; | 44 return false; |
(...skipping 29 matching lines...) Expand all Loading... |
74 // the total time, including both host resolution and TCP connect() times. | 74 // the total time, including both host resolution and TCP connect() times. |
75 // | 75 // |
76 // TODO(eroman): The use of this constant needs to be re-evaluated. The time | 76 // TODO(eroman): The use of this constant needs to be re-evaluated. The time |
77 // needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since | 77 // needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since |
78 // the address list may contain many alternatives, and most of those may | 78 // the address list may contain many alternatives, and most of those may |
79 // timeout. Even worse, the per-connect timeout threshold varies greatly | 79 // timeout. Even worse, the per-connect timeout threshold varies greatly |
80 // between systems (anywhere from 20 seconds to 190 seconds). | 80 // between systems (anywhere from 20 seconds to 190 seconds). |
81 // See comment #12 at http://crbug.com/23364 for specifics. | 81 // See comment #12 at http://crbug.com/23364 for specifics. |
82 static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes. | 82 static const int kTransportConnectJobTimeoutInSeconds = 240; // 4 minutes. |
83 | 83 |
| 84 TransportConnectJobHelper::TransportConnectJobHelper( |
| 85 const scoped_refptr<TransportSocketParams>& params, |
| 86 ClientSocketFactory* client_socket_factory, |
| 87 HostResolver* host_resolver, |
| 88 LoadTimingInfo::ConnectTiming* connect_timing) |
| 89 : params_(params), |
| 90 client_socket_factory_(client_socket_factory), |
| 91 resolver_(host_resolver), |
| 92 next_state_(STATE_NONE), |
| 93 connect_timing_(connect_timing) {} |
| 94 |
| 95 TransportConnectJobHelper::~TransportConnectJobHelper() {} |
| 96 |
| 97 int TransportConnectJobHelper::DoResolveHost(RequestPriority priority, |
| 98 const BoundNetLog& net_log) { |
| 99 next_state_ = STATE_RESOLVE_HOST_COMPLETE; |
| 100 connect_timing_->dns_start = base::TimeTicks::Now(); |
| 101 |
| 102 return resolver_.Resolve( |
| 103 params_->destination(), priority, &addresses_, on_io_complete_, net_log); |
| 104 } |
| 105 |
| 106 int TransportConnectJobHelper::DoResolveHostComplete( |
| 107 int result, |
| 108 const BoundNetLog& net_log) { |
| 109 connect_timing_->dns_end = base::TimeTicks::Now(); |
| 110 // Overwrite connection start time, since for connections that do not go |
| 111 // through proxies, |connect_start| should not include dns lookup time. |
| 112 connect_timing_->connect_start = connect_timing_->dns_end; |
| 113 |
| 114 if (result == OK) { |
| 115 // Invoke callback, and abort if it fails. |
| 116 if (!params_->host_resolution_callback().is_null()) |
| 117 result = params_->host_resolution_callback().Run(addresses_, net_log); |
| 118 |
| 119 if (result == OK) |
| 120 next_state_ = STATE_TRANSPORT_CONNECT; |
| 121 } |
| 122 return result; |
| 123 } |
| 124 |
| 125 base::TimeDelta TransportConnectJobHelper::HistogramDuration( |
| 126 ConnectionLatencyHistogram race_result) { |
| 127 DCHECK(!connect_timing_->connect_start.is_null()); |
| 128 DCHECK(!connect_timing_->dns_start.is_null()); |
| 129 base::TimeTicks now = base::TimeTicks::Now(); |
| 130 base::TimeDelta total_duration = now - connect_timing_->dns_start; |
| 131 UMA_HISTOGRAM_CUSTOM_TIMES("Net.DNS_Resolution_And_TCP_Connection_Latency2", |
| 132 total_duration, |
| 133 base::TimeDelta::FromMilliseconds(1), |
| 134 base::TimeDelta::FromMinutes(10), |
| 135 100); |
| 136 |
| 137 base::TimeDelta connect_duration = now - connect_timing_->connect_start; |
| 138 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", |
| 139 connect_duration, |
| 140 base::TimeDelta::FromMilliseconds(1), |
| 141 base::TimeDelta::FromMinutes(10), |
| 142 100); |
| 143 |
| 144 switch (race_result) { |
| 145 case CONNECTION_LATENCY_IPV4_WINS_RACE: |
| 146 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race", |
| 147 connect_duration, |
| 148 base::TimeDelta::FromMilliseconds(1), |
| 149 base::TimeDelta::FromMinutes(10), |
| 150 100); |
| 151 break; |
| 152 |
| 153 case CONNECTION_LATENCY_IPV4_NO_RACE: |
| 154 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", |
| 155 connect_duration, |
| 156 base::TimeDelta::FromMilliseconds(1), |
| 157 base::TimeDelta::FromMinutes(10), |
| 158 100); |
| 159 break; |
| 160 |
| 161 case CONNECTION_LATENCY_IPV6_RACEABLE: |
| 162 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", |
| 163 connect_duration, |
| 164 base::TimeDelta::FromMilliseconds(1), |
| 165 base::TimeDelta::FromMinutes(10), |
| 166 100); |
| 167 break; |
| 168 |
| 169 case CONNECTION_LATENCY_IPV6_SOLO: |
| 170 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", |
| 171 connect_duration, |
| 172 base::TimeDelta::FromMilliseconds(1), |
| 173 base::TimeDelta::FromMinutes(10), |
| 174 100); |
| 175 break; |
| 176 |
| 177 default: |
| 178 NOTREACHED(); |
| 179 break; |
| 180 } |
| 181 |
| 182 return connect_duration; |
| 183 } |
| 184 |
84 TransportConnectJob::TransportConnectJob( | 185 TransportConnectJob::TransportConnectJob( |
85 const std::string& group_name, | 186 const std::string& group_name, |
86 RequestPriority priority, | 187 RequestPriority priority, |
87 const scoped_refptr<TransportSocketParams>& params, | 188 const scoped_refptr<TransportSocketParams>& params, |
88 base::TimeDelta timeout_duration, | 189 base::TimeDelta timeout_duration, |
89 ClientSocketFactory* client_socket_factory, | 190 ClientSocketFactory* client_socket_factory, |
90 HostResolver* host_resolver, | 191 HostResolver* host_resolver, |
91 Delegate* delegate, | 192 Delegate* delegate, |
92 NetLog* net_log) | 193 NetLog* net_log) |
93 : ConnectJob(group_name, timeout_duration, priority, delegate, | 194 : ConnectJob(group_name, timeout_duration, priority, delegate, |
94 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), | 195 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), |
95 params_(params), | 196 helper_(params, client_socket_factory, host_resolver, &connect_timing_), |
96 client_socket_factory_(client_socket_factory), | |
97 resolver_(host_resolver), | |
98 next_state_(STATE_NONE), | |
99 interval_between_connects_(CONNECT_INTERVAL_GT_20MS) { | 197 interval_between_connects_(CONNECT_INTERVAL_GT_20MS) { |
| 198 helper_.SetOnIOComplete(this); |
100 } | 199 } |
101 | 200 |
102 TransportConnectJob::~TransportConnectJob() { | 201 TransportConnectJob::~TransportConnectJob() { |
103 // We don't worry about cancelling the host resolution and TCP connect, since | 202 // We don't worry about cancelling the host resolution and TCP connect, since |
104 // ~SingleRequestHostResolver and ~StreamSocket will take care of it. | 203 // ~SingleRequestHostResolver and ~StreamSocket will take care of it. |
105 } | 204 } |
106 | 205 |
107 LoadState TransportConnectJob::GetLoadState() const { | 206 LoadState TransportConnectJob::GetLoadState() const { |
108 switch (next_state_) { | 207 switch (helper_.next_state()) { |
109 case STATE_RESOLVE_HOST: | 208 case TransportConnectJobHelper::STATE_RESOLVE_HOST: |
110 case STATE_RESOLVE_HOST_COMPLETE: | 209 case TransportConnectJobHelper::STATE_RESOLVE_HOST_COMPLETE: |
111 return LOAD_STATE_RESOLVING_HOST; | 210 return LOAD_STATE_RESOLVING_HOST; |
112 case STATE_TRANSPORT_CONNECT: | 211 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT: |
113 case STATE_TRANSPORT_CONNECT_COMPLETE: | 212 case TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE: |
114 return LOAD_STATE_CONNECTING; | 213 return LOAD_STATE_CONNECTING; |
115 case STATE_NONE: | 214 case TransportConnectJobHelper::STATE_NONE: |
116 return LOAD_STATE_IDLE; | 215 return LOAD_STATE_IDLE; |
117 } | 216 } |
118 NOTREACHED(); | 217 NOTREACHED(); |
119 return LOAD_STATE_IDLE; | 218 return LOAD_STATE_IDLE; |
120 } | 219 } |
121 | 220 |
122 // static | 221 // static |
123 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { | 222 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) { |
124 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) { | 223 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) { |
125 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) { | 224 if (i->GetFamily() == ADDRESS_FAMILY_IPV4) { |
126 std::rotate(list->begin(), i, list->end()); | 225 std::rotate(list->begin(), i, list->end()); |
127 break; | 226 break; |
128 } | 227 } |
129 } | 228 } |
130 } | 229 } |
131 | 230 |
132 void TransportConnectJob::OnIOComplete(int result) { | |
133 int rv = DoLoop(result); | |
134 if (rv != ERR_IO_PENDING) | |
135 NotifyDelegateOfCompletion(rv); // Deletes |this| | |
136 } | |
137 | |
138 int TransportConnectJob::DoLoop(int result) { | |
139 DCHECK_NE(next_state_, STATE_NONE); | |
140 | |
141 int rv = result; | |
142 do { | |
143 State state = next_state_; | |
144 next_state_ = STATE_NONE; | |
145 switch (state) { | |
146 case STATE_RESOLVE_HOST: | |
147 DCHECK_EQ(OK, rv); | |
148 rv = DoResolveHost(); | |
149 break; | |
150 case STATE_RESOLVE_HOST_COMPLETE: | |
151 rv = DoResolveHostComplete(rv); | |
152 break; | |
153 case STATE_TRANSPORT_CONNECT: | |
154 DCHECK_EQ(OK, rv); | |
155 rv = DoTransportConnect(); | |
156 break; | |
157 case STATE_TRANSPORT_CONNECT_COMPLETE: | |
158 rv = DoTransportConnectComplete(rv); | |
159 break; | |
160 default: | |
161 NOTREACHED(); | |
162 rv = ERR_FAILED; | |
163 break; | |
164 } | |
165 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
166 | |
167 return rv; | |
168 } | |
169 | |
170 int TransportConnectJob::DoResolveHost() { | 231 int TransportConnectJob::DoResolveHost() { |
171 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | 232 return helper_.DoResolveHost(priority(), net_log()); |
172 connect_timing_.dns_start = base::TimeTicks::Now(); | |
173 | |
174 return resolver_.Resolve( | |
175 params_->destination(), | |
176 priority(), | |
177 &addresses_, | |
178 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this)), | |
179 net_log()); | |
180 } | 233 } |
181 | 234 |
182 int TransportConnectJob::DoResolveHostComplete(int result) { | 235 int TransportConnectJob::DoResolveHostComplete(int result) { |
183 connect_timing_.dns_end = base::TimeTicks::Now(); | 236 return helper_.DoResolveHostComplete(result, net_log()); |
184 // Overwrite connection start time, since for connections that do not go | |
185 // through proxies, |connect_start| should not include dns lookup time. | |
186 connect_timing_.connect_start = connect_timing_.dns_end; | |
187 | |
188 if (result == OK) { | |
189 // Invoke callback, and abort if it fails. | |
190 if (!params_->host_resolution_callback().is_null()) | |
191 result = params_->host_resolution_callback().Run(addresses_, net_log()); | |
192 | |
193 if (result == OK) | |
194 next_state_ = STATE_TRANSPORT_CONNECT; | |
195 } | |
196 return result; | |
197 } | 237 } |
198 | 238 |
199 int TransportConnectJob::DoTransportConnect() { | 239 int TransportConnectJob::DoTransportConnect() { |
200 base::TimeTicks now = base::TimeTicks::Now(); | 240 base::TimeTicks now = base::TimeTicks::Now(); |
201 base::TimeTicks last_connect_time; | 241 base::TimeTicks last_connect_time; |
202 { | 242 { |
203 base::AutoLock lock(g_last_connect_time_lock.Get()); | 243 base::AutoLock lock(g_last_connect_time_lock.Get()); |
204 last_connect_time = g_last_connect_time.Get(); | 244 last_connect_time = g_last_connect_time.Get(); |
205 *g_last_connect_time.Pointer() = now; | 245 *g_last_connect_time.Pointer() = now; |
206 } | 246 } |
207 if (last_connect_time.is_null()) { | 247 if (last_connect_time.is_null()) { |
208 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; | 248 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; |
209 } else { | 249 } else { |
210 int64 interval = (now - last_connect_time).InMilliseconds(); | 250 int64 interval = (now - last_connect_time).InMilliseconds(); |
211 if (interval <= 10) | 251 if (interval <= 10) |
212 interval_between_connects_ = CONNECT_INTERVAL_LE_10MS; | 252 interval_between_connects_ = CONNECT_INTERVAL_LE_10MS; |
213 else if (interval <= 20) | 253 else if (interval <= 20) |
214 interval_between_connects_ = CONNECT_INTERVAL_LE_20MS; | 254 interval_between_connects_ = CONNECT_INTERVAL_LE_20MS; |
215 else | 255 else |
216 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; | 256 interval_between_connects_ = CONNECT_INTERVAL_GT_20MS; |
217 } | 257 } |
218 | 258 |
219 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; | 259 helper_.set_next_state( |
220 transport_socket_ = client_socket_factory_->CreateTransportClientSocket( | 260 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE); |
221 addresses_, net_log().net_log(), net_log().source()); | 261 transport_socket_ = |
222 int rv = transport_socket_->Connect( | 262 helper_.client_socket_factory()->CreateTransportClientSocket( |
223 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this))); | 263 helper_.addresses(), net_log().net_log(), net_log().source()); |
| 264 int rv = transport_socket_->Connect(helper_.on_io_complete()); |
224 if (rv == ERR_IO_PENDING && | 265 if (rv == ERR_IO_PENDING && |
225 addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV6 && | 266 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 && |
226 !AddressListOnlyContainsIPv6(addresses_)) { | 267 !AddressListOnlyContainsIPv6(helper_.addresses())) { |
227 fallback_timer_.Start(FROM_HERE, | 268 fallback_timer_.Start( |
228 base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs), | 269 FROM_HERE, |
229 this, &TransportConnectJob::DoIPv6FallbackTransportConnect); | 270 base::TimeDelta::FromMilliseconds( |
| 271 TransportConnectJobHelper::kIPv6FallbackTimerInMs), |
| 272 this, |
| 273 &TransportConnectJob::DoIPv6FallbackTransportConnect); |
230 } | 274 } |
231 return rv; | 275 return rv; |
232 } | 276 } |
233 | 277 |
234 int TransportConnectJob::DoTransportConnectComplete(int result) { | 278 int TransportConnectJob::DoTransportConnectComplete(int result) { |
235 if (result == OK) { | 279 if (result == OK) { |
236 bool is_ipv4 = addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV4; | 280 bool is_ipv4 = |
237 DCHECK(!connect_timing_.connect_start.is_null()); | 281 helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4; |
238 DCHECK(!connect_timing_.dns_start.is_null()); | 282 TransportConnectJobHelper::ConnectionLatencyHistogram race_result = |
239 base::TimeTicks now = base::TimeTicks::Now(); | 283 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN; |
240 base::TimeDelta total_duration = now - connect_timing_.dns_start; | 284 if (is_ipv4) { |
241 UMA_HISTOGRAM_CUSTOM_TIMES( | 285 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE; |
242 "Net.DNS_Resolution_And_TCP_Connection_Latency2", | 286 } else { |
243 total_duration, | 287 if (AddressListOnlyContainsIPv6(helper_.addresses())) { |
244 base::TimeDelta::FromMilliseconds(1), | 288 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO; |
245 base::TimeDelta::FromMinutes(10), | 289 } else { |
246 100); | 290 race_result = |
247 | 291 TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE; |
248 base::TimeDelta connect_duration = now - connect_timing_.connect_start; | 292 } |
249 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", | 293 } |
250 connect_duration, | 294 base::TimeDelta connect_duration = helper_.HistogramDuration(race_result); |
251 base::TimeDelta::FromMilliseconds(1), | |
252 base::TimeDelta::FromMinutes(10), | |
253 100); | |
254 | |
255 switch (interval_between_connects_) { | 295 switch (interval_between_connects_) { |
256 case CONNECT_INTERVAL_LE_10MS: | 296 case CONNECT_INTERVAL_LE_10MS: |
257 UMA_HISTOGRAM_CUSTOM_TIMES( | 297 UMA_HISTOGRAM_CUSTOM_TIMES( |
258 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms", | 298 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms", |
259 connect_duration, | 299 connect_duration, |
260 base::TimeDelta::FromMilliseconds(1), | 300 base::TimeDelta::FromMilliseconds(1), |
261 base::TimeDelta::FromMinutes(10), | 301 base::TimeDelta::FromMinutes(10), |
262 100); | 302 100); |
263 break; | 303 break; |
264 case CONNECT_INTERVAL_LE_20MS: | 304 case CONNECT_INTERVAL_LE_20MS: |
(...skipping 10 matching lines...) Expand all Loading... |
275 connect_duration, | 315 connect_duration, |
276 base::TimeDelta::FromMilliseconds(1), | 316 base::TimeDelta::FromMilliseconds(1), |
277 base::TimeDelta::FromMinutes(10), | 317 base::TimeDelta::FromMinutes(10), |
278 100); | 318 100); |
279 break; | 319 break; |
280 default: | 320 default: |
281 NOTREACHED(); | 321 NOTREACHED(); |
282 break; | 322 break; |
283 } | 323 } |
284 | 324 |
285 if (is_ipv4) { | |
286 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", | |
287 connect_duration, | |
288 base::TimeDelta::FromMilliseconds(1), | |
289 base::TimeDelta::FromMinutes(10), | |
290 100); | |
291 } else { | |
292 if (AddressListOnlyContainsIPv6(addresses_)) { | |
293 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", | |
294 connect_duration, | |
295 base::TimeDelta::FromMilliseconds(1), | |
296 base::TimeDelta::FromMinutes(10), | |
297 100); | |
298 } else { | |
299 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", | |
300 connect_duration, | |
301 base::TimeDelta::FromMilliseconds(1), | |
302 base::TimeDelta::FromMinutes(10), | |
303 100); | |
304 } | |
305 } | |
306 SetSocket(transport_socket_.Pass()); | 325 SetSocket(transport_socket_.Pass()); |
307 fallback_timer_.Stop(); | 326 fallback_timer_.Stop(); |
308 } else { | 327 } else { |
309 // Be a bit paranoid and kill off the fallback members to prevent reuse. | 328 // Be a bit paranoid and kill off the fallback members to prevent reuse. |
310 fallback_transport_socket_.reset(); | 329 fallback_transport_socket_.reset(); |
311 fallback_addresses_.reset(); | 330 fallback_addresses_.reset(); |
312 } | 331 } |
313 | 332 |
314 return result; | 333 return result; |
315 } | 334 } |
316 | 335 |
317 void TransportConnectJob::DoIPv6FallbackTransportConnect() { | 336 void TransportConnectJob::DoIPv6FallbackTransportConnect() { |
318 // The timer should only fire while we're waiting for the main connect to | 337 // The timer should only fire while we're waiting for the main connect to |
319 // succeed. | 338 // succeed. |
320 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { | 339 if (helper_.next_state() != |
| 340 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { |
321 NOTREACHED(); | 341 NOTREACHED(); |
322 return; | 342 return; |
323 } | 343 } |
324 | 344 |
325 DCHECK(!fallback_transport_socket_.get()); | 345 DCHECK(!fallback_transport_socket_.get()); |
326 DCHECK(!fallback_addresses_.get()); | 346 DCHECK(!fallback_addresses_.get()); |
327 | 347 |
328 fallback_addresses_.reset(new AddressList(addresses_)); | 348 fallback_addresses_.reset(new AddressList(helper_.addresses())); |
329 MakeAddressListStartWithIPv4(fallback_addresses_.get()); | 349 MakeAddressListStartWithIPv4(fallback_addresses_.get()); |
330 fallback_transport_socket_ = | 350 fallback_transport_socket_ = |
331 client_socket_factory_->CreateTransportClientSocket( | 351 helper_.client_socket_factory()->CreateTransportClientSocket( |
332 *fallback_addresses_, net_log().net_log(), net_log().source()); | 352 *fallback_addresses_, net_log().net_log(), net_log().source()); |
333 fallback_connect_start_time_ = base::TimeTicks::Now(); | 353 fallback_connect_start_time_ = base::TimeTicks::Now(); |
334 int rv = fallback_transport_socket_->Connect( | 354 int rv = fallback_transport_socket_->Connect( |
335 base::Bind( | 355 base::Bind( |
336 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, | 356 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, |
337 base::Unretained(this))); | 357 base::Unretained(this))); |
338 if (rv != ERR_IO_PENDING) | 358 if (rv != ERR_IO_PENDING) |
339 DoIPv6FallbackTransportConnectComplete(rv); | 359 DoIPv6FallbackTransportConnectComplete(rv); |
340 } | 360 } |
341 | 361 |
342 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { | 362 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { |
343 // This should only happen when we're waiting for the main connect to succeed. | 363 // This should only happen when we're waiting for the main connect to succeed. |
344 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { | 364 if (helper_.next_state() != |
| 365 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) { |
345 NOTREACHED(); | 366 NOTREACHED(); |
346 return; | 367 return; |
347 } | 368 } |
348 | 369 |
349 DCHECK_NE(ERR_IO_PENDING, result); | 370 DCHECK_NE(ERR_IO_PENDING, result); |
350 DCHECK(fallback_transport_socket_.get()); | 371 DCHECK(fallback_transport_socket_.get()); |
351 DCHECK(fallback_addresses_.get()); | 372 DCHECK(fallback_addresses_.get()); |
352 | 373 |
353 if (result == OK) { | 374 if (result == OK) { |
354 DCHECK(!fallback_connect_start_time_.is_null()); | 375 DCHECK(!fallback_connect_start_time_.is_null()); |
355 DCHECK(!connect_timing_.dns_start.is_null()); | 376 connect_timing_.connect_start = fallback_connect_start_time_; |
356 base::TimeTicks now = base::TimeTicks::Now(); | 377 helper_.HistogramDuration( |
357 base::TimeDelta total_duration = now - connect_timing_.dns_start; | 378 TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE); |
358 UMA_HISTOGRAM_CUSTOM_TIMES( | |
359 "Net.DNS_Resolution_And_TCP_Connection_Latency2", | |
360 total_duration, | |
361 base::TimeDelta::FromMilliseconds(1), | |
362 base::TimeDelta::FromMinutes(10), | |
363 100); | |
364 | |
365 base::TimeDelta connect_duration = now - fallback_connect_start_time_; | |
366 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", | |
367 connect_duration, | |
368 base::TimeDelta::FromMilliseconds(1), | |
369 base::TimeDelta::FromMinutes(10), | |
370 100); | |
371 | |
372 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race", | |
373 connect_duration, | |
374 base::TimeDelta::FromMilliseconds(1), | |
375 base::TimeDelta::FromMinutes(10), | |
376 100); | |
377 SetSocket(fallback_transport_socket_.Pass()); | 379 SetSocket(fallback_transport_socket_.Pass()); |
378 next_state_ = STATE_NONE; | 380 helper_.set_next_state(TransportConnectJobHelper::STATE_NONE); |
379 transport_socket_.reset(); | 381 transport_socket_.reset(); |
380 } else { | 382 } else { |
381 // Be a bit paranoid and kill off the fallback members to prevent reuse. | 383 // Be a bit paranoid and kill off the fallback members to prevent reuse. |
382 fallback_transport_socket_.reset(); | 384 fallback_transport_socket_.reset(); |
383 fallback_addresses_.reset(); | 385 fallback_addresses_.reset(); |
384 } | 386 } |
385 NotifyDelegateOfCompletion(result); // Deletes |this| | 387 NotifyDelegateOfCompletion(result); // Deletes |this| |
386 } | 388 } |
387 | 389 |
388 int TransportConnectJob::ConnectInternal() { | 390 int TransportConnectJob::ConnectInternal() { |
389 next_state_ = STATE_RESOLVE_HOST; | 391 return helper_.DoConnectInternal(this); |
390 return DoLoop(OK); | |
391 } | 392 } |
392 | 393 |
393 scoped_ptr<ConnectJob> | 394 scoped_ptr<ConnectJob> |
394 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( | 395 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( |
395 const std::string& group_name, | 396 const std::string& group_name, |
396 const PoolBase::Request& request, | 397 const PoolBase::Request& request, |
397 ConnectJob::Delegate* delegate) const { | 398 ConnectJob::Delegate* delegate) const { |
398 return scoped_ptr<ConnectJob>( | 399 return scoped_ptr<ConnectJob>( |
399 new TransportConnectJob(group_name, | 400 new TransportConnectJob(group_name, |
400 request.priority(), | 401 request.priority(), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 int TransportClientSocketPool::RequestSocket( | 433 int TransportClientSocketPool::RequestSocket( |
433 const std::string& group_name, | 434 const std::string& group_name, |
434 const void* params, | 435 const void* params, |
435 RequestPriority priority, | 436 RequestPriority priority, |
436 ClientSocketHandle* handle, | 437 ClientSocketHandle* handle, |
437 const CompletionCallback& callback, | 438 const CompletionCallback& callback, |
438 const BoundNetLog& net_log) { | 439 const BoundNetLog& net_log) { |
439 const scoped_refptr<TransportSocketParams>* casted_params = | 440 const scoped_refptr<TransportSocketParams>* casted_params = |
440 static_cast<const scoped_refptr<TransportSocketParams>*>(params); | 441 static_cast<const scoped_refptr<TransportSocketParams>*>(params); |
441 | 442 |
| 443 NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params); |
| 444 |
| 445 return base_.RequestSocket(group_name, *casted_params, priority, handle, |
| 446 callback, net_log); |
| 447 } |
| 448 |
| 449 void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket( |
| 450 const BoundNetLog& net_log, |
| 451 const scoped_refptr<TransportSocketParams>* casted_params) { |
442 if (net_log.IsLogging()) { | 452 if (net_log.IsLogging()) { |
443 // TODO(eroman): Split out the host and port parameters. | 453 // TODO(eroman): Split out the host and port parameters. |
444 net_log.AddEvent( | 454 net_log.AddEvent( |
445 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, | 455 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, |
446 CreateNetLogHostPortPairCallback( | 456 CreateNetLogHostPortPairCallback( |
447 &casted_params->get()->destination().host_port_pair())); | 457 &casted_params->get()->destination().host_port_pair())); |
448 } | 458 } |
449 | |
450 return base_.RequestSocket(group_name, *casted_params, priority, handle, | |
451 callback, net_log); | |
452 } | 459 } |
453 | 460 |
454 void TransportClientSocketPool::RequestSockets( | 461 void TransportClientSocketPool::RequestSockets( |
455 const std::string& group_name, | 462 const std::string& group_name, |
456 const void* params, | 463 const void* params, |
457 int num_sockets, | 464 int num_sockets, |
458 const BoundNetLog& net_log) { | 465 const BoundNetLog& net_log) { |
459 const scoped_refptr<TransportSocketParams>* casted_params = | 466 const scoped_refptr<TransportSocketParams>* casted_params = |
460 static_cast<const scoped_refptr<TransportSocketParams>*>(params); | 467 static_cast<const scoped_refptr<TransportSocketParams>*>(params); |
461 | 468 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 HigherLayeredPool* higher_pool) { | 535 HigherLayeredPool* higher_pool) { |
529 base_.AddHigherLayeredPool(higher_pool); | 536 base_.AddHigherLayeredPool(higher_pool); |
530 } | 537 } |
531 | 538 |
532 void TransportClientSocketPool::RemoveHigherLayeredPool( | 539 void TransportClientSocketPool::RemoveHigherLayeredPool( |
533 HigherLayeredPool* higher_pool) { | 540 HigherLayeredPool* higher_pool) { |
534 base_.RemoveHigherLayeredPool(higher_pool); | 541 base_.RemoveHigherLayeredPool(higher_pool); |
535 } | 542 } |
536 | 543 |
537 } // namespace net | 544 } // namespace net |
OLD | NEW |