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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 base::MessageLoop::current()->PostDelayedTask( | 138 base::MessageLoop::current()->PostDelayedTask( |
139 FROM_HERE, | 139 FROM_HERE, |
140 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff, | 140 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff, |
141 weak_ptr_factory_.GetWeakPtr()), | 141 weak_ptr_factory_.GetWeakPtr()), |
142 backoff_entry_->GetTimeUntilRelease()); | 142 backoff_entry_->GetTimeUntilRelease()); |
143 return; | 143 return; |
144 } | 144 } |
145 | 145 |
146 DVLOG(1) << "Attempting connection to MCS endpoint."; | 146 DVLOG(1) << "Attempting connection to MCS endpoint."; |
147 waiting_for_backoff_ = false; | 147 waiting_for_backoff_ = false; |
148 // It's necessary to close the socket before attempting any new connection, | |
149 // otherwise it's possible to hit a use-after-free in the connection handler. | |
150 // crbug.com/462319 | |
151 CloseSocket(); | |
148 ConnectImpl(); | 152 ConnectImpl(); |
149 } | 153 } |
150 | 154 |
151 bool ConnectionFactoryImpl::IsEndpointReachable() const { | 155 bool ConnectionFactoryImpl::IsEndpointReachable() const { |
152 return connection_handler_ && connection_handler_->CanSendMessage(); | 156 return connection_handler_ && connection_handler_->CanSendMessage(); |
153 } | 157 } |
154 | 158 |
155 std::string ConnectionFactoryImpl::GetConnectionStateString() const { | 159 std::string ConnectionFactoryImpl::GetConnectionStateString() const { |
156 if (IsEndpointReachable()) | 160 if (IsEndpointReachable()) |
157 return "CONNECTED"; | 161 return "CONNECTED"; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 | 209 |
206 // Network changes get special treatment as they can trigger a one-off canary | 210 // Network changes get special treatment as they can trigger a one-off canary |
207 // request that bypasses backoff (but does nothing if a connection is in | 211 // request that bypasses backoff (but does nothing if a connection is in |
208 // progress). Other connection reset events can be ignored as a connection | 212 // progress). Other connection reset events can be ignored as a connection |
209 // is already awaiting backoff expiration. | 213 // is already awaiting backoff expiration. |
210 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { | 214 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { |
211 DVLOG(1) << "Backoff expiration pending, ignoring reset."; | 215 DVLOG(1) << "Backoff expiration pending, ignoring reset."; |
212 return; | 216 return; |
213 } | 217 } |
214 | 218 |
215 if (logging_in_) { | 219 if (reason == NETWORK_CHANGE) { |
220 // Canary attempts bypass backoff without resetting it. These will have no | |
221 // effect if we're already in the process of connecting. | |
fgorski
2015/03/04 17:43:04
To confirm. There is no need to close socket here,
Nicolas Zea
2015/03/04 17:56:42
We do it on line 204 above.
| |
222 ConnectImpl(); | |
223 return; | |
224 } else if (logging_in_) { | |
216 // Failures prior to login completion just reuse the existing backoff entry. | 225 // Failures prior to login completion just reuse the existing backoff entry. |
217 logging_in_ = false; | 226 logging_in_ = false; |
218 backoff_entry_->InformOfRequest(false); | 227 backoff_entry_->InformOfRequest(false); |
219 } else if (reason == LOGIN_FAILURE || | 228 } else if (reason == LOGIN_FAILURE || |
220 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { | 229 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { |
221 // Failures due to login, or within the reset window of a login, restore | 230 // Failures due to login, or within the reset window of a login, restore |
222 // the backoff entry that was saved off at login completion time. | 231 // the backoff entry that was saved off at login completion time. |
223 backoff_entry_.swap(previous_backoff_); | 232 backoff_entry_.swap(previous_backoff_); |
224 backoff_entry_->InformOfRequest(false); | 233 backoff_entry_->InformOfRequest(false); |
225 } else if (reason == NETWORK_CHANGE) { | |
226 ConnectImpl(); // Canary attempts bypass backoff without resetting it. | |
227 return; | |
228 } else { | 234 } else { |
229 // We shouldn't be in backoff in thise case. | 235 // We shouldn't be in backoff in thise case. |
230 DCHECK_EQ(0, backoff_entry_->failure_count()); | 236 DCHECK_EQ(0, backoff_entry_->failure_count()); |
231 } | 237 } |
232 | 238 |
233 // At this point the last login time has been consumed or deemed irrelevant, | 239 // At this point the last login time has been consumed or deemed irrelevant, |
234 // reset it. | 240 // reset it. |
235 last_login_time_ = base::TimeTicks(); | 241 last_login_time_ = base::TimeTicks(); |
236 | 242 |
237 Connect(); | 243 Connect(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 net::IPEndPoint ip_endpoint; | 286 net::IPEndPoint ip_endpoint; |
281 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); | 287 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); |
282 if (result != net::OK) | 288 if (result != net::OK) |
283 return net::IPEndPoint(); | 289 return net::IPEndPoint(); |
284 | 290 |
285 return ip_endpoint; | 291 return ip_endpoint; |
286 } | 292 } |
287 | 293 |
288 void ConnectionFactoryImpl::ConnectImpl() { | 294 void ConnectionFactoryImpl::ConnectImpl() { |
289 DCHECK(!IsEndpointReachable()); | 295 DCHECK(!IsEndpointReachable()); |
290 DCHECK(!socket_handle_.socket()); | 296 // TODO(zea): Make this a dcheck again. crbug.com/462319 |
297 CHECK(!socket_handle_.socket()); | |
291 | 298 |
292 // TODO(zea): if the network is offline, don't attempt to connect. | 299 // TODO(zea): if the network is offline, don't attempt to connect. |
293 // See crbug.com/396687 | 300 // See crbug.com/396687 |
294 | 301 |
295 connecting_ = true; | 302 connecting_ = true; |
296 GURL current_endpoint = GetCurrentEndpoint(); | 303 GURL current_endpoint = GetCurrentEndpoint(); |
297 recorder_->RecordConnectionInitiated(current_endpoint.host()); | 304 recorder_->RecordConnectionInitiated(current_endpoint.host()); |
298 RebuildNetworkSessionAuthCache(); | 305 RebuildNetworkSessionAuthCache(); |
299 int status = gcm_network_session_->proxy_service()->ResolveProxy( | 306 int status = gcm_network_session_->proxy_service()->ResolveProxy( |
300 current_endpoint, | 307 current_endpoint, |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 | 569 |
563 void ConnectionFactoryImpl::RebuildNetworkSessionAuthCache() { | 570 void ConnectionFactoryImpl::RebuildNetworkSessionAuthCache() { |
564 if (!http_network_session_.get() || !http_network_session_->http_auth_cache()) | 571 if (!http_network_session_.get() || !http_network_session_->http_auth_cache()) |
565 return; | 572 return; |
566 | 573 |
567 gcm_network_session_->http_auth_cache()->UpdateAllFrom( | 574 gcm_network_session_->http_auth_cache()->UpdateAllFrom( |
568 *http_network_session_->http_auth_cache()); | 575 *http_network_session_->http_auth_cache()); |
569 } | 576 } |
570 | 577 |
571 } // namespace gcm | 578 } // namespace gcm |
OLD | NEW |