Chromium Code Reviews| 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" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 bool ShouldRestorePreviousBackoff(const base::TimeTicks& login_time, | 34 bool ShouldRestorePreviousBackoff(const base::TimeTicks& login_time, |
| 35 const base::TimeTicks& now_ticks) { | 35 const base::TimeTicks& now_ticks) { |
| 36 return !login_time.is_null() && | 36 return !login_time.is_null() && |
| 37 now_ticks - login_time <= | 37 now_ticks - login_time <= |
| 38 base::TimeDelta::FromSeconds(kConnectionResetWindowSecs); | 38 base::TimeDelta::FromSeconds(kConnectionResetWindowSecs); |
| 39 } | 39 } |
| 40 | 40 |
| 41 } // namespace | 41 } // namespace |
| 42 | 42 |
| 43 ConnectionFactoryImpl::ConnectionFactoryImpl( | 43 ConnectionFactoryImpl::ConnectionFactoryImpl( |
| 44 const GURL& mcs_endpoint, | 44 const std::vector<GURL>& mcs_endpoints, |
| 45 const net::BackoffEntry::Policy& backoff_policy, | 45 const net::BackoffEntry::Policy& backoff_policy, |
| 46 scoped_refptr<net::HttpNetworkSession> network_session, | 46 scoped_refptr<net::HttpNetworkSession> network_session, |
| 47 net::NetLog* net_log) | 47 net::NetLog* net_log) |
| 48 : mcs_endpoint_(mcs_endpoint), | 48 : mcs_endpoints_(mcs_endpoints), |
| 49 next_endpoint_(0), | |
| 50 last_successful_endpoint_(0), | |
| 49 backoff_policy_(backoff_policy), | 51 backoff_policy_(backoff_policy), |
| 50 network_session_(network_session), | 52 network_session_(network_session), |
| 51 bound_net_log_( | 53 bound_net_log_( |
| 52 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), | 54 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), |
| 53 pac_request_(NULL), | 55 pac_request_(NULL), |
| 54 connecting_(false), | 56 connecting_(false), |
| 55 logging_in_(false), | 57 logging_in_(false), |
| 56 weak_ptr_factory_(this) { | 58 weak_ptr_factory_(this) { |
| 59 DCHECK_GE(mcs_endpoints_.size(), 1U); | |
| 57 } | 60 } |
| 58 | 61 |
| 59 ConnectionFactoryImpl::~ConnectionFactoryImpl() { | 62 ConnectionFactoryImpl::~ConnectionFactoryImpl() { |
| 60 if (pac_request_) { | 63 if (pac_request_) { |
| 61 network_session_->proxy_service()->CancelPacRequest(pac_request_); | 64 network_session_->proxy_service()->CancelPacRequest(pac_request_); |
| 62 pac_request_ = NULL; | 65 pac_request_ = NULL; |
| 63 } | 66 } |
| 64 } | 67 } |
| 65 | 68 |
| 66 void ConnectionFactoryImpl::Initialize( | 69 void ConnectionFactoryImpl::Initialize( |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 // necessary, so no need to call again. | 180 // necessary, so no need to call again. |
| 178 } | 181 } |
| 179 | 182 |
| 180 void ConnectionFactoryImpl::OnIPAddressChanged() { | 183 void ConnectionFactoryImpl::OnIPAddressChanged() { |
| 181 DVLOG(1) << "IP Address changed, resetting backoff."; | 184 DVLOG(1) << "IP Address changed, resetting backoff."; |
| 182 backoff_entry_->Reset(); | 185 backoff_entry_->Reset(); |
| 183 // Connect(..) should be retrying with backoff already if a connection is | 186 // Connect(..) should be retrying with backoff already if a connection is |
| 184 // necessary, so no need to call again. | 187 // necessary, so no need to call again. |
| 185 } | 188 } |
| 186 | 189 |
| 190 GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { | |
| 191 if (IsEndpointReachable()) | |
| 192 return mcs_endpoints_[last_successful_endpoint_]; | |
| 193 return mcs_endpoints_[next_endpoint_]; | |
| 194 } | |
| 195 | |
| 187 void ConnectionFactoryImpl::ConnectImpl() { | 196 void ConnectionFactoryImpl::ConnectImpl() { |
| 188 DCHECK(connecting_); | 197 DCHECK(connecting_); |
| 189 DCHECK(!socket_handle_.socket()); | 198 DCHECK(!socket_handle_.socket()); |
| 190 | 199 |
| 191 int status = network_session_->proxy_service()->ResolveProxy( | 200 int status = network_session_->proxy_service()->ResolveProxy( |
| 192 mcs_endpoint_, | 201 GetCurrentEndpoint(), |
| 193 &proxy_info_, | 202 &proxy_info_, |
| 194 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, | 203 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, |
| 195 weak_ptr_factory_.GetWeakPtr()), | 204 weak_ptr_factory_.GetWeakPtr()), |
| 196 &pac_request_, | 205 &pac_request_, |
| 197 bound_net_log_); | 206 bound_net_log_); |
| 198 if (status != net::ERR_IO_PENDING) | 207 if (status != net::ERR_IO_PENDING) |
| 199 OnProxyResolveDone(status); | 208 OnProxyResolveDone(status); |
| 200 } | 209 } |
| 201 | 210 |
| 202 void ConnectionFactoryImpl::InitHandler() { | 211 void ConnectionFactoryImpl::InitHandler() { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 227 // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering | 236 // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering |
| 228 // another proxy. | 237 // another proxy. |
| 229 DCHECK_NE(result, net::OK); | 238 DCHECK_NE(result, net::OK); |
| 230 if (result == net::ERR_IO_PENDING) | 239 if (result == net::ERR_IO_PENDING) |
| 231 return; // Proxy reconsideration pending. Return. | 240 return; // Proxy reconsideration pending. Return. |
| 232 LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result; | 241 LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result; |
| 233 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false); | 242 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false); |
| 234 CloseSocket(); | 243 CloseSocket(); |
| 235 backoff_entry_->InformOfRequest(false); | 244 backoff_entry_->InformOfRequest(false); |
| 236 UMA_HISTOGRAM_SPARSE_SLOWLY("GCM.ConnectionFailureErrorCode", result); | 245 UMA_HISTOGRAM_SPARSE_SLOWLY("GCM.ConnectionFailureErrorCode", result); |
| 246 | |
| 247 // If there are other endpoints available, use the next endpoint on the | |
| 248 // subsequent retry. | |
| 249 next_endpoint_++; | |
|
jianli
2014/03/20 23:10:21
What if GetCurrentEndpoint() uses last_successful_
Nicolas Zea
2014/03/20 23:53:30
While connecting, GetCurrentEndpoint() will not re
jianli
2014/03/21 00:13:18
Could you please add a comment in GetCurrentEndpoi
Nicolas Zea
2014/03/21 00:35:10
Done.
| |
| 250 if (next_endpoint_ >= mcs_endpoints_.size()) | |
| 251 next_endpoint_ = 0; | |
| 237 Connect(); | 252 Connect(); |
| 238 return; | 253 return; |
| 239 } | 254 } |
| 240 | 255 |
| 241 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); | 256 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); |
| 257 UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_); | |
| 258 UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy", | |
| 259 !(proxy_info_.is_empty() || proxy_info_.is_direct())); | |
| 242 ReportSuccessfulProxyConnection(); | 260 ReportSuccessfulProxyConnection(); |
| 243 | 261 |
| 262 // Reset the endpoint back to the default. | |
| 263 // TODO(zea): consider prioritizing endpoints more intelligently based on | |
| 264 // which ones succeed most for this client? Although that will affect | |
| 265 // measuring the success rate of the default endpoint vs fallback. | |
| 266 last_successful_endpoint_ = next_endpoint_; | |
|
jianli
2014/03/20 23:10:21
What if GetCurrentEndpoint() uses last_successful_
Nicolas Zea
2014/03/20 23:53:30
See above.
| |
| 267 next_endpoint_ = 0; | |
| 244 connecting_ = false; | 268 connecting_ = false; |
| 245 logging_in_ = true; | 269 logging_in_ = true; |
| 246 DVLOG(1) << "MCS endpoint socket connection success, starting login."; | 270 DVLOG(1) << "MCS endpoint socket connection success, starting login."; |
| 247 InitHandler(); | 271 InitHandler(); |
| 248 } | 272 } |
| 249 | 273 |
| 250 void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) { | 274 void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) { |
| 251 DCHECK(!connecting_); | 275 DCHECK(!connecting_); |
| 252 if (result != net::OK) { | 276 if (result != net::OK) { |
| 253 // TODO(zea): Consider how to handle errors that may require some sort of | 277 // TODO(zea): Consider how to handle errors that may require some sort of |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 // Failed to resolve proxy. Retry later. | 317 // Failed to resolve proxy. Retry later. |
| 294 OnConnectDone(status); | 318 OnConnectDone(status); |
| 295 return; | 319 return; |
| 296 } | 320 } |
| 297 | 321 |
| 298 DVLOG(1) << "Resolved proxy with PAC:" << proxy_info_.ToPacString(); | 322 DVLOG(1) << "Resolved proxy with PAC:" << proxy_info_.ToPacString(); |
| 299 | 323 |
| 300 net::SSLConfig ssl_config; | 324 net::SSLConfig ssl_config; |
| 301 network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); | 325 network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); |
| 302 status = net::InitSocketHandleForTlsConnect( | 326 status = net::InitSocketHandleForTlsConnect( |
| 303 net::HostPortPair::FromURL(mcs_endpoint_), | 327 net::HostPortPair::FromURL(GetCurrentEndpoint()), |
| 304 network_session_.get(), | 328 network_session_.get(), |
| 305 proxy_info_, | 329 proxy_info_, |
| 306 ssl_config, | 330 ssl_config, |
| 307 ssl_config, | 331 ssl_config, |
| 308 net::kPrivacyModeDisabled, | 332 net::kPrivacyModeDisabled, |
| 309 bound_net_log_, | 333 bound_net_log_, |
| 310 &socket_handle_, | 334 &socket_handle_, |
| 311 base::Bind(&ConnectionFactoryImpl::OnConnectDone, | 335 base::Bind(&ConnectionFactoryImpl::OnConnectDone, |
| 312 weak_ptr_factory_.GetWeakPtr())); | 336 weak_ptr_factory_.GetWeakPtr())); |
| 313 if (status != net::ERR_IO_PENDING) | 337 if (status != net::ERR_IO_PENDING) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 } | 391 } |
| 368 | 392 |
| 369 net::SSLConfig ssl_config; | 393 net::SSLConfig ssl_config; |
| 370 network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); | 394 network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); |
| 371 if (proxy_info_.is_https() && ssl_config.send_client_cert) { | 395 if (proxy_info_.is_https() && ssl_config.send_client_cert) { |
| 372 network_session_->ssl_client_auth_cache()->Remove( | 396 network_session_->ssl_client_auth_cache()->Remove( |
| 373 proxy_info_.proxy_server().host_port_pair()); | 397 proxy_info_.proxy_server().host_port_pair()); |
| 374 } | 398 } |
| 375 | 399 |
| 376 int status = network_session_->proxy_service()->ReconsiderProxyAfterError( | 400 int status = network_session_->proxy_service()->ReconsiderProxyAfterError( |
| 377 mcs_endpoint_, &proxy_info_, | 401 GetCurrentEndpoint(), &proxy_info_, |
| 378 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, | 402 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, |
| 379 weak_ptr_factory_.GetWeakPtr()), | 403 weak_ptr_factory_.GetWeakPtr()), |
| 380 &pac_request_, | 404 &pac_request_, |
| 381 bound_net_log_); | 405 bound_net_log_); |
| 382 if (status == net::OK || status == net::ERR_IO_PENDING) { | 406 if (status == net::OK || status == net::ERR_IO_PENDING) { |
| 383 CloseSocket(); | 407 CloseSocket(); |
| 384 } else { | 408 } else { |
| 385 // If ReconsiderProxyAfterError() failed synchronously, it means | 409 // If ReconsiderProxyAfterError() failed synchronously, it means |
| 386 // there was nothing left to fall-back to, so fail the transaction | 410 // there was nothing left to fall-back to, so fail the transaction |
| 387 // with the last connection error we got. | 411 // with the last connection error we got. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 410 // the destroyed socket. | 434 // the destroyed socket. |
| 411 if (connection_handler_) | 435 if (connection_handler_) |
| 412 connection_handler_->Reset(); | 436 connection_handler_->Reset(); |
| 413 | 437 |
| 414 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) | 438 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) |
| 415 socket_handle_.socket()->Disconnect(); | 439 socket_handle_.socket()->Disconnect(); |
| 416 socket_handle_.Reset(); | 440 socket_handle_.Reset(); |
| 417 } | 441 } |
| 418 | 442 |
| 419 } // namespace gcm | 443 } // namespace gcm |
| OLD | NEW |