1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "jingle/notifier/communicator/login.h"
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "base/time/time.h"
12 #include "net/base/host_port_pair.h"
13 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
14 #include "webrtc/base/common.h"
15 #include "webrtc/base/firewallsocketserver.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/base/physicalsocketserver.h"
18 #include "webrtc/base/taskrunner.h"
19 #include "webrtc/libjingle/xmpp/asyncsocket.h"
20 #include "webrtc/libjingle/xmpp/prexmppauth.h"
21 #include "webrtc/libjingle/xmpp/xmppclient.h"
22 #include "webrtc/libjingle/xmpp/xmppclientsettings.h"
23 #include "webrtc/libjingle/xmpp/xmppengine.h"
27 Login::Delegate::~Delegate() {}
29 Login::Login(Delegate
* delegate
,
30 const buzz::XmppClientSettings
& user_settings
,
31 const scoped_refptr
<net::URLRequestContextGetter
>&
32 request_context_getter
,
33 const ServerList
& servers
,
34 bool try_ssltcp_first
,
35 const std::string
& auth_mechanism
)
36 : delegate_(delegate
),
37 login_settings_(user_settings
,
38 request_context_getter
,
42 net::NetworkChangeNotifier::AddIPAddressObserver(this);
43 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
44 // TODO(akalin): Add as DNSObserver once bug 130610 is fixed.
45 ResetReconnectState();
49 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
50 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
53 void Login::StartConnection() {
54 DVLOG(1) << "Starting connection...";
55 single_attempt_
.reset(new SingleLoginAttempt(login_settings_
, this));
58 void Login::UpdateXmppSettings(const buzz::XmppClientSettings
& user_settings
) {
59 DVLOG(1) << "XMPP settings updated";
60 login_settings_
.set_user_settings(user_settings
);
63 // In the code below, we assume that calling a delegate method may end
64 // up in ourselves being deleted, so we always call it last.
66 // TODO(akalin): Add unit tests to enforce the behavior above.
68 void Login::OnConnect(base::WeakPtr
<buzz::XmppTaskParentInterface
> base_task
) {
69 DVLOG(1) << "Connected";
70 ResetReconnectState();
71 delegate_
->OnConnect(base_task
);
74 void Login::OnRedirect(const ServerInformation
& redirect_server
) {
75 DVLOG(1) << "Redirected";
76 login_settings_
.SetRedirectServer(redirect_server
);
77 // Drop the current connection, and start the login process again.
79 delegate_
->OnTransientDisconnection();
82 void Login::OnCredentialsRejected() {
83 DVLOG(1) << "Credentials rejected";
85 delegate_
->OnCredentialsRejected();
88 void Login::OnSettingsExhausted() {
89 DVLOG(1) << "Settings exhausted";
91 delegate_
->OnTransientDisconnection();
94 void Login::OnIPAddressChanged() {
95 DVLOG(1) << "IP address changed";
99 void Login::OnConnectionTypeChanged(
100 net::NetworkChangeNotifier::ConnectionType type
) {
101 DVLOG(1) << "Connection type changed";
105 void Login::OnDNSChanged() {
106 DVLOG(1) << "DNS changed";
110 void Login::OnNetworkEvent() {
111 // Reconnect in 1 to 9 seconds (vary the time a little to try to
112 // avoid spikey behavior on network hiccups).
113 reconnect_interval_
= base::TimeDelta::FromSeconds(base::RandInt(1, 9));
115 delegate_
->OnTransientDisconnection();
118 void Login::ResetReconnectState() {
119 reconnect_interval_
=
120 base::TimeDelta::FromSeconds(base::RandInt(5, 25));
121 reconnect_timer_
.Stop();
124 void Login::TryReconnect() {
125 DCHECK_GT(reconnect_interval_
.InSeconds(), 0);
126 single_attempt_
.reset();
127 reconnect_timer_
.Stop();
128 DVLOG(1) << "Reconnecting in "
129 << reconnect_interval_
.InSeconds() << " seconds";
130 reconnect_timer_
.Start(
131 FROM_HERE
, reconnect_interval_
, this, &Login::DoReconnect
);
134 void Login::DoReconnect() {
135 // Double reconnect time up to 30 minutes.
136 const base::TimeDelta kMaxReconnectInterval
=
137 base::TimeDelta::FromMinutes(30);
138 reconnect_interval_
*= 2;
139 if (reconnect_interval_
> kMaxReconnectInterval
)
140 reconnect_interval_
= kMaxReconnectInterval
;
141 DVLOG(1) << "Reconnecting...";
145 } // namespace notifier