• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/xmpp_connection.h"
6 
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 "talk/xmpp/xmppclientsettings.h"
19 
20 namespace notifier {
21 
~Delegate()22 XmppConnection::Delegate::~Delegate() {}
23 
24 namespace {
25 
CreateSocket(const buzz::XmppClientSettings & xmpp_client_settings,const scoped_refptr<net::URLRequestContextGetter> & request_context_getter)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
34   // XmppSocketAdapter.
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(),
40           ssl_config,
41           request_context_getter,
42           use_fake_ssl_client_socket);
43   return new jingle_glue::ChromeAsyncSocket(client_socket_factory,
44                                             kReadBufSize, kWriteBufSize);
45 }
46 
47 }  // namespace
48 
XmppConnection(const buzz::XmppClientSettings & xmpp_client_settings,const scoped_refptr<net::URLRequestContextGetter> & request_context_getter,Delegate * delegate,buzz::PreXmppAuth * pre_xmpp_auth)49 XmppConnection::XmppConnection(
50     const buzz::XmppClientSettings& xmpp_client_settings,
51     const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
52     Delegate* delegate,
53     buzz::PreXmppAuth* pre_xmpp_auth)
54     : task_pump_(new jingle_glue::TaskPump()),
55       on_connect_called_(false),
56       delegate_(delegate) {
57   DCHECK(delegate_);
58   // Owned by |task_pump_|, but is guaranteed to live at least as long
59   // as this function.
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),
72                                 pre_xmpp_auth);
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();
77 }
78 
~XmppConnection()79 XmppConnection::~XmppConnection() {
80   DCHECK(CalledOnValidThread());
81   ClearClient();
82   task_pump_->Stop();
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());
90 }
91 
OnStateChange(buzz::XmppEngine::State state)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";
97     return;
98   }
99   if (!delegate_) {
100     LOG(DFATAL) << "delegate_ unexpectedly NULL";
101     return;
102   }
103   switch (state) {
104     case buzz::XmppEngine::STATE_OPEN:
105       if (on_connect_called_) {
106         LOG(DFATAL) << "State changed to STATE_OPEN more than once";
107       } else {
108         delegate_->OnConnect(weak_xmpp_client_);
109         on_connect_called_ = true;
110       }
111       break;
112     case buzz::XmppEngine::STATE_CLOSED: {
113       int subcode = 0;
114       buzz::XmppEngine::Error error =
115           weak_xmpp_client_->GetError(&subcode);
116       const buzz::XmlElement* stream_error =
117           weak_xmpp_client_->GetStreamError();
118       ClearClient();
119       Delegate* delegate = delegate_;
120       delegate_ = NULL;
121       delegate->OnError(error, subcode, stream_error);
122       break;
123     }
124     default:
125       // Do nothing.
126       break;
127   }
128 }
129 
OnInputLog(const char * data,int len)130 void XmppConnection::OnInputLog(const char* data, int len) {
131   DCHECK(CalledOnValidThread());
132   VLOG(2) << "XMPP Input: " << base::StringPiece(data, len);
133 }
134 
OnOutputLog(const char * data,int len)135 void XmppConnection::OnOutputLog(const char* data, int len) {
136   DCHECK(CalledOnValidThread());
137   VLOG(2) << "XMPP Output: " << base::StringPiece(data, len);
138 }
139 
ClearClient()140 void XmppConnection::ClearClient() {
141   if (weak_xmpp_client_.get()) {
142     weak_xmpp_client_->Invalidate();
143     DCHECK(!weak_xmpp_client_.get());
144   }
145 }
146 
147 }  // namespace notifier
148