| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 : mcs_endpoints_(mcs_endpoints), | 50 : mcs_endpoints_(mcs_endpoints), |
| 51 next_endpoint_(0), | 51 next_endpoint_(0), |
| 52 last_successful_endpoint_(0), | 52 last_successful_endpoint_(0), |
| 53 backoff_policy_(backoff_policy), | 53 backoff_policy_(backoff_policy), |
| 54 network_session_(network_session), | 54 network_session_(network_session), |
| 55 bound_net_log_( | 55 bound_net_log_( |
| 56 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), | 56 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), |
| 57 pac_request_(NULL), | 57 pac_request_(NULL), |
| 58 connecting_(false), | 58 connecting_(false), |
| 59 waiting_for_backoff_(false), | 59 waiting_for_backoff_(false), |
| 60 waiting_for_network_online_(false), |
| 60 logging_in_(false), | 61 logging_in_(false), |
| 61 recorder_(recorder), | 62 recorder_(recorder), |
| 62 listener_(NULL), | 63 listener_(NULL), |
| 63 weak_ptr_factory_(this) { | 64 weak_ptr_factory_(this) { |
| 64 DCHECK_GE(mcs_endpoints_.size(), 1U); | 65 DCHECK_GE(mcs_endpoints_.size(), 1U); |
| 65 } | 66 } |
| 66 | 67 |
| 67 ConnectionFactoryImpl::~ConnectionFactoryImpl() { | 68 ConnectionFactoryImpl::~ConnectionFactoryImpl() { |
| 68 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 69 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
| 69 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | |
| 70 if (pac_request_) { | 70 if (pac_request_) { |
| 71 network_session_->proxy_service()->CancelPacRequest(pac_request_); | 71 network_session_->proxy_service()->CancelPacRequest(pac_request_); |
| 72 pac_request_ = NULL; | 72 pac_request_ = NULL; |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 void ConnectionFactoryImpl::Initialize( | 76 void ConnectionFactoryImpl::Initialize( |
| 77 const BuildLoginRequestCallback& request_builder, | 77 const BuildLoginRequestCallback& request_builder, |
| 78 const ConnectionHandler::ProtoReceivedCallback& read_callback, | 78 const ConnectionHandler::ProtoReceivedCallback& read_callback, |
| 79 const ConnectionHandler::ProtoSentCallback& write_callback) { | 79 const ConnectionHandler::ProtoSentCallback& write_callback) { |
| 80 DCHECK(!connection_handler_); | 80 DCHECK(!connection_handler_); |
| 81 | 81 |
| 82 previous_backoff_ = CreateBackoffEntry(&backoff_policy_); | 82 previous_backoff_ = CreateBackoffEntry(&backoff_policy_); |
| 83 backoff_entry_ = CreateBackoffEntry(&backoff_policy_); | 83 backoff_entry_ = CreateBackoffEntry(&backoff_policy_); |
| 84 request_builder_ = request_builder; | 84 request_builder_ = request_builder; |
| 85 | 85 |
| 86 net::NetworkChangeNotifier::AddIPAddressObserver(this); | 86 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| 87 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 87 waiting_for_network_online_ = net::NetworkChangeNotifier::IsOffline(); |
| 88 connection_handler_ = CreateConnectionHandler( | 88 connection_handler_ = CreateConnectionHandler( |
| 89 base::TimeDelta::FromMilliseconds(kReadTimeoutMs), | 89 base::TimeDelta::FromMilliseconds(kReadTimeoutMs), |
| 90 read_callback, | 90 read_callback, |
| 91 write_callback, | 91 write_callback, |
| 92 base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback, | 92 base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback, |
| 93 weak_ptr_factory_.GetWeakPtr())).Pass(); | 93 weak_ptr_factory_.GetWeakPtr())).Pass(); |
| 94 } | 94 } |
| 95 | 95 |
| 96 ConnectionHandler* ConnectionFactoryImpl::GetConnectionHandler() const { | 96 ConnectionHandler* ConnectionFactoryImpl::GetConnectionHandler() const { |
| 97 return connection_handler_.get(); | 97 return connection_handler_.get(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 | 143 |
| 144 std::string ConnectionFactoryImpl::GetConnectionStateString() const { | 144 std::string ConnectionFactoryImpl::GetConnectionStateString() const { |
| 145 if (IsEndpointReachable()) | 145 if (IsEndpointReachable()) |
| 146 return "CONNECTED"; | 146 return "CONNECTED"; |
| 147 if (logging_in_) | 147 if (logging_in_) |
| 148 return "LOGGING IN"; | 148 return "LOGGING IN"; |
| 149 if (connecting_) | 149 if (connecting_) |
| 150 return "CONNECTING"; | 150 return "CONNECTING"; |
| 151 if (waiting_for_backoff_) | 151 if (waiting_for_backoff_) |
| 152 return "WAITING FOR BACKOFF"; | 152 return "WAITING FOR BACKOFF"; |
| 153 if (waiting_for_network_online_) |
| 154 return "WAITING FOR NETWORK CHANGE"; |
| 153 return "NOT CONNECTED"; | 155 return "NOT CONNECTED"; |
| 154 } | 156 } |
| 155 | 157 |
| 156 void ConnectionFactoryImpl::SignalConnectionReset( | 158 void ConnectionFactoryImpl::SignalConnectionReset( |
| 157 ConnectionResetReason reason) { | 159 ConnectionResetReason reason) { |
| 158 // A failure can trigger multiple resets, so no need to do anything if a | 160 // A failure can trigger multiple resets, so no need to do anything if a |
| 159 // connection is already in progress. | 161 // connection is already in progress. |
| 160 if (connecting_) { | 162 if (connecting_) { |
| 161 DVLOG(1) << "Connection in progress, ignoring reset."; | 163 DVLOG(1) << "Connection in progress, ignoring reset."; |
| 162 return; | 164 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 175 base::TimeDelta::FromSeconds(1), | 177 base::TimeDelta::FromSeconds(1), |
| 176 base::TimeDelta::FromHours(24), | 178 base::TimeDelta::FromHours(24), |
| 177 50); | 179 50); |
| 178 // |last_login_time_| will be reset below, before attempting the new | 180 // |last_login_time_| will be reset below, before attempting the new |
| 179 // connection. | 181 // connection. |
| 180 } | 182 } |
| 181 | 183 |
| 182 CloseSocket(); | 184 CloseSocket(); |
| 183 DCHECK(!IsEndpointReachable()); | 185 DCHECK(!IsEndpointReachable()); |
| 184 | 186 |
| 187 if (waiting_for_network_online_) |
| 188 return; |
| 189 |
| 185 // Network changes get special treatment as they can trigger a one-off canary | 190 // Network changes get special treatment as they can trigger a one-off canary |
| 186 // request that bypasses backoff (but does nothing if a connection is in | 191 // request that bypasses backoff (but does nothing if a connection is in |
| 187 // progress). Other connection reset events can be ignored as a connection | 192 // progress). Other connection reset events can be ignored as a connection |
| 188 // is already awaiting backoff expiration. | 193 // is already awaiting backoff expiration. |
| 189 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { | 194 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { |
| 190 DVLOG(1) << "Backoff expiration pending, ignoring reset."; | 195 DVLOG(1) << "Backoff expiration pending, ignoring reset."; |
| 191 return; | 196 return; |
| 192 } | 197 } |
| 193 | 198 |
| 194 if (logging_in_) { | 199 if (logging_in_) { |
| 195 // Failures prior to login completion just reuse the existing backoff entry. | 200 // Failures prior to login completion just reuse the existing backoff entry. |
| 196 logging_in_ = false; | 201 logging_in_ = false; |
| 197 backoff_entry_->InformOfRequest(false); | 202 backoff_entry_->InformOfRequest(false); |
| 198 } else if (reason == LOGIN_FAILURE || | 203 } else if (reason == LOGIN_FAILURE || |
| 199 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { | 204 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { |
| 200 // Failures due to login, or within the reset window of a login, restore | 205 // Failures due to login, or within the reset window of a login, restore |
| 201 // the backoff entry that was saved off at login completion time. | 206 // the backoff entry that was saved off at login completion time. |
| 202 backoff_entry_.swap(previous_backoff_); | 207 backoff_entry_.swap(previous_backoff_); |
| 203 backoff_entry_->InformOfRequest(false); | 208 backoff_entry_->InformOfRequest(false); |
| 204 } else if (reason == NETWORK_CHANGE) { | 209 } else if (reason == NETWORK_CHANGE) { |
| 205 ConnectImpl(); // Canary attempts bypass backoff without resetting it. | 210 ConnectImpl(); // Canary attempts bypass backoff without resetting it. |
| 206 return; | 211 return; |
| 207 } else { | 212 } else { |
| 208 // We shouldn't be in backoff in thise case. | 213 // We shouldn't be in backoff in thise case. |
| 209 DCHECK_EQ(0, backoff_entry_->failure_count()); | 214 DCHECK_EQ(0, backoff_entry_->failure_count()); |
| 210 } | 215 } |
| 211 DCHECK(!connecting_); | |
| 212 DCHECK(!waiting_for_backoff_); | |
| 213 | 216 |
| 214 // At this point the last login time has been consumed or deemed irrelevant, | 217 // At this point the last login time has been consumed or deemed irrelevant, |
| 215 // reset it. | 218 // reset it. |
| 216 last_login_time_ = base::TimeTicks(); | 219 last_login_time_ = base::TimeTicks(); |
| 217 | 220 |
| 218 Connect(); | 221 Connect(); |
| 219 } | 222 } |
| 220 | 223 |
| 221 void ConnectionFactoryImpl::SetConnectionListener( | 224 void ConnectionFactoryImpl::SetConnectionListener( |
| 222 ConnectionListener* listener) { | 225 ConnectionListener* listener) { |
| 223 listener_ = listener; | 226 listener_ = listener; |
| 224 } | 227 } |
| 225 | 228 |
| 226 base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const { | 229 base::TimeTicks ConnectionFactoryImpl::NextRetryAttempt() const { |
| 227 if (!backoff_entry_) | 230 if (!backoff_entry_) |
| 228 return base::TimeTicks(); | 231 return base::TimeTicks(); |
| 229 return backoff_entry_->GetReleaseTime(); | 232 return backoff_entry_->GetReleaseTime(); |
| 230 } | 233 } |
| 231 | 234 |
| 232 void ConnectionFactoryImpl::OnConnectionTypeChanged( | 235 void ConnectionFactoryImpl::OnNetworkChanged( |
| 233 net::NetworkChangeNotifier::ConnectionType type) { | 236 net::NetworkChangeNotifier::ConnectionType type) { |
| 234 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) | 237 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) { |
| 238 DVLOG(1) << "Network lost, resettion connection."; |
| 239 waiting_for_network_online_ = true; |
| 240 |
| 241 // Will do nothing due to |waiting_for_network_online_ == true|. |
| 242 SignalConnectionReset(NETWORK_CHANGE); |
| 235 return; | 243 return; |
| 244 } |
| 236 | 245 |
| 237 DVLOG(1) << "Connection type changed to " << type << ", reconnecting."; | 246 DVLOG(1) << "Connection type changed to " << type << ", reconnecting."; |
| 238 | 247 waiting_for_network_online_ = false; |
| 239 // The connection may have been silently dropped, attempt to reconnect. | |
| 240 SignalConnectionReset(NETWORK_CHANGE); | 248 SignalConnectionReset(NETWORK_CHANGE); |
| 241 } | 249 } |
| 242 | 250 |
| 243 void ConnectionFactoryImpl::OnIPAddressChanged() { | |
| 244 DVLOG(1) << "IP Address changed, reconnecting."; | |
| 245 | |
| 246 // The connection may have been silently dropped, attempt to reconnect. | |
| 247 SignalConnectionReset(NETWORK_CHANGE); | |
| 248 } | |
| 249 | |
| 250 GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { | 251 GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { |
| 251 // Note that IsEndpointReachable() returns false anytime connecting_ is true, | 252 // Note that IsEndpointReachable() returns false anytime connecting_ is true, |
| 252 // so while connecting this always uses |next_endpoint_|. | 253 // so while connecting this always uses |next_endpoint_|. |
| 253 if (IsEndpointReachable()) | 254 if (IsEndpointReachable()) |
| 254 return mcs_endpoints_[last_successful_endpoint_]; | 255 return mcs_endpoints_[last_successful_endpoint_]; |
| 255 return mcs_endpoints_[next_endpoint_]; | 256 return mcs_endpoints_[next_endpoint_]; |
| 256 } | 257 } |
| 257 | 258 |
| 258 net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() { | 259 net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() { |
| 259 if (!socket_handle_.socket()) | 260 if (!socket_handle_.socket()) |
| 260 return net::IPEndPoint(); | 261 return net::IPEndPoint(); |
| 261 | 262 |
| 262 net::IPEndPoint ip_endpoint; | 263 net::IPEndPoint ip_endpoint; |
| 263 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); | 264 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); |
| 264 if (result != net::OK) | 265 if (result != net::OK) |
| 265 return net::IPEndPoint(); | 266 return net::IPEndPoint(); |
| 266 | 267 |
| 267 return ip_endpoint; | 268 return ip_endpoint; |
| 268 } | 269 } |
| 269 | 270 |
| 270 void ConnectionFactoryImpl::ConnectImpl() { | 271 void ConnectionFactoryImpl::ConnectImpl() { |
| 271 DCHECK(!IsEndpointReachable()); | 272 DCHECK(!IsEndpointReachable()); |
| 272 DCHECK(!socket_handle_.socket()); | 273 DCHECK(!socket_handle_.socket()); |
| 273 | 274 |
| 275 if (waiting_for_network_online_) |
| 276 return; |
| 277 |
| 274 connecting_ = true; | 278 connecting_ = true; |
| 275 GURL current_endpoint = GetCurrentEndpoint(); | 279 GURL current_endpoint = GetCurrentEndpoint(); |
| 276 recorder_->RecordConnectionInitiated(current_endpoint.host()); | 280 recorder_->RecordConnectionInitiated(current_endpoint.host()); |
| 277 int status = network_session_->proxy_service()->ResolveProxy( | 281 int status = network_session_->proxy_service()->ResolveProxy( |
| 278 current_endpoint, | 282 current_endpoint, |
| 279 &proxy_info_, | 283 &proxy_info_, |
| 280 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, | 284 base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, |
| 281 weak_ptr_factory_.GetWeakPtr()), | 285 weak_ptr_factory_.GetWeakPtr()), |
| 282 &pac_request_, | 286 &pac_request_, |
| 283 bound_net_log_); | 287 bound_net_log_); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 // the destroyed socket. | 533 // the destroyed socket. |
| 530 if (connection_handler_) | 534 if (connection_handler_) |
| 531 connection_handler_->Reset(); | 535 connection_handler_->Reset(); |
| 532 | 536 |
| 533 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) | 537 if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) |
| 534 socket_handle_.socket()->Disconnect(); | 538 socket_handle_.socket()->Disconnect(); |
| 535 socket_handle_.Reset(); | 539 socket_handle_.Reset(); |
| 536 } | 540 } |
| 537 | 541 |
| 538 } // namespace gcm | 542 } // namespace gcm |
| OLD | NEW |