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/base/xmpp_connection.h"
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_piece.h"
11 #include "jingle/glue/chrome_async_socket.h"
12 #include "jingle/glue/task_pump.h"
13 #include "jingle/glue/xmpp_client_socket_factory.h"
14 #include "jingle/notifier/base/weak_xmpp_client.h"
15 #include "net/socket/client_socket_factory.h"
16 #include "net/ssl/ssl_config_service.h"
17 #include "net/url_request/url_request_context.h"
18 #include "webrtc/libjingle/xmpp/xmppclientsettings.h"
22 XmppConnection::Delegate::~Delegate() {}
26 buzz::AsyncSocket
* CreateSocket(
27 const buzz::XmppClientSettings
& xmpp_client_settings
,
28 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
) {
29 bool use_fake_ssl_client_socket
=
30 (xmpp_client_settings
.protocol() == cricket::PROTO_SSLTCP
);
31 // The default SSLConfig is good enough for us for now.
32 const net::SSLConfig ssl_config
;
33 // These numbers were taken from similar numbers in
35 const size_t kReadBufSize
= 64U * 1024U;
36 const size_t kWriteBufSize
= 64U * 1024U;
37 jingle_glue::XmppClientSocketFactory
* const client_socket_factory
=
38 new jingle_glue::XmppClientSocketFactory(
39 net::ClientSocketFactory::GetDefaultFactory(),
41 request_context_getter
,
42 use_fake_ssl_client_socket
);
43 return new jingle_glue::ChromeAsyncSocket(client_socket_factory
,
44 kReadBufSize
, kWriteBufSize
);
49 XmppConnection::XmppConnection(
50 const buzz::XmppClientSettings
& xmpp_client_settings
,
51 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
53 buzz::PreXmppAuth
* pre_xmpp_auth
)
54 : task_pump_(new jingle_glue::TaskPump()),
55 on_connect_called_(false),
58 // Owned by |task_pump_|, but is guaranteed to live at least as long
60 WeakXmppClient
* weak_xmpp_client
= new WeakXmppClient(task_pump_
.get());
61 weak_xmpp_client
->SignalStateChange
.connect(
62 this, &XmppConnection::OnStateChange
);
63 weak_xmpp_client
->SignalLogInput
.connect(
64 this, &XmppConnection::OnInputLog
);
65 weak_xmpp_client
->SignalLogOutput
.connect(
66 this, &XmppConnection::OnOutputLog
);
67 const char kLanguage
[] = "en";
68 buzz::XmppReturnStatus connect_status
=
69 weak_xmpp_client
->Connect(xmpp_client_settings
, kLanguage
,
70 CreateSocket(xmpp_client_settings
,
71 request_context_getter
),
73 // buzz::XmppClient::Connect() should never fail.
74 DCHECK_EQ(connect_status
, buzz::XMPP_RETURN_OK
);
75 weak_xmpp_client
->Start();
76 weak_xmpp_client_
= weak_xmpp_client
->AsWeakPtr();
79 XmppConnection::~XmppConnection() {
80 DCHECK(CalledOnValidThread());
83 base::MessageLoop
* current_message_loop
= base::MessageLoop::current();
84 CHECK(current_message_loop
);
85 // We do this because XmppConnection may get destroyed as a result
86 // of a signal from XmppClient. If we delete |task_pump_| here, bad
87 // things happen when the stack pops back up to the XmppClient's
88 // (which is deleted by |task_pump_|) function.
89 current_message_loop
->DeleteSoon(FROM_HERE
, task_pump_
.release());
92 void XmppConnection::OnStateChange(buzz::XmppEngine::State state
) {
93 DCHECK(CalledOnValidThread());
94 VLOG(1) << "XmppClient state changed to " << state
;
95 if (!weak_xmpp_client_
.get()) {
96 LOG(DFATAL
) << "weak_xmpp_client_ unexpectedly NULL";
100 LOG(DFATAL
) << "delegate_ unexpectedly NULL";
104 case buzz::XmppEngine::STATE_OPEN
:
105 if (on_connect_called_
) {
106 LOG(DFATAL
) << "State changed to STATE_OPEN more than once";
108 delegate_
->OnConnect(weak_xmpp_client_
);
109 on_connect_called_
= true;
112 case buzz::XmppEngine::STATE_CLOSED
: {
114 buzz::XmppEngine::Error error
=
115 weak_xmpp_client_
->GetError(&subcode
);
116 const buzz::XmlElement
* stream_error
=
117 weak_xmpp_client_
->GetStreamError();
119 Delegate
* delegate
= delegate_
;
121 delegate
->OnError(error
, subcode
, stream_error
);
130 void XmppConnection::OnInputLog(const char* data
, int len
) {
131 DCHECK(CalledOnValidThread());
132 VLOG(2) << "XMPP Input: " << base::StringPiece(data
, len
);
135 void XmppConnection::OnOutputLog(const char* data
, int len
) {
136 DCHECK(CalledOnValidThread());
137 VLOG(2) << "XMPP Output: " << base::StringPiece(data
, len
);
140 void XmppConnection::ClearClient() {
141 if (weak_xmpp_client_
.get()) {
142 weak_xmpp_client_
->Invalidate();
143 DCHECK(!weak_xmpp_client_
.get());
147 } // namespace notifier