Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: net/socket/transport_client_socket_pool.cc

Issue 240873003: Create WebSocketTransportClientSocketPool (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Factor out CurrentAddress() method in SubJob class. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 data_(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 data_.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 (data_.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 data_.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 data_.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 data_.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 data_.client_socket_factory()->CreateTransportClientSocket(
223 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this))); 263 data_.addresses(), net_log().net_log(), net_log().source());
264 int rv = transport_socket_->Connect(data_.on_io_complete());
224 if (rv == ERR_IO_PENDING && 265 if (rv == ERR_IO_PENDING &&
225 addresses_.front().GetFamily() == ADDRESS_FAMILY_IPV6 && 266 data_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 &&
226 !AddressListOnlyContainsIPv6(addresses_)) { 267 !AddressListOnlyContainsIPv6(data_.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 = data_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4;
237 DCHECK(!connect_timing_.connect_start.is_null()); 281 TransportConnectJobHelper::ConnectionLatencyHistogram race_result =
238 DCHECK(!connect_timing_.dns_start.is_null()); 282 TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN;
239 base::TimeTicks now = base::TimeTicks::Now(); 283 if (is_ipv4) {
240 base::TimeDelta total_duration = now - connect_timing_.dns_start; 284 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
241 UMA_HISTOGRAM_CUSTOM_TIMES( 285 } else {
242 "Net.DNS_Resolution_And_TCP_Connection_Latency2", 286 if (AddressListOnlyContainsIPv6(data_.addresses())) {
243 total_duration, 287 race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
244 base::TimeDelta::FromMilliseconds(1), 288 } else {
245 base::TimeDelta::FromMinutes(10), 289 race_result =
246 100); 290 TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE;
247 291 }
248 base::TimeDelta connect_duration = now - connect_timing_.connect_start; 292 }
249 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", 293 base::TimeDelta connect_duration = data_.HistogramDuration(race_result);
250 connect_duration,
251 base::TimeDelta::FromMilliseconds(1),
252 base::TimeDelta::FromMinutes(10),
253 100);
254
255 switch (interval_between_connects_) { 294 switch (interval_between_connects_) {
256 case CONNECT_INTERVAL_LE_10MS: 295 case CONNECT_INTERVAL_LE_10MS:
257 UMA_HISTOGRAM_CUSTOM_TIMES( 296 UMA_HISTOGRAM_CUSTOM_TIMES(
258 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms", 297 "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms",
259 connect_duration, 298 connect_duration,
260 base::TimeDelta::FromMilliseconds(1), 299 base::TimeDelta::FromMilliseconds(1),
261 base::TimeDelta::FromMinutes(10), 300 base::TimeDelta::FromMinutes(10),
262 100); 301 100);
263 break; 302 break;
264 case CONNECT_INTERVAL_LE_20MS: 303 case CONNECT_INTERVAL_LE_20MS:
(...skipping 10 matching lines...) Expand all
275 connect_duration, 314 connect_duration,
276 base::TimeDelta::FromMilliseconds(1), 315 base::TimeDelta::FromMilliseconds(1),
277 base::TimeDelta::FromMinutes(10), 316 base::TimeDelta::FromMinutes(10),
278 100); 317 100);
279 break; 318 break;
280 default: 319 default:
281 NOTREACHED(); 320 NOTREACHED();
282 break; 321 break;
283 } 322 }
284 323
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()); 324 SetSocket(transport_socket_.Pass());
307 fallback_timer_.Stop(); 325 fallback_timer_.Stop();
308 } else { 326 } else {
309 // Be a bit paranoid and kill off the fallback members to prevent reuse. 327 // Be a bit paranoid and kill off the fallback members to prevent reuse.
310 fallback_transport_socket_.reset(); 328 fallback_transport_socket_.reset();
311 fallback_addresses_.reset(); 329 fallback_addresses_.reset();
312 } 330 }
313 331
314 return result; 332 return result;
315 } 333 }
316 334
317 void TransportConnectJob::DoIPv6FallbackTransportConnect() { 335 void TransportConnectJob::DoIPv6FallbackTransportConnect() {
318 // The timer should only fire while we're waiting for the main connect to 336 // The timer should only fire while we're waiting for the main connect to
319 // succeed. 337 // succeed.
320 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { 338 if (data_.next_state() !=
339 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) {
321 NOTREACHED(); 340 NOTREACHED();
322 return; 341 return;
323 } 342 }
324 343
325 DCHECK(!fallback_transport_socket_.get()); 344 DCHECK(!fallback_transport_socket_.get());
326 DCHECK(!fallback_addresses_.get()); 345 DCHECK(!fallback_addresses_.get());
327 346
328 fallback_addresses_.reset(new AddressList(addresses_)); 347 fallback_addresses_.reset(new AddressList(data_.addresses()));
329 MakeAddressListStartWithIPv4(fallback_addresses_.get()); 348 MakeAddressListStartWithIPv4(fallback_addresses_.get());
330 fallback_transport_socket_ = 349 fallback_transport_socket_ =
331 client_socket_factory_->CreateTransportClientSocket( 350 data_.client_socket_factory()->CreateTransportClientSocket(
332 *fallback_addresses_, net_log().net_log(), net_log().source()); 351 *fallback_addresses_, net_log().net_log(), net_log().source());
333 fallback_connect_start_time_ = base::TimeTicks::Now(); 352 fallback_connect_start_time_ = base::TimeTicks::Now();
334 int rv = fallback_transport_socket_->Connect( 353 int rv = fallback_transport_socket_->Connect(
335 base::Bind( 354 base::Bind(
336 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, 355 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete,
337 base::Unretained(this))); 356 base::Unretained(this)));
338 if (rv != ERR_IO_PENDING) 357 if (rv != ERR_IO_PENDING)
339 DoIPv6FallbackTransportConnectComplete(rv); 358 DoIPv6FallbackTransportConnectComplete(rv);
340 } 359 }
341 360
342 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) { 361 void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) {
343 // This should only happen when we're waiting for the main connect to succeed. 362 // This should only happen when we're waiting for the main connect to succeed.
344 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { 363 if (data_.next_state() !=
364 TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE) {
345 NOTREACHED(); 365 NOTREACHED();
346 return; 366 return;
347 } 367 }
348 368
349 DCHECK_NE(ERR_IO_PENDING, result); 369 DCHECK_NE(ERR_IO_PENDING, result);
350 DCHECK(fallback_transport_socket_.get()); 370 DCHECK(fallback_transport_socket_.get());
351 DCHECK(fallback_addresses_.get()); 371 DCHECK(fallback_addresses_.get());
352 372
353 if (result == OK) { 373 if (result == OK) {
354 DCHECK(!fallback_connect_start_time_.is_null()); 374 DCHECK(!fallback_connect_start_time_.is_null());
355 DCHECK(!connect_timing_.dns_start.is_null()); 375 connect_timing_.connect_start = fallback_connect_start_time_;
356 base::TimeTicks now = base::TimeTicks::Now(); 376 data_.HistogramDuration(
357 base::TimeDelta total_duration = now - connect_timing_.dns_start; 377 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()); 378 SetSocket(fallback_transport_socket_.Pass());
378 next_state_ = STATE_NONE; 379 data_.set_next_state(TransportConnectJobHelper::STATE_NONE);
379 transport_socket_.reset(); 380 transport_socket_.reset();
380 } else { 381 } else {
381 // Be a bit paranoid and kill off the fallback members to prevent reuse. 382 // Be a bit paranoid and kill off the fallback members to prevent reuse.
382 fallback_transport_socket_.reset(); 383 fallback_transport_socket_.reset();
383 fallback_addresses_.reset(); 384 fallback_addresses_.reset();
384 } 385 }
385 NotifyDelegateOfCompletion(result); // Deletes |this| 386 NotifyDelegateOfCompletion(result); // Deletes |this|
386 } 387 }
387 388
388 int TransportConnectJob::ConnectInternal() { 389 int TransportConnectJob::ConnectInternal() {
389 next_state_ = STATE_RESOLVE_HOST; 390 return data_.DoConnectInternal(this);
390 return DoLoop(OK);
391 } 391 }
392 392
393 scoped_ptr<ConnectJob> 393 scoped_ptr<ConnectJob>
394 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob( 394 TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob(
395 const std::string& group_name, 395 const std::string& group_name,
396 const PoolBase::Request& request, 396 const PoolBase::Request& request,
397 ConnectJob::Delegate* delegate) const { 397 ConnectJob::Delegate* delegate) const {
398 return scoped_ptr<ConnectJob>( 398 return scoped_ptr<ConnectJob>(
399 new TransportConnectJob(group_name, 399 new TransportConnectJob(group_name,
400 request.priority(), 400 request.priority(),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 int TransportClientSocketPool::RequestSocket( 432 int TransportClientSocketPool::RequestSocket(
433 const std::string& group_name, 433 const std::string& group_name,
434 const void* params, 434 const void* params,
435 RequestPriority priority, 435 RequestPriority priority,
436 ClientSocketHandle* handle, 436 ClientSocketHandle* handle,
437 const CompletionCallback& callback, 437 const CompletionCallback& callback,
438 const BoundNetLog& net_log) { 438 const BoundNetLog& net_log) {
439 const scoped_refptr<TransportSocketParams>* casted_params = 439 const scoped_refptr<TransportSocketParams>* casted_params =
440 static_cast<const scoped_refptr<TransportSocketParams>*>(params); 440 static_cast<const scoped_refptr<TransportSocketParams>*>(params);
441 441
442 NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params);
443
444 return base_.RequestSocket(group_name, *casted_params, priority, handle,
445 callback, net_log);
446 }
447
448 void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
449 const BoundNetLog& net_log,
450 const scoped_refptr<TransportSocketParams>* casted_params) {
442 if (net_log.IsLogging()) { 451 if (net_log.IsLogging()) {
443 // TODO(eroman): Split out the host and port parameters. 452 // TODO(eroman): Split out the host and port parameters.
444 net_log.AddEvent( 453 net_log.AddEvent(
445 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, 454 NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET,
446 CreateNetLogHostPortPairCallback( 455 CreateNetLogHostPortPairCallback(
447 &casted_params->get()->destination().host_port_pair())); 456 &casted_params->get()->destination().host_port_pair()));
448 } 457 }
449
450 return base_.RequestSocket(group_name, *casted_params, priority, handle,
451 callback, net_log);
452 } 458 }
453 459
454 void TransportClientSocketPool::RequestSockets( 460 void TransportClientSocketPool::RequestSockets(
455 const std::string& group_name, 461 const std::string& group_name,
456 const void* params, 462 const void* params,
457 int num_sockets, 463 int num_sockets,
458 const BoundNetLog& net_log) { 464 const BoundNetLog& net_log) {
459 const scoped_refptr<TransportSocketParams>* casted_params = 465 const scoped_refptr<TransportSocketParams>* casted_params =
460 static_cast<const scoped_refptr<TransportSocketParams>*>(params); 466 static_cast<const scoped_refptr<TransportSocketParams>*>(params);
461 467
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 HigherLayeredPool* higher_pool) { 534 HigherLayeredPool* higher_pool) {
529 base_.AddHigherLayeredPool(higher_pool); 535 base_.AddHigherLayeredPool(higher_pool);
530 } 536 }
531 537
532 void TransportClientSocketPool::RemoveHigherLayeredPool( 538 void TransportClientSocketPool::RemoveHigherLayeredPool(
533 HigherLayeredPool* higher_pool) { 539 HigherLayeredPool* higher_pool) {
534 base_.RemoveHigherLayeredPool(higher_pool); 540 base_.RemoveHigherLayeredPool(higher_pool);
535 } 541 }
536 542
537 } // namespace net 543 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698