webrtc/talk/xmpp/xmppengine.h

350 lines
13 KiB
C++

/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_XMPP_XMPPENGINE_H_
#define TALK_XMPP_XMPPENGINE_H_
// also part of the API
#include "webrtc/libjingle/xmllite/qname.h"
#include "webrtc/libjingle/xmllite/xmlelement.h"
#include "webrtc/libjingle/xmpp/jid.h"
namespace buzz {
class XmppEngine;
class SaslHandler;
typedef void * XmppIqCookie;
//! XMPP stanza error codes.
//! Used in XmppEngine.SendStanzaError().
enum XmppStanzaError {
XSE_BAD_REQUEST,
XSE_CONFLICT,
XSE_FEATURE_NOT_IMPLEMENTED,
XSE_FORBIDDEN,
XSE_GONE,
XSE_INTERNAL_SERVER_ERROR,
XSE_ITEM_NOT_FOUND,
XSE_JID_MALFORMED,
XSE_NOT_ACCEPTABLE,
XSE_NOT_ALLOWED,
XSE_PAYMENT_REQUIRED,
XSE_RECIPIENT_UNAVAILABLE,
XSE_REDIRECT,
XSE_REGISTRATION_REQUIRED,
XSE_SERVER_NOT_FOUND,
XSE_SERVER_TIMEOUT,
XSE_RESOURCE_CONSTRAINT,
XSE_SERVICE_UNAVAILABLE,
XSE_SUBSCRIPTION_REQUIRED,
XSE_UNDEFINED_CONDITION,
XSE_UNEXPECTED_REQUEST,
};
// XmppReturnStatus
// This is used by API functions to synchronously return status.
enum XmppReturnStatus {
XMPP_RETURN_OK,
XMPP_RETURN_BADARGUMENT,
XMPP_RETURN_BADSTATE,
XMPP_RETURN_PENDING,
XMPP_RETURN_UNEXPECTED,
XMPP_RETURN_NOTYETIMPLEMENTED,
};
// TlsOptions
// This is used by API to identify TLS setting.
enum TlsOptions {
TLS_DISABLED,
TLS_ENABLED,
TLS_REQUIRED
};
//! Callback for socket output for an XmppEngine connection.
//! Register via XmppEngine.SetOutputHandler. An XmppEngine
//! can call back to this handler while it is processing
//! Connect, SendStanza, SendIq, Disconnect, or HandleInput.
class XmppOutputHandler {
public:
virtual ~XmppOutputHandler() {}
//! Deliver the specified bytes to the XMPP socket.
virtual void WriteOutput(const char * bytes, size_t len) = 0;
//! Initiate TLS encryption on the socket.
//! The implementation must verify that the SSL
//! certificate matches the given domainname.
virtual void StartTls(const std::string & domainname) = 0;
//! Called when engine wants the connecton closed.
virtual void CloseConnection() = 0;
};
//! Callback to deliver engine state change notifications
//! to the object managing the engine.
class XmppSessionHandler {
public:
virtual ~XmppSessionHandler() {}
//! Called when engine changes state. Argument is new state.
virtual void OnStateChange(int state) = 0;
};
//! Callback to deliver stanzas to an Xmpp application module.
//! Register via XmppEngine.SetDefaultSessionHandler or via
//! XmppEngine.AddSessionHAndler.
class XmppStanzaHandler {
public:
virtual ~XmppStanzaHandler() {}
//! Process the given stanza.
//! The handler must return true if it has handled the stanza.
//! A false return value causes the stanza to be passed on to
//! the next registered handler.
virtual bool HandleStanza(const XmlElement * stanza) = 0;
};
//! Callback to deliver iq responses (results and errors).
//! Register while sending an iq via XmppEngine.SendIq.
//! Iq responses are routed to matching XmppIqHandlers in preference
//! to sending to any registered SessionHandlers.
class XmppIqHandler {
public:
virtual ~XmppIqHandler() {}
//! Called to handle the iq response.
//! The response may be either a result or an error, and will have
//! an 'id' that matches the request and a 'from' that matches the
//! 'to' of the request. Called no more than once; once this is
//! called, the handler is automatically unregistered.
virtual void IqResponse(XmppIqCookie cookie, const XmlElement * pelStanza) = 0;
};
//! The XMPP connection engine.
//! This engine implements the client side of the 'core' XMPP protocol.
//! To use it, register an XmppOutputHandler to handle socket output
//! and pass socket input to HandleInput. Then application code can
//! set up the connection with a user, password, and other settings,
//! and then call Connect() to initiate the connection.
//! An application can listen for events and receive stanzas by
//! registering an XmppStanzaHandler via AddStanzaHandler().
class XmppEngine {
public:
static XmppEngine * Create();
virtual ~XmppEngine() {}
//! Error codes. See GetError().
enum Error {
ERROR_NONE = 0, //!< No error
ERROR_XML, //!< Malformed XML or encoding error
ERROR_STREAM, //!< XMPP stream error - see GetStreamError()
ERROR_VERSION, //!< XMPP version error
ERROR_UNAUTHORIZED, //!< User is not authorized (rejected credentials)
ERROR_TLS, //!< TLS could not be negotiated
ERROR_AUTH, //!< Authentication could not be negotiated
ERROR_BIND, //!< Resource or session binding could not be negotiated
ERROR_CONNECTION_CLOSED,//!< Connection closed by output handler.
ERROR_DOCUMENT_CLOSED, //!< Closed by </stream:stream>
ERROR_SOCKET, //!< Socket error
ERROR_NETWORK_TIMEOUT, //!< Some sort of timeout (eg., we never got the roster)
ERROR_MISSING_USERNAME //!< User has a Google Account but no nickname
};
//! States. See GetState().
enum State {
STATE_NONE = 0, //!< Nonexistent state
STATE_START, //!< Initial state.
STATE_OPENING, //!< Exchanging stream headers, authenticating and so on.
STATE_OPEN, //!< Authenticated and bound.
STATE_CLOSED, //!< Session closed, possibly due to error.
};
// SOCKET INPUT AND OUTPUT ------------------------------------------------
//! Registers the handler for socket output
virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh) = 0;
//! Provides socket input to the engine
virtual XmppReturnStatus HandleInput(const char * bytes, size_t len) = 0;
//! Advises the engine that the socket has closed
virtual XmppReturnStatus ConnectionClosed(int subcode) = 0;
// SESSION SETUP ---------------------------------------------------------
//! Indicates the (bare) JID for the user to use.
virtual XmppReturnStatus SetUser(const Jid & jid)= 0;
//! Get the login (bare) JID.
virtual const Jid & GetUser() = 0;
//! Provides different methods for credentials for login.
//! Takes ownership of this object; deletes when login is done
virtual XmppReturnStatus SetSaslHandler(SaslHandler * h) = 0;
//! Sets whether TLS will be used within the connection (default true).
virtual XmppReturnStatus SetTls(TlsOptions useTls) = 0;
//! Sets an alternate domain from which we allows TLS certificates.
//! This is for use in the case where a we want to allow a proxy to
//! serve up its own certificate rather than one owned by the underlying
//! domain.
virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname,
const std::string & proxy_domain) = 0;
//! Gets whether TLS will be used within the connection.
virtual TlsOptions GetTls() = 0;
//! Sets the request resource name, if any (optional).
//! Note that the resource name may be overridden by the server; after
//! binding, the actual resource name is available as part of FullJid().
virtual XmppReturnStatus SetRequestedResource(const std::string& resource) = 0;
//! Gets the request resource name.
virtual const std::string & GetRequestedResource() = 0;
//! Sets language
virtual void SetLanguage(const std::string & lang) = 0;
// SESSION MANAGEMENT ---------------------------------------------------
//! Set callback for state changes.
virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler) = 0;
//! Initiates the XMPP connection.
//! After supplying connection settings, call this once to initiate,
//! (optionally) encrypt, authenticate, and bind the connection.
virtual XmppReturnStatus Connect() = 0;
//! The current engine state.
virtual State GetState() = 0;
//! Returns true if the connection is encrypted (under TLS)
virtual bool IsEncrypted() = 0;
//! The error code.
//! Consult this after XmppOutputHandler.OnClose().
virtual Error GetError(int *subcode) = 0;
//! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM.
//! Notice the stanza returned is owned by the XmppEngine and
//! is deleted when the engine is destroyed.
virtual const XmlElement * GetStreamError() = 0;
//! Closes down the connection.
//! Sends CloseConnection to output, and disconnects and registered
//! session handlers. After Disconnect completes, it is guaranteed
//! that no further callbacks will be made.
virtual XmppReturnStatus Disconnect() = 0;
// APPLICATION USE -------------------------------------------------------
enum HandlerLevel {
HL_NONE = 0,
HL_PEEK, //!< Sees messages before all other processing; cannot abort
HL_SINGLE, //!< Watches for a single message, e.g., by id and sender
HL_SENDER, //!< Watches for a type of message from a specific sender
HL_TYPE, //!< Watches a type of message, e.g., all groupchat msgs
HL_ALL, //!< Watches all messages - gets last shot
HL_COUNT, //!< Count of handler levels
};
//! Adds a listener for session events.
//! Stanza delivery is chained to session handlers; the first to
//! return 'true' is the last to get each stanza.
virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler, HandlerLevel level = HL_PEEK) = 0;
//! Removes a listener for session events.
virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler) = 0;
//! Sends a stanza to the server.
virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza) = 0;
//! Sends raw text to the server
virtual XmppReturnStatus SendRaw(const std::string & text) = 0;
//! Sends an iq to the server, and registers a callback for the result.
//! Returns the cookie passed to the result handler.
virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
XmppIqHandler* iq_handler,
XmppIqCookie* cookie) = 0;
//! Unregisters an iq callback handler given its cookie.
//! No callback will come to this handler after it's unregistered.
virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
XmppIqHandler** iq_handler) = 0;
//! Forms and sends an error in response to the given stanza.
//! Swaps to and from, sets type to "error", and adds error information
//! based on the passed code. Text is optional and may be STR_EMPTY.
virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
XmppStanzaError code,
const std::string & text) = 0;
//! The fullly bound JID.
//! This JID is only valid after binding has succeeded. If the value
//! is JID_NULL, the binding has not succeeded.
virtual const Jid & FullJid() = 0;
//! The next unused iq id for this connection.
//! Call this when building iq stanzas, to ensure that each iq
//! gets its own unique id.
virtual std::string NextId() = 0;
};
}
// Move these to a better location
#define XMPP_FAILED(x) \
( (x) == buzz::XMPP_RETURN_OK ? false : true) \
#define XMPP_SUCCEEDED(x) \
( (x) == buzz::XMPP_RETURN_OK ? true : false) \
#define IFR(x) \
do { \
xmpp_status = (x); \
if (XMPP_FAILED(xmpp_status)) { \
return xmpp_status; \
} \
} while (false) \
#define IFC(x) \
do { \
xmpp_status = (x); \
if (XMPP_FAILED(xmpp_status)) { \
goto Cleanup; \
} \
} while (false) \
#endif // TALK_XMPP_XMPPENGINE_H_