- add sources.
[platform/framework/web/crosswalk.git] / src / jingle / notifier / communicator / login.cc
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.
4
5 #include "jingle/notifier/communicator/login.h"
6
7 #include <string>
8
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 "talk/base/common.h"
14 #include "talk/base/firewallsocketserver.h"
15 #include "talk/base/logging.h"
16 #include "talk/base/physicalsocketserver.h"
17 #include "talk/base/taskrunner.h"
18 #include "talk/xmllite/xmlelement.h"
19 #include "talk/xmpp/asyncsocket.h"
20 #include "talk/xmpp/prexmppauth.h"
21 #include "talk/xmpp/xmppclient.h"
22 #include "talk/xmpp/xmppclientsettings.h"
23 #include "talk/xmpp/xmppengine.h"
24
25 namespace notifier {
26
27 Login::Delegate::~Delegate() {}
28
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,
39                       servers,
40                       try_ssltcp_first,
41                       auth_mechanism) {
42   net::NetworkChangeNotifier::AddIPAddressObserver(this);
43   net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
44   // TODO(akalin): Add as DNSObserver once bug 130610 is fixed.
45   ResetReconnectState();
46 }
47
48 Login::~Login() {
49   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
50   net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
51 }
52
53 void Login::StartConnection() {
54   DVLOG(1) << "Starting connection...";
55   single_attempt_.reset(new SingleLoginAttempt(login_settings_, this));
56 }
57
58 void Login::UpdateXmppSettings(const buzz::XmppClientSettings& user_settings) {
59   DVLOG(1) << "XMPP settings updated";
60   login_settings_.set_user_settings(user_settings);
61 }
62
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.
65 //
66 // TODO(akalin): Add unit tests to enforce the behavior above.
67
68 void Login::OnConnect(base::WeakPtr<buzz::XmppTaskParentInterface> base_task) {
69   DVLOG(1) << "Connected";
70   ResetReconnectState();
71   delegate_->OnConnect(base_task);
72 }
73
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.
78   StartConnection();
79   delegate_->OnTransientDisconnection();
80 }
81
82 void Login::OnCredentialsRejected() {
83   DVLOG(1) << "Credentials rejected";
84   TryReconnect();
85   delegate_->OnCredentialsRejected();
86 }
87
88 void Login::OnSettingsExhausted() {
89   DVLOG(1) << "Settings exhausted";
90   TryReconnect();
91   delegate_->OnTransientDisconnection();
92 }
93
94 void Login::OnIPAddressChanged() {
95   DVLOG(1) << "IP address changed";
96   OnNetworkEvent();
97 }
98
99 void Login::OnConnectionTypeChanged(
100     net::NetworkChangeNotifier::ConnectionType type) {
101   DVLOG(1) << "Connection type changed";
102   OnNetworkEvent();
103 }
104
105 void Login::OnDNSChanged() {
106   DVLOG(1) << "DNS changed";
107   OnNetworkEvent();
108 }
109
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));
114   TryReconnect();
115   delegate_->OnTransientDisconnection();
116 }
117
118 void Login::ResetReconnectState() {
119   reconnect_interval_ =
120       base::TimeDelta::FromSeconds(base::RandInt(5, 25));
121   reconnect_timer_.Stop();
122 }
123
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);
132 }
133
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...";
142   StartConnection();
143 }
144
145 }  // namespace notifier