• 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 _xmppengineimpl_h_
29 #define _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 
45 //! The XMPP connection engine.
46 //! This engine implements the client side of the 'core' XMPP protocol.
47 //! To use it, register an XmppOutputHandler to handle socket output
48 //! and pass socket input to HandleInput.  Then application code can
49 //! set up the connection with a user, password, and other settings,
50 //! and then call Connect() to initiate the connection.
51 //! An application can listen for events and receive stanzas by
52 //! registering an XmppStanzaHandler via AddStanzaHandler().
53 class XmppEngineImpl : public XmppEngine {
54 public:
55   XmppEngineImpl();
56   virtual ~XmppEngineImpl();
57 
58   // SOCKET INPUT AND OUTPUT ------------------------------------------------
59 
60   //! Registers the handler for socket output
61   virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh);
62 
63   //! Provides socket input to the engine
64   virtual XmppReturnStatus HandleInput(const char * bytes, size_t len);
65 
66   //! Advises the engine that the socket has closed
67   virtual XmppReturnStatus ConnectionClosed(int subcode);
68 
69   // SESSION SETUP ---------------------------------------------------------
70 
71   //! Indicates the (bare) JID for the user to use.
72   virtual XmppReturnStatus SetUser(const Jid & jid);
73 
74   //! Get the login (bare) JID.
75   virtual const Jid & GetUser();
76 
77   //! Indicates the autentication to use.  Takes ownership of the object.
78   virtual XmppReturnStatus SetSaslHandler(SaslHandler * sasl_handler);
79 
80   //! Sets whether TLS will be used within the connection (default true).
81   virtual XmppReturnStatus SetUseTls(bool useTls);
82 
83   //! Sets an alternate domain from which we allows TLS certificates.
84   //! This is for use in the case where a we want to allow a proxy to
85   //! serve up its own certificate rather than one owned by the underlying
86   //! domain.
87   virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname,
88                                         const std::string & proxy_domain);
89 
90   //! Gets whether TLS will be used within the connection.
91   virtual bool GetUseTls();
92 
93   //! Sets the request resource name, if any (optional).
94   //! Note that the resource name may be overridden by the server; after
95   //! binding, the actual resource name is available as part of FullJid().
96   virtual XmppReturnStatus SetRequestedResource(const std::string& resource);
97 
98   //! Gets the request resource name.
99   virtual const std::string & GetRequestedResource();
100 
101   //! Sets language
SetLanguage(const std::string & lang)102   virtual void SetLanguage(const std::string & lang) {
103     lang_ = lang;
104   }
105 
106   // SESSION MANAGEMENT ---------------------------------------------------
107 
108   //! Set callback for state changes.
109   virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler);
110 
111   //! Initiates the XMPP connection.
112   //! After supplying connection settings, call this once to initiate,
113   //! (optionally) encrypt, authenticate, and bind the connection.
114   virtual XmppReturnStatus Connect();
115 
116   //! The current engine state.
GetState()117   virtual State GetState() { return state_; }
118 
119   //! Returns true if the connection is encrypted (under TLS)
IsEncrypted()120   virtual bool IsEncrypted() { return encrypted_; }
121 
122   //! The error code.
123   //! Consult this after XmppOutputHandler.OnClose().
GetError(int * subcode)124   virtual Error GetError(int *subcode) {
125      if (subcode) {
126        *subcode = subcode_;
127      }
128      return error_code_;
129   }
130 
131   //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
132   //! Notice the stanza returned is owned by the XmppEngine and
133   //! is deleted when the engine is destroyed.
GetStreamError()134   virtual const XmlElement * GetStreamError() { return stream_error_.get(); }
135 
136   //! Closes down the connection.
137   //! Sends CloseConnection to output, and disconnects and registered
138   //! session handlers.  After Disconnect completes, it is guaranteed
139   //! that no further callbacks will be made.
140   virtual XmppReturnStatus Disconnect();
141 
142   // APPLICATION USE -------------------------------------------------------
143 
144   //! Adds a listener for session events.
145   //! Stanza delivery is chained to session handlers; the first to
146   //! return 'true' is the last to get each stanza.
147   virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler,
148                                             XmppEngine::HandlerLevel level);
149 
150   //! Removes a listener for session events.
151   virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler);
152 
153   //! Sends a stanza to the server.
154   virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza);
155 
156   //! Sends raw text to the server
157   virtual XmppReturnStatus SendRaw(const std::string & text);
158 
159   //! Sends an iq to the server, and registers a callback for the result.
160   //! Returns the cookie passed to the result handler.
161   virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
162                                   XmppIqHandler* iq_handler,
163                                   XmppIqCookie* cookie);
164 
165   //! Unregisters an iq callback handler given its cookie.
166   //! No callback will come to this handler after it's unregistered.
167   virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
168                                       XmppIqHandler** iq_handler);
169 
170   //! Forms and sends an error in response to the given stanza.
171   //! Swaps to and from, sets type to "error", and adds error information
172   //! based on the passed code.  Text is optional and may be STR_EMPTY.
173   virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
174                                            XmppStanzaError code,
175                                            const std::string & text);
176 
177   //! The fullly bound JID.
178   //! This JID is only valid after binding has succeeded.  If the value
179   //! is JID_NULL, the binding has not succeeded.
FullJid()180   virtual const Jid & FullJid() { return bound_jid_; }
181 
182   //! The next unused iq id for this connection.
183   //! Call this when building iq stanzas, to ensure that each iq
184   //! gets its own unique id.
185   virtual std::string NextId();
186 
187 private:
188   friend class XmppLoginTask;
189   friend class XmppIqEntry;
190 
191   void IncomingStanza(const XmlElement *pelStanza);
192   void IncomingStart(const XmlElement *pelStanza);
193   void IncomingEnd(bool isError);
194 
195   void InternalSendStart(const std::string & domainName);
196   void InternalSendStanza(const XmlElement * pelStanza);
197   std::string ChooseBestSaslMechanism(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 * pelStreamError);
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() {}
StartStream(const XmlElement * pelStream)212     virtual void StartStream(const XmlElement * pelStream)
213       { outer_->IncomingStart(pelStream); }
Stanza(const XmlElement * pelStanza)214     virtual void Stanza(const XmlElement * pelStanza)
215       { outer_->IncomingStanza(pelStanza); }
EndStream()216     virtual void EndStream()
217       { outer_->IncomingEnd(false); }
XmlError()218     virtual void XmlError()
219       { outer_->IncomingEnd(true); }
220   private:
221     XmppEngineImpl * const outer_;
222   };
223 
224   class EnterExit {
225    public:
226     EnterExit(XmppEngineImpl* engine);
227     ~EnterExit();
228    private:
229     XmppEngineImpl* engine_;
230     State state_;
231     Error error_;
232 
233   };
234 
235   friend class StanzaParseHandler;
236   friend class EnterExit;
237 
238   StanzaParseHandler stanzaParseHandler_;
239   XmppStanzaParser stanzaParser_;
240 
241 
242   // state
243   int engine_entered_;
244   Jid user_jid_;
245   std::string password_;
246   std::string requested_resource_;
247   bool tls_needed_;
248   std::string tls_server_hostname_;
249   std::string tls_server_domain_;
250   talk_base::scoped_ptr<XmppLoginTask> login_task_;
251   std::string lang_;
252 
253   int next_id_;
254   Jid bound_jid_;
255   State state_;
256   bool encrypted_;
257   Error error_code_;
258   int subcode_;
259   talk_base::scoped_ptr<XmlElement> stream_error_;
260   bool raised_reset_;
261   XmppOutputHandler* output_handler_;
262   XmppSessionHandler* session_handler_;
263 
264   typedef std::vector<XmppStanzaHandler*> StanzaHandlerVector;
265   talk_base::scoped_ptr<StanzaHandlerVector> stanza_handlers_[HL_COUNT];
266 
267   typedef std::vector<XmppIqEntry*> IqEntryVector;
268   talk_base::scoped_ptr<IqEntryVector> iq_entries_;
269 
270   talk_base::scoped_ptr<SaslHandler> sasl_handler_;
271 
272   talk_base::scoped_ptr<std::stringstream> output_;
273 };
274 
275 }
276 
277 
278 #endif
279