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
3 // found in the LICENSE file.
5 #include "remoting/signaling/xmpp_signal_strategy.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/observer_list.h"
13 #include "base/rand_util.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/threading/thread_checker.h"
18 #include "base/time/time.h"
19 #include "base/timer/timer.h"
20 #include "jingle/glue/proxy_resolving_client_socket.h"
21 #include "net/cert/cert_verifier.h"
22 #include "net/http/transport_security_state.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"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "remoting/base/buffered_socket_writer.h"
28 #include "remoting/signaling/xmpp_login_handler.h"
29 #include "remoting/signaling/xmpp_stream_parser.h"
30 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
32 // Use 50 seconds keep-alive interval, in case routers terminate
33 // connections that are idle for more than a minute.
34 const int kKeepAliveIntervalSeconds
= 50;
36 const int kReadBufferSize
= 4096;
38 const int kDefaultXmppPort
= 5222;
39 const int kDefaultHttpsPort
= 443;
43 XmppSignalStrategy::XmppServerConfig::XmppServerConfig()
44 : port(kDefaultXmppPort
), use_tls(true) {
47 XmppSignalStrategy::XmppServerConfig::~XmppServerConfig() {
50 class XmppSignalStrategy::Core
: public XmppLoginHandler::Delegate
{
53 net::ClientSocketFactory
* socket_factory
,
54 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
55 const XmppServerConfig
& xmpp_server_config
);
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
);
67 void SetAuthInfo(const std::string
& username
,
68 const std::string
& auth_token
);
72 // StartTls() hasn't been called. |socket_| is not encrypted.
75 // StartTls() has been called. Waiting for |writer_| to finish writing
76 // data before starting TLS.
79 // TLS has been started, waiting for TLS handshake to finish.
86 void OnSocketConnected(int result
);
87 void OnTlsConnected(int result
);
90 void OnReadResult(int result
);
91 void HandleReadResult(int result
);
93 // XmppLoginHandler::Delegate interface.
94 void SendMessage(const std::string
& message
) override
;
95 void StartTls() override
;
96 void OnHandshakeDone(const std::string
& jid
,
97 scoped_ptr
<XmppStreamParser
> parser
) override
;
98 void OnLoginHandlerError(SignalStrategy::Error error
) override
;
100 // Callback for BufferedSocketWriter.
101 void OnMessageSent();
103 // Event handlers for XmppStreamParser.
104 void OnStanza(const scoped_ptr
<buzz::XmlElement
> stanza
);
105 void OnParserError();
107 void OnNetworkError(int error
);
109 void SendKeepAlive();
111 net::ClientSocketFactory
* socket_factory_
;
112 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
113 XmppServerConfig xmpp_server_config_
;
115 // Used by the |socket_|.
116 scoped_ptr
<net::CertVerifier
> cert_verifier_
;
117 scoped_ptr
<net::TransportSecurityState
> transport_security_state_
;
119 scoped_ptr
<net::StreamSocket
> socket_
;
120 scoped_ptr
<BufferedSocketWriter
> writer_
;
121 int pending_writes_
= 0;
122 scoped_refptr
<net::IOBuffer
> read_buffer_
;
123 bool read_pending_
= false;
125 TlsState tls_state_
= TlsState::NOT_REQUESTED
;
127 scoped_ptr
<XmppLoginHandler
> login_handler_
;
128 scoped_ptr
<XmppStreamParser
> stream_parser_
;
133 base::ObserverList
<Listener
, true> listeners_
;
135 base::Timer keep_alive_timer_
;
137 base::ThreadChecker thread_checker_
;
139 DISALLOW_COPY_AND_ASSIGN(Core
);
142 XmppSignalStrategy::Core::Core(
143 net::ClientSocketFactory
* socket_factory
,
144 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
145 const XmppSignalStrategy::XmppServerConfig
& xmpp_server_config
)
146 : socket_factory_(socket_factory
),
147 request_context_getter_(request_context_getter
),
148 xmpp_server_config_(xmpp_server_config
),
151 base::TimeDelta::FromSeconds(kKeepAliveIntervalSeconds
),
152 base::Bind(&Core::SendKeepAlive
, base::Unretained(this)),
155 // Non-secure connections are allowed only for debugging.
156 CHECK(xmpp_server_config_
.use_tls
);
160 XmppSignalStrategy::Core::~Core() {
164 void XmppSignalStrategy::Core::Connect() {
165 DCHECK(thread_checker_
.CalledOnValidThread());
167 // Disconnect first if we are currently connected.
172 FOR_EACH_OBSERVER(Listener
, listeners_
,
173 OnSignalStrategyStateChange(CONNECTING
));
175 socket_
.reset(new jingle_glue::ProxyResolvingClientSocket(
176 socket_factory_
, request_context_getter_
, net::SSLConfig(),
177 net::HostPortPair(xmpp_server_config_
.host
, xmpp_server_config_
.port
)));
179 int result
= socket_
->Connect(base::Bind(
180 &Core::OnSocketConnected
, base::Unretained(this)));
181 if (result
!= net::ERR_IO_PENDING
)
182 OnSocketConnected(result
);
185 void XmppSignalStrategy::Core::Disconnect() {
186 DCHECK(thread_checker_
.CalledOnValidThread());
189 login_handler_
.reset();
190 stream_parser_
.reset();
193 tls_state_
= TlsState::NOT_REQUESTED
;
195 FOR_EACH_OBSERVER(Listener
, listeners_
,
196 OnSignalStrategyStateChange(DISCONNECTED
));
200 SignalStrategy::State
XmppSignalStrategy::Core::GetState() const {
201 DCHECK(thread_checker_
.CalledOnValidThread());
203 if (stream_parser_
) {
206 } else if (socket_
) {
213 SignalStrategy::Error
XmppSignalStrategy::Core::GetError() const {
214 DCHECK(thread_checker_
.CalledOnValidThread());
218 std::string
XmppSignalStrategy::Core::GetLocalJid() const {
219 DCHECK(thread_checker_
.CalledOnValidThread());
223 void XmppSignalStrategy::Core::AddListener(Listener
* listener
) {
224 DCHECK(thread_checker_
.CalledOnValidThread());
225 listeners_
.AddObserver(listener
);
228 void XmppSignalStrategy::Core::RemoveListener(Listener
* listener
) {
229 DCHECK(thread_checker_
.CalledOnValidThread());
230 listeners_
.RemoveObserver(listener
);
233 bool XmppSignalStrategy::Core::SendStanza(scoped_ptr
<buzz::XmlElement
> stanza
) {
234 DCHECK(thread_checker_
.CalledOnValidThread());
236 if (!stream_parser_
) {
237 VLOG(0) << "Dropping signalling message because XMPP "
238 "connection has been terminated.";
242 SendMessage(stanza
->Str());
246 void XmppSignalStrategy::Core::SetAuthInfo(const std::string
& username
,
247 const std::string
& auth_token
) {
248 DCHECK(thread_checker_
.CalledOnValidThread());
249 xmpp_server_config_
.username
= username
;
250 xmpp_server_config_
.auth_token
= auth_token
;
253 void XmppSignalStrategy::Core::SendMessage(const std::string
& message
) {
254 DCHECK(thread_checker_
.CalledOnValidThread());
255 DCHECK(tls_state_
== TlsState::NOT_REQUESTED
||
256 tls_state_
== TlsState::CONNECTED
);
258 scoped_refptr
<net::IOBufferWithSize
> buffer
=
259 new net::IOBufferWithSize(message
.size());
260 memcpy(buffer
->data(), message
.data(), message
.size());
261 writer_
->Write(buffer
,
262 base::Bind(&Core::OnMessageSent
, base::Unretained(this)));
265 void XmppSignalStrategy::Core::StartTls() {
266 DCHECK(thread_checker_
.CalledOnValidThread());
267 DCHECK(login_handler_
);
268 DCHECK(tls_state_
== TlsState::NOT_REQUESTED
||
269 tls_state_
== TlsState::WAITING_FOR_FLUSH
);
271 if (writer_
->has_data_pending()) {
272 tls_state_
= TlsState::WAITING_FOR_FLUSH
;
276 tls_state_
= TlsState::CONNECTING
;
278 // Reset the writer so we don't try to write to the raw socket anymore.
281 DCHECK(!read_pending_
);
283 scoped_ptr
<net::ClientSocketHandle
> socket_handle(
284 new net::ClientSocketHandle());
285 socket_handle
->SetSocket(socket_
.Pass());
287 cert_verifier_
.reset(net::CertVerifier::CreateDefault());
288 transport_security_state_
.reset(new net::TransportSecurityState());
289 net::SSLClientSocketContext context
;
290 context
.cert_verifier
= cert_verifier_
.get();
291 context
.transport_security_state
= transport_security_state_
.get();
293 socket_
= socket_factory_
->CreateSSLClientSocket(
294 socket_handle
.Pass(),
295 net::HostPortPair(xmpp_server_config_
.host
, kDefaultHttpsPort
),
296 net::SSLConfig(), context
);
298 int result
= socket_
->Connect(
299 base::Bind(&Core::OnTlsConnected
, base::Unretained(this)));
300 if (result
!= net::ERR_IO_PENDING
)
301 OnTlsConnected(result
);
304 void XmppSignalStrategy::Core::OnHandshakeDone(
305 const std::string
& jid
,
306 scoped_ptr
<XmppStreamParser
> parser
) {
307 DCHECK(thread_checker_
.CalledOnValidThread());
310 stream_parser_
= parser
.Pass();
311 stream_parser_
->SetCallbacks(
312 base::Bind(&Core::OnStanza
, base::Unretained(this)),
313 base::Bind(&Core::OnParserError
, base::Unretained(this)));
315 // Don't need |login_handler_| anymore.
316 login_handler_
.reset();
318 FOR_EACH_OBSERVER(Listener
, listeners_
,
319 OnSignalStrategyStateChange(CONNECTED
));
322 void XmppSignalStrategy::Core::OnLoginHandlerError(
323 SignalStrategy::Error error
) {
324 DCHECK(thread_checker_
.CalledOnValidThread());
330 void XmppSignalStrategy::Core::OnMessageSent() {
331 DCHECK(thread_checker_
.CalledOnValidThread());
333 if (tls_state_
== TlsState::WAITING_FOR_FLUSH
&&
334 !writer_
->has_data_pending()) {
339 void XmppSignalStrategy::Core::OnStanza(
340 const scoped_ptr
<buzz::XmlElement
> stanza
) {
341 DCHECK(thread_checker_
.CalledOnValidThread());
343 base::ObserverListBase
<Listener
>::Iterator
it(&listeners_
);
344 for (Listener
* listener
= it
.GetNext(); listener
; listener
= it
.GetNext()) {
345 if (listener
->OnSignalStrategyIncomingStanza(stanza
.get()))
350 void XmppSignalStrategy::Core::OnParserError() {
351 DCHECK(thread_checker_
.CalledOnValidThread());
353 error_
= NETWORK_ERROR
;
357 void XmppSignalStrategy::Core::OnSocketConnected(int result
) {
358 DCHECK(thread_checker_
.CalledOnValidThread());
360 if (result
!= net::OK
) {
361 OnNetworkError(result
);
365 writer_
= BufferedSocketWriter::CreateForSocket(
366 socket_
.get(), base::Bind(&Core::OnNetworkError
, base::Unretained(this)));
368 XmppLoginHandler::TlsMode tls_mode
;
369 if (xmpp_server_config_
.use_tls
) {
370 tls_mode
= (xmpp_server_config_
.port
== kDefaultXmppPort
)
371 ? XmppLoginHandler::TlsMode::WITH_HANDSHAKE
372 : XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
;
374 tls_mode
= XmppLoginHandler::TlsMode::NO_TLS
;
377 // The server name is passed as to attribute in the <stream>. When connecting
378 // to talk.google.com it affects the certificate the server will use for TLS:
379 // talk.google.com uses gmail certificate when specified server is gmail.com
380 // or googlemail.com and google.com cert otherwise. In the same time it
381 // doesn't accept talk.google.com as target server. Here we use google.com
382 // server name when authenticating to talk.google.com. This ensures that the
383 // server will use google.com cert which will be accepted by the TLS
384 // implementation in Chrome (TLS API doesn't allow specifying domain other
385 // than the one that was passed to connect()).
386 std::string server
= xmpp_server_config_
.host
;
387 if (server
== "talk.google.com")
388 server
= "google.com";
390 login_handler_
.reset(
391 new XmppLoginHandler(server
, xmpp_server_config_
.username
,
392 xmpp_server_config_
.auth_token
, tls_mode
, this));
393 login_handler_
->Start();
398 void XmppSignalStrategy::Core::OnTlsConnected(int result
) {
399 DCHECK(thread_checker_
.CalledOnValidThread());
400 DCHECK(tls_state_
== TlsState::CONNECTING
);
401 tls_state_
= TlsState::CONNECTED
;
403 if (result
!= net::OK
) {
404 OnNetworkError(result
);
408 writer_
= BufferedSocketWriter::CreateForSocket(
409 socket_
.get(), base::Bind(&Core::OnNetworkError
, base::Unretained(this)));
411 login_handler_
->OnTlsStarted();
416 void XmppSignalStrategy::Core::ReadSocket() {
417 DCHECK(thread_checker_
.CalledOnValidThread());
419 while (socket_
&& !read_pending_
&& (tls_state_
== TlsState::NOT_REQUESTED
||
420 tls_state_
== TlsState::CONNECTED
)) {
421 read_buffer_
= new net::IOBuffer(kReadBufferSize
);
422 int result
= socket_
->Read(
423 read_buffer_
.get(), kReadBufferSize
,
424 base::Bind(&Core::OnReadResult
, base::Unretained(this)));
425 HandleReadResult(result
);
429 void XmppSignalStrategy::Core::OnReadResult(int result
) {
430 DCHECK(thread_checker_
.CalledOnValidThread());
431 DCHECK(read_pending_
);
432 read_pending_
= false;
433 HandleReadResult(result
);
437 void XmppSignalStrategy::Core::HandleReadResult(int result
) {
438 DCHECK(thread_checker_
.CalledOnValidThread());
440 if (result
== net::ERR_IO_PENDING
) {
441 read_pending_
= true;
446 OnNetworkError(result
);
451 // Connection was closed by the server.
457 if (stream_parser_
) {
458 stream_parser_
->AppendData(std::string(read_buffer_
->data(), result
));
460 login_handler_
->OnDataReceived(std::string(read_buffer_
->data(), result
));
464 void XmppSignalStrategy::Core::OnNetworkError(int error
) {
465 DCHECK(thread_checker_
.CalledOnValidThread());
467 LOG(ERROR
) << "XMPP socket error " << error
;
468 error_
= NETWORK_ERROR
;
472 void XmppSignalStrategy::Core::SendKeepAlive() {
473 DCHECK(thread_checker_
.CalledOnValidThread());
475 if (GetState() == CONNECTED
)
479 XmppSignalStrategy::XmppSignalStrategy(
480 net::ClientSocketFactory
* socket_factory
,
481 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
482 const XmppServerConfig
& xmpp_server_config
)
483 : core_(new Core(socket_factory
,
484 request_context_getter
,
485 xmpp_server_config
)) {
488 XmppSignalStrategy::~XmppSignalStrategy() {
489 // All listeners should be removed at this point, so it's safe to detach
491 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE
, core_
.release());
494 void XmppSignalStrategy::Connect() {
498 void XmppSignalStrategy::Disconnect() {
502 SignalStrategy::State
XmppSignalStrategy::GetState() const {
503 return core_
->GetState();
506 SignalStrategy::Error
XmppSignalStrategy::GetError() const {
507 return core_
->GetError();
510 std::string
XmppSignalStrategy::GetLocalJid() const {
511 return core_
->GetLocalJid();
514 void XmppSignalStrategy::AddListener(Listener
* listener
) {
515 core_
->AddListener(listener
);
518 void XmppSignalStrategy::RemoveListener(Listener
* listener
) {
519 core_
->RemoveListener(listener
);
521 bool XmppSignalStrategy::SendStanza(scoped_ptr
<buzz::XmlElement
> stanza
) {
522 return core_
->SendStanza(stanza
.Pass());
525 std::string
XmppSignalStrategy::GetNextId() {
526 return base::Uint64ToString(base::RandUint64());
529 void XmppSignalStrategy::SetAuthInfo(const std::string
& username
,
530 const std::string
& auth_token
) {
531 core_
->SetAuthInfo(username
, auth_token
);
534 } // namespace remoting