Yate

xmpputils.h

00001 
00024 #ifndef __XMPPUTILS_H
00025 #define __XMPPUTILS_H
00026 
00027 #include <yateclass.h>
00028 #include <xmlparser.h>
00029 
00030 #ifdef _WINDOWS
00031 
00032 #ifdef LIBYJINGLE_EXPORTS
00033 #define YJINGLE_API __declspec(dllexport)
00034 #else
00035 #ifndef LIBYJINGLE_STATIC
00036 #define YJINGLE_API __declspec(dllimport)
00037 #endif
00038 #endif
00039 
00040 #endif /* _WINDOWS */
00041 
00042 #ifndef YJINGLE_API
00043 #define YJINGLE_API
00044 #endif
00045 
00049 namespace TelEngine {
00050 
00051 class XMPPServerInfo;                    // Server info class
00052 class XMPPNamespace;                     // XMPP namespaces
00053 class XMPPError;                         // XMPP errors
00054 class JabberID;                          // A Jabber ID (JID)
00055 class JIDIdentity;                       // A JID's identity
00056 class JIDFeature;                        // A JID's feature
00057 class JIDFeatureSasl;                    // A JID's SASL feature
00058 class JIDFeatureList;                    // Feature list
00059 class XMPPUtils;                         // Utilities
00060 class XMPPDirVal;                        // Direction flags
00061 
00066 class YJINGLE_API XMPPServerInfo : public RefObject
00067 {
00068 public:
00072     enum ServerFlag {
00073         NoAutoRestart     = 0x0001,      // Don't auto restart streams when down
00074         KeepRoster        = 0x0002,      // Tell the presence service to keep the roster for this server
00075         TlsRequired       = 0x0004,      // The server always requires connection encryption
00076         OldStyleAuth      = 0x0008,      // The server doesn't support RFC 3920 TLS/SASL ...
00077         AllowPlainAuth    = 0x0020,      // Allow plain password authentication
00078         AllowUnsafeSetup  = 0x0040,      // Allow user account setup on unenchrypted streams
00079     };
00080 
00091     inline XMPPServerInfo(const char* name, const char* address, int port,
00092         const char* password, const char* identity, const char* fullidentity,
00093         int flags)
00094         : m_name(name), m_address(address), m_port(port), m_password(password),
00095         m_identity(identity), m_fullIdentity(fullidentity), m_flags(flags)
00096         {}
00097 
00103     inline XMPPServerInfo(const char* name, int port)
00104         : m_name(name), m_port(port)
00105         {}
00106 
00111     inline const String& address() const
00112         { return m_address; }
00113 
00118     inline const String& name() const
00119         { return m_name; }
00120 
00125     inline const int port() const
00126         { return m_port; }
00127 
00132     inline const String& password() const
00133         { return m_password; }
00134 
00139     inline const String& identity() const
00140         { return m_identity; }
00141 
00146     inline const String& fullIdentity() const
00147         { return m_fullIdentity; }
00148 
00153     inline bool flag(int mask) const
00154         { return 0 != (m_flags & mask); }
00155 
00159     static TokenDict s_flagName[];
00160 
00161 private:
00162     String m_name;                       // Domain name
00163     String m_address;                    // IP address
00164     int m_port;                          // Port
00165     String m_password;                   // Authentication data
00166     String m_identity;                   // Identity. Used for Jabber Component protocol
00167     String m_fullIdentity;               // Full identity for this server
00168     int m_flags;                         // Server flags
00169 };
00170 
00171 
00176 class YJINGLE_API XMPPNamespace
00177 {
00178 public:
00179     enum Type {
00180         Stream = 1,                      // http://etherx.jabber.org/streams
00181         Client,                          // jabber:client
00182         Server,                          // jabber:server
00183         ComponentAccept,                 // jabber:component:accept
00184         ComponentConnect,                // jabber:component:connect
00185         StreamError,                     // urn:ietf:params:xml:ns:xmpp-streams
00186         StanzaError,                     // urn:ietf:params:xml:ns:xmpp-stanzas
00187         Register,                        // http://jabber.org/features/iq-register
00188         IqRegister,                      // jabber:iq:register
00189         IqPrivate,                       // jabber:iq:private
00190         IqAuth,                          // jabber:iq:auth
00191         IqAuthFeature,                   // http://jabber.org/features/iq-auth
00192         Starttls,                        // urn:ietf:params:xml:ns:xmpp-tls
00193         Sasl,                            // urn:ietf:params:xml:ns:xmpp-sasl
00194         Session,                         // urn:ietf:params:xml:ns:xmpp-session
00195         Bind,                            // urn:ietf:params:xml:ns:xmpp-bind
00196         Roster,                          // jabber:iq:roster
00197         DynamicRoster,                   // jabber:iq:roster-dynamic
00198         DiscoInfo,                       // http://jabber.org/protocol/disco#info
00199         DiscoItems,                      // http://jabber.org/protocol/disco#items
00200         VCard,                           // vcard-temp
00201         SIProfileFileTransfer,           // http://jabber.org/protocol/si/profile/file-transfer
00202         ByteStreams,                     // http://jabber.org/protocol/bytestreams
00203         Jingle,                          // xmlns='urn:xmpp:jingle:0
00204         JingleError,                     // urn:xmpp:jingle:errors:0
00205         JingleAppsRtp,                   // urn:xmpp:jingle:apps:rtp:0
00206         JingleAppsRtpInfo,               // urn:xmpp:jingle:apps:rtp:info:0
00207         JingleAppsRtpAudio,              // urn:xmpp:jingle:apps:rtp:audio
00208         JingleAppsFileTransfer,          // urn:xmpp:jingle:apps:file-transfer:0
00209         JingleTransportIceUdp,           // urn:xmpp:jingle:transports:ice-udp:0
00210         JingleTransportRawUdp,           // urn:xmpp:jingle:transports:raw-udp:0
00211         JingleTransportRawUdpInfo,       // urn:xmpp:jingle:transports:raw-udp:info:0
00212         JingleTransportByteStreams,      // urn:xmpp:jingle:transports:bytestreams:0
00213         JingleTransfer,                  // urn:xmpp:jingle:transfer:0
00214         Dtmf,                            // urn:xmpp:jingle:dtmf:0
00215         JingleSession,                   // http://www.google.com/session
00216         JingleAudio,                     // http://www.google.com/session/phone
00217         JingleTransport,                 // http://www.google.com/transport/p2p
00218         JingleRtpInfoOld,                // urn:xmpp:jingle:apps:rtp:info
00219         DtmfOld,                         // http://jabber.org/protocol/jingle/info/dtmf
00220         Command,                         // http://jabber.org/protocol/command
00221         CapVoiceV1,                      // http://www.google.com/xmpp/protocol/voice/v1
00222         Count,
00223     };
00224 
00228     inline const char* operator[](Type index)
00229         { return lookup(index,s_value); }
00230 
00234     static bool isText(Type index, const char* txt);
00235 
00239     static inline Type type(const char* txt) {
00240             int tmp = lookup(txt,s_value,Count);
00241             return tmp ? (Type)tmp : Count;
00242         }
00243 
00244 private:
00245     static TokenDict s_value[];          // Namespace list
00246 };
00247 
00248 
00253 class YJINGLE_API XMPPError
00254 {
00255 public:
00259     enum Type {
00260         NoError = 0,
00261         // Stream errors
00262         BadFormat,                       // bad-format
00263         BadNamespace,                    // bad-namespace-prefix
00264         ConnTimeout,                     // connection-timeout
00265         HostGone,                        // host-gone
00266         HostUnknown,                     // host-unknown
00267         BadAddressing,                   // improper-addressing
00268         Internal,                        // internal-server-error
00269         InvalidFrom,                     // invalid-from
00270         InvalidId,                       // invalid-id
00271         InvalidNamespace,                // invalid-namespace
00272         InvalidXml,                      // invalid-xml
00273         NotAuth,                         // not-authorized
00274         Policy,                          // policy-violation
00275         RemoteConn,                      // remote-connection-failed
00276         ResConstraint,                   // resource-constraint
00277         RestrictedXml,                   // restricted-xml
00278         SeeOther,                        // see-other-host
00279         Shutdown,                        // system-shutdown
00280         UndefinedCondition,              // undefined-condition
00281         UnsupportedEnc,                  // unsupported-encoding
00282         UnsupportedStanza,               // unsupported-stanza-type
00283         UnsupportedVersion,              // unsupported-version
00284         Xml,                             // xml-not-well-formed
00285         // Auth failures
00286         Aborted,                         // aborted
00287         IncorrectEnc,                    // incorrect-encoding
00288         InvalidAuth,                     // invalid-authzid
00289         InvalidMechanism,                // invalid-mechanism
00290         MechanismTooWeak,                // mechanism-too-weak
00291         NotAuthorized,                   // not-authorized
00292         TempAuthFailure,                 // temporary-auth-failure
00293         // Stanza errors
00294         SBadRequest,                     // bad-request
00295         SConflict,                       // conflict
00296         SFeatureNotImpl,                 // feature-not-implemented
00297         SForbidden,                      // forbidden
00298         SGone,                           // gone
00299         SInternal,                       // internal-server-error
00300         SItemNotFound,                   // item-not-found
00301         SBadJid,                         // jid-malformed
00302         SNotAcceptable,                  // not-acceptable
00303         SNotAllowed,                     // not-allowed
00304         SPayment,                        // payment-required
00305         SUnavailable,                    // recipient-unavailable
00306         SRedirect,                       // redirect
00307         SReg,                            // registration-required
00308         SNoRemote,                       // remote-server-not-found
00309         SRemoteTimeout,                  // remote-server-timeout
00310         SResource,                       // resource-constraint
00311         SServiceUnavailable,             // service-unavailable
00312         SSubscription,                   // subscription-required
00313         SUndefinedCondition,             // undefined-condition
00314         SRequest,                        // unexpected-request
00315         // Misc
00316         DtmfNoMethod,                    // unsupported-dtmf-method
00317         ItemNotFound,                    // item-not-found 
00318         Count,
00319     };
00320 
00324     enum ErrorType {
00325         TypeCancel = 1000,               // do not retry (the error is unrecoverable)
00326         TypeContinue,                    // proceed (the condition was only a warning)
00327         TypeModify,                      // retry after changing the data sent
00328         TypeAuth,                        // retry after providing credentials
00329         TypeWait,                        // retry after waiting (the error is temporary)
00330         TypeCount,
00331     };
00332 
00336     inline const char* operator[](int index)
00337         { return lookup(index,s_value); }
00338 
00342     static bool isText(int index, const char* txt);
00343 
00347     static inline int type(const char* txt)
00348         { return lookup(txt,s_value,Count); }
00349 
00350 private:
00351     static TokenDict s_value[];          // Error list
00352 };
00353 
00354 
00359 class YJINGLE_API JabberID : public String
00360 {
00361 public:
00365     inline JabberID() {}
00366 
00371     inline JabberID(const char* jid)
00372         { set(jid); }
00373 
00380     JabberID(const char* node, const char* domain, const char* resource = 0)
00381         { set(node,domain,resource); }
00382 
00387     inline const String& node() const
00388         { return m_node; }
00389 
00394     inline const String& bare() const
00395         { return m_bare; }
00396 
00401     inline const String& domain() const
00402         { return m_domain; }
00403 
00408     inline void domain(const char* d)
00409         { set(m_node.c_str(),d,m_resource.c_str()); }
00410 
00415     inline const String& resource() const
00416         { return m_resource; }
00417 
00422     inline bool isFull() const
00423         { return m_node && m_domain && m_resource; }
00424 
00431     inline bool match(const JabberID& src) const
00432         { return (src.resource().null() || (resource() == src.resource())) && (bare() &= src.bare()); }
00433 
00439     inline bool operator==(const JabberID& src) const
00440         { return (resource() == src.resource()) && (bare() &= src.bare()); }
00441 
00447     inline bool operator==(const String& src) const
00448         { JabberID tmp(src); return operator==(tmp); }
00449 
00455     inline bool operator!=(const JabberID& src) const
00456         { return !operator==(src); }
00457 
00463     inline bool operator!=(const String& src) const
00464         { return !operator==(src); }
00465 
00470     inline void resource(const char* res)
00471         { set(m_node.c_str(),m_domain.c_str(),res); }
00472 
00477     void set(const char* jid);
00478 
00485     void set(const char* node, const char* domain, const char* resource = 0);
00486 
00492     static bool valid(const String& value);
00493 
00497     static Regexp s_regExpValid;
00498 
00499 private:
00500     void parse();                        // Parse the string. Set the data 
00501 
00502     String m_node;                       // The node part
00503     String m_domain;                     // The domain part
00504     String m_resource;                   // The resource part
00505     String m_bare;                       // The bare JID: node@domain
00506 };
00507 
00508 
00513 class YJINGLE_API JIDIdentity : public RefObject
00514 {
00515 public:
00519     enum Category {
00520         Account,                         // account
00521         Client,                          // client
00522         Component,                       // component
00523         Gateway,                         // gateway
00524         CategoryUnknown
00525     };
00526 
00530     enum Type {
00531         AccountRegistered,               // registered
00532         ClientPhone,                     // phone
00533         ComponentGeneric,                // generic
00534         ComponentPresence,               // presence
00535         GatewayGeneric,                  // generic
00536         TypeUnknown
00537     };
00538 
00545     inline JIDIdentity(Category c, Type t, const char* name = 0)
00546         : m_name(name), m_category(c), m_type(t)
00547         {}
00548 
00552     virtual ~JIDIdentity()
00553         {}
00554 
00559     XMLElement* toXML();
00560 
00565     bool fromXML(const XMLElement* element);
00566 
00571     virtual const String& toString() const
00572         { return m_name; }
00573 
00579     virtual void* getObject(const String& name) const {
00580             if (name == "JIDIdentity")
00581                 return (void*)this;
00582             return RefObject::getObject(name);
00583         }
00584 
00589     inline void setName(const char* name)
00590         { if (name) m_name = name; }
00591 
00596     static inline const char* categoryText(Category c)
00597         { return lookup(c,s_category); }
00598 
00603     static inline Category categoryValue(const char* c)
00604         { return (Category)lookup(c,s_category,CategoryUnknown); }
00605 
00610     static inline const char* typeText(Type t)
00611         { return lookup(t,s_type); }
00612 
00617     static inline Type typeValue(const char* t)
00618         { return (Type)lookup(t,s_category,TypeUnknown); }
00619 
00620 private:
00621     static TokenDict s_category[];
00622     static TokenDict s_type[];
00623 
00624     String m_name;
00625     Category m_category;                 // Category
00626     Type m_type;                         // Type
00627 };
00628 
00629 
00634 class YJINGLE_API JIDFeature : public RefObject
00635 {
00636 public:
00642     inline JIDFeature(XMPPNamespace::Type feature, bool required = false)
00643         : m_feature(feature),
00644         m_required(required)
00645         {}
00646 
00650     virtual ~JIDFeature()
00651         {}
00652 
00657     inline bool required() const
00658         { return m_required; }
00659 
00663     inline operator XMPPNamespace::Type()
00664         { return m_feature; }
00665 
00666 private:
00667     XMPPNamespace::Type m_feature;       // The feature
00668     bool m_required;                     // Required flag
00669 };
00670 
00671 
00676 class YJINGLE_API JIDFeatureSasl : public JIDFeature
00677 {
00678 public:
00682     enum Mechanism {
00683         MechNone     = 0x00,             // No authentication mechanism
00684         MechMD5      = 0x01,             // MD5 digest
00685         MechSHA1     = 0x02,             // SHA1 digest
00686         MechPlain    = 0x04,             // Plain text password
00687     };
00688 
00694     inline JIDFeatureSasl(int mech, bool required = false)
00695         : JIDFeature(XMPPNamespace::Sasl,required),
00696         m_mechanism(mech)
00697         {}
00698 
00703     inline int mechanism() const
00704         { return m_mechanism; }
00705 
00710     inline bool mechanism(Mechanism mech) const
00711         { return 0 != (m_mechanism & mech); }
00712 
00716     inline operator XMPPNamespace::Type()
00717         { return JIDFeature::operator XMPPNamespace::Type(); }
00718 
00722     static TokenDict s_authMech[];
00723 
00724 private:
00725     int m_mechanism;                     // Authentication mechanisms
00726 };
00727 
00728 
00733 class YJINGLE_API JIDFeatureList
00734 {
00735 public:
00742     inline bool add(XMPPNamespace::Type feature, bool required = false) {
00743             if (get(feature))
00744                 return false;
00745             m_features.append(new JIDFeature(feature,required));
00746             return true;
00747         }
00748 
00754     inline bool add(JIDFeature* feature) {
00755             if (!feature || get(*feature)) {
00756                 TelEngine::destruct(feature);
00757                 return false;
00758             }
00759             m_features.append(feature);
00760             return true;
00761         }
00762 
00767     inline void remove(XMPPNamespace::Type feature)
00768         { m_features.remove(get(feature),true); }
00769 
00775     JIDFeature* get(XMPPNamespace::Type feature);
00776 
00782     XMLElement* addTo(XMLElement* element);
00783 
00790     void fromXml(XMLElement* element, bool reset = true);
00791 
00795     inline void clear()
00796         { m_features.clear(); }
00797 
00798 private:
00799     ObjList m_features;                  // The features
00800 };
00801 
00802 
00807 class YJINGLE_API XMPPUtils
00808 {
00809 public:
00813     enum IqType {
00814         IqSet,                           // set
00815         IqGet,                           // get
00816         IqResult,                        // result
00817         IqError,                         // error
00818         IqCount,
00819     };
00820 
00824     enum CommandAction {
00825         CommExecute,
00826         CommCancel,
00827         CommPrev,
00828         CommNext,
00829         CommComplete,
00830     };
00831 
00835     enum CommandStatus {
00836         CommExecuting,
00837         CommCompleted,
00838         CommCancelled,
00839     };
00840 
00848     static XMLElement* createElement(const char* name, XMPPNamespace::Type ns,
00849         const char* text = 0);
00850 
00858     static XMLElement* createElement(XMLElement::Type type, XMPPNamespace::Type ns,
00859         const char* text = 0);
00860 
00869     static XMLElement* createIq(IqType type, const char* from,
00870         const char* to, const char* id);
00871 
00880     static XMLElement* createIqBind(const char* from,
00881         const char* to, const char* id, const ObjList& resources);
00882 
00891     static XMLElement* createVCard(bool get, const char* from, const char* to, const char* id);
00892 
00900     static XMLElement* createCommand(CommandAction action, const char* node,
00901         const char* sessionId = 0);
00902 
00910     static XMLElement* createIdentity(const char* category,
00911         const char* type, const char* name);
00912 
00921     static XMLElement* createIqDisco(const char* from, const char* to,
00922         const char* id, bool info = true);
00923 
00934     static XMLElement* createDiscoInfoRes(const char* from, const char* to,
00935         const char* id, JIDFeatureList* features, JIDIdentity* identity);
00936 
00944     static XMLElement* createError(XMPPError::ErrorType type,
00945         XMPPError::Type error, const char* text = 0);
00946 
00956     static XMLElement* createError(XMLElement* xml, XMPPError::ErrorType type,
00957         XMPPError::Type error, const char* text = 0);
00958 
00965     static XMLElement* createStreamError(XMPPError::Type error,
00966         const char* text = 0);
00967 
00979     static XMLElement* createRegisterQuery(IqType type, const char* from,
00980         const char* to, const char* id,
00981         XMLElement* child1 = 0, XMLElement* child2 = 0, XMLElement* child3 = 0);
00982 
00992     static inline XMLElement* createRegisterQuery(const char* from,
00993         const char* to, const char* id,
00994         const char* username, const char* password) {
00995             return createRegisterQuery(XMPPUtils::IqSet,from,to,id,
00996                 new XMLElement(XMLElement::Username,0,username),
00997                 new XMLElement(XMLElement::Password,0,password));
00998         }
00999 
01006     static bool hasXmlns(XMLElement& element, XMPPNamespace::Type ns);
01007 
01014     static void decodeError(XMLElement* element, String& error, String& text);
01015 
01023     static void encodeDateTimeSec(String& buf, unsigned int timeSec,
01024         unsigned int fractions = 0);
01025 
01033     static unsigned int decodeDateTimeSec(const String& time, unsigned int* fractions = 0);
01034 
01041     static void print(String& xmlStr, XMLElement& element, const char* indent = 0);
01042 
01052     static bool split(NamedList& dest, const char* src, const char sep,
01053         bool nameFirst);
01054 
01061     static int decodeFlags(const String& src, const TokenDict* dict);
01062 
01069     static void buildFlags(String& dest, int src, const TokenDict* dict);
01070 
01077     static bool addChidren(XMLElement* dest, ObjList& list);
01078 
01084     static inline IqType iqType(const char* text)
01085         { return (IqType)lookup(text,s_iq,IqCount); }
01086 
01090     static TokenDict s_iq[];
01091 
01095     static TokenDict s_commandAction[];
01096 
01100     static TokenDict s_commandStatus[];
01101 };
01102 
01107 class YJINGLE_API XMPPDirVal
01108 {
01109 public:
01110     enum Direction {
01111         None = 0,
01112         To   = 1,
01113         From = 2,
01114         Both = 3,
01115     };
01116 
01121     inline XMPPDirVal(int flags = None)
01122         : m_value(flags)
01123         {}
01124 
01129     inline XMPPDirVal(const char* name)
01130         : m_value(lookup(name,None))
01131         {}
01132 
01137     inline void replace(int flag)
01138         { m_value = flag; }
01139 
01144     inline void replace(const char* name)
01145         { m_value = lookup(name,None); }
01146 
01151     inline void set(int flag)
01152         { m_value |= flag; }
01153 
01158     inline void reset(int flag)
01159         { m_value &= ~flag; }
01160 
01166     inline bool flag(int mask) const
01167         { return (m_value & mask) != 0; }
01168 
01173     inline bool to() const
01174         { return flag(To); }
01175 
01180     inline bool from() const
01181         { return flag(From); }
01182 
01186     inline operator int()
01187         { return m_value; }
01188 
01195     static inline const char* lookup(int flag, const char* defVal = "")
01196         { return TelEngine::lookup(flag,s_names,defVal); }
01197 
01204     static inline int lookup(const char* name, int defVal = None)
01205         { return TelEngine::lookup(name,s_names,defVal); }
01206 
01210     static TokenDict s_names[];
01211 
01212 private:
01213     int m_value;                         // The value
01214 };
01215 
01216 };
01217 
01218 #endif /* __XMPPUTILS_H */
01219 
01220 /* vi: set ts=8 sw=4 sts=4 noet: */