summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-27 21:14:33 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-27 21:14:33 +0000
commit7fdad3a542e60dd9426e103b813421f3d1b37b40 (patch)
treeae69f246354040d3502f7642ff7e4f90093b5e2c
parentc347f49fc32d3a35873040992ef0c7374de41332 (diff)
downloadchromium_src-7fdad3a542e60dd9426e103b813421f3d1b37b40.zip
chromium_src-7fdad3a542e60dd9426e103b813421f3d1b37b40.tar.gz
chromium_src-7fdad3a542e60dd9426e103b813421f3d1b37b40.tar.bz2
Rewrote handing of auto-reconnection and network changes for sync notifier.
BUG=47883 TEST=manual (turning network connection off and on) Review URL: http://codereview.chromium.org/2809056 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53839 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/notifier/server_notifier_thread.cc9
-rw-r--r--jingle/jingle.gyp2
-rw-r--r--jingle/notifier/communicator/auto_reconnect.cc125
-rw-r--r--jingle/notifier/communicator/auto_reconnect.h67
-rw-r--r--jingle/notifier/communicator/connection_options.cc1
-rw-r--r--jingle/notifier/communicator/connection_options.h3
-rw-r--r--jingle/notifier/communicator/login.cc291
-rw-r--r--jingle/notifier/communicator/login.h82
-rw-r--r--jingle/notifier/communicator/login_connection_state.h8
-rw-r--r--jingle/notifier/communicator/single_login_attempt.cc6
-rw-r--r--jingle/notifier/communicator/single_login_attempt.h2
-rw-r--r--jingle/notifier/listener/mediator_thread_impl.cc18
12 files changed, 101 insertions, 513 deletions
diff --git a/chrome/browser/sync/notifier/server_notifier_thread.cc b/chrome/browser/sync/notifier/server_notifier_thread.cc
index 0e5be0c..d9975cb 100644
--- a/chrome/browser/sync/notifier/server_notifier_thread.cc
+++ b/chrome/browser/sync/notifier/server_notifier_thread.cc
@@ -15,7 +15,7 @@ namespace sync_notifier {
ServerNotifierThread::ServerNotifierThread(bool use_chrome_async_socket)
: notifier::MediatorThreadImpl(use_chrome_async_socket),
- state_(notifier::STATE_CLOSED) {}
+ state_(notifier::STATE_DISCONNECTED) {}
ServerNotifierThread::~ServerNotifierThread() {}
@@ -77,8 +77,7 @@ void ServerNotifierThread::OnClientStateChangeMessage(
notifier::LoginConnectionState state) {
DCHECK_EQ(MessageLoop::current(), worker_message_loop());
state_ = state;
- if (state_ != notifier::STATE_OPENED) {
- // Assume anything but an opened state invalidates xmpp_client().
+ if (state_ != notifier::STATE_CONNECTED) {
StopInvalidationListener();
}
MediatorThreadImpl::OnClientStateChangeMessage(state);
@@ -86,7 +85,7 @@ void ServerNotifierThread::OnClientStateChangeMessage(
void ServerNotifierThread::StartInvalidationListener() {
DCHECK_EQ(MessageLoop::current(), worker_message_loop());
- if (state_ != notifier::STATE_OPENED) {
+ if (state_ != notifier::STATE_CONNECTED) {
return;
}
buzz::XmppClient* client = xmpp_client();
@@ -108,7 +107,7 @@ void ServerNotifierThread::StartInvalidationListener() {
void ServerNotifierThread::RegisterTypesAndSignalSubscribed() {
DCHECK_EQ(MessageLoop::current(), worker_message_loop());
- if (state_ != notifier::STATE_OPENED) {
+ if (state_ != notifier::STATE_CONNECTED) {
return;
}
diff --git a/jingle/jingle.gyp b/jingle/jingle.gyp
index e950c46..b3edc24 100644
--- a/jingle/jingle.gyp
+++ b/jingle/jingle.gyp
@@ -23,8 +23,6 @@
'notifier/base/static_assert.h',
'notifier/base/task_pump.cc',
'notifier/base/task_pump.h',
- 'notifier/communicator/auto_reconnect.cc',
- 'notifier/communicator/auto_reconnect.h',
'notifier/communicator/connection_options.cc',
'notifier/communicator/connection_options.h',
'notifier/communicator/connection_settings.cc',
diff --git a/jingle/notifier/communicator/auto_reconnect.cc b/jingle/notifier/communicator/auto_reconnect.cc
deleted file mode 100644
index 4b16e93..0000000
--- a/jingle/notifier/communicator/auto_reconnect.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// 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 "jingle/notifier/communicator/auto_reconnect.h"
-
-#include "base/rand_util.h"
-#include "jingle/notifier/communicator/login.h"
-
-namespace notifier {
-
-const int kResetReconnectInfoDelaySec = 2;
-
-AutoReconnect::AutoReconnect()
- : reconnect_timer_started_(false),
- is_idle_(false) {
- SetupReconnectInterval();
-}
-
-void AutoReconnect::NetworkStateChanged(bool is_alive) {
- if (is_retrying() && is_alive) {
- // Reconnect in 1 to 9 seconds (vary the time a little to try to avoid
- // spikey behavior on network hiccups).
- StartReconnectTimerWithInterval(
- base::TimeDelta::FromSeconds(base::RandInt(1, 9)));
- }
-}
-
-void AutoReconnect::StartReconnectTimer() {
- StartReconnectTimerWithInterval(reconnect_interval_);
-}
-
-void AutoReconnect::StartReconnectTimerWithInterval(
- base::TimeDelta interval) {
- // 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).
- reconnect_timer_.Stop();
- reconnect_timer_.Start(interval, this, &AutoReconnect::DoReconnect);
- reconnect_timer_started_ = true;
- SignalTimerStartStop();
-}
-
-void AutoReconnect::DoReconnect() {
- reconnect_timer_started_ = false;
-
- // If timed out again, double autoreconnect time up to 30 minutes.
- reconnect_interval_ *= 2;
- if (reconnect_interval_ > base::TimeDelta::FromMinutes(30)) {
- reconnect_interval_ = base::TimeDelta::FromMinutes(30);
- }
- SignalStartConnection();
-}
-
-void AutoReconnect::StopReconnectTimer() {
- if (reconnect_timer_started_) {
- reconnect_timer_started_ = false;
- reconnect_timer_.Stop();
- SignalTimerStartStop();
- }
-}
-
-void AutoReconnect::StopDelayedResetTimer() {
- delayed_reset_timer_.Stop();
-}
-
-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_ =
- base::TimeDelta::FromSeconds(base::RandInt(120, 360));
- } else {
- // If we weren't idle, try the connection 5 - 25 seconds later.
- reconnect_interval_ =
- base::TimeDelta::FromSeconds(base::RandInt(5, 25));
- }
-}
-
-void AutoReconnect::OnPowerSuspend(bool suspended) {
- if (suspended) {
- // When the computer comes back on, ensure that the reconnect happens
- // quickly (5 - 25 seconds).
- reconnect_interval_ =
- base::TimeDelta::FromSeconds(base::RandInt(5, 25));
- }
-}
-
-void AutoReconnect::OnClientStateChange(LoginConnectionState state) {
- // On any state change, stop the reset timer.
- StopDelayedResetTimer();
- switch (state) {
- case STATE_RETRYING:
- // Do nothing.
- break;
-
- case 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 STATE_OPENING:
- StopReconnectTimer();
- break;
-
- case 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_.Start(
- base::TimeDelta::FromSeconds(kResetReconnectInfoDelaySec),
- this, &AutoReconnect::ResetState);
- break;
- }
-}
-
-} // namespace notifier
diff --git a/jingle/notifier/communicator/auto_reconnect.h b/jingle/notifier/communicator/auto_reconnect.h
deleted file mode 100644
index 6b2fa09..0000000
--- a/jingle/notifier/communicator/auto_reconnect.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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.
-
-#ifndef JINGLE_NOTIFIER_COMMUNICATOR_AUTO_RECONNECT_H_
-#define JINGLE_NOTIFIER_COMMUNICATOR_AUTO_RECONNECT_H_
-
-#include <string>
-
-#include "base/time.h"
-#include "base/timer.h"
-#include "jingle/notifier/communicator/login_connection_state.h"
-#include "talk/base/sigslot.h"
-
-namespace notifier {
-
-class AutoReconnect : public sigslot::has_slots<> {
- public:
- AutoReconnect();
- void StartReconnectTimer();
- void StopReconnectTimer();
- void OnClientStateChange(LoginConnectionState state);
-
- void NetworkStateChanged(bool is_alive);
-
- // Callback when power is suspended.
- void OnPowerSuspend(bool suspended);
-
- void set_idle(bool idle) {
- is_idle_ = idle;
- }
-
- // Returns true if the auto-retry is to be done (pending a countdown).
- bool is_retrying() const {
- return reconnect_timer_started_;
- }
-
- sigslot::signal0<> SignalTimerStartStop;
- sigslot::signal0<> SignalStartConnection;
-
- private:
- void StartReconnectTimerWithInterval(base::TimeDelta interval);
- void DoReconnect();
- void ResetState();
- void SetupReconnectInterval();
- void StopDelayedResetTimer();
-
- base::TimeDelta reconnect_interval_;
- bool reconnect_timer_started_;
- base::OneShotTimer<AutoReconnect> reconnect_timer_;
- base::OneShotTimer<AutoReconnect> delayed_reset_timer_;
-
- bool is_idle_;
- DISALLOW_COPY_AND_ASSIGN(AutoReconnect);
-};
-
-// Wait 2 seconds until after we actually connect to reset reconnect related
-// items.
-//
-// The reason for this delay is to avoid the situation in which buzz is trying
-// to block the client due to abuse and the client responses by going into
-// rapid reconnect mode, which makes the problem more severe.
-extern const int kResetReconnectInfoDelaySec;
-
-} // namespace notifier
-
-#endif // JINGLE_NOTIFIER_COMMUNICATOR_AUTO_RECONNECT_H_
diff --git a/jingle/notifier/communicator/connection_options.cc b/jingle/notifier/communicator/connection_options.cc
index fe52d7f..c103127 100644
--- a/jingle/notifier/communicator/connection_options.cc
+++ b/jingle/notifier/communicator/connection_options.cc
@@ -8,7 +8,6 @@ namespace notifier {
ConnectionOptions::ConnectionOptions()
: autodetect_proxy_(true),
- auto_reconnect_(true),
proxy_port_(0),
use_proxy_auth_(0),
allow_unverified_certs_(false) {
diff --git a/jingle/notifier/communicator/connection_options.h b/jingle/notifier/communicator/connection_options.h
index de09910..4f24b44 100644
--- a/jingle/notifier/communicator/connection_options.h
+++ b/jingle/notifier/communicator/connection_options.h
@@ -17,7 +17,6 @@ class ConnectionOptions {
ConnectionOptions();
bool autodetect_proxy() const { return autodetect_proxy_; }
- bool auto_reconnect() const { return auto_reconnect_; }
const std::string& proxy_host() const { return proxy_host_; }
int proxy_port() const { return proxy_port_; }
bool use_proxy_auth() const { return use_proxy_auth_; }
@@ -26,7 +25,6 @@ class ConnectionOptions {
bool allow_unverified_certs() const { return allow_unverified_certs_; }
void set_autodetect_proxy(bool f) { autodetect_proxy_ = f; }
- void set_auto_reconnect(bool f) { auto_reconnect_ = f; }
void set_proxy_host(const std::string& val) { proxy_host_ = val; }
void set_proxy_port(int val) { proxy_port_ = val; }
void set_use_proxy_auth(bool f) { use_proxy_auth_ = f; }
@@ -41,7 +39,6 @@ class ConnectionOptions {
private:
bool autodetect_proxy_;
- bool auto_reconnect_;
std::string proxy_host_;
int proxy_port_;
bool use_proxy_auth_;
diff --git a/jingle/notifier/communicator/login.cc b/jingle/notifier/communicator/login.cc
index 7cf4952..7d3c4c8 100644
--- a/jingle/notifier/communicator/login.cc
+++ b/jingle/notifier/communicator/login.cc
@@ -7,8 +7,8 @@
#include "jingle/notifier/communicator/login.h"
#include "base/logging.h"
+#include "base/rand_util.h"
#include "base/time.h"
-#include "jingle/notifier/communicator/auto_reconnect.h"
#include "jingle/notifier/communicator/connection_options.h"
#include "jingle/notifier/communicator/login_settings.h"
#include "jingle/notifier/communicator/product_info.h"
@@ -31,9 +31,6 @@ namespace notifier {
// Redirect valid for 5 minutes.
static const int kRedirectTimeoutMinutes = 5;
-// Disconnect if network stays down for more than 10 seconds.
-static const int kDisconnectionDelaySecs = 10;
-
Login::Login(talk_base::TaskParent* parent,
bool use_chrome_async_socket,
const buzz::XmppClientSettings& user_settings,
@@ -43,8 +40,7 @@ Login::Login(talk_base::TaskParent* parent,
ServerInformation* server_list,
int server_count,
talk_base::FirewallManager* firewall,
- bool proxy_only,
- bool previous_login_successful)
+ bool proxy_only)
: parent_(parent),
use_chrome_async_socket_(use_chrome_async_socket),
login_settings_(new LoginSettings(user_settings,
@@ -55,38 +51,15 @@ Login::Login(talk_base::TaskParent* parent,
server_count,
firewall,
proxy_only)),
+ state_(STATE_DISCONNECTED),
single_attempt_(NULL),
- successful_connection_(previous_login_successful),
- state_(STATE_OPENING),
- redirect_port_(0),
- unexpected_disconnect_occurred_(false),
- google_host_(user_settings.host()),
- google_user_(user_settings.user()) {
- // Hook up all the signals and observers.
+ redirect_port_(0) {
net::NetworkChangeNotifier::AddObserver(this);
- auto_reconnect_.SignalStartConnection.connect(this,
- &Login::StartConnection);
- auto_reconnect_.SignalTimerStartStop.connect(
- this,
- &Login::OnAutoReconnectTimerChange);
- SignalClientStateChange.connect(&auto_reconnect_,
- &AutoReconnect::OnClientStateChange);
- SignalIdleChange.connect(&auto_reconnect_,
- &AutoReconnect::set_idle);
- SignalPowerSuspended.connect(&auto_reconnect_,
- &AutoReconnect::OnPowerSuspend);
-
- // Then check the initial state of the connection.
- CheckConnection();
+ ResetReconnectState();
}
-// Defined so that the destructors are executed here (and the corresponding
-// classes don't need to be included in the header file).
Login::~Login() {
- if (single_attempt_) {
- single_attempt_->Abort();
- single_attempt_ = NULL;
- }
+ Disconnect();
net::NetworkChangeNotifier::RemoveObserver(this);
}
@@ -103,126 +76,68 @@ void Login::StartConnection() {
login_settings_->clear_server_override();
}
- if (single_attempt_) {
- single_attempt_->Abort();
- single_attempt_ = NULL;
- }
+ Disconnect();
+
+ LOG(INFO) << "Starting connection...";
+
single_attempt_ = new SingleLoginAttempt(parent_,
login_settings_.get(),
use_chrome_async_socket_,
- successful_connection_);
+ true);
// Do the signaling hook-ups.
- single_attempt_->SignalLoginFailure.connect(this, &Login::OnLoginFailure);
- single_attempt_->SignalRedirect.connect(this, &Login::OnRedirect);
- single_attempt_->SignalClientStateChange.connect(
- this,
- &Login::OnClientStateChange);
single_attempt_->SignalUnexpectedDisconnect.connect(
this,
- &Login::OnUnexpectedDisconnect);
+ &Login::TryReconnect);
+ single_attempt_->SignalNeedAutoReconnect.connect(
+ this,
+ &Login::TryReconnect);
+ single_attempt_->SignalLoginFailure.connect(this, &Login::OnLoginFailure);
single_attempt_->SignalLogoff.connect(
this,
- &Login::OnLogoff);
- single_attempt_->SignalNeedAutoReconnect.connect(
+ &Login::Disconnect);
+ single_attempt_->SignalRedirect.connect(this, &Login::OnRedirect);
+ single_attempt_->SignalClientStateChange.connect(
this,
- &Login::DoAutoReconnect);
+ &Login::OnClientStateChange);
SignalLogInput.repeat(single_attempt_->SignalLogInput);
SignalLogOutput.repeat(single_attempt_->SignalLogOutput);
single_attempt_->Start();
}
-const std::string& Login::google_host() const {
- return google_host_;
-}
-
-const std::string& Login::google_user() const {
- return google_user_;
-}
-
-const talk_base::ProxyInfo& Login::proxy() const {
- return proxy_info_;
-}
-
void Login::OnLoginFailure(const LoginFailure& failure) {
- auto_reconnect_.StopReconnectTimer();
- HandleClientStateChange(STATE_CLOSED);
SignalLoginFailure(failure);
+ TryReconnect();
}
-void Login::OnLogoff() {
- HandleClientStateChange(STATE_CLOSED);
-}
-
-void Login::OnClientStateChange(buzz::XmppEngine::State state) {
- LoginConnectionState new_state = STATE_CLOSED;
-
- switch (state) {
- case buzz::XmppEngine::STATE_NONE:
- case buzz::XmppEngine::STATE_CLOSED:
- // Ignore the closed state (because we may be trying the next dns entry).
- //
- // But we go to this state for other signals when there is no retry
- // happening.
- new_state = state_;
- break;
-
- case buzz::XmppEngine::STATE_START:
- case buzz::XmppEngine::STATE_OPENING:
- new_state = STATE_OPENING;
- break;
+void Login::OnRedirect(const std::string& redirect_server, int redirect_port) {
+ DCHECK_NE(redirect_port_, 0);
- case buzz::XmppEngine::STATE_OPEN:
- new_state = STATE_OPENED;
- break;
+ redirect_time_ = base::Time::Now();
+ redirect_server_ = redirect_server;
+ redirect_port_ = redirect_port;
- default:
- DCHECK(false);
- break;
- }
- HandleClientStateChange(new_state);
+ // Drop the current connection, and start the login process again.
+ StartConnection();
}
-void Login::HandleClientStateChange(LoginConnectionState new_state) {
- // Do we need to transition between the retrying and closed states?
- if (auto_reconnect_.is_retrying()) {
- if (new_state == STATE_CLOSED) {
- new_state = STATE_RETRYING;
- }
- } else {
- if (new_state == STATE_RETRYING) {
- new_state = STATE_CLOSED;
- }
+void Login::OnClientStateChange(buzz::XmppEngine::State state) {
+ // We only care about when we're connected.
+ if (state == buzz::XmppEngine::STATE_OPEN) {
+ ResetReconnectState();
+ ChangeState(STATE_CONNECTED);
}
+}
- if (new_state != state_) {
+void Login::ChangeState(LoginConnectionState new_state) {
+ if (state_ != new_state) {
state_ = new_state;
- reset_unexpected_timer_.Stop();
-
- if (state_ == STATE_OPENED) {
- successful_connection_ = true;
-
- google_host_ = single_attempt_->xmpp_client()->jid().domain();
- google_user_ = single_attempt_->xmpp_client()->jid().node();
- proxy_info_ = single_attempt_->proxy();
-
- reset_unexpected_timer_.Start(
- base::TimeDelta::FromSeconds(kResetReconnectInfoDelaySec),
- this, &Login::ResetUnexpectedDisconnect);
- }
+ LOG(INFO) << "Signalling new state " << state_;
SignalClientStateChange(state_);
}
}
-void Login::OnAutoReconnectTimerChange() {
- if (!single_attempt_ || !single_attempt_->xmpp_client()) {
- HandleClientStateChange(STATE_CLOSED);
- return;
- }
- OnClientStateChange(single_attempt_->xmpp_client()->GetState());
-}
-
buzz::XmppClient* Login::xmpp_client() {
if (!single_attempt_) {
return NULL;
@@ -230,122 +145,48 @@ buzz::XmppClient* Login::xmpp_client() {
return single_attempt_->xmpp_client();
}
-void Login::UseNextConnection() {
- if (!single_attempt_) {
- // Just in case, there is an obscure case that causes this to get called
- // when there is no single_attempt_.
- return;
- }
- single_attempt_->UseNextConnection();
-}
-
-void Login::UseCurrentConnection() {
- if (!single_attempt_) {
- // Just in case, there is an obscure case that causes this to get called
- // when there is no single_attempt_.
- return;
- }
- single_attempt_->UseCurrentConnection();
-}
-
-void Login::OnRedirect(const std::string& redirect_server, int redirect_port) {
- DCHECK_NE(redirect_port_, 0);
-
- redirect_time_ = base::Time::Now();
- redirect_server_ = redirect_server;
- redirect_port_ = redirect_port;
-
- // Drop the current connection, and start the login process again.
- StartConnection();
-}
-
-void Login::OnUnexpectedDisconnect() {
- reset_unexpected_timer_.Stop();
-
- // Start the login process again.
- if (unexpected_disconnect_occurred_) {
- // If we already have received an unexpected disconnect recently, then our
- // account may have be jailed due to abuse, so we shouldn't make the
- // situation worse by trying really hard to reconnect. Instead, we'll do
- // the autoreconnect route, which has exponential back-off.
- DoAutoReconnect();
- return;
- }
- StartConnection();
- unexpected_disconnect_occurred_ = true;
-}
-
-void Login::ResetUnexpectedDisconnect() {
- unexpected_disconnect_occurred_ = false;
+void Login::OnIPAddressChanged() {
+ LOG(INFO) << "Detected IP address change";
+ // Reconnect in 1 to 9 seconds (vary the time a little to try to
+ // avoid spikey behavior on network hiccups).
+ reconnect_interval_ = base::TimeDelta::FromSeconds(base::RandInt(1, 9));
+ TryReconnect();
}
-void Login::DoAutoReconnect() {
- bool allow_auto_reconnect =
- login_settings_->connection_options().auto_reconnect();
- // Start the reconnect time before aborting the connection to ensure that
- // AutoReconnect::is_retrying() is true, so that the Login doesn't
- // transition to the CLOSED state (which would cause the reconnection timer
- // to reset and not double).
- if (allow_auto_reconnect) {
- auto_reconnect_.StartReconnectTimer();
- }
-
+void Login::Disconnect() {
if (single_attempt_) {
+ LOG(INFO) << "Disconnecting";
single_attempt_->Abort();
single_attempt_ = NULL;
}
-
- if (!allow_auto_reconnect) {
- HandleClientStateChange(STATE_CLOSED);
- return;
- }
+ ChangeState(STATE_DISCONNECTED);
}
-void Login::OnIPAddressChanged() {
- LOG(INFO) << "IP address change detected";
- CheckConnection();
+void Login::ResetReconnectState() {
+ reconnect_interval_ =
+ base::TimeDelta::FromSeconds(base::RandInt(5, 25));
+ reconnect_timer_.Stop();
}
-void Login::CheckConnection() {
- // We don't check the connection if we're using ChromeAsyncSocket,
- // as this code requires a libjingle thread to be running. This
- // code will go away in a future cleanup CL, anyway.
- if (!use_chrome_async_socket_) {
- LOG(INFO) << "Checking connection";
- talk_base::PhysicalSocketServer physical;
- scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM));
- bool alive =
- !socket->Connect(talk_base::SocketAddress("talk.google.com", 5222));
- LOG(INFO) << "Network is " << (alive ? "alive" : "not alive");
- if (alive) {
- // Our connection is up. If we have a disconnect timer going,
- // stop it so we don't disconnect.
- disconnect_timer_.Stop();
- } else {
- // Our network connection is down. Start the disconnect timer if
- // it's not already going. Don't disconnect immediately to avoid
- // constant connection/disconnection due to flaky network
- // interfaces.
- if (!disconnect_timer_.IsRunning()) {
- disconnect_timer_.Start(
- base::TimeDelta::FromSeconds(kDisconnectionDelaySecs),
- this, &Login::OnDisconnectTimeout);
- }
- }
- auto_reconnect_.NetworkStateChanged(alive);
- }
+void Login::TryReconnect() {
+ DCHECK_GT(reconnect_interval_.InSeconds(), 0);
+ Disconnect();
+ reconnect_timer_.Stop();
+ LOG(INFO) << "Reconnecting in "
+ << reconnect_interval_.InSeconds() << " seconds";
+ reconnect_timer_.Start(
+ reconnect_interval_, this, &Login::DoReconnect);
}
-void Login::OnDisconnectTimeout() {
- if (state_ != STATE_OPENED) {
- return;
+void Login::DoReconnect() {
+ // Double reconnect time up to 30 minutes.
+ const base::TimeDelta kMaxReconnectInterval =
+ base::TimeDelta::FromMinutes(30);
+ reconnect_interval_ *= 2;
+ if (reconnect_interval_ > kMaxReconnectInterval) {
+ reconnect_interval_ = kMaxReconnectInterval;
}
-
- if (single_attempt_) {
- single_attempt_->Abort();
- single_attempt_ = NULL;
- }
-
+ LOG(INFO) << "Reconnecting...";
StartConnection();
}
diff --git a/jingle/notifier/communicator/login.h b/jingle/notifier/communicator/login.h
index 29dc9e3..d555a8a 100644
--- a/jingle/notifier/communicator/login.h
+++ b/jingle/notifier/communicator/login.h
@@ -10,7 +10,6 @@
#include "base/time.h"
#include "base/timer.h"
#include "jingle/notifier/base/sigslotrepeater.h"
-#include "jingle/notifier/communicator/auto_reconnect.h"
#include "jingle/notifier/communicator/login_connection_state.h"
#include "net/base/network_change_notifier.h"
#include "talk/base/proxyinfo.h"
@@ -58,44 +57,14 @@ class Login : public net::NetworkChangeNotifier::Observer,
ServerInformation* server_list,
int server_count,
talk_base::FirewallManager* firewall,
- bool proxy_only,
- bool previous_login_successful);
+ bool proxy_only);
virtual ~Login();
- LoginConnectionState connection_state() const {
- return state_;
- }
-
void StartConnection();
- void UseNextConnection();
- void UseCurrentConnection();
- buzz::XmppClient* xmpp_client();
-
- // Start the auto-reconnect. It may not do the auto-reconnect if
- // auto-reconnect is turned off.
- void DoAutoReconnect();
-
- const LoginSettings& login_settings() const {
- return *(login_settings_.get());
- }
-
- // Returns the best guess at the host responsible for the account (which we
- // use to determine if it is a dasher account or not).
- //
- // After login this may return a more accurate answer, which accounts for
- // open sign-up accounts.
- const std::string& google_host() const;
- // Analogous to google_host but for the user account ("fred" in
- // "fred@gmail.com").
- const std::string& google_user() const;
-
- // Returns the proxy that is being used to connect (or the default proxy
- // information if all attempted connections failed).
- //
- // Do not call until StartConnection has been called.
- const talk_base::ProxyInfo& proxy() const;
+ buzz::XmppClient* xmpp_client();
+ // net::NetworkChangeNotifier::Observer implementation.
virtual void OnIPAddressChanged();
sigslot::signal1<LoginConnectionState> SignalClientStateChange;
@@ -103,47 +72,44 @@ class Login : public net::NetworkChangeNotifier::Observer,
sigslot::signal1<const LoginFailure&> SignalLoginFailure;
sigslot::repeater2<const char*, int> SignalLogInput;
sigslot::repeater2<const char*, int> SignalLogOutput;
- sigslot::repeater1<bool> SignalIdleChange;
-
- // The creator should hook this up to a signal that indicates when the power
- // is being suspended.
- sigslot::repeater1<bool> SignalPowerSuspended;
private:
- void CheckConnection();
-
- void OnRedirect(const std::string& redirect_server, int redirect_port);
- void OnUnexpectedDisconnect();
- void OnClientStateChange(buzz::XmppEngine::State state);
void OnLoginFailure(const LoginFailure& failure);
void OnLogoff();
- void OnAutoReconnectTimerChange();
+ void OnRedirect(const std::string& redirect_server, int redirect_port);
+ void OnClientStateChange(buzz::XmppEngine::State state);
+
+ void ChangeState(LoginConnectionState new_state);
+
+ // Abort any existing connection.
+ void Disconnect();
- void HandleClientStateChange(LoginConnectionState new_state);
- void ResetUnexpectedDisconnect();
+ // Stops any existing reconnect timer and sets an initial reconnect
+ // interval.
+ void ResetReconnectState();
- void OnDisconnectTimeout();
+ // Tries to reconnect in some point in the future. If called
+ // repeatedly, will wait longer and longer until reconnecting.
+ void TryReconnect();
+
+ // The actual function (called by |reconnect_timer_|) that does the
+ // reconnection.
+ void DoReconnect();
talk_base::TaskParent* parent_;
bool use_chrome_async_socket_;
scoped_ptr<LoginSettings> login_settings_;
- AutoReconnect auto_reconnect_;
+ LoginConnectionState state_;
SingleLoginAttempt* single_attempt_;
- bool successful_connection_;
- LoginConnectionState state_;
+ // reconnection state.
+ base::TimeDelta reconnect_interval_;
+ base::OneShotTimer<Login> reconnect_timer_;
// server redirect information
base::Time redirect_time_;
std::string redirect_server_;
int redirect_port_;
- bool unexpected_disconnect_occurred_;
- base::OneShotTimer<Login> reset_unexpected_timer_;
- std::string google_host_;
- std::string google_user_;
- talk_base::ProxyInfo proxy_info_;
-
- base::OneShotTimer<Login> disconnect_timer_;
DISALLOW_COPY_AND_ASSIGN(Login);
};
diff --git a/jingle/notifier/communicator/login_connection_state.h b/jingle/notifier/communicator/login_connection_state.h
index db90451..d4c6470 100644
--- a/jingle/notifier/communicator/login_connection_state.h
+++ b/jingle/notifier/communicator/login_connection_state.h
@@ -11,12 +11,8 @@
namespace notifier {
enum LoginConnectionState {
- STATE_CLOSED,
- // Same as the closed state but indicates that a countdown is
- // happening for auto-retrying the connection.
- STATE_RETRYING,
- STATE_OPENING,
- STATE_OPENED,
+ STATE_DISCONNECTED,
+ STATE_CONNECTED,
};
} // namespace notifier
diff --git a/jingle/notifier/communicator/single_login_attempt.cc b/jingle/notifier/communicator/single_login_attempt.cc
index 8f1e26f..69dd21e 100644
--- a/jingle/notifier/communicator/single_login_attempt.cc
+++ b/jingle/notifier/communicator/single_login_attempt.cc
@@ -99,10 +99,6 @@ SingleLoginAttempt::~SingleLoginAttempt() {
DCHECK(!client_);
}
-bool SingleLoginAttempt::auto_reconnect() const {
- return login_settings_->connection_options().auto_reconnect();
-}
-
const talk_base::ProxyInfo& SingleLoginAttempt::proxy() const {
DCHECK(connection_generator_.get());
return connection_generator_->proxy();
@@ -157,7 +153,7 @@ void SingleLoginAttempt::OnAttemptedAllConnections(
LOG(INFO) << "Connection failed with error " << code_;
// We were connected and we had a problem.
- if (successful_connection_ && auto_reconnect()) {
+ if (successful_connection_) {
SignalNeedAutoReconnect();
// Expect to be deleted at this point.
return;
diff --git a/jingle/notifier/communicator/single_login_attempt.h b/jingle/notifier/communicator/single_login_attempt.h
index 582615d..8b4f93b 100644
--- a/jingle/notifier/communicator/single_login_attempt.h
+++ b/jingle/notifier/communicator/single_login_attempt.h
@@ -118,8 +118,6 @@ class SingleLoginAttempt : public talk_base::Task, public sigslot::has_slots<> {
void OnAttemptedAllConnections(bool successfully_resolved_dns,
int first_dns_error);
- bool auto_reconnect() const;
-
bool use_chrome_async_socket_;
buzz::XmppEngine::State state_;
buzz::XmppEngine::Error code_;
diff --git a/jingle/notifier/listener/mediator_thread_impl.cc b/jingle/notifier/listener/mediator_thread_impl.cc
index 402346e..bdbbf5b 100644
--- a/jingle/notifier/listener/mediator_thread_impl.cc
+++ b/jingle/notifier/listener/mediator_thread_impl.cc
@@ -206,12 +206,7 @@ void MediatorThreadImpl::DoLogin(
NULL,
// Both the proxy and a non-proxy route
// will be attempted.
- false,
- // |previous_login_successful| is true
- // because we have already done a
- // successful gaia login at this point
- // through another mechanism.
- true));
+ false));
login_->SignalClientStateChange.connect(
this, &MediatorThreadImpl::OnClientStateChangeMessage);
@@ -332,21 +327,16 @@ void MediatorThreadImpl::OnClientStateChangeMessageOnParentThread(
LoginConnectionState state) {
DCHECK_EQ(MessageLoop::current(), parent_message_loop_);
switch (state) {
- case STATE_CLOSED:
- if (delegate_) {
- delegate_->OnConnectionStateChange(false);
- }
- break;
- case STATE_RETRYING:
- case STATE_OPENING:
+ case STATE_DISCONNECTED:
LOG(INFO) << "P2P: Thread trying to connect.";
// Maybe first time logon, maybe intermediate network disruption. Assume
// the server went down, and lost our subscription for updates.
if (delegate_) {
+ delegate_->OnConnectionStateChange(false);
delegate_->OnSubscriptionStateChange(false);
}
break;
- case STATE_OPENED:
+ case STATE_CONNECTED:
if (delegate_) {
delegate_->OnConnectionStateChange(true);
}