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_
.reset(new BufferedSocketWriter());
366 writer_
->Init(socket_
.get(), base::Bind(&Core::OnNetworkError
,
367 base::Unretained(this)));
369 XmppLoginHandler::TlsMode tls_mode
;
370 if (xmpp_server_config_
.use_tls
) {
371 tls_mode
= (xmpp_server_config_
.port
== kDefaultXmppPort
)
372 ? XmppLoginHandler::TlsMode::WITH_HANDSHAKE
373 : XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE
;
375 tls_mode
= XmppLoginHandler::TlsMode::NO_TLS
;
378 // The server name is passed as to attribute in the <stream>. When connecting
379 // to talk.google.com it affects the certificate the server will use for TLS:
380 // talk.google.com uses gmail certificate when specified server is gmail.com
381 // or googlemail.com and google.com cert otherwise. In the same time it
382 // doesn't accept talk.google.com as target server. Here we use google.com
383 // server name when authenticating to talk.google.com. This ensures that the
384 // server will use google.com cert which will be accepted by the TLS
385 // implementation in Chrome (TLS API doesn't allow specifying domain other
386 // than the one that was passed to connect()).
387 std::string server
= xmpp_server_config_
.host
;
388 if (server
== "talk.google.com")
389 server
= "google.com";
391 login_handler_
.reset(
392 new XmppLoginHandler(server
, xmpp_server_config_
.username
,
393 xmpp_server_config_
.auth_token
, tls_mode
, this));
394 login_handler_
->Start();
399 void XmppSignalStrategy::Core::OnTlsConnected(int result
) {
400 DCHECK(thread_checker_
.CalledOnValidThread());
401 DCHECK(tls_state_
== TlsState::CONNECTING
);
402 tls_state_
= TlsState::CONNECTED
;
404 if (result
!= net::OK
) {
405 OnNetworkError(result
);
409 writer_
.reset(new BufferedSocketWriter());
410 writer_
->Init(socket_
.get(), base::Bind(&Core::OnNetworkError
,
411 base::Unretained(this)));
413 login_handler_
->OnTlsStarted();
418 void XmppSignalStrategy::Core::ReadSocket() {
419 DCHECK(thread_checker_
.CalledOnValidThread());
421 while (socket_
&& !read_pending_
&& (tls_state_
== TlsState::NOT_REQUESTED
||
422 tls_state_
== TlsState::CONNECTED
)) {
423 read_buffer_
= new net::IOBuffer(kReadBufferSize
);
424 int result
= socket_
->Read(
425 read_buffer_
.get(), kReadBufferSize
,
426 base::Bind(&Core::OnReadResult
, base::Unretained(this)));
427 HandleReadResult(result
);
431 void XmppSignalStrategy::Core::OnReadResult(int result
) {
432 DCHECK(thread_checker_
.CalledOnValidThread());
433 DCHECK(read_pending_
);
434 read_pending_
= false;
435 HandleReadResult(result
);
439 void XmppSignalStrategy::Core::HandleReadResult(int result
) {
440 DCHECK(thread_checker_
.CalledOnValidThread());
442 if (result
== net::ERR_IO_PENDING
) {
443 read_pending_
= true;
448 OnNetworkError(result
);
453 // Connection was closed by the server.
459 if (stream_parser_
) {
460 stream_parser_
->AppendData(std::string(read_buffer_
->data(), result
));
462 login_handler_
->OnDataReceived(std::string(read_buffer_
->data(), result
));
466 void XmppSignalStrategy::Core::OnNetworkError(int error
) {
467 DCHECK(thread_checker_
.CalledOnValidThread());
469 LOG(ERROR
) << "XMPP socket error " << error
;
470 error_
= NETWORK_ERROR
;
474 void XmppSignalStrategy::Core::SendKeepAlive() {
475 DCHECK(thread_checker_
.CalledOnValidThread());
477 if (GetState() == CONNECTED
)
481 XmppSignalStrategy::XmppSignalStrategy(
482 net::ClientSocketFactory
* socket_factory
,
483 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
484 const XmppServerConfig
& xmpp_server_config
)
485 : core_(new Core(socket_factory
,
486 request_context_getter
,
487 xmpp_server_config
)) {
490 XmppSignalStrategy::~XmppSignalStrategy() {
491 // All listeners should be removed at this point, so it's safe to detach
493 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE
, core_
.release());
496 void XmppSignalStrategy::Connect() {
500 void XmppSignalStrategy::Disconnect() {
504 SignalStrategy::State
XmppSignalStrategy::GetState() const {
505 return core_
->GetState();
508 SignalStrategy::Error
XmppSignalStrategy::GetError() const {
509 return core_
->GetError();
512 std::string
XmppSignalStrategy::GetLocalJid() const {
513 return core_
->GetLocalJid();
516 void XmppSignalStrategy::AddListener(Listener
* listener
) {
517 core_
->AddListener(listener
);
520 void XmppSignalStrategy::RemoveListener(Listener
* listener
) {
521 core_
->RemoveListener(listener
);
523 bool XmppSignalStrategy::SendStanza(scoped_ptr
<buzz::XmlElement
> stanza
) {
524 return core_
->SendStanza(stanza
.Pass());
527 std::string
XmppSignalStrategy::GetNextId() {
528 return base::Uint64ToString(base::RandUint64());
531 void XmppSignalStrategy::SetAuthInfo(const std::string
& username
,
532 const std::string
& auth_token
) {
533 core_
->SetAuthInfo(username
, auth_token
);
536 } // namespace remoting