| Index: google_apis/gcm/engine/connection_factory_impl.cc
|
| diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc
|
| index ebfd367c9a85c571da3b3914477dab303e1fc673..deb810264171bab7fe326114fcc3dec19249fc90 100644
|
| --- a/google_apis/gcm/engine/connection_factory_impl.cc
|
| +++ b/google_apis/gcm/engine/connection_factory_impl.cc
|
| @@ -41,11 +41,13 @@ bool ShouldRestorePreviousBackoff(const base::TimeTicks& login_time,
|
| } // namespace
|
|
|
| ConnectionFactoryImpl::ConnectionFactoryImpl(
|
| - const GURL& mcs_endpoint,
|
| + const std::vector<GURL>& mcs_endpoints,
|
| const net::BackoffEntry::Policy& backoff_policy,
|
| scoped_refptr<net::HttpNetworkSession> network_session,
|
| net::NetLog* net_log)
|
| - : mcs_endpoint_(mcs_endpoint),
|
| + : mcs_endpoints_(mcs_endpoints),
|
| + next_endpoint_(0),
|
| + last_successful_endpoint_(0),
|
| backoff_policy_(backoff_policy),
|
| network_session_(network_session),
|
| bound_net_log_(
|
| @@ -54,6 +56,7 @@ ConnectionFactoryImpl::ConnectionFactoryImpl(
|
| connecting_(false),
|
| logging_in_(false),
|
| weak_ptr_factory_(this) {
|
| + DCHECK_GE(mcs_endpoints_.size(), 1U);
|
| }
|
|
|
| ConnectionFactoryImpl::~ConnectionFactoryImpl() {
|
| @@ -184,12 +187,20 @@ void ConnectionFactoryImpl::OnIPAddressChanged() {
|
| // necessary, so no need to call again.
|
| }
|
|
|
| +GURL ConnectionFactoryImpl::GetCurrentEndpoint() const {
|
| + // Note that IsEndpointReachable() returns false anytime connecting_ is true,
|
| + // so while connecting this always uses |next_endpoint_|.
|
| + if (IsEndpointReachable())
|
| + return mcs_endpoints_[last_successful_endpoint_];
|
| + return mcs_endpoints_[next_endpoint_];
|
| +}
|
| +
|
| void ConnectionFactoryImpl::ConnectImpl() {
|
| DCHECK(connecting_);
|
| DCHECK(!socket_handle_.socket());
|
|
|
| int status = network_session_->proxy_service()->ResolveProxy(
|
| - mcs_endpoint_,
|
| + GetCurrentEndpoint(),
|
| &proxy_info_,
|
| base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
|
| weak_ptr_factory_.GetWeakPtr()),
|
| @@ -234,13 +245,28 @@ void ConnectionFactoryImpl::OnConnectDone(int result) {
|
| CloseSocket();
|
| backoff_entry_->InformOfRequest(false);
|
| UMA_HISTOGRAM_SPARSE_SLOWLY("GCM.ConnectionFailureErrorCode", result);
|
| +
|
| + // If there are other endpoints available, use the next endpoint on the
|
| + // subsequent retry.
|
| + next_endpoint_++;
|
| + if (next_endpoint_ >= mcs_endpoints_.size())
|
| + next_endpoint_ = 0;
|
| Connect();
|
| return;
|
| }
|
|
|
| UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true);
|
| + UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_);
|
| + UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy",
|
| + !(proxy_info_.is_empty() || proxy_info_.is_direct()));
|
| ReportSuccessfulProxyConnection();
|
|
|
| + // Reset the endpoint back to the default.
|
| + // TODO(zea): consider prioritizing endpoints more intelligently based on
|
| + // which ones succeed most for this client? Although that will affect
|
| + // measuring the success rate of the default endpoint vs fallback.
|
| + last_successful_endpoint_ = next_endpoint_;
|
| + next_endpoint_ = 0;
|
| connecting_ = false;
|
| logging_in_ = true;
|
| DVLOG(1) << "MCS endpoint socket connection success, starting login.";
|
| @@ -300,7 +326,7 @@ void ConnectionFactoryImpl::OnProxyResolveDone(int status) {
|
| net::SSLConfig ssl_config;
|
| network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
|
| status = net::InitSocketHandleForTlsConnect(
|
| - net::HostPortPair::FromURL(mcs_endpoint_),
|
| + net::HostPortPair::FromURL(GetCurrentEndpoint()),
|
| network_session_.get(),
|
| proxy_info_,
|
| ssl_config,
|
| @@ -374,7 +400,7 @@ int ConnectionFactoryImpl::ReconsiderProxyAfterError(int error) {
|
| }
|
|
|
| int status = network_session_->proxy_service()->ReconsiderProxyAfterError(
|
| - mcs_endpoint_, &proxy_info_,
|
| + GetCurrentEndpoint(), &proxy_info_,
|
| base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
|
| weak_ptr_factory_.GetWeakPtr()),
|
| &pac_request_,
|
|
|