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