• 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 _xmppengine_h_
29 #define _xmppengine_h_
30 
31 // also part of the API
32 #include "talk/xmpp/jid.h"
33 #include "talk/xmllite/qname.h"
34 #include "talk/xmllite/xmlelement.h"
35 
36 
37 namespace buzz {
38 
39 class XmppEngine;
40 class SaslHandler;
41 typedef void * XmppIqCookie;
42 
43 //! XMPP stanza error codes.
44 //! Used in XmppEngine.SendStanzaError().
45 enum XmppStanzaError {
46   XSE_BAD_REQUEST,
47   XSE_CONFLICT,
48   XSE_FEATURE_NOT_IMPLEMENTED,
49   XSE_FORBIDDEN,
50   XSE_GONE,
51   XSE_INTERNAL_SERVER_ERROR,
52   XSE_ITEM_NOT_FOUND,
53   XSE_JID_MALFORMED,
54   XSE_NOT_ACCEPTABLE,
55   XSE_NOT_ALLOWED,
56   XSE_PAYMENT_REQUIRED,
57   XSE_RECIPIENT_UNAVAILABLE,
58   XSE_REDIRECT,
59   XSE_REGISTRATION_REQUIRED,
60   XSE_SERVER_NOT_FOUND,
61   XSE_SERVER_TIMEOUT,
62   XSE_RESOURCE_CONSTRAINT,
63   XSE_SERVICE_UNAVAILABLE,
64   XSE_SUBSCRIPTION_REQUIRED,
65   XSE_UNDEFINED_CONDITION,
66   XSE_UNEXPECTED_REQUEST,
67 };
68 
69 // XmppReturnStatus
70 //    This is used by API functions to synchronously return status.
71 enum XmppReturnStatus {
72   XMPP_RETURN_OK,
73   XMPP_RETURN_BADARGUMENT,
74   XMPP_RETURN_BADSTATE,
75   XMPP_RETURN_PENDING,
76   XMPP_RETURN_UNEXPECTED,
77   XMPP_RETURN_NOTYETIMPLEMENTED,
78 };
79 
80 // TlsOptions
81 //    This is used by API to identify TLS setting.
82 enum TlsOptions {
83   TLS_DISABLED,
84   TLS_ENABLED,
85   TLS_REQUIRED
86 };
87 
88 //! Callback for socket output for an XmppEngine connection.
89 //! Register via XmppEngine.SetOutputHandler.  An XmppEngine
90 //! can call back to this handler while it is processing
91 //! Connect, SendStanza, SendIq, Disconnect, or HandleInput.
92 class XmppOutputHandler {
93 public:
~XmppOutputHandler()94   virtual ~XmppOutputHandler() {}
95 
96   //! Deliver the specified bytes to the XMPP socket.
97   virtual void WriteOutput(const char * bytes, size_t len) = 0;
98 
99   //! Initiate TLS encryption on the socket.
100   //! The implementation must verify that the SSL
101   //! certificate matches the given domainname.
102   virtual void StartTls(const std::string & domainname) = 0;
103 
104   //! Called when engine wants the connecton closed.
105   virtual void CloseConnection() = 0;
106 };
107 
108 //! Callback to deliver engine state change notifications
109 //! to the object managing the engine.
110 class XmppSessionHandler {
111 public:
~XmppSessionHandler()112   virtual ~XmppSessionHandler() {}
113   //! Called when engine changes state. Argument is new state.
114   virtual void OnStateChange(int state) = 0;
115 };
116 
117 //! Callback to deliver stanzas to an Xmpp application module.
118 //! Register via XmppEngine.SetDefaultSessionHandler or via
119 //! XmppEngine.AddSessionHAndler.
120 class XmppStanzaHandler {
121 public:
~XmppStanzaHandler()122   virtual ~XmppStanzaHandler() {}
123   //! Process the given stanza.
124   //! The handler must return true if it has handled the stanza.
125   //! A false return value causes the stanza to be passed on to
126   //! the next registered handler.
127   virtual bool HandleStanza(const XmlElement * stanza) = 0;
128 };
129 
130 //! Callback to deliver iq responses (results and errors).
131 //! Register while sending an iq via XmppEngine.SendIq.
132 //! Iq responses are routed to matching XmppIqHandlers in preference
133 //! to sending to any registered SessionHandlers.
134 class XmppIqHandler {
135 public:
~XmppIqHandler()136   virtual ~XmppIqHandler() {}
137   //! Called to handle the iq response.
138   //! The response may be either a result or an error, and will have
139   //! an 'id' that matches the request and a 'from' that matches the
140   //! 'to' of the request.  Called no more than once; once this is
141   //! called, the handler is automatically unregistered.
142   virtual void IqResponse(XmppIqCookie cookie, const XmlElement * pelStanza) = 0;
143 };
144 
145 //! The XMPP connection engine.
146 //! This engine implements the client side of the 'core' XMPP protocol.
147 //! To use it, register an XmppOutputHandler to handle socket output
148 //! and pass socket input to HandleInput.  Then application code can
149 //! set up the connection with a user, password, and other settings,
150 //! and then call Connect() to initiate the connection.
151 //! An application can listen for events and receive stanzas by
152 //! registering an XmppStanzaHandler via AddStanzaHandler().
153 class XmppEngine {
154 public:
155   static XmppEngine * Create();
~XmppEngine()156   virtual ~XmppEngine() {}
157 
158   //! Error codes. See GetError().
159   enum Error {
160     ERROR_NONE = 0,         //!< No error
161     ERROR_XML,              //!< Malformed XML or encoding error
162     ERROR_STREAM,           //!< XMPP stream error - see GetStreamError()
163     ERROR_VERSION,          //!< XMPP version error
164     ERROR_UNAUTHORIZED,     //!< User is not authorized (rejected credentials)
165     ERROR_TLS,              //!< TLS could not be negotiated
166     ERROR_AUTH,             //!< Authentication could not be negotiated
167     ERROR_BIND,             //!< Resource or session binding could not be negotiated
168     ERROR_CONNECTION_CLOSED,//!< Connection closed by output handler.
169     ERROR_DOCUMENT_CLOSED,  //!< Closed by </stream:stream>
170     ERROR_SOCKET,           //!< Socket error
171     ERROR_NETWORK_TIMEOUT,  //!< Some sort of timeout (eg., we never got the roster)
172     ERROR_MISSING_USERNAME  //!< User has a Google Account but no nickname
173   };
174 
175   //! States.  See GetState().
176   enum State {
177     STATE_NONE = 0,        //!< Nonexistent state
178     STATE_START,           //!< Initial state.
179     STATE_OPENING,         //!< Exchanging stream headers, authenticating and so on.
180     STATE_OPEN,            //!< Authenticated and bound.
181     STATE_CLOSED,          //!< Session closed, possibly due to error.
182   };
183 
184   // SOCKET INPUT AND OUTPUT ------------------------------------------------
185 
186   //! Registers the handler for socket output
187   virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh) = 0;
188 
189   //! Provides socket input to the engine
190   virtual XmppReturnStatus HandleInput(const char * bytes, size_t len) = 0;
191 
192   //! Advises the engine that the socket has closed
193   virtual XmppReturnStatus ConnectionClosed(int subcode) = 0;
194 
195   // SESSION SETUP ---------------------------------------------------------
196 
197   //! Indicates the (bare) JID for the user to use.
198   virtual XmppReturnStatus SetUser(const Jid & jid)= 0;
199 
200   //! Get the login (bare) JID.
201   virtual const Jid & GetUser() = 0;
202 
203   //! Provides different methods for credentials for login.
204   //! Takes ownership of this object; deletes when login is done
205   virtual XmppReturnStatus SetSaslHandler(SaslHandler * h) = 0;
206 
207   //! Sets whether TLS will be used within the connection (default true).
208   virtual XmppReturnStatus SetTls(TlsOptions useTls) = 0;
209 
210   //! Sets an alternate domain from which we allows TLS certificates.
211   //! This is for use in the case where a we want to allow a proxy to
212   //! serve up its own certificate rather than one owned by the underlying
213   //! domain.
214   virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname,
215                                         const std::string & proxy_domain) = 0;
216 
217   //! Gets whether TLS will be used within the connection.
218   virtual TlsOptions GetTls() = 0;
219 
220   //! Sets the request resource name, if any (optional).
221   //! Note that the resource name may be overridden by the server; after
222   //! binding, the actual resource name is available as part of FullJid().
223   virtual XmppReturnStatus SetRequestedResource(const std::string& resource) = 0;
224 
225   //! Gets the request resource name.
226   virtual const std::string & GetRequestedResource() = 0;
227 
228   //! Sets language
229   virtual void SetLanguage(const std::string & lang) = 0;
230 
231   // SESSION MANAGEMENT ---------------------------------------------------
232 
233   //! Set callback for state changes.
234   virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler) = 0;
235 
236   //! Initiates the XMPP connection.
237   //! After supplying connection settings, call this once to initiate,
238   //! (optionally) encrypt, authenticate, and bind the connection.
239   virtual XmppReturnStatus Connect() = 0;
240 
241   //! The current engine state.
242   virtual State GetState() = 0;
243 
244   //! Returns true if the connection is encrypted (under TLS)
245   virtual bool IsEncrypted() = 0;
246 
247   //! The error code.
248   //! Consult this after XmppOutputHandler.OnClose().
249   virtual Error GetError(int *subcode) = 0;
250 
251   //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
252   //! Notice the stanza returned is owned by the XmppEngine and
253   //! is deleted when the engine is destroyed.
254   virtual const XmlElement * GetStreamError() = 0;
255 
256   //! Closes down the connection.
257   //! Sends CloseConnection to output, and disconnects and registered
258   //! session handlers.  After Disconnect completes, it is guaranteed
259   //! that no further callbacks will be made.
260   virtual XmppReturnStatus Disconnect() = 0;
261 
262   // APPLICATION USE -------------------------------------------------------
263 
264   enum HandlerLevel {
265     HL_NONE = 0,
266     HL_PEEK,   //!< Sees messages before all other processing; cannot abort
267     HL_SINGLE, //!< Watches for a single message, e.g., by id and sender
268     HL_SENDER, //!< Watches for a type of message from a specific sender
269     HL_TYPE,   //!< Watches a type of message, e.g., all groupchat msgs
270     HL_ALL,    //!< Watches all messages - gets last shot
271     HL_COUNT,  //!< Count of handler levels
272   };
273 
274   //! Adds a listener for session events.
275   //! Stanza delivery is chained to session handlers; the first to
276   //! return 'true' is the last to get each stanza.
277   virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler, HandlerLevel level = HL_PEEK) = 0;
278 
279   //! Removes a listener for session events.
280   virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler) = 0;
281 
282   //! Sends a stanza to the server.
283   virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza) = 0;
284 
285   //! Sends raw text to the server
286   virtual XmppReturnStatus SendRaw(const std::string & text) = 0;
287 
288   //! Sends an iq to the server, and registers a callback for the result.
289   //! Returns the cookie passed to the result handler.
290   virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
291                                   XmppIqHandler* iq_handler,
292                                   XmppIqCookie* cookie) = 0;
293 
294   //! Unregisters an iq callback handler given its cookie.
295   //! No callback will come to this handler after it's unregistered.
296   virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
297                                       XmppIqHandler** iq_handler) = 0;
298 
299 
300   //! Forms and sends an error in response to the given stanza.
301   //! Swaps to and from, sets type to "error", and adds error information
302   //! based on the passed code.  Text is optional and may be STR_EMPTY.
303   virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
304                                            XmppStanzaError code,
305                                            const std::string & text) = 0;
306 
307   //! The fullly bound JID.
308   //! This JID is only valid after binding has succeeded.  If the value
309   //! is JID_NULL, the binding has not succeeded.
310   virtual const Jid & FullJid() = 0;
311 
312   //! The next unused iq id for this connection.
313   //! Call this when building iq stanzas, to ensure that each iq
314   //! gets its own unique id.
315   virtual std::string NextId() = 0;
316 
317 };
318 
319 }
320 
321 
322 // Move these to a better location
323 
324 #define XMPP_FAILED(x)                      \
325   ( (x) == buzz::XMPP_RETURN_OK ? false : true)   \
326 
327 
328 #define XMPP_SUCCEEDED(x)                   \
329   ( (x) == buzz::XMPP_RETURN_OK ? true : false)   \
330 
331 #define IFR(x)                        \
332   do {                                \
333     xmpp_status = (x);                \
334     if (XMPP_FAILED(xmpp_status)) {   \
335       return xmpp_status;             \
336     }                                 \
337   } while (false)                     \
338 
339 
340 #define IFC(x)                        \
341   do {                                \
342     xmpp_status = (x);                \
343     if (XMPP_FAILED(xmpp_status)) {   \
344       goto Cleanup;                   \
345     }                                 \
346   } while (false)                     \
347 
348 
349 #endif
350