Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: remoting/signaling/xmpp_signal_strategy.cc

Issue 958703003: Remove dependency on XMPP implementation in WebRTC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "remoting/signaling/xmpp_signal_strategy.h" 5 #include "remoting/signaling/xmpp_signal_strategy.h"
6 6
7 #include <vector>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/location.h" 10 #include "base/location.h"
9 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/observer_list.h"
13 #include "base/rand_util.h"
10 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
11 #include "base/strings/string_util.h" 15 #include "base/strings/string_number_conversions.h"
12 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
13 #include "jingle/glue/chrome_async_socket.h" 17 #include "base/threading/thread_checker.h"
14 #include "jingle/glue/task_pump.h" 18 #include "base/time/time.h"
15 #include "jingle/glue/xmpp_client_socket_factory.h" 19 #include "base/timer/timer.h"
16 #include "jingle/notifier/base/gaia_constants.h" 20 #include "jingle/glue/proxy_resolving_client_socket.h"
17 #include "jingle/notifier/base/gaia_token_pre_xmpp_auth.h" 21 #include "net/cert/cert_verifier.h"
22 #include "net/http/transport_security_state.h"
18 #include "net/socket/client_socket_factory.h" 23 #include "net/socket/client_socket_factory.h"
24 #include "net/socket/client_socket_handle.h"
25 #include "net/socket/ssl_client_socket.h"
19 #include "net/url_request/url_request_context_getter.h" 26 #include "net/url_request/url_request_context_getter.h"
20 #include "third_party/webrtc/base/thread.h" 27 #include "remoting/base/buffered_socket_writer.h"
21 #include "third_party/webrtc/libjingle/xmpp/prexmppauth.h" 28 #include "remoting/signaling/xmpp_login_handler.h"
22 #include "third_party/webrtc/libjingle/xmpp/saslcookiemechanism.h" 29 #include "remoting/signaling/xmpp_stream_parser.h"
30 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
23 31
24 const char kDefaultResourceName[] = "chromoting"; 32 // Use 50 seconds keep-alive interval, in case routers terminate
25
26 // Use 58 seconds keep-alive interval, in case routers terminate
27 // connections that are idle for more than a minute. 33 // connections that are idle for more than a minute.
28 const int kKeepAliveIntervalSeconds = 50; 34 const int kKeepAliveIntervalSeconds = 50;
29 35
30 // Read buffer size used by ChromeAsyncSocket for read and write buffers. 36 const int kReadBufferSize = 4096;
31 //
32 // TODO(sergeyu): Currently jingle::ChromeAsyncSocket fails Write() when the
33 // write buffer is full and talk::XmppClient just ignores the error. As result
34 // chunks of data sent to the server are dropped (and they may not be full XMPP
35 // stanzas). The problem needs to be fixed either in XmppClient on
36 // ChromeAsyncSocket (e.g. ChromeAsyncSocket could close the connection when
37 // buffer is full).
38 const size_t kReadBufferSize = 64 * 1024;
39 const size_t kWriteBufferSize = 64 * 1024;
40 37
41 const int kDefaultXmppPort = 5222; 38 const int kDefaultXmppPort = 5222;
42 const int kDefaultHttpsPort = 443; 39 const int kDefaultHttpsPort = 443;
43 40
44 namespace remoting { 41 namespace remoting {
45 42
46 XmppSignalStrategy::XmppServerConfig::XmppServerConfig() {} 43 XmppSignalStrategy::XmppServerConfig::XmppServerConfig()
47 XmppSignalStrategy::XmppServerConfig::~XmppServerConfig() {} 44 : port(kDefaultXmppPort), use_tls(true) {
45 }
48 46
49 XmppSignalStrategy::XmppSignalStrategy( 47 XmppSignalStrategy::XmppServerConfig::~XmppServerConfig() {
48 }
49
50 class XmppSignalStrategy::Core : public XmppLoginHandler::Delegate {
51 public:
52 Core(
53 net::ClientSocketFactory* socket_factory,
54 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
55 const XmppServerConfig& xmpp_server_config);
56 ~Core() override;
57
58 void Connect();
59 void Disconnect();
60 State GetState() const;
61 Error GetError() const;
62 std::string GetLocalJid() const;
63 void AddListener(Listener* listener);
64 void RemoveListener(Listener* listener);
65 bool SendStanza(scoped_ptr<buzz::XmlElement> stanza);
66
67 void SetAuthInfo(const std::string& username,
68 const std::string& auth_token,
69 const std::string& auth_service);
70
71 void VerifyNoListeners();
72
73 private:
74 void OnSocketConnected(int result);
75 void OnTlsConnected(int result);
76
77 void ReadSocket();
78 void OnReadResult(int result);
79 void HandleReadResult(int result);
80
81 // XmppLoginHandler::Delegate interface.
82 void SendMessage(const std::string& message) override;
83 void StartTls() override;
84 void OnHandshakeDone(const std::string& jid,
85 scoped_ptr<XmppStreamParser> parser) override;
86 void OnLoginHandlerError(SignalStrategy::Error error) override;
87
88 // Event handlers for XmppStreamParser.
89 void OnStanza(const scoped_ptr<buzz::XmlElement> stanza);
90 void OnParserError();
91
92 void OnNetworkError(int error);
93
94 void SendKeepAlive();
95
96 net::ClientSocketFactory* socket_factory_;
97 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
98 XmppServerConfig xmpp_server_config_;
99
100 // Used by the |socket_|.
101 scoped_ptr<net::CertVerifier> cert_verifier_;
102 scoped_ptr<net::TransportSecurityState> transport_security_state_;
103
104 scoped_ptr<net::StreamSocket> socket_;
105 scoped_ptr<BufferedSocketWriter> writer_;
106 scoped_refptr<net::IOBuffer> read_buffer_;
107 bool read_pending_;
108 bool tls_pending_;
109
110 scoped_ptr<XmppLoginHandler> login_handler_;
111 scoped_ptr<XmppStreamParser> stream_parser_;
112 std::string jid_;
113
114 Error error_;
115
116 ObserverList<Listener, true> listeners_;
117
118 base::Timer keep_alive_timer_;
119
120 base::ThreadChecker thread_checker_;
121
122 DISALLOW_COPY_AND_ASSIGN(Core);
123 };
124
125 XmppSignalStrategy::Core::Core(
50 net::ClientSocketFactory* socket_factory, 126 net::ClientSocketFactory* socket_factory,
51 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, 127 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
52 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config) 128 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config)
53 : socket_factory_(socket_factory), 129 : socket_factory_(socket_factory),
54 request_context_getter_(request_context_getter), 130 request_context_getter_(request_context_getter),
55 resource_name_(kDefaultResourceName),
56 xmpp_client_(nullptr),
57 xmpp_server_config_(xmpp_server_config), 131 xmpp_server_config_(xmpp_server_config),
58 state_(DISCONNECTED), 132 read_pending_(false),
59 error_(OK) { 133 tls_pending_(false),
60 #if defined(NDEBUG) 134 error_(OK),
61 CHECK(xmpp_server_config_.use_tls); 135 keep_alive_timer_(
62 #endif 136 FROM_HERE,
63 } 137 base::TimeDelta::FromSeconds(kKeepAliveIntervalSeconds),
64 138 base::Bind(&Core::SendKeepAlive, base::Unretained(this)),
65 XmppSignalStrategy::~XmppSignalStrategy() { 139 true) {
66 Disconnect(); 140 // The flag is currently ignored.
67 141 DCHECK(xmpp_server_config_.use_tls);
rmsousa 2015/02/28 06:33:29 could you add a // TODO to support it no tls in de
Sergey Ulanov 2015/03/02 18:11:10 Implemented support for non-tls connections now.
68 // Destroying task runner will destroy XmppClient, but XmppClient may be on
69 // the stack and it doesn't handle this case properly, so we need to delay
70 // destruction.
71 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
72 FROM_HERE, task_runner_.release());
73 }
74
75 void XmppSignalStrategy::Connect() {
76 DCHECK(CalledOnValidThread());
77
78 // Disconnect first if we are currently connected.
79 Disconnect();
80
81 buzz::XmppClientSettings settings;
82 buzz::Jid login_jid(xmpp_server_config_.username);
83 settings.set_user(login_jid.node());
84 settings.set_host(login_jid.domain());
85 settings.set_resource(resource_name_);
86 settings.set_token_service(xmpp_server_config_.auth_service);
87 settings.set_auth_token(buzz::AUTH_MECHANISM_GOOGLE_TOKEN,
88 xmpp_server_config_.auth_token);
89
90 int port = xmpp_server_config_.port;
91 142
92 // Port 5222 may be blocked by firewall. talk.google.com allows connections on 143 // Port 5222 may be blocked by firewall. talk.google.com allows connections on
93 // port 443 which can be used instead of 5222. The webapp still requests to 144 // port 443 which can be used instead of 5222. The webapp still requests to
94 // use port 5222 for backwards compatibility with older versions of the host 145 // use port 5222 for backwards compatibility with older versions of the host
95 // that do not pass correct |use_fake_ssl_client_socket| value to 146 // that do not pass correct |use_fake_ssl_client_socket| value to
96 // XmppClientSocketFactory (and so cannot connect to port 443). In case we are 147 // XmppClientSocketFactory (and so cannot connect to port 443). In case we are
97 // connecting to talk.google.com try to use port 443 anyway. 148 // connecting to talk.google.com try to use port 443 anyway.
98 // 149 //
99 // TODO(sergeyu): Once all hosts support connections on port 443 150 // TODO(sergeyu): Once all hosts support connections on port 443
100 // the webapp needs to be updated to request port 443 and these 2 lines can be 151 // the webapp needs to be updated to request port 443 and these 2 lines can be
101 // removed. crbug.com/443384 152 // removed. crbug.com/443384
102 if (xmpp_server_config_.host == "talk.google.com" && port == kDefaultXmppPort) 153 if (xmpp_server_config_.host == "talk.google.com" &&
103 port = kDefaultHttpsPort; 154 xmpp_server_config_.port == kDefaultXmppPort) {
104 155 xmpp_server_config_.port = kDefaultHttpsPort;
105 settings.set_server( 156 }
106 rtc::SocketAddress(xmpp_server_config_.host, port)); 157 }
107 settings.set_use_tls( 158
108 xmpp_server_config_.use_tls ? buzz::TLS_ENABLED : buzz::TLS_DISABLED); 159 XmppSignalStrategy::Core::~Core() {
109 160 Disconnect();
110 // Enable fake SSL handshake when connecting over HTTPS port. 161 }
111 bool use_fake_ssl_client_socket = (port == kDefaultHttpsPort); 162
112 163 void XmppSignalStrategy::Core::Connect() {
113 scoped_ptr<jingle_glue::XmppClientSocketFactory> xmpp_socket_factory( 164 DCHECK(thread_checker_.CalledOnValidThread());
114 new jingle_glue::XmppClientSocketFactory(socket_factory_, 165
115 net::SSLConfig(), 166 // Disconnect first if we are currently connected.
116 request_context_getter_, 167 Disconnect();
117 use_fake_ssl_client_socket)); 168
118 buzz::AsyncSocket* socket = new jingle_glue::ChromeAsyncSocket( 169 error_ = OK;
119 xmpp_socket_factory.release(), kReadBufferSize, kWriteBufferSize); 170
120 171 FOR_EACH_OBSERVER(Listener, listeners_,
121 task_runner_.reset(new jingle_glue::TaskPump()); 172 OnSignalStrategyStateChange(CONNECTING));
122 xmpp_client_ = new buzz::XmppClient(task_runner_.get()); 173
123 xmpp_client_->Connect( 174 socket_.reset(new jingle_glue::ProxyResolvingClientSocket(
124 settings, std::string(), socket, CreatePreXmppAuth(settings)); 175 socket_factory_, request_context_getter_, net::SSLConfig(),
125 xmpp_client_->SignalStateChange 176 net::HostPortPair(xmpp_server_config_.host, xmpp_server_config_.port)));
126 .connect(this, &XmppSignalStrategy::OnConnectionStateChanged); 177
127 xmpp_client_->engine()->AddStanzaHandler(this, buzz::XmppEngine::HL_TYPE); 178 int result = socket_->Connect(base::Bind(
128 xmpp_client_->Start(); 179 &Core::OnSocketConnected, base::Unretained(this)));
129 180 if (result != net::ERR_IO_PENDING)
130 SetState(CONNECTING); 181 OnSocketConnected(result);
182 }
183
184 void XmppSignalStrategy::Core::Disconnect() {
185 DCHECK(thread_checker_.CalledOnValidThread());
186
187 if (socket_) {
188 login_handler_.reset();
189 stream_parser_.reset();
190 writer_.reset();
191 socket_.reset();
192
193 FOR_EACH_OBSERVER(Listener, listeners_,
194 OnSignalStrategyStateChange(DISCONNECTED));
195 }
196 }
197
198 SignalStrategy::State XmppSignalStrategy::Core::GetState() const {
199 DCHECK(thread_checker_.CalledOnValidThread());
200
201 if (stream_parser_) {
202 DCHECK(socket_);
203 return CONNECTED;
204 } else if (socket_) {
205 return CONNECTING;
206 } else {
207 return DISCONNECTED;
208 }
209 }
210
211 SignalStrategy::Error XmppSignalStrategy::Core::GetError() const {
212 DCHECK(thread_checker_.CalledOnValidThread());
213 return error_;
214 }
215
216 std::string XmppSignalStrategy::Core::GetLocalJid() const {
217 DCHECK(thread_checker_.CalledOnValidThread());
218 return jid_;
219 }
220
221 void XmppSignalStrategy::Core::AddListener(Listener* listener) {
222 DCHECK(thread_checker_.CalledOnValidThread());
223 listeners_.AddObserver(listener);
224 }
225
226 void XmppSignalStrategy::Core::RemoveListener(Listener* listener) {
227 DCHECK(thread_checker_.CalledOnValidThread());
228 listeners_.RemoveObserver(listener);
229 }
230
231 bool XmppSignalStrategy::Core::SendStanza(scoped_ptr<buzz::XmlElement> stanza) {
232 DCHECK(thread_checker_.CalledOnValidThread());
233
234 if (!stream_parser_) {
235 VLOG(0) << "Dropping signalling message because XMPP "
236 "connection has been terminated.";
237 return false;
238 }
239
240 SendMessage(stanza->Str());
241 return true;
242 }
243
244 void XmppSignalStrategy::Core::SetAuthInfo(const std::string& username,
245 const std::string& auth_token,
246 const std::string& auth_service) {
247 DCHECK(thread_checker_.CalledOnValidThread());
248 xmpp_server_config_.username = username;
249 xmpp_server_config_.auth_token = auth_token;
250 xmpp_server_config_.auth_service = auth_service;
251 }
252
253 void XmppSignalStrategy::Core::SendMessage(const std::string& message) {
254 DCHECK(thread_checker_.CalledOnValidThread());
255 scoped_refptr<net::IOBufferWithSize> buffer =
256 new net::IOBufferWithSize(message.size());
257 memcpy(buffer->data(), message.data(), message.size());
258 writer_->Write(buffer, base::Closure());
259 }
260
261 void XmppSignalStrategy::Core::StartTls() {
262 DCHECK(thread_checker_.CalledOnValidThread());
263 DCHECK(login_handler_);
264
265 // Reset the writer so we don't try to write to the row socket anymore.
rmsousa 2015/02/28 06:33:29 nit: raw socket
Sergey Ulanov 2015/03/02 18:11:10 Done.
266 DCHECK_EQ(writer_->GetBufferSize(), 0);
267 writer_.reset();
268
269 DCHECK(!read_pending_);
270
271 scoped_ptr<net::ClientSocketHandle> socket_handle(
272 new net::ClientSocketHandle());
273 socket_handle->SetSocket(socket_.Pass());
274
275 cert_verifier_.reset(net::CertVerifier::CreateDefault());
276 transport_security_state_.reset(new net::TransportSecurityState());
277 net::SSLClientSocketContext context;
278 context.cert_verifier = cert_verifier_.get();
279 context.transport_security_state = transport_security_state_.get();
280
281 socket_ = socket_factory_->CreateSSLClientSocket(
282 socket_handle.Pass(),
283 net::HostPortPair(xmpp_server_config_.host, kDefaultHttpsPort),
284 net::SSLConfig(), context);
285
286 tls_pending_ = true;
287 int result = socket_->Connect(
288 base::Bind(&Core::OnTlsConnected, base::Unretained(this)));
289 if (result != net::ERR_IO_PENDING)
290 OnTlsConnected(result);
291 }
292
293 void XmppSignalStrategy::Core::OnHandshakeDone(
294 const std::string& jid,
295 scoped_ptr<XmppStreamParser> parser) {
296 DCHECK(thread_checker_.CalledOnValidThread());
297
298 jid_ = jid;
299 stream_parser_ = parser.Pass();
300 stream_parser_->SetCallbacks(
301 base::Bind(&Core::OnStanza, base::Unretained(this)),
302 base::Bind(&Core::OnParserError, base::Unretained(this)));
303
304 // Don't need |login_handler_| anymore.
305 login_handler_.reset();
306
307 FOR_EACH_OBSERVER(Listener, listeners_,
308 OnSignalStrategyStateChange(CONNECTED));
309 }
310
311 void XmppSignalStrategy::Core::OnLoginHandlerError(
312 SignalStrategy::Error error) {
313 DCHECK(thread_checker_.CalledOnValidThread());
314
315 error_ = error;
316 Disconnect();
317 }
318
319 void XmppSignalStrategy::Core::OnStanza(
320 const scoped_ptr<buzz::XmlElement> stanza) {
321 DCHECK(thread_checker_.CalledOnValidThread());
322
323 ObserverListBase<Listener>::Iterator it(listeners_);
324 for (Listener* listener = it.GetNext(); listener; listener = it.GetNext()) {
325 if (listener->OnSignalStrategyIncomingStanza(stanza.get()))
326 return;
327 }
328 }
329
330 void XmppSignalStrategy::Core::OnParserError() {
331 DCHECK(thread_checker_.CalledOnValidThread());
332
333 error_ = NETWORK_ERROR;
334 Disconnect();
335 }
336
337 void XmppSignalStrategy::Core::OnSocketConnected(int result) {
338 DCHECK(thread_checker_.CalledOnValidThread());
339
340 if (result != net::OK) {
341 OnNetworkError(result);
342 return;
343 }
344
345 writer_.reset(new BufferedSocketWriter());
346 writer_->Init(socket_.get(), base::Bind(&Core::OnNetworkError,
347 base::Unretained(this)));
348
349 bool need_handshake_before_tls =
350 (xmpp_server_config_.port == kDefaultXmppPort);
351
352 // The server name is passed as to attribute in the <stream>. When connecting
353 // to talk.google.com it affects the certificate the server will use for TLS:
354 // talk.google.com uses gmail certificate when specified server is gmail.com
355 // or googlemail.com and google.com cert otherwise. In the same time it
356 // doesn't accept talk.google.com as target server. Here we use google.com
357 // server name when authenticating to talk.google.com. This ensures that the
358 // server will use google.com cert which will be accepted by the TLS
359 // implementation in Chrome (TLS API doesn't allow specifying domain other
360 // than the one that was passed to connect()).
361 std::string server = xmpp_server_config_.host;
362 if (server == "talk.google.com")
363 server = "google.com";
364
365 login_handler_.reset(new XmppLoginHandler(
366 server, xmpp_server_config_.username, xmpp_server_config_.auth_token,
367 xmpp_server_config_.auth_service, need_handshake_before_tls, this));
368 login_handler_->Start();
369
370 ReadSocket();
371 }
372
373 void XmppSignalStrategy::Core::OnTlsConnected(int result) {
374 DCHECK(thread_checker_.CalledOnValidThread());
375 DCHECK(tls_pending_);
376 tls_pending_ = false;
377
378 if (result != net::OK) {
379 OnNetworkError(result);
380 return;
381 }
382
383 writer_.reset(new BufferedSocketWriter());
384 writer_->Init(socket_.get(), base::Bind(&Core::OnNetworkError,
385 base::Unretained(this)));
386
387 login_handler_->OnTlsStarted();
388
389 ReadSocket();
390 }
391
392 void XmppSignalStrategy::Core::ReadSocket() {
393 DCHECK(thread_checker_.CalledOnValidThread());
394
395 while (socket_ && !read_pending_ && !tls_pending_) {
396 read_buffer_ = new net::IOBuffer(kReadBufferSize);
397 int result = socket_->Read(
398 read_buffer_.get(), kReadBufferSize,
399 base::Bind(&Core::OnReadResult, base::Unretained(this)));
400 HandleReadResult(result);
401 }
402 }
403
404 void XmppSignalStrategy::Core::OnReadResult(int result) {
405 DCHECK(thread_checker_.CalledOnValidThread());
406 DCHECK(read_pending_);
407 read_pending_ = false;
408 HandleReadResult(result);
409 ReadSocket();
410 }
411
412 void XmppSignalStrategy::Core::HandleReadResult(int result) {
413 DCHECK(thread_checker_.CalledOnValidThread());
414
415 if (result == net::ERR_IO_PENDING) {
416 read_pending_ = true;
417 return;
418 }
419
420 if (result < 0) {
421 OnNetworkError(result);
422 return;
423 }
424
425 if (result == 0) {
426 // Connection was closed by the server.
427 error_ = OK;
428 Disconnect();
429 return;
430 }
431
432 if (stream_parser_) {
433 stream_parser_->AppendData(std::string(read_buffer_->data(), result));
434 } else {
435 login_handler_->OnDataReceived(std::string(read_buffer_->data(), result));
436 }
437 }
438
439 void XmppSignalStrategy::Core::OnNetworkError(int error) {
440 DCHECK(thread_checker_.CalledOnValidThread());
441
442 LOG(ERROR) << "XMPP socket error " << error;
443 error_ = NETWORK_ERROR;
444 Disconnect();
445 }
446
447 void XmppSignalStrategy::Core::SendKeepAlive() {
448 DCHECK(thread_checker_.CalledOnValidThread());
449
450 if (GetState() == CONNECTED)
451 SendMessage(" ");
452 }
453
454 XmppSignalStrategy::XmppSignalStrategy(
455 net::ClientSocketFactory* socket_factory,
456 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
457 const XmppServerConfig& xmpp_server_config)
458 : core_(new Core(socket_factory,
459 request_context_getter,
460 xmpp_server_config)) {
461 }
462
463 XmppSignalStrategy::~XmppSignalStrategy() {
464 // All listeners should be removed at this point, so it's safe to detach
465 // |core_|.
466 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, core_.release());
467 }
468
469 void XmppSignalStrategy::Connect() {
470 core_->Connect();
131 } 471 }
132 472
133 void XmppSignalStrategy::Disconnect() { 473 void XmppSignalStrategy::Disconnect() {
134 DCHECK(CalledOnValidThread()); 474 core_->Disconnect();
135
136 if (xmpp_client_) {
137 xmpp_client_->engine()->RemoveStanzaHandler(this);
138
139 xmpp_client_->Disconnect();
140
141 // |xmpp_client_| should be set to nullptr in OnConnectionStateChanged()
142 // in response to Disconnect() call above.
143 DCHECK(xmpp_client_ == nullptr);
144 }
145 } 475 }
146 476
147 SignalStrategy::State XmppSignalStrategy::GetState() const { 477 SignalStrategy::State XmppSignalStrategy::GetState() const {
148 DCHECK(CalledOnValidThread()); 478 return core_->GetState();
149 return state_;
150 } 479 }
151 480
152 SignalStrategy::Error XmppSignalStrategy::GetError() const { 481 SignalStrategy::Error XmppSignalStrategy::GetError() const {
153 DCHECK(CalledOnValidThread()); 482 return core_->GetError();
154 return error_;
155 } 483 }
156 484
157 std::string XmppSignalStrategy::GetLocalJid() const { 485 std::string XmppSignalStrategy::GetLocalJid() const {
158 DCHECK(CalledOnValidThread()); 486 return core_->GetLocalJid();
159 return xmpp_client_->jid().Str();
160 } 487 }
161 488
162 void XmppSignalStrategy::AddListener(Listener* listener) { 489 void XmppSignalStrategy::AddListener(Listener* listener) {
163 DCHECK(CalledOnValidThread()); 490 core_->AddListener(listener);
164 listeners_.AddObserver(listener);
165 } 491 }
166 492
167 void XmppSignalStrategy::RemoveListener(Listener* listener) { 493 void XmppSignalStrategy::RemoveListener(Listener* listener) {
168 DCHECK(CalledOnValidThread()); 494 core_->RemoveListener(listener);
169 listeners_.RemoveObserver(listener); 495 }
170 }
171
172 bool XmppSignalStrategy::SendStanza(scoped_ptr<buzz::XmlElement> stanza) { 496 bool XmppSignalStrategy::SendStanza(scoped_ptr<buzz::XmlElement> stanza) {
173 DCHECK(CalledOnValidThread()); 497 return core_->SendStanza(stanza.Pass());
174 if (!xmpp_client_) {
175 VLOG(0) << "Dropping signalling message because XMPP "
176 "connection has been terminated.";
177 return false;
178 }
179
180 buzz::XmppReturnStatus status = xmpp_client_->SendStanza(stanza.release());
181 return status == buzz::XMPP_RETURN_OK || status == buzz::XMPP_RETURN_PENDING;
182 } 498 }
183 499
184 std::string XmppSignalStrategy::GetNextId() { 500 std::string XmppSignalStrategy::GetNextId() {
185 DCHECK(CalledOnValidThread()); 501 return base::Uint64ToString(base::RandUint64());
186 if (!xmpp_client_) {
187 // If the connection has been terminated then it doesn't matter
188 // what Id we return.
189 return std::string();
190 }
191 return xmpp_client_->NextId();
192 }
193
194 bool XmppSignalStrategy::HandleStanza(const buzz::XmlElement* stanza) {
195 DCHECK(CalledOnValidThread());
196 ObserverListBase<Listener>::Iterator it(listeners_);
197 Listener* listener;
198 while ((listener = it.GetNext()) != nullptr) {
199 if (listener->OnSignalStrategyIncomingStanza(stanza))
200 return true;
201 }
202 return false;
203 } 502 }
204 503
205 void XmppSignalStrategy::SetAuthInfo(const std::string& username, 504 void XmppSignalStrategy::SetAuthInfo(const std::string& username,
206 const std::string& auth_token, 505 const std::string& auth_token,
207 const std::string& auth_service) { 506 const std::string& auth_service) {
208 DCHECK(CalledOnValidThread()); 507 core_->SetAuthInfo(username, auth_token, auth_service);
209 xmpp_server_config_.username = username;
210 xmpp_server_config_.auth_token = auth_token;
211 xmpp_server_config_.auth_service = auth_service;
212 }
213
214 void XmppSignalStrategy::SetResourceName(const std::string &resource_name) {
215 DCHECK(CalledOnValidThread());
216 resource_name_ = resource_name;
217 }
218
219 void XmppSignalStrategy::OnConnectionStateChanged(
220 buzz::XmppEngine::State state) {
221 DCHECK(CalledOnValidThread());
222
223 if (state == buzz::XmppEngine::STATE_OPEN) {
224 keep_alive_timer_.Start(
225 FROM_HERE, base::TimeDelta::FromSeconds(kKeepAliveIntervalSeconds),
226 this, &XmppSignalStrategy::SendKeepAlive);
227 SetState(CONNECTED);
228 } else if (state == buzz::XmppEngine::STATE_CLOSED) {
229 // Make sure we dump errors to the log.
230 int subcode;
231 buzz::XmppEngine::Error error = xmpp_client_->GetError(&subcode);
232 VLOG(0) << "XMPP connection was closed: error=" << error
233 << ", subcode=" << subcode;
234
235 keep_alive_timer_.Stop();
236
237 // Client is destroyed by the TaskRunner after the client is
238 // closed. Reset the pointer so we don't try to use it later.
239 xmpp_client_ = nullptr;
240
241 switch (error) {
242 case buzz::XmppEngine::ERROR_UNAUTHORIZED:
243 case buzz::XmppEngine::ERROR_AUTH:
244 case buzz::XmppEngine::ERROR_MISSING_USERNAME:
245 error_ = AUTHENTICATION_FAILED;
246 break;
247
248 default:
249 error_ = NETWORK_ERROR;
250 }
251
252 SetState(DISCONNECTED);
253 }
254 }
255
256 void XmppSignalStrategy::SetState(State new_state) {
257 if (state_ != new_state) {
258 state_ = new_state;
259 FOR_EACH_OBSERVER(Listener, listeners_,
260 OnSignalStrategyStateChange(new_state));
261 }
262 }
263
264 void XmppSignalStrategy::SendKeepAlive() {
265 xmpp_client_->SendRaw(" ");
266 }
267
268 // static
269 buzz::PreXmppAuth* XmppSignalStrategy::CreatePreXmppAuth(
270 const buzz::XmppClientSettings& settings) {
271 buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY);
272 std::string mechanism = notifier::kDefaultGaiaAuthMechanism;
273 if (settings.token_service() == "oauth2") {
274 mechanism = "X-OAUTH2";
275 }
276
277 return new notifier::GaiaTokenPreXmppAuth(
278 jid.Str(), settings.auth_token(), settings.token_service(), mechanism);
279 } 508 }
280 509
281 } // namespace remoting 510 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698