• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_LIBJINGLE_XMPP_XMPPENGINEIMPL_H_
12 #define WEBRTC_LIBJINGLE_XMPP_XMPPENGINEIMPL_H_
13 
14 #include <sstream>
15 #include <vector>
16 #include "webrtc/libjingle/xmpp/xmppengine.h"
17 #include "webrtc/libjingle/xmpp/xmppstanzaparser.h"
18 
19 namespace buzz {
20 
21 class XmppLoginTask;
22 class XmppEngine;
23 class XmppIqEntry;
24 class SaslHandler;
25 class SaslMechanism;
26 
27 //! The XMPP connection engine.
28 //! This engine implements the client side of the 'core' XMPP protocol.
29 //! To use it, register an XmppOutputHandler to handle socket output
30 //! and pass socket input to HandleInput.  Then application code can
31 //! set up the connection with a user, password, and other settings,
32 //! and then call Connect() to initiate the connection.
33 //! An application can listen for events and receive stanzas by
34 //! registering an XmppStanzaHandler via AddStanzaHandler().
35 class XmppEngineImpl : public XmppEngine {
36  public:
37   XmppEngineImpl();
38   virtual ~XmppEngineImpl();
39 
40   // SOCKET INPUT AND OUTPUT ------------------------------------------------
41 
42   //! Registers the handler for socket output
43   virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh);
44 
45   //! Provides socket input to the engine
46   virtual XmppReturnStatus HandleInput(const char* bytes, size_t len);
47 
48   //! Advises the engine that the socket has closed
49   virtual XmppReturnStatus ConnectionClosed(int subcode);
50 
51   // SESSION SETUP ---------------------------------------------------------
52 
53   //! Indicates the (bare) JID for the user to use.
54   virtual XmppReturnStatus SetUser(const Jid& jid);
55 
56   //! Get the login (bare) JID.
57   virtual const Jid& GetUser();
58 
59   //! Indicates the autentication to use.  Takes ownership of the object.
60   virtual XmppReturnStatus SetSaslHandler(SaslHandler* sasl_handler);
61 
62   //! Sets whether TLS will be used within the connection (default true).
63   virtual XmppReturnStatus SetTls(TlsOptions use_tls);
64 
65   //! Sets an alternate domain from which we allows TLS certificates.
66   //! This is for use in the case where a we want to allow a proxy to
67   //! serve up its own certificate rather than one owned by the underlying
68   //! domain.
69   virtual XmppReturnStatus SetTlsServer(const std::string& proxy_hostname,
70                                         const std::string& proxy_domain);
71 
72   //! Gets whether TLS will be used within the connection.
73   virtual TlsOptions GetTls();
74 
75   //! Sets the request resource name, if any (optional).
76   //! Note that the resource name may be overridden by the server; after
77   //! binding, the actual resource name is available as part of FullJid().
78   virtual XmppReturnStatus SetRequestedResource(const std::string& resource);
79 
80   //! Gets the request resource name.
81   virtual const std::string& GetRequestedResource();
82 
83   //! Sets language
SetLanguage(const std::string & lang)84   virtual void SetLanguage(const std::string& lang) {
85     lang_ = lang;
86   }
87 
88   // SESSION MANAGEMENT ---------------------------------------------------
89 
90   //! Set callback for state changes.
91   virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler);
92 
93   //! Initiates the XMPP connection.
94   //! After supplying connection settings, call this once to initiate,
95   //! (optionally) encrypt, authenticate, and bind the connection.
96   virtual XmppReturnStatus Connect();
97 
98   //! The current engine state.
GetState()99   virtual State GetState() { return state_; }
100 
101   //! Returns true if the connection is encrypted (under TLS)
IsEncrypted()102   virtual bool IsEncrypted() { return encrypted_; }
103 
104   //! The error code.
105   //! Consult this after XmppOutputHandler.OnClose().
GetError(int * subcode)106   virtual Error GetError(int *subcode) {
107      if (subcode) {
108        *subcode = subcode_;
109      }
110      return error_code_;
111   }
112 
113   //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
114   //! Notice the stanza returned is owned by the XmppEngine and
115   //! is deleted when the engine is destroyed.
GetStreamError()116   virtual const XmlElement* GetStreamError() { return stream_error_.get(); }
117 
118   //! Closes down the connection.
119   //! Sends CloseConnection to output, and disconnects and registered
120   //! session handlers.  After Disconnect completes, it is guaranteed
121   //! that no further callbacks will be made.
122   virtual XmppReturnStatus Disconnect();
123 
124   // APPLICATION USE -------------------------------------------------------
125 
126   //! Adds a listener for session events.
127   //! Stanza delivery is chained to session handlers; the first to
128   //! return 'true' is the last to get each stanza.
129   virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler,
130                                             XmppEngine::HandlerLevel level);
131 
132   //! Removes a listener for session events.
133   virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler);
134 
135   //! Sends a stanza to the server.
136   virtual XmppReturnStatus SendStanza(const XmlElement* stanza);
137 
138   //! Sends raw text to the server
139   virtual XmppReturnStatus SendRaw(const std::string& text);
140 
141   //! Sends an iq to the server, and registers a callback for the result.
142   //! Returns the cookie passed to the result handler.
143   virtual XmppReturnStatus SendIq(const XmlElement* stanza,
144                                   XmppIqHandler* iq_handler,
145                                   XmppIqCookie* cookie);
146 
147   //! Unregisters an iq callback handler given its cookie.
148   //! No callback will come to this handler after it's unregistered.
149   virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
150                                       XmppIqHandler** iq_handler);
151 
152   //! Forms and sends an error in response to the given stanza.
153   //! Swaps to and from, sets type to "error", and adds error information
154   //! based on the passed code.  Text is optional and may be STR_EMPTY.
155   virtual XmppReturnStatus SendStanzaError(const XmlElement* pelOriginal,
156                                            XmppStanzaError code,
157                                            const std::string& text);
158 
159   //! The fullly bound JID.
160   //! This JID is only valid after binding has succeeded.  If the value
161   //! is JID_NULL, the binding has not succeeded.
FullJid()162   virtual const Jid& FullJid() { return bound_jid_; }
163 
164   //! The next unused iq id for this connection.
165   //! Call this when building iq stanzas, to ensure that each iq
166   //! gets its own unique id.
167   virtual std::string NextId();
168 
169  private:
170   friend class XmppLoginTask;
171   friend class XmppIqEntry;
172 
173   void IncomingStanza(const XmlElement *stanza);
174   void IncomingStart(const XmlElement *stanza);
175   void IncomingEnd(bool isError);
176 
177   void InternalSendStart(const std::string& domainName);
178   void InternalSendStanza(const XmlElement* stanza);
179   std::string ChooseBestSaslMechanism(
180       const std::vector<std::string>& mechanisms, bool encrypted);
181   SaslMechanism* GetSaslMechanism(const std::string& name);
182   void SignalBound(const Jid& fullJid);
183   void SignalStreamError(const XmlElement* streamError);
184   void SignalError(Error errorCode, int subCode);
185   bool HasError();
186   void DeleteIqCookies();
187   bool HandleIqResponse(const XmlElement* element);
188   void StartTls(const std::string& domain);
RaiseReset()189   void RaiseReset() { raised_reset_ = true; }
190 
191   class StanzaParseHandler : public XmppStanzaParseHandler {
192    public:
StanzaParseHandler(XmppEngineImpl * outer)193     StanzaParseHandler(XmppEngineImpl* outer) : outer_(outer) {}
~StanzaParseHandler()194     virtual ~StanzaParseHandler() {}
195 
StartStream(const XmlElement * stream)196     virtual void StartStream(const XmlElement* stream) {
197       outer_->IncomingStart(stream);
198     }
Stanza(const XmlElement * stanza)199     virtual void Stanza(const XmlElement* stanza) {
200       outer_->IncomingStanza(stanza);
201     }
EndStream()202     virtual void EndStream() {
203       outer_->IncomingEnd(false);
204     }
XmlError()205     virtual void XmlError() {
206       outer_->IncomingEnd(true);
207     }
208 
209    private:
210     XmppEngineImpl* const outer_;
211   };
212 
213   class EnterExit {
214    public:
215     EnterExit(XmppEngineImpl* engine);
216     ~EnterExit();
217    private:
218     XmppEngineImpl* engine_;
219     State state_;
220   };
221 
222   friend class StanzaParseHandler;
223   friend class EnterExit;
224 
225   StanzaParseHandler stanza_parse_handler_;
226   XmppStanzaParser stanza_parser_;
227 
228   // state
229   int engine_entered_;
230   Jid user_jid_;
231   std::string password_;
232   std::string requested_resource_;
233   TlsOptions tls_option_;
234   std::string tls_server_hostname_;
235   std::string tls_server_domain_;
236   rtc::scoped_ptr<XmppLoginTask> login_task_;
237   std::string lang_;
238 
239   int next_id_;
240   Jid bound_jid_;
241   State state_;
242   bool encrypted_;
243   Error error_code_;
244   int subcode_;
245   rtc::scoped_ptr<XmlElement> stream_error_;
246   bool raised_reset_;
247   XmppOutputHandler* output_handler_;
248   XmppSessionHandler* session_handler_;
249 
250   XmlnsStack xmlns_stack_;
251 
252   typedef std::vector<XmppStanzaHandler*> StanzaHandlerVector;
253   rtc::scoped_ptr<StanzaHandlerVector> stanza_handlers_[HL_COUNT];
254 
255   typedef std::vector<XmppIqEntry*> IqEntryVector;
256   rtc::scoped_ptr<IqEntryVector> iq_entries_;
257 
258   rtc::scoped_ptr<SaslHandler> sasl_handler_;
259 
260   rtc::scoped_ptr<std::stringstream> output_;
261 };
262 
263 }  // namespace buzz
264 
265 #endif  // WEBRTC_LIBJINGLE_XMPP_XMPPENGINEIMPL_H_
266