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