| Index: chrome/browser/sync/notifier/communicator/auto_reconnect.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/communicator/auto_reconnect.cc (revision 0)
|
| +++ chrome/browser/sync/notifier/communicator/auto_reconnect.cc (revision 0)
|
| @@ -0,0 +1,155 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/sync/notifier/communicator/auto_reconnect.h"
|
| +
|
| +#include "chrome/browser/sync/notifier/base/network_status_detector_task.h"
|
| +#include "chrome/browser/sync/notifier/base/time.h"
|
| +#include "chrome/browser/sync/notifier/base/timer.h"
|
| +#include "talk/base/common.h"
|
| +
|
| +namespace notifier {
|
| +const int kResetReconnectInfoDelaySec = 2;
|
| +
|
| +AutoReconnect::AutoReconnect(talk_base::Task* parent,
|
| + NetworkStatusDetectorTask* network_status)
|
| + : reconnect_interval_ns_(0),
|
| + reconnect_timer_(NULL),
|
| + delayed_reset_timer_(NULL),
|
| + parent_(parent),
|
| + is_idle_(false) {
|
| + SetupReconnectInterval();
|
| + if (network_status) {
|
| + network_status->SignalNetworkStateDetected.connect(
|
| + this, &AutoReconnect::OnNetworkStateDetected);
|
| + }
|
| +}
|
| +
|
| +void AutoReconnect::OnNetworkStateDetected(bool was_alive, bool is_alive) {
|
| + if (is_retrying() && !was_alive && is_alive) {
|
| + // Reconnect in 1 to 9 seconds (vary the time a little to try to avoid
|
| + // spikey behavior on network hiccups).
|
| + StartReconnectTimerWithInterval((rand() % 9 + 1) * kSecsTo100ns);
|
| + }
|
| +}
|
| +
|
| +int AutoReconnect::seconds_until() const {
|
| + if (!is_retrying() || !reconnect_timer_->get_timeout_time()) {
|
| + return 0;
|
| + }
|
| + int64 time_until_100ns =
|
| + reconnect_timer_->get_timeout_time() - GetCurrent100NSTime();
|
| + if (time_until_100ns < 0) {
|
| + return 0;
|
| + }
|
| +
|
| + // Do a ceiling on the value (to avoid returning before its time)
|
| + return (time_until_100ns + kSecsTo100ns - 1) / kSecsTo100ns;
|
| +}
|
| +
|
| +void AutoReconnect::StartReconnectTimer() {
|
| + StartReconnectTimerWithInterval(reconnect_interval_ns_);
|
| +}
|
| +
|
| +void AutoReconnect::StartReconnectTimerWithInterval(time64 interval_ns) {
|
| + // Don't call StopReconnectTimer because we don't
|
| + // want other classes to detect that the intermediate state of
|
| + // the timer being stopped. (We're avoiding the call to SignalTimerStartStop
|
| + // while reconnect_timer_ is NULL.)
|
| + if (reconnect_timer_) {
|
| + reconnect_timer_->Abort();
|
| + reconnect_timer_ = NULL;
|
| + }
|
| + reconnect_timer_ = new Timer(parent_,
|
| + static_cast<int>(interval_ns / kSecsTo100ns),
|
| + false); // repeat
|
| + reconnect_timer_->SignalTimeout.connect(this,
|
| + &AutoReconnect::DoReconnect);
|
| + SignalTimerStartStop();
|
| +}
|
| +
|
| +void AutoReconnect::DoReconnect() {
|
| + reconnect_timer_ = NULL;
|
| +
|
| + // if timed out again, double autoreconnect time up to 30 minutes
|
| + reconnect_interval_ns_ *= 2;
|
| + if (reconnect_interval_ns_ > 30 * kMinsTo100ns) {
|
| + reconnect_interval_ns_ = 30 * kMinsTo100ns;
|
| + }
|
| + SignalStartConnection();
|
| +}
|
| +
|
| +void AutoReconnect::StopReconnectTimer() {
|
| + if (reconnect_timer_) {
|
| + reconnect_timer_->Abort();
|
| + reconnect_timer_ = NULL;
|
| + SignalTimerStartStop();
|
| + }
|
| +}
|
| +
|
| +void AutoReconnect::StopDelayedResetTimer() {
|
| + if (delayed_reset_timer_) {
|
| + delayed_reset_timer_->Abort();
|
| + delayed_reset_timer_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void AutoReconnect::ResetState() {
|
| + StopDelayedResetTimer();
|
| + StopReconnectTimer();
|
| + SetupReconnectInterval();
|
| +}
|
| +
|
| +void AutoReconnect::SetupReconnectInterval() {
|
| + if (is_idle_) {
|
| + // If we were idle, start the timer over again (120 - 360 seconds).
|
| + reconnect_interval_ns_ = (rand() % 240 + 120) * kSecsTo100ns;
|
| + } else {
|
| + // If we weren't idle, try the connection 5 - 25 seconds later.
|
| + reconnect_interval_ns_ = (rand() % 20 + 5) * kSecsTo100ns;
|
| + }
|
| +}
|
| +
|
| +void AutoReconnect::OnPowerSuspend(bool suspended) {
|
| + if (suspended) {
|
| + // When the computer comes back on, ensure that the reconnect
|
| + // happens quickly (5 - 25 seconds).
|
| + reconnect_interval_ns_ = (rand() % 20 + 5) * kSecsTo100ns;
|
| + }
|
| +}
|
| +
|
| +void AutoReconnect::OnClientStateChange(Login::ConnectionState state) {
|
| + // On any state change, stop the reset timer.
|
| + StopDelayedResetTimer();
|
| + switch (state) {
|
| + case Login::STATE_RETRYING:
|
| + // do nothing
|
| + break;
|
| +
|
| + case Login::STATE_CLOSED:
|
| + // When the user has been logged out and no auto-reconnect
|
| + // is happening, then the autoreconnect intervals should be
|
| + // reset.
|
| + ResetState();
|
| + break;
|
| +
|
| + case Login::STATE_OPENING:
|
| + StopReconnectTimer();
|
| + break;
|
| +
|
| + case Login::STATE_OPENED:
|
| + // Reset autoreconnect timeout sequence after being connected
|
| + // for a bit of time. This helps in the case that we are
|
| + // connecting briefly and then getting disconnect like when
|
| + // an account hits an abuse limit.
|
| + StopReconnectTimer();
|
| + delayed_reset_timer_ = new Timer(parent_,
|
| + kResetReconnectInfoDelaySec,
|
| + false); // repeat
|
| + delayed_reset_timer_->SignalTimeout.connect(this,
|
| + &AutoReconnect::ResetState);
|
| + break;
|
| + }
|
| +}
|
| +} // namespace notifier
|
|
|
| Property changes on: chrome\browser\sync\notifier\communicator\auto_reconnect.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|