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