333 lines
12 KiB
C
333 lines
12 KiB
C
|
/*
|
||
|
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#ifndef WEBRTC_LIBJINGLE_XMPP_XMPPENGINE_H_
|
||
|
#define WEBRTC_LIBJINGLE_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 // WEBRTC_LIBJINGLE_XMPP_XMPPENGINE_H_
|