631 lines
18 KiB
C++
631 lines
18 KiB
C++
/**
|
|
* xmpputils.h
|
|
* Yet Another Jabber Component Protocol Stack
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
*
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
* Copyright (C) 2004-2006 Null Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef __XMPPUTILS_H
|
|
#define __XMPPUTILS_H
|
|
|
|
#include <yateclass.h>
|
|
#include <xmlparser.h>
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#ifdef LIBYJINGLE_EXPORTS
|
|
#define YJINGLE_API __declspec(dllexport)
|
|
#else
|
|
#ifndef LIBYJINGLE_STATIC
|
|
#define YJINGLE_API __declspec(dllimport)
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* _WINDOWS */
|
|
|
|
#ifndef YJINGLE_API
|
|
#define YJINGLE_API
|
|
#endif
|
|
|
|
/**
|
|
* Holds all Telephony Engine related classes.
|
|
*/
|
|
namespace TelEngine {
|
|
|
|
class XMPPNamespace;
|
|
class XMPPErrorCode;
|
|
class XMPPError;
|
|
class JabberID;
|
|
class JIDIdentity;
|
|
class JIDFeature;
|
|
class JIDFeatureList;
|
|
class XMPPUtils;
|
|
|
|
/**
|
|
* This class holds the XMPP/JabberComponent/Jingle namespace enumerations and the associated strings.
|
|
* @short XMPP namespaces.
|
|
*/
|
|
class YJINGLE_API XMPPNamespace
|
|
{
|
|
public:
|
|
enum Type {
|
|
Stream, // http://etherx.jabber.org/streams
|
|
ComponentAccept, // jabber:component:accept
|
|
ComponentConnect, // jabber:component:connect
|
|
StreamError, // urn:ietf:params:xml:ns:xmpp-streams
|
|
StanzaError, // urn:ietf:params:xml:ns:xmpp-stanzas
|
|
Bind, // urn:ietf:params:xml:ns:xmpp-bind
|
|
DiscoInfo, // http://jabber.org/protocol/disco#info
|
|
DiscoItems, // http://jabber.org/protocol/disco#items
|
|
Jingle, // http://www.google.com/session
|
|
JingleAudio, // http://www.google.com/session/phone
|
|
JingleTransport, // http://www.google.com/transport/p2p
|
|
Dtmf, // http://jabber.org/protocol/jingle/info/dtmf
|
|
DtmfError, // http://jabber.org/protocol/jingle/info/dtmf#errors
|
|
Command, // http://jabber.org/protocol/command
|
|
CapVoiceV1, // http://www.google.com/xmpp/protocol/voice/v1
|
|
Count,
|
|
};
|
|
|
|
inline const char* operator[](Type index)
|
|
{ return lookup(index,s_value); }
|
|
|
|
static bool isText(Type index, const char* txt);
|
|
|
|
static inline Type type(const char* txt) {
|
|
int tmp = lookup(txt,s_value,Count);
|
|
return tmp ? (Type)tmp : Count;
|
|
}
|
|
|
|
private:
|
|
static TokenDict s_value[]; // Namespace list
|
|
};
|
|
|
|
/**
|
|
* This class holds the XMPP error type, error enumerations and associated strings
|
|
* @short XMPP errors.
|
|
*/
|
|
class YJINGLE_API XMPPError
|
|
{
|
|
public:
|
|
// Error type
|
|
enum ErrorType {
|
|
TypeCancel = 0, // do not retry (the error is unrecoverable)
|
|
TypeContinue, // proceed (the condition was only a warning)
|
|
TypeModify, // retry after changing the data sent
|
|
TypeAuth, // retry after providing credentials
|
|
TypeWait, // retry after waiting (the error is temporary)
|
|
TypeCount,
|
|
};
|
|
|
|
enum Type {
|
|
// Stream errors
|
|
BadFormat = TypeCount + 1, // bad-format
|
|
BadNamespace, // bad-namespace-prefix
|
|
ConnTimeout, // connection-timeout
|
|
HostGone, // host-gone
|
|
HostUnknown, // host-unknown
|
|
BadAddressing, // improper-addressing
|
|
Internal, // internal-server-error
|
|
InvalidFrom, // invalid-from
|
|
InvalidId, // invalid-id
|
|
InvalidNamespace, // invalid-namespace
|
|
InvalidXml, // invalid-xml
|
|
NotAuth, // not-authorized
|
|
Policy, // policy-violation
|
|
RemoteConn, // remote-connection-failed
|
|
ResConstraint, // resource-constraint
|
|
RestrictedXml, // restricted-xml
|
|
SeeOther, // see-other-host
|
|
Shutdown, // system-shutdown
|
|
UndefinedCondition, // undefined-condition
|
|
UnsupportedEnc, // unsupported-encoding
|
|
UnsupportedStanza, // unsupported-stanza-type
|
|
UnsupportedVersion, // unsupported-version
|
|
Xml, // xml-not-well-formed
|
|
// Stanza errors
|
|
SBadRequest, // bad-request
|
|
SConflict, // conflict
|
|
SFeatureNotImpl, // feature-not-implemented
|
|
SForbidden, // forbidden
|
|
SGone, // gone
|
|
SInternal, // internal-server-error
|
|
SItemNotFound, // item-not-found
|
|
SBadJid, // jid-malformed
|
|
SNotAcceptable, // not-acceptable
|
|
SNotAllowed, // not-allowed
|
|
SNotAuth, // not-authorized
|
|
SPayment, // payment-required
|
|
SUnavailable, // recipient-unavailable
|
|
SRedirect, // redirect
|
|
SReg, // registration-required
|
|
SNoRemote, // remote-server-not-found
|
|
SRemoteTimeout, // remote-server-timeout
|
|
SResource, // resource-constraint
|
|
SServiceUnavailable, // service-unavailable
|
|
SSubscription, // subscription-required
|
|
SUndefinedCondition, // undefined-condition
|
|
SRequest, // unexpected-request
|
|
// Dtmf
|
|
DtmfNoMethod, // unsupported-dtmf-method
|
|
Count,
|
|
};
|
|
|
|
inline const char* operator[](int index)
|
|
{ return lookup(index,s_value); }
|
|
|
|
static bool isText(int index, const char* txt);
|
|
|
|
static inline int type(const char* txt)
|
|
{ return lookup(txt,s_value,Count); }
|
|
|
|
private:
|
|
static TokenDict s_value[]; // Error list
|
|
};
|
|
|
|
/**
|
|
* This class holds a Jabber ID in form "node@domain/resource" or "node@domain".
|
|
* @short A Jabber ID.
|
|
*/
|
|
class YJINGLE_API JabberID : public String
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
inline JabberID() {}
|
|
|
|
/**
|
|
* Constructor.
|
|
* Constructs a JID from a given string.
|
|
* @param jid The JID string.
|
|
*/
|
|
inline JabberID(const char* jid)
|
|
{ set(jid); }
|
|
|
|
/**
|
|
* Constructor.
|
|
* Constructs a JID from user, domain, resource.
|
|
* @param node The node.
|
|
* @param domain The domain.
|
|
* @param resource The resource.
|
|
*/
|
|
JabberID(const char* node, const char* domain, const char* resource = 0)
|
|
{ set(node,domain,resource); }
|
|
|
|
/**
|
|
* Get the node part of the JID.
|
|
* @return The node part of the JID.
|
|
*/
|
|
inline const String& node() const
|
|
{ return m_node; }
|
|
|
|
/**
|
|
* Get the bare JID: "node@domain".
|
|
* @return The bare JID.
|
|
*/
|
|
inline const String& bare() const
|
|
{ return m_bare; }
|
|
|
|
/**
|
|
* Get the domain part of the JID.
|
|
* @return The domain part of the JID.
|
|
*/
|
|
inline const String& domain() const
|
|
{ return m_domain; }
|
|
|
|
/**
|
|
* Set the domain part of the JID.
|
|
* @param d The new domain part of the JID.
|
|
*/
|
|
inline void domain(const char* d)
|
|
{ set(m_node.c_str(),d,m_resource.c_str()); }
|
|
|
|
/**
|
|
* Get the resource part of the JID.
|
|
* @return The resource part of the JID.
|
|
*/
|
|
inline const String& resource() const
|
|
{ return m_resource; }
|
|
|
|
/**
|
|
* Try to match another JID to this one. If src has a resource compare with
|
|
* the full JID. Otherwise compare the bare JID.
|
|
* @param src The JID to match.
|
|
* @return True if matched.
|
|
*/
|
|
inline bool match(const JabberID& src) const
|
|
{ return (src.resource() ? src == *this : bare() == src.bare()); }
|
|
|
|
/**
|
|
* Set the resource part of the JID.
|
|
* @param res The new resource part of the JID.
|
|
*/
|
|
inline void resource(const char* res)
|
|
{ set(m_node.c_str(),m_domain.c_str(),res); }
|
|
|
|
/**
|
|
* Set the data.
|
|
* @param jid The JID string to assign.
|
|
*/
|
|
void set(const char* jid);
|
|
|
|
/**
|
|
* Set the data.
|
|
* @param node The node.
|
|
* @param domain The domain.
|
|
* @param resource The resource.
|
|
*/
|
|
void set(const char* node, const char* domain, const char* resource = 0);
|
|
|
|
/**
|
|
* Check if the given string contains valid characters.
|
|
* @param value The string to check.
|
|
* @return True if value is valid or 0. False if value is a non empty invalid string.
|
|
*/
|
|
static bool valid(const String& value);
|
|
|
|
/**
|
|
* Keep the regexp used to check the validity of a string.
|
|
*/
|
|
static Regexp s_regExpValid;
|
|
|
|
private:
|
|
void parse(); // Parse the string. Set the data
|
|
|
|
String m_node; // The node part
|
|
String m_domain; // The domain part
|
|
String m_resource; // The resource part
|
|
String m_bare; // The bare JID: node@domain
|
|
};
|
|
|
|
/**
|
|
* This class holds an identity for a JID.
|
|
* @short JID identity.
|
|
*/
|
|
class YJINGLE_API JIDIdentity : public String, public RefObject
|
|
{
|
|
public:
|
|
enum Category {
|
|
Account, // account
|
|
Client, // client
|
|
Component, // component
|
|
Gateway, // gateway
|
|
CategoryUnknown
|
|
};
|
|
|
|
enum Type {
|
|
AccountRegistered, // registered
|
|
ClientPhone, // phone
|
|
ComponentGeneric, // generic
|
|
ComponentPresence, // presence
|
|
GatewayGeneric, // generic
|
|
TypeUnknown
|
|
};
|
|
|
|
inline JIDIdentity(Category c, Type t, const char* name = 0)
|
|
: String(name), m_category(c), m_type(t)
|
|
{}
|
|
|
|
virtual ~JIDIdentity()
|
|
{}
|
|
|
|
XMLElement* toXML();
|
|
|
|
bool fromXML(const XMLElement* element);
|
|
|
|
static inline const char* categoryText(Category c)
|
|
{ return lookup(c,s_category); }
|
|
|
|
static inline Category categoryValue(const char* c)
|
|
{ return (Category)lookup(c,s_category,CategoryUnknown); }
|
|
|
|
static inline const char* typeText(Type t)
|
|
{ return lookup(t,s_type); }
|
|
|
|
static inline Type typeValue(const char* t)
|
|
{ return (Type)lookup(t,s_category,TypeUnknown); }
|
|
|
|
private:
|
|
static TokenDict s_category[];
|
|
static TokenDict s_type[];
|
|
|
|
Category m_category; // Category
|
|
Type m_type; // Type
|
|
};
|
|
|
|
/**
|
|
* This class holds a JID feature.
|
|
* @short JID feature.
|
|
*/
|
|
class YJINGLE_API JIDFeature : public RefObject
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
inline JIDFeature(XMPPNamespace::Type feature)
|
|
: m_feature(feature)
|
|
{}
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
virtual ~JIDFeature()
|
|
{}
|
|
|
|
/**
|
|
* XMPPNamespace::Type conversion operator.
|
|
*/
|
|
inline operator XMPPNamespace::Type()
|
|
{ return m_feature; }
|
|
|
|
private:
|
|
XMPPNamespace::Type m_feature; // The feature
|
|
};
|
|
|
|
/**
|
|
* This class holds a list of features.
|
|
* @short Feature list.
|
|
*/
|
|
class YJINGLE_API JIDFeatureList
|
|
{
|
|
public:
|
|
/**
|
|
* Add a feature to the list.
|
|
* @param feature The feature to add.
|
|
* @return False if the given feature already exists.
|
|
*/
|
|
inline bool add(XMPPNamespace::Type feature) {
|
|
if (get(feature))
|
|
return false;
|
|
m_features.append(new JIDFeature(feature));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove a feature from the list.
|
|
* @param feature The feature to remove.
|
|
*/
|
|
inline void remove(XMPPNamespace::Type feature)
|
|
{ m_features.remove(get(feature),true); }
|
|
|
|
/**
|
|
* Get a feature from the list.
|
|
* @param feature The feature to get.
|
|
* @return Pointer to the feature or 0 if it doesn't exists.
|
|
*/
|
|
JIDFeature* get(XMPPNamespace::Type feature);
|
|
|
|
/**
|
|
* Add 'feature' children to the given element.
|
|
* @param element The target XMLElement.
|
|
* @return The given element.
|
|
*/
|
|
XMLElement* addTo(XMLElement* element);
|
|
|
|
private:
|
|
ObjList m_features; // The features
|
|
};
|
|
|
|
/**
|
|
* This class is a general XMPP utilities.
|
|
* @short General XMPP utilities.
|
|
*/
|
|
class YJINGLE_API XMPPUtils
|
|
{
|
|
public:
|
|
/**
|
|
* Iq type enumeration.
|
|
*/
|
|
enum IqType {
|
|
IqSet, // set
|
|
IqGet, // get
|
|
IqResult, // result
|
|
IqError, // error
|
|
IqCount,
|
|
};
|
|
|
|
/**
|
|
* Message type enumeration.
|
|
*/
|
|
enum MsgType {
|
|
MsgChat, // chat
|
|
MsgCount,
|
|
};
|
|
|
|
/**
|
|
* Command action enumeration.
|
|
*/
|
|
enum CommandAction {
|
|
CommExecute,
|
|
CommCancel,
|
|
CommPrev,
|
|
CommNext,
|
|
CommComplete,
|
|
};
|
|
|
|
/**
|
|
* Command status enumeration.
|
|
*/
|
|
enum CommandStatus {
|
|
CommExecuting,
|
|
CommCompleted,
|
|
CommCancelled,
|
|
};
|
|
|
|
/**
|
|
* Create an XML element with an 'xmlns' attribute.
|
|
* @param name Element's name.
|
|
* @param ns 'xmlns' attribute.
|
|
* @param text Optional text for the element.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createElement(const char* name, XMPPNamespace::Type ns,
|
|
const char* text = 0);
|
|
|
|
/**
|
|
* Create an XML element with an 'xmlns' attribute.
|
|
* @param type Element's type.
|
|
* @param ns 'xmlns' attribute.
|
|
* @param text Optional text for the element.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createElement(XMLElement::Type type, XMPPNamespace::Type ns,
|
|
const char* text = 0);
|
|
|
|
/**
|
|
* Create a 'message' element.
|
|
* @param type Message type as enumeration
|
|
* @param from The 'from' attribute.
|
|
* @param to The 'to' attribute.
|
|
* @param id The 'id' attribute.
|
|
* @param message The message body.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createMessage(MsgType type, const char* from,
|
|
const char* to, const char* id, const char* message);
|
|
|
|
/**
|
|
* Create an 'iq' element.
|
|
* @param type Iq type as enumeration
|
|
* @param from The 'from' attribute.
|
|
* @param to The 'to' attribute.
|
|
* @param id The 'id' attribute.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createIq(IqType type, const char* from,
|
|
const char* to, const char* id);
|
|
|
|
/**
|
|
* Create an 'iq' element with a 'bind' child containing the resources.
|
|
* @param from The 'from' attribute.
|
|
* @param to The 'to' attribute.
|
|
* @param id The 'id' attribute.
|
|
* @param resources The resources to bind (strings).
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createIqBind(const char* from,
|
|
const char* to, const char* id, const ObjList& resources);
|
|
|
|
/**
|
|
* Create a 'command' element
|
|
* @param action The command action.
|
|
* @param node The command.
|
|
* @param sessionId Optional session ID for the command.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createCommand(CommandAction action, const char* node,
|
|
const char* sessionId = 0);
|
|
|
|
/**
|
|
* Create an 'identity' element.
|
|
* @param category The 'category' attribute.
|
|
* @param type The 'type' attribute.
|
|
* @param name The 'name' attribute.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createIdentity(const char* category,
|
|
const char* type, const char* name);
|
|
|
|
/**
|
|
* Create an 'iq' of type 'get' element with a 'query' child.
|
|
* @param from The 'from' attribute.
|
|
* @param to The 'to' attribute.
|
|
* @param id The 'id' attribute.
|
|
* @param info True to create a query info request. False to create a query items request.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createIqDisco(const char* from, const char* to,
|
|
const char* id, bool info = true);
|
|
|
|
/**
|
|
* Create a 'error' element.
|
|
* @param type Error type.
|
|
* @param error The error.
|
|
* @param text Optional text to add to the error element.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createError(XMPPError::ErrorType type,
|
|
XMPPError::Type error, const char* text = 0);
|
|
|
|
/**
|
|
* Create a 'stream:error' element.
|
|
* @param error The XMPP defined condition.
|
|
* @param text Optional text to add to the error.
|
|
* @return A valid XMLElement pointer.
|
|
*/
|
|
static XMLElement* createStreamError(XMPPError::Type error,
|
|
const char* text = 0);
|
|
|
|
/**
|
|
* Print an XMLElement to a string.
|
|
* @param xmlStr The destination string.
|
|
* @param element The element to print.
|
|
* @param indent The indent. 0 if it is the root element.
|
|
*/
|
|
static void print(String& xmlStr, XMLElement* element, const char* indent = 0);
|
|
|
|
/**
|
|
* Split a string at a delimiter character and fills a named list with its parts.
|
|
* Skip empty parts.
|
|
* @param dest The destination NamedList.
|
|
* @param src Pointer to the string.
|
|
* @param sep The delimiter.
|
|
* @param nameFirst True to add the parts as name and index as value.
|
|
* False to do the other way.
|
|
*/
|
|
static bool split(NamedList& dest, const char* src, const char sep,
|
|
bool nameFirst);
|
|
|
|
/**
|
|
* Get the type of an 'iq' stanza as enumeration.
|
|
* @param text The text to check.
|
|
* @return Iq type as enumeration.
|
|
*/
|
|
static inline IqType iqType(const char* text)
|
|
{ return (IqType)lookup(text,s_iq,IqCount); }
|
|
|
|
/**
|
|
* Keep the types of 'iq' stanzas.
|
|
*/
|
|
static TokenDict s_iq[];
|
|
|
|
/**
|
|
* Keep the types of 'message' stanzas.
|
|
*/
|
|
static TokenDict s_msg[];
|
|
|
|
/**
|
|
* Keep the command actions
|
|
*/
|
|
static TokenDict s_commandAction[];
|
|
|
|
/**
|
|
* Keep the command status
|
|
*/
|
|
static TokenDict s_commandStatus[];
|
|
};
|
|
|
|
};
|
|
|
|
#endif /* __XMPPUTILS_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|