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