OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "google_apis/gcm/engine/connection_factory_impl.h" | 5 #include "google_apis/gcm/engine/connection_factory_impl.h" |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/metrics/sparse_histogram.h" | 9 #include "base/metrics/sparse_histogram.h" |
10 #include "google_apis/gcm/engine/connection_handler_impl.h" | 10 #include "google_apis/gcm/engine/connection_handler_impl.h" |
11 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" | |
11 #include "google_apis/gcm/protocol/mcs.pb.h" | 12 #include "google_apis/gcm/protocol/mcs.pb.h" |
12 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
13 #include "net/http/http_network_session.h" | 14 #include "net/http/http_network_session.h" |
14 #include "net/http/http_request_headers.h" | 15 #include "net/http/http_request_headers.h" |
15 #include "net/proxy/proxy_info.h" | 16 #include "net/proxy/proxy_info.h" |
16 #include "net/socket/client_socket_handle.h" | 17 #include "net/socket/client_socket_handle.h" |
17 #include "net/socket/client_socket_pool_manager.h" | 18 #include "net/socket/client_socket_pool_manager.h" |
18 #include "net/ssl/ssl_config_service.h" | 19 #include "net/ssl/ssl_config_service.h" |
19 | 20 |
20 namespace gcm { | 21 namespace gcm { |
(...skipping 16 matching lines...) Expand all Loading... | |
37 now_ticks - login_time <= | 38 now_ticks - login_time <= |
38 base::TimeDelta::FromSeconds(kConnectionResetWindowSecs); | 39 base::TimeDelta::FromSeconds(kConnectionResetWindowSecs); |
39 } | 40 } |
40 | 41 |
41 } // namespace | 42 } // namespace |
42 | 43 |
43 ConnectionFactoryImpl::ConnectionFactoryImpl( | 44 ConnectionFactoryImpl::ConnectionFactoryImpl( |
44 const std::vector<GURL>& mcs_endpoints, | 45 const std::vector<GURL>& mcs_endpoints, |
45 const net::BackoffEntry::Policy& backoff_policy, | 46 const net::BackoffEntry::Policy& backoff_policy, |
46 scoped_refptr<net::HttpNetworkSession> network_session, | 47 scoped_refptr<net::HttpNetworkSession> network_session, |
47 net::NetLog* net_log) | 48 net::NetLog* net_log, |
49 GCMStatsRecorder* recorder) | |
48 : mcs_endpoints_(mcs_endpoints), | 50 : mcs_endpoints_(mcs_endpoints), |
49 next_endpoint_(0), | 51 next_endpoint_(0), |
50 last_successful_endpoint_(0), | 52 last_successful_endpoint_(0), |
51 backoff_policy_(backoff_policy), | 53 backoff_policy_(backoff_policy), |
52 network_session_(network_session), | 54 network_session_(network_session), |
53 bound_net_log_( | 55 bound_net_log_( |
54 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), | 56 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), |
55 pac_request_(NULL), | 57 pac_request_(NULL), |
56 connecting_(false), | 58 connecting_(false), |
57 waiting_for_backoff_(false), | 59 waiting_for_backoff_(false), |
58 logging_in_(false), | 60 logging_in_(false), |
61 recorder_(recorder), | |
59 weak_ptr_factory_(this) { | 62 weak_ptr_factory_(this) { |
60 DCHECK_GE(mcs_endpoints_.size(), 1U); | 63 DCHECK_GE(mcs_endpoints_.size(), 1U); |
61 } | 64 } |
62 | 65 |
63 ConnectionFactoryImpl::~ConnectionFactoryImpl() { | 66 ConnectionFactoryImpl::~ConnectionFactoryImpl() { |
64 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 67 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
65 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 68 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
66 if (pac_request_) { | 69 if (pac_request_) { |
67 network_session_->proxy_service()->CancelPacRequest(pac_request_); | 70 network_session_->proxy_service()->CancelPacRequest(pac_request_); |
68 pac_request_ = NULL; | 71 pac_request_ = NULL; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 if (connecting_ || logging_in_ || IsEndpointReachable()) { | 114 if (connecting_ || logging_in_ || IsEndpointReachable()) { |
112 waiting_for_backoff_ = false; | 115 waiting_for_backoff_ = false; |
113 return; | 116 return; |
114 } | 117 } |
115 | 118 |
116 if (backoff_entry_->ShouldRejectRequest()) { | 119 if (backoff_entry_->ShouldRejectRequest()) { |
117 DVLOG(1) << "Delaying MCS endpoint connection for " | 120 DVLOG(1) << "Delaying MCS endpoint connection for " |
118 << backoff_entry_->GetTimeUntilRelease().InMilliseconds() | 121 << backoff_entry_->GetTimeUntilRelease().InMilliseconds() |
119 << " milliseconds."; | 122 << " milliseconds."; |
120 waiting_for_backoff_ = true; | 123 waiting_for_backoff_ = true; |
124 recorder_->RecordConnectionDelayedDueToBackoff( | |
125 backoff_entry_->GetTimeUntilRelease().InMilliseconds()); | |
121 base::MessageLoop::current()->PostDelayedTask( | 126 base::MessageLoop::current()->PostDelayedTask( |
122 FROM_HERE, | 127 FROM_HERE, |
123 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff, | 128 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff, |
124 weak_ptr_factory_.GetWeakPtr()), | 129 weak_ptr_factory_.GetWeakPtr()), |
125 backoff_entry_->GetTimeUntilRelease()); | 130 backoff_entry_->GetTimeUntilRelease()); |
126 return; | 131 return; |
127 } | 132 } |
128 | 133 |
129 DVLOG(1) << "Attempting connection to MCS endpoint."; | 134 DVLOG(1) << "Attempting connection to MCS endpoint."; |
130 waiting_for_backoff_ = false; | 135 waiting_for_backoff_ = false; |
131 ConnectImpl(); | 136 ConnectImpl(); |
132 } | 137 } |
133 | 138 |
134 bool ConnectionFactoryImpl::IsEndpointReachable() const { | 139 bool ConnectionFactoryImpl::IsEndpointReachable() const { |
135 return connection_handler_ && connection_handler_->CanSendMessage(); | 140 return connection_handler_ && connection_handler_->CanSendMessage(); |
136 } | 141 } |
137 | 142 |
138 void ConnectionFactoryImpl::SignalConnectionReset( | 143 void ConnectionFactoryImpl::SignalConnectionReset( |
139 ConnectionResetReason reason) { | 144 ConnectionResetReason reason) { |
140 // A failure can trigger multiple resets, so no need to do anything if a | 145 // A failure can trigger multiple resets, so no need to do anything if a |
141 // connection is already in progress. | 146 // connection is already in progress. |
142 if (connecting_) { | 147 if (connecting_) { |
143 DVLOG(1) << "Connection in progress, ignoring reset."; | 148 DVLOG(1) << "Connection in progress, ignoring reset."; |
144 return; | 149 return; |
145 } | 150 } |
146 | 151 |
147 UMA_HISTOGRAM_ENUMERATION("GCM.ConnectionResetReason", | 152 UMA_HISTOGRAM_ENUMERATION("GCM.ConnectionResetReason", |
148 reason, | 153 reason, |
149 CONNECTION_RESET_COUNT); | 154 CONNECTION_RESET_COUNT); |
155 recorder_->RecordConnectionResetSignaled(reason); | |
150 if (!last_login_time_.is_null()) { | 156 if (!last_login_time_.is_null()) { |
151 UMA_HISTOGRAM_CUSTOM_TIMES("GCM.ConnectionUpTime", | 157 UMA_HISTOGRAM_CUSTOM_TIMES("GCM.ConnectionUpTime", |
152 NowTicks() - last_login_time_, | 158 NowTicks() - last_login_time_, |
153 base::TimeDelta::FromSeconds(1), | 159 base::TimeDelta::FromSeconds(1), |
154 base::TimeDelta::FromHours(24), | 160 base::TimeDelta::FromHours(24), |
155 50); | 161 50); |
156 // |last_login_time_| will be reset below, before attempting the new | 162 // |last_login_time_| will be reset below, before attempting the new |
157 // connection. | 163 // connection. |
158 } | 164 } |
159 | 165 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 if (IsEndpointReachable()) | 232 if (IsEndpointReachable()) |
227 return mcs_endpoints_[last_successful_endpoint_]; | 233 return mcs_endpoints_[last_successful_endpoint_]; |
228 return mcs_endpoints_[next_endpoint_]; | 234 return mcs_endpoints_[next_endpoint_]; |
229 } | 235 } |
230 | 236 |
231 void ConnectionFactoryImpl::ConnectImpl() { | 237 void ConnectionFactoryImpl::ConnectImpl() { |
232 DCHECK(!IsEndpointReachable()); | 238 DCHECK(!IsEndpointReachable()); |
233 DCHECK(!socket_handle_.socket()); | 239 DCHECK(!socket_handle_.socket()); |
234 | 240 |
235 connecting_ = true; | 241 connecting_ = true; |
242 GURL cur_endpoint = GetCurrentEndpoint(); | |
jianli
2014/04/23 17:22:35
nit: avoid using abbreviation if possible. so name
juyik
2014/04/23 21:36:56
Done.
| |
243 recorder_->RecordConnectionInitiated(cur_endpoint.host()); | |
236 int status = network_session_->proxy_service()->ResolveProxy( | 244 int status = network_session_->proxy_service()->ResolveProxy( |
237 GetCurrentEndpoint(), | 245 cur_endpoint, |
238 &proxy_info_, | 246 &proxy_info_, |
239 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, | 247 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, |
240 weak_ptr_factory_.GetWeakPtr()), | 248 weak_ptr_factory_.GetWeakPtr()), |
241 &pac_request_, | 249 &pac_request_, |
242 bound_net_log_); | 250 bound_net_log_); |
243 if (status != net::ERR_IO_PENDING) | 251 if (status != net::ERR_IO_PENDING) |
244 OnProxyResolveDone(status); | 252 OnProxyResolveDone(status); |
245 } | 253 } |
246 | 254 |
247 void ConnectionFactoryImpl::InitHandler() { | 255 void ConnectionFactoryImpl::InitHandler() { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 connecting_ = false; | 308 connecting_ = false; |
301 Connect(); | 309 Connect(); |
302 return; | 310 return; |
303 } | 311 } |
304 | 312 |
305 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); | 313 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); |
306 UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_); | 314 UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_); |
307 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy", | 315 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy", |
308 !(proxy_info_.is_empty() || proxy_info_.is_direct())); | 316 !(proxy_info_.is_empty() || proxy_info_.is_direct())); |
309 ReportSuccessfulProxyConnection(); | 317 ReportSuccessfulProxyConnection(); |
318 recorder_->RecordConnectionSuccess(); | |
310 | 319 |
311 // Reset the endpoint back to the default. | 320 // Reset the endpoint back to the default. |
312 // TODO(zea): consider prioritizing endpoints more intelligently based on | 321 // TODO(zea): consider prioritizing endpoints more intelligently based on |
313 // which ones succeed most for this client? Although that will affect | 322 // which ones succeed most for this client? Although that will affect |
314 // measuring the success rate of the default endpoint vs fallback. | 323 // measuring the success rate of the default endpoint vs fallback. |
315 last_successful_endpoint_ = next_endpoint_; | 324 last_successful_endpoint_ = next_endpoint_; |
316 next_endpoint_ = 0; | 325 next_endpoint_ = 0; |
317 connecting_ = false; | 326 connecting_ = false; |
318 logging_in_ = true; | 327 logging_in_ = true; |
319 DVLOG(1) << "MCS endpoint socket connection success, starting login."; | 328 DVLOG(1) << "MCS endpoint socket connection success, starting login."; |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 // the destroyed socket. | 492 // the destroyed socket. |
484 if (connection_handler_) | 493 if (connection_handler_) |
485 connection_handler_->Reset(); | 494 connection_handler_->Reset(); |
486 | 495 |
487 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) | 496 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) |
488 socket_handle_.socket()->Disconnect(); | 497 socket_handle_.socket()->Disconnect(); |
489 socket_handle_.Reset(); | 498 socket_handle_.Reset(); |
490 } | 499 } |
491 | 500 |
492 } // namespace gcm | 501 } // namespace gcm |
OLD | NEW |