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

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

Issue 10309002: Reimplements net::AddressList without struct addrinfo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing NET_EXPORT to *PortOnAddressList. Created 8 years, 7 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 | Annotate | Revision Log
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>
8
7 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
8 #include "base/logging.h" 10 #include "base/logging.h"
9 #include "base/message_loop.h" 11 #include "base/message_loop.h"
10 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
11 #include "base/string_util.h" 13 #include "base/string_util.h"
12 #include "base/time.h" 14 #include "base/time.h"
13 #include "base/values.h" 15 #include "base/values.h"
14 #include "net/base/ip_endpoint.h" 16 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_log.h" 17 #include "net/base/net_log.h"
16 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
17 #include "net/base/sys_addrinfo.h"
18 #include "net/socket/client_socket_factory.h" 19 #include "net/socket/client_socket_factory.h"
19 #include "net/socket/client_socket_handle.h" 20 #include "net/socket/client_socket_handle.h"
20 #include "net/socket/client_socket_pool_base.h" 21 #include "net/socket/client_socket_pool_base.h"
21 #include "net/socket/tcp_client_socket.h" 22 #include "net/socket/tcp_client_socket.h"
22 23
23 using base::TimeDelta; 24 using base::TimeDelta;
24 25
25 namespace net { 26 namespace net {
26 27
27 // TODO(willchan): Base this off RTT instead of statically setting it. Note we 28 // TODO(willchan): Base this off RTT instead of statically setting it. Note we
28 // choose a timeout that is different from the backup connect job timer so they 29 // choose a timeout that is different from the backup connect job timer so they
29 // don't synchronize. 30 // don't synchronize.
30 const int TransportConnectJob::kIPv6FallbackTimerInMs = 300; 31 const int TransportConnectJob::kIPv6FallbackTimerInMs = 300;
31 32
32 namespace { 33 namespace {
33 34
34 bool AddressListStartsWithIPv6AndHasAnIPv4Addr(const AddressList& addrlist) { 35 // Returns true iff all addresses in |list| are in the IPv6 family.
35 const struct addrinfo* ai = addrlist.head(); 36 bool AddressListOnlyContainsIPv6(const AddressList& list) {
36 if (ai->ai_family != AF_INET6) 37 DCHECK(!list.empty());
37 return false; 38 for (AddressList::const_iterator iter = list.begin(); iter != list.end();
38 39 ++iter) {
39 ai = ai->ai_next; 40 if (iter->GetFamily() != AF_INET6)
40 while (ai) {
41 if (ai->ai_family != AF_INET6)
42 return true;
43 ai = ai->ai_next;
44 }
45
46 return false;
47 }
48
49 bool AddressListOnlyContainsIPv6Addresses(const AddressList& addrlist) {
50 DCHECK(addrlist.head());
51 for (const struct addrinfo* ai = addrlist.head(); ai; ai = ai->ai_next) {
52 if (ai->ai_family != AF_INET6)
53 return false; 41 return false;
54 } 42 }
55
56 return true; 43 return true;
57 } 44 }
58 45
59 } // namespace 46 } // namespace
60 47
61 TransportSocketParams::TransportSocketParams( 48 TransportSocketParams::TransportSocketParams(
62 const HostPortPair& host_port_pair, 49 const HostPortPair& host_port_pair,
63 RequestPriority priority, 50 RequestPriority priority,
64 bool disable_resolver_cache, 51 bool disable_resolver_cache,
65 bool ignore_limits) 52 bool ignore_limits)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 case STATE_TRANSPORT_CONNECT: 103 case STATE_TRANSPORT_CONNECT:
117 case STATE_TRANSPORT_CONNECT_COMPLETE: 104 case STATE_TRANSPORT_CONNECT_COMPLETE:
118 return LOAD_STATE_CONNECTING; 105 return LOAD_STATE_CONNECTING;
119 default: 106 default:
120 NOTREACHED(); 107 NOTREACHED();
121 return LOAD_STATE_IDLE; 108 return LOAD_STATE_IDLE;
122 } 109 }
123 } 110 }
124 111
125 // static 112 // static
126 void TransportConnectJob::MakeAddrListStartWithIPv4(AddressList* addrlist) { 113 void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) {
127 if (addrlist->head()->ai_family != AF_INET6) 114 for (AddressList::iterator i = list->begin(); i != list->end(); ++i) {
128 return; 115 if (i->GetFamily() == AF_INET) {
129 bool has_ipv4 = false; 116 std::rotate(list->begin(), i, list->end());
eroman 2012/05/04 01:08:41 Hmm I'll need to lookup rotate and think about thi
130 for (const struct addrinfo* ai = addrlist->head(); ai; ai = ai->ai_next) {
131 if (ai->ai_family != AF_INET6) {
132 has_ipv4 = true;
133 break; 117 break;
134 } 118 }
135 } 119 }
136 if (!has_ipv4)
137 return;
138
139 struct addrinfo* head = CreateCopyOfAddrinfo(addrlist->head(), true);
140 struct addrinfo* tail = head;
141 while (tail->ai_next)
142 tail = tail->ai_next;
143 char* canonname = head->ai_canonname;
144 head->ai_canonname = NULL;
145 while (head->ai_family == AF_INET6) {
146 tail->ai_next = head;
147 tail = head;
148 head = head->ai_next;
149 tail->ai_next = NULL;
150 }
151 head->ai_canonname = canonname;
152
153 *addrlist = AddressList::CreateByCopying(head);
154 FreeCopyOfAddrinfo(head);
155 } 120 }
156 121
157 void TransportConnectJob::OnIOComplete(int result) { 122 void TransportConnectJob::OnIOComplete(int result) {
158 int rv = DoLoop(result); 123 int rv = DoLoop(result);
159 if (rv != ERR_IO_PENDING) 124 if (rv != ERR_IO_PENDING)
160 NotifyDelegateOfCompletion(rv); // Deletes |this| 125 NotifyDelegateOfCompletion(rv); // Deletes |this|
161 } 126 }
162 127
163 int TransportConnectJob::DoLoop(int result) { 128 int TransportConnectJob::DoLoop(int result) {
164 DCHECK_NE(next_state_, STATE_NONE); 129 DCHECK_NE(next_state_, STATE_NONE);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 } 172 }
208 173
209 int TransportConnectJob::DoTransportConnect() { 174 int TransportConnectJob::DoTransportConnect() {
210 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; 175 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
211 transport_socket_.reset(client_socket_factory_->CreateTransportClientSocket( 176 transport_socket_.reset(client_socket_factory_->CreateTransportClientSocket(
212 addresses_, net_log().net_log(), net_log().source())); 177 addresses_, net_log().net_log(), net_log().source()));
213 connect_start_time_ = base::TimeTicks::Now(); 178 connect_start_time_ = base::TimeTicks::Now();
214 int rv = transport_socket_->Connect( 179 int rv = transport_socket_->Connect(
215 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this))); 180 base::Bind(&TransportConnectJob::OnIOComplete, base::Unretained(this)));
216 if (rv == ERR_IO_PENDING && 181 if (rv == ERR_IO_PENDING &&
217 AddressListStartsWithIPv6AndHasAnIPv4Addr(addresses_)) { 182 addresses_.front().GetFamily() == AF_INET6 &&
183 !AddressListOnlyContainsIPv6(addresses_)) {
218 fallback_timer_.Start(FROM_HERE, 184 fallback_timer_.Start(FROM_HERE,
219 base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs), 185 base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs),
220 this, &TransportConnectJob::DoIPv6FallbackTransportConnect); 186 this, &TransportConnectJob::DoIPv6FallbackTransportConnect);
221 } 187 }
222 return rv; 188 return rv;
223 } 189 }
224 190
225 int TransportConnectJob::DoTransportConnectComplete(int result) { 191 int TransportConnectJob::DoTransportConnectComplete(int result) {
226 if (result == OK) { 192 if (result == OK) {
227 bool is_ipv4 = addresses_.head()->ai_family != AF_INET6; 193 bool is_ipv4 = addresses_.front().GetFamily() != AF_INET6;
228 DCHECK(connect_start_time_ != base::TimeTicks()); 194 DCHECK(connect_start_time_ != base::TimeTicks());
229 DCHECK(start_time_ != base::TimeTicks()); 195 DCHECK(start_time_ != base::TimeTicks());
230 base::TimeTicks now = base::TimeTicks::Now(); 196 base::TimeTicks now = base::TimeTicks::Now();
231 base::TimeDelta total_duration = now - start_time_; 197 base::TimeDelta total_duration = now - start_time_;
232 UMA_HISTOGRAM_CUSTOM_TIMES( 198 UMA_HISTOGRAM_CUSTOM_TIMES(
233 "Net.DNS_Resolution_And_TCP_Connection_Latency2", 199 "Net.DNS_Resolution_And_TCP_Connection_Latency2",
234 total_duration, 200 total_duration,
235 base::TimeDelta::FromMilliseconds(1), 201 base::TimeDelta::FromMilliseconds(1),
236 base::TimeDelta::FromMinutes(10), 202 base::TimeDelta::FromMinutes(10),
237 100); 203 100);
238 204
239 base::TimeDelta connect_duration = now - connect_start_time_; 205 base::TimeDelta connect_duration = now - connect_start_time_;
240 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", 206 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency",
241 connect_duration, 207 connect_duration,
242 base::TimeDelta::FromMilliseconds(1), 208 base::TimeDelta::FromMilliseconds(1),
243 base::TimeDelta::FromMinutes(10), 209 base::TimeDelta::FromMinutes(10),
244 100); 210 100);
245 211
246 if (is_ipv4) { 212 if (is_ipv4) {
247 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race", 213 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
248 connect_duration, 214 connect_duration,
249 base::TimeDelta::FromMilliseconds(1), 215 base::TimeDelta::FromMilliseconds(1),
250 base::TimeDelta::FromMinutes(10), 216 base::TimeDelta::FromMinutes(10),
251 100); 217 100);
252 } else { 218 } else {
253 if (AddressListOnlyContainsIPv6Addresses(addresses_)) { 219 if (AddressListOnlyContainsIPv6(addresses_)) {
254 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo", 220 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo",
255 connect_duration, 221 connect_duration,
256 base::TimeDelta::FromMilliseconds(1), 222 base::TimeDelta::FromMilliseconds(1),
257 base::TimeDelta::FromMinutes(10), 223 base::TimeDelta::FromMinutes(10),
258 100); 224 100);
259 } else { 225 } else {
260 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable", 226 UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable",
261 connect_duration, 227 connect_duration,
262 base::TimeDelta::FromMilliseconds(1), 228 base::TimeDelta::FromMilliseconds(1),
263 base::TimeDelta::FromMinutes(10), 229 base::TimeDelta::FromMinutes(10),
(...skipping 16 matching lines...) Expand all
280 // succeed. 246 // succeed.
281 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) { 247 if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) {
282 NOTREACHED(); 248 NOTREACHED();
283 return; 249 return;
284 } 250 }
285 251
286 DCHECK(!fallback_transport_socket_.get()); 252 DCHECK(!fallback_transport_socket_.get());
287 DCHECK(!fallback_addresses_.get()); 253 DCHECK(!fallback_addresses_.get());
288 254
289 fallback_addresses_.reset(new AddressList(addresses_)); 255 fallback_addresses_.reset(new AddressList(addresses_));
290 MakeAddrListStartWithIPv4(fallback_addresses_.get()); 256 MakeAddressListStartWithIPv4(fallback_addresses_.get());
291 fallback_transport_socket_.reset( 257 fallback_transport_socket_.reset(
292 client_socket_factory_->CreateTransportClientSocket( 258 client_socket_factory_->CreateTransportClientSocket(
293 *fallback_addresses_, net_log().net_log(), net_log().source())); 259 *fallback_addresses_, net_log().net_log(), net_log().source()));
294 fallback_connect_start_time_ = base::TimeTicks::Now(); 260 fallback_connect_start_time_ = base::TimeTicks::Now();
295 int rv = fallback_transport_socket_->Connect( 261 int rv = fallback_transport_socket_->Connect(
296 base::Bind( 262 base::Bind(
297 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete, 263 &TransportConnectJob::DoIPv6FallbackTransportConnectComplete,
298 base::Unretained(this))); 264 base::Unretained(this)));
299 if (rv != ERR_IO_PENDING) 265 if (rv != ERR_IO_PENDING)
300 DoIPv6FallbackTransportConnectComplete(rv); 266 DoIPv6FallbackTransportConnectComplete(rv);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 454
489 base::TimeDelta TransportClientSocketPool::ConnectionTimeout() const { 455 base::TimeDelta TransportClientSocketPool::ConnectionTimeout() const {
490 return base_.ConnectionTimeout(); 456 return base_.ConnectionTimeout();
491 } 457 }
492 458
493 ClientSocketPoolHistograms* TransportClientSocketPool::histograms() const { 459 ClientSocketPoolHistograms* TransportClientSocketPool::histograms() const {
494 return base_.histograms(); 460 return base_.histograms();
495 } 461 }
496 462
497 } // namespace net 463 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698