yate/libs/yjingle/xmpputils.h

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: */