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