00001
00024 #ifndef __YATEJABBER_H
00025 #define __YATEJABBER_H
00026
00027 #include <xmpputils.h>
00028 #include <xmlparser.h>
00029
00033 namespace TelEngine {
00034
00035 class JBEvent;
00036 class JBStream;
00037 class JBComponentStream;
00038 class JBClientStream;
00039 class JBThread;
00040 class JBThreadList;
00041 class JBEngine;
00042 class JBService;
00043 class JBPresence;
00044 class JIDResource;
00045 class JIDResourceList;
00046 class XMPPUser;
00047 class XMPPUserRoster;
00048
00054 class YJINGLE_API JBEvent : public RefObject
00055 {
00056 friend class JBStream;
00057 friend class JBClientStream;
00058 public:
00062 enum Type {
00063
00064 Terminated = 1,
00065 Destroy = 2,
00066 Running = 3,
00067
00068 WriteFail = 10,
00069
00070 Presence = 20,
00071 Message = 30,
00072 Iq = 50,
00073 IqError = 51,
00074 IqResult = 52,
00075
00076 IqDiscoInfoGet = 60,
00077 IqDiscoInfoSet = 61,
00078 IqDiscoInfoRes = 62,
00079 IqDiscoInfoErr = 63,
00080 IqDiscoItemsGet = 64,
00081 IqDiscoItemsSet = 65,
00082 IqDiscoItemsRes = 66,
00083 IqDiscoItemsErr = 67,
00084
00085 IqCommandGet = 70,
00086 IqCommandSet = 71,
00087 IqCommandRes = 72,
00088 IqCommandErr = 73,
00089
00090 IqJingleGet = 80,
00091 IqJingleSet = 81,
00092 IqJingleRes = 82,
00093 IqJingleErr = 83,
00094
00095 IqRosterSet = 91,
00096 IqRosterRes = 92,
00097 IqRosterErr = 93,
00098
00099
00100 IqClientRosterUpdate = 150,
00101
00102 Unhandled = 200,
00103 Invalid = 500,
00104 };
00105
00113 JBEvent(Type type, JBStream* stream, XMLElement* element, XMLElement* child = 0);
00114
00122 JBEvent(Type type, JBStream* stream, XMLElement* element, const String& senderID);
00123
00127 virtual ~JBEvent();
00128
00133 inline int type() const
00134 { return m_type; }
00135
00140 inline const char* name() const
00141 { return lookup(type()); }
00142
00147 inline const String& stanzaType() const
00148 { return m_stanzaType; }
00149
00154 inline const JabberID& from() const
00155 { return m_from; }
00156
00161 inline const JabberID& to() const
00162 { return m_to; }
00163
00169 inline const String& id() const
00170 { return m_id; }
00171
00176 inline const String& text() const
00177 { return m_text; }
00178
00183 inline JBStream* stream() const
00184 { return m_stream; }
00185
00190 inline XMLElement* element() const
00191 { return m_element; }
00192
00197 inline XMLElement* child() const
00198 { return m_child; }
00199
00206 inline XMLElement* releaseXML(bool del = false) {
00207 TelEngine::destruct(m_child);
00208 if (del) {
00209 TelEngine::destruct(m_element);
00210 return 0;
00211 }
00212 XMLElement* tmp = m_element;
00213 m_element = 0;
00214 return tmp;
00215 }
00216
00220 void releaseStream();
00221
00230 XMLElement* createError(XMPPError::ErrorType type, XMPPError::Type error, const char* text = 0);
00231
00236 inline static const char* lookup(int type)
00237 { return TelEngine::lookup(type,s_type); }
00238
00239 private:
00240 static TokenDict s_type[];
00241 JBEvent() {}
00242 bool init(JBStream* stream, XMLElement* element);
00243
00244 Type m_type;
00245 JBStream* m_stream;
00246 bool m_link;
00247 XMLElement* m_element;
00248 XMLElement* m_child;
00249 String m_stanzaType;
00250 JabberID m_from;
00251 JabberID m_to;
00252 String m_id;
00253
00254 String m_text;
00255
00256 };
00257
00262 class YJINGLE_API JBSocket
00263 {
00264 friend class JBStream;
00265 public:
00273 JBSocket(JBEngine* engine, JBStream* stream,
00274 const char* address, int port);
00275
00279 inline ~JBSocket()
00280 { terminate(); }
00281
00286 inline bool valid() const
00287 { return m_socket && m_socket->valid(); }
00288
00293 inline const SocketAddr& addr() const
00294 { return m_address; }
00295
00300 inline const String& error() const
00301 { return m_error; }
00302
00311 bool connect(bool& terminated, const char* newAddr, int newPort = 0);
00312
00317 void terminate(bool shutdown = false);
00318
00326 bool recv(char* buffer, unsigned int& len);
00327
00334 bool send(const char* buffer, unsigned int& len);
00335
00336 private:
00337 JBEngine* m_engine;
00338 JBStream* m_stream;
00339 Socket* m_socket;
00340 String m_remoteDomain;
00341 SocketAddr m_address;
00342 Mutex m_streamMutex;
00343 Mutex m_receiveMutex;
00344 String m_error;
00345 };
00346
00352 class YJINGLE_API JBStream : public RefObject
00353 {
00354 friend class JBEngine;
00355 friend class JBEvent;
00356 public:
00360 enum State {
00361 Idle = 0,
00362 Connecting = 1,
00363 Started = 2,
00364 Securing = 3,
00365 Register = 4,
00366 Auth = 5,
00367 Running = 6,
00368 Destroy = 7,
00369 };
00370
00374 enum Error {
00375 ErrorNone = 0,
00376 ErrorContext,
00377 ErrorPending,
00378 ErrorNoSocket,
00379 };
00380
00384 enum Flags {
00385 AutoRestart = 0x0001,
00386 AllowPlainAuth = 0x0002,
00387
00388
00389 NoVersion1 = 0x0004,
00390 UseTls = 0x0008,
00391
00392 UseSasl = 0x0010,
00393
00394 AllowUnsafeSetup = 0x0020,
00395 StreamSecured = 0x0100,
00396 StreamAuthenticated = 0x0200,
00397 NoRemoteVersion1 = 0x0400,
00398 };
00399
00404 virtual ~JBStream();
00405
00410 inline int type() const
00411 { return m_type; }
00412
00417 inline State state() const
00418 { return m_state; }
00419
00424 inline bool outgoing() const
00425 { return m_outgoing; }
00426
00431 inline const String& name() const
00432 { return m_name; }
00433
00438 inline const String& id() const
00439 { return m_id; }
00440
00445 inline JBEngine* engine() const
00446 { return m_engine; }
00447
00452 inline const JabberID& local() const
00453 { return m_local; }
00454
00459 inline const JabberID& remote() const
00460 { return m_remote; }
00461
00466 inline const SocketAddr& addr() const
00467 { return m_socket.addr(); }
00468
00474 inline bool flag(int mask) const
00475 { return 0 != (m_flags & mask); }
00476
00481 inline Mutex* streamMutex()
00482 { return &m_socket.m_streamMutex; }
00483
00488 void connect();
00489
00496 bool receive();
00497
00505 virtual Error sendStanza(XMLElement* stanza, const char* senderId = 0);
00506
00515 JBEvent* getEvent(u_int64_t time);
00516
00529 void terminate(bool destroy, XMLElement* recvStanza, XMPPError::Type error, const char* reason,
00530 bool send, bool final = false, bool sendError = true);
00531
00538 inline void removePending(const String& id, bool notify = false) {
00539 Lock lock(m_socket.m_streamMutex);
00540 removePending(notify,&id,false);
00541 }
00542
00547 virtual const String& toString() const
00548 { return name(); }
00549
00554 virtual void* getObject(const String& name) const;
00555
00561 static const char* lookupState(int state);
00562
00566 static TokenDict s_flagName[];
00567
00568 protected:
00572 enum WaitState {
00573 WaitIdle,
00574 WaitStart,
00575 WaitFeatures,
00576 WaitBindRsp,
00577 WaitSessionRsp,
00578 WaitTlsRsp,
00579 WaitChallenge,
00580 WaitResponse,
00581 WaitAborted,
00582 };
00583
00592 JBStream(JBEngine* engine, int type, XMPPServerInfo& info,
00593 const JabberID& localJid, const JabberID& remoteJid);
00594
00598 inline JBStream()
00599 : m_socket(0,0,0,0)
00600 {}
00601
00605 virtual void destroyed();
00606
00615 virtual bool checkDestination(XMLElement* xml, bool& respond);
00616
00621 virtual XMLElement* getStreamStart();
00622
00627 virtual XMLElement* getAuthStart();
00628
00633 virtual void processRunning(XMLElement* xml);
00634
00639 virtual void processRegister(XMLElement* xml);
00640
00645 virtual void processAuth(XMLElement* xml);
00646
00652 virtual void processSecuring(XMLElement* xml);
00653
00658 virtual void processStarted(XMLElement* xml);
00659
00663 virtual void streamRunning()
00664 {}
00665
00673 JBEvent* getIqEvent(XMLElement* xml, int iqType, XMPPError::Type& error);
00674
00679 bool sendStreamStart();
00680
00687 bool sendStreamXML(XMLElement* e, State newState);
00688
00695 void invalidStreamXML(XMLElement* xml, XMPPError::Type error, const char* reason);
00696
00701 void errorStreamXML(XMLElement* xml);
00702
00708 void dropXML(XMLElement* xml, bool unexpected = true);
00709
00714 void changeState(State newState);
00715
00723 bool getStreamFeatures(XMLElement* features);
00724
00729 bool startTls();
00730
00736 bool startRegister();
00737
00743 bool startAuth();
00744
00752 bool sendAuthResponse(XMLElement* challenge = 0);
00753
00761 void buildSaslResponse(String& response, String* realm = 0,
00762 String* nonce = 0);
00763
00768 void setClientAuthMechanism();
00769
00776 void buildDigestMD5Sasl(String& dest, bool authenticate = true);
00777
00782 void setRecvCount(int value);
00783
00789 bool startIdleTimer(u_int64_t time = Time::msecNow());
00790
00795 inline JBEvent* lastEvent() {
00796 ObjList* o = m_events.last();
00797 return o ? static_cast<JBEvent*>(o->get()) : 0;
00798 }
00799
00803 String m_name;
00804
00808 String m_password;
00809
00813 JIDFeatureList m_localFeatures;
00814
00818 JIDFeatureList m_remoteFeatures;
00819
00823 int m_flags;
00824
00828 unsigned int m_challengeCount;
00829
00833 WaitState m_waitState;
00834
00838 JIDFeatureSasl::Mechanism m_authMech;
00839
00843 ObjList m_events;
00844
00848 bool m_register;
00849
00850 private:
00851
00852
00853 void eventTerminated(const JBEvent* event);
00854
00855
00856
00857 Error sendPending();
00858
00859
00860
00861 void removePending(bool notify, const String* id, bool force);
00862
00863
00864 void resetStream();
00865
00866 int m_type;
00867 State m_state;
00868 bool m_outgoing;
00869 unsigned int m_restart;
00870 unsigned int m_restartMax;
00871 u_int64_t m_timeToFillRestart;
00872 u_int64_t m_setupTimeout;
00873 u_int64_t m_idleTimeout;
00874 String m_id;
00875 JabberID m_local;
00876 JabberID m_remote;
00877 JBEngine* m_engine;
00878 JBSocket m_socket;
00879 XMLParser m_parser;
00880 ObjList m_outXML;
00881 JBEvent* m_lastEvent;
00882 JBEvent* m_terminateEvent;
00883 JBEvent* m_startEvent;
00884 int m_recvCount;
00885 XMLElementOut* m_streamXML;
00886 unsigned int m_declarationSent;
00887
00888 unsigned int m_nonceCount;
00889 String m_nc;
00890 String m_nonce;
00891 String m_cnonce;
00892 String m_realm;
00893
00894 unsigned int m_registerId;
00895 };
00896
00901 class YJINGLE_API JBComponentStream : public JBStream
00902 {
00903 friend class JBEngine;
00904 public:
00908 virtual ~JBComponentStream()
00909 {}
00910
00916 virtual void* getObject(const String& name) const;
00917
00918 protected:
00926 JBComponentStream(JBEngine* engine, XMPPServerInfo& info,
00927 const JabberID& localJid, const JabberID& remoteJid);
00928
00933 virtual XMLElement* getStreamStart();
00934
00939 virtual XMLElement* getAuthStart();
00940
00945 virtual void processAuth(XMLElement* xml);
00946
00951 virtual void processStarted(XMLElement* xml);
00952
00953 private:
00954
00955 JBComponentStream() {}
00956 };
00957
00962 class YJINGLE_API JBClientStream : public JBStream
00963 {
00964 friend class JBEngine;
00965 public:
00969 virtual ~JBClientStream();
00970
00975 inline XMPPUserRoster* roster()
00976 { return m_roster; }
00977
00982 inline JIDResource* getResource()
00983 { return m_resource; }
00984
00990 virtual void* getObject(const String& name) const;
00991
00997 XMPPUser* getRemote(const JabberID& jid);
00998
01005 virtual Error sendStanza(XMLElement* stanza, const char* senderId = 0);
01006
01007 protected:
01015 JBClientStream(JBEngine* engine, XMPPServerInfo& info, const JabberID& jid,
01016 const NamedList& params);
01017
01030 JBClientStream(JBEngine* engine, const JabberID& jid,
01031 const String& password, const SocketAddr& address,
01032 bool autoRestart, unsigned int maxRestart, u_int64_t incRestartInterval,
01033 bool allowPlainAuth = false, bool outgoing = true);
01034
01038 virtual void streamRunning();
01039
01044 virtual void processRunning(XMLElement* xml);
01045
01053 virtual bool checkDestination(XMLElement* xml, bool& respond);
01054
01055 private:
01056
01057 JBClientStream() {}
01058
01059 XMPPUserRoster* m_roster;
01060 JIDResource* m_resource;
01061 String m_rosterReqId;
01062 };
01063
01064
01069 class YJINGLE_API JBThread : public GenObject
01070 {
01071 public:
01075 enum Type {
01076 StreamConnect,
01077 EngineReceive,
01078 EngineProcess,
01079
01080 Presence,
01081 Jingle,
01082 Message
01083 };
01084
01088 virtual ~JBThread();
01089
01094 inline Type type() const
01095 { return m_type; }
01096
01102 virtual void cancelThread(bool hard = false) = 0;
01103
01113 static bool start(Type type, JBThreadList* list, void* client, int sleep = 0, int prio = Thread::Normal);
01114
01115 protected:
01123 JBThread(Type type, JBThreadList* owner, void* client, int sleep = 2);
01124
01128 void runClient();
01129
01134 inline void* client()
01135 { return m_client; }
01136
01137 private:
01138 Type m_type;
01139 JBThreadList* m_owner;
01140 void* m_client;
01141 int m_sleep;
01142 };
01143
01144
01149 class YJINGLE_API JBThreadList
01150 {
01151 friend class JBThread;
01152 public:
01157 inline DebugEnabler* owner() const
01158 { return m_owner; }
01159
01166 void cancelThreads(bool wait = true, bool hard = false);
01167
01168 protected:
01173 JBThreadList(DebugEnabler* owner = 0)
01174 : m_mutex(true,"JBThreadList"),
01175 m_owner(owner), m_cancelling(false)
01176 { m_threads.setDelete(false); }
01177
01182 inline void setOwner(DebugEnabler* dbg)
01183 { m_owner = dbg; }
01184
01185 private:
01186 Mutex m_mutex;
01187 DebugEnabler* m_owner;
01188 ObjList m_threads;
01189 bool m_cancelling;
01190 };
01191
01192
01197 class YJINGLE_API JBEngine : public DebugEnabler, public Mutex,
01198 public GenObject, public JBThreadList
01199 {
01200 friend class JBStream;
01201 public:
01205 enum Protocol {
01206 Component = 1,
01207 Client = 2,
01208 };
01209
01213 enum Service {
01214 ServiceJingle = 0,
01215 ServiceIq = 1,
01216 ServiceMessage = 2,
01217 ServicePresence = 3,
01218 ServiceCommand = 4,
01219 ServiceDisco = 5,
01220 ServiceStream = 6,
01221 ServiceWriteFail = 7,
01222 ServiceRoster = 8,
01223 ServiceCount = 9
01224 };
01225
01230 JBEngine(Protocol proto);
01231
01235 virtual ~JBEngine();
01236
01241 inline Protocol protocol() const
01242 { return m_protocol; }
01243
01248 inline const JabberID& componentServer() const
01249 { return m_componentDomain; }
01250
01255 inline void setAlternateDomain(const char* domain = 0)
01256 { m_alternateDomain = domain; }
01257
01262 inline const JabberID& getAlternateDomain() const
01263 { return m_alternateDomain; }
01264
01269 inline const String& defaultResource() const
01270 { return m_defaultResource; }
01271
01276 inline const ObjList& streams() const
01277 { return m_streams; }
01278
01282 virtual void destruct();
01283
01288 virtual void initialize(const NamedList& params);
01289
01293 void cleanup();
01294
01301 void setComponentServer(const char* domain);
01302
01308 JBStream* findStream(const String& name);
01309
01320 JBStream* getStream(const JabberID* jid = 0, bool create = true);
01321
01328 bool getStream(JBStream*& stream, bool& release);
01329
01335 JBClientStream* createClientStream(NamedList& params);
01336
01342 bool receive();
01343
01350 bool process(u_int64_t time);
01351
01357 bool checkDupId(const JBStream* stream);
01358
01365 bool checkComponentFrom(JBComponentStream* stream, const char* from);
01366
01371 virtual void connect(JBStream* stream);
01372
01377 virtual bool exiting() const
01378 { return false; }
01379
01385 virtual bool encryptStream(JBStream* stream);
01386
01392 void appendServer(XMPPServerInfo* server, bool open);
01393
01403 bool getServerIdentity(String& destination, bool full, const char* token = 0,
01404 bool domain = true);
01405
01413 XMPPServerInfo* findServerInfo(const char* token, bool domain);
01414
01423 void attachService(JBService* service, Service type, int prio = -1);
01424
01430 void detachService(JBService* service);
01431
01438 void printXml(const XMLElement& xml, const JBStream* stream, bool send) const;
01439
01444 inline static const char* lookupProto(int proto, const char* def = 0)
01445 { return lookup(proto,s_protoName,def); }
01446
01451 inline static int lookupProto(const char* proto, int def = 0)
01452 { return lookup(proto,s_protoName,def); }
01453
01454 private:
01455
01456 bool processDisco(JBEvent* event);
01457
01458 bool processCommand(JBEvent* event);
01459
01460 bool received(Service service, JBEvent* event);
01461 static TokenDict s_protoName[];
01462
01463 Protocol m_protocol;
01464 u_int32_t m_restartUpdateInterval;
01465 u_int32_t m_restartCount;
01466 u_int64_t m_streamSetupInterval;
01467 u_int64_t m_streamIdleInterval;
01468 int m_printXml;
01469 ObjList m_streams;
01470 JIDIdentity* m_identity;
01471 JIDFeatureList m_features;
01472 JabberID m_componentDomain;
01473 String m_componentAddr;
01474 int m_componentCheckFrom;
01475
01476 JabberID m_alternateDomain;
01477 String m_defaultResource;
01478 Mutex m_serverMutex;
01479 ObjList m_server;
01480 Mutex m_servicesMutex;
01481 ObjList m_services[ServiceCount];
01482 bool m_initialized;
01483 };
01484
01485
01491 class YJINGLE_API JBService : public DebugEnabler, public Mutex, public GenObject
01492 {
01493 public:
01501 JBService(JBEngine* engine, const char* name, const NamedList* params, int prio);
01502
01506 virtual ~JBService();
01507
01512 inline JBEngine* engine()
01513 { return m_engine; }
01514
01519 inline int priority() const
01520 { return m_priority; }
01521
01530 bool received(JBEvent* event);
01531
01536 virtual void initialize(const NamedList& params)
01537 {}
01538
01542 virtual void destruct();
01543
01544 protected:
01553 virtual bool accept(JBEvent* event, bool& processed, bool& insert);
01554
01559 JBEvent* deque();
01560
01564 bool m_initialized;
01565
01566 private:
01567 inline JBService() {}
01568 JBEngine* m_engine;
01569 int m_priority;
01570 ObjList m_events;
01571 };
01572
01573
01578 class YJINGLE_API JBMessage : public JBService, public JBThreadList
01579 {
01580 public:
01584 enum MsgType {
01585 Chat,
01586 GroupChat,
01587 HeadLine,
01588 Normal,
01589 Error,
01590 None,
01591 };
01592
01599 inline JBMessage(JBEngine* engine, const NamedList* params, int prio = 0)
01600 : JBService(engine,"jbmsgrecv",params,prio), m_syncProcess(true)
01601 { JBThreadList::setOwner(this); }
01602
01606 virtual ~JBMessage()
01607 { cancelThreads(); }
01608
01613 virtual void initialize(const NamedList& params);
01614
01619 inline JBEvent* getMessage()
01620 { return deque(); }
01621
01627 virtual void processMessage(JBEvent* event);
01628
01638 static XMLElement* createMessage(const char* type, const char* from,
01639 const char* to, const char* id, const char* message);
01640
01650 static inline XMLElement* createMessage(MsgType type, const char* from,
01651 const char* to, const char* id, const char* message)
01652 { return createMessage(lookup(type,s_msg,""),from,to,id,message); }
01653
01659 static inline MsgType msgType(const char* text)
01660 { return (MsgType)lookup(text,s_msg,None); }
01661
01667 static inline const char* msgText(MsgType msg)
01668 { return lookup(msg,s_msg,0); }
01669
01673 static TokenDict s_msg[];
01674
01675 protected:
01683 virtual bool accept(JBEvent* event, bool& processed, bool& insert);
01684
01685 private:
01686 bool m_syncProcess;
01687 };
01688
01689
01695 class YJINGLE_API JBPresence : public JBService, public JBThreadList
01696 {
01697 friend class XMPPUserRoster;
01698 public:
01702 enum Presence {
01703 Error = 0,
01704 Probe = 1,
01705 Subscribe = 2,
01706 Subscribed = 3,
01707 Unavailable = 4,
01708 Unsubscribe = 5,
01709 Unsubscribed = 6,
01710 None = 7,
01711 };
01712
01719 JBPresence(JBEngine* engine, const NamedList* params, int prio = 0);
01720
01724 virtual ~JBPresence();
01725
01730 inline XMPPDirVal autoSubscribe() const
01731 { return m_autoSubscribe; }
01732
01737 inline bool delUnavailable() const
01738 { return m_delUnavailable; }
01739
01744 inline XMPPDirVal addOnSubscribe() const
01745 { return m_addOnSubscribe; }
01746
01751 inline XMPPDirVal addOnProbe() const
01752 { return m_addOnProbe; }
01753
01758 inline XMPPDirVal addOnPresence() const
01759 { return m_addOnPresence; }
01760
01765 inline bool autoRoster() const
01766 { return m_autoRoster; }
01767
01772 inline bool ignoreNonRoster() const
01773 { return m_ignoreNonRoster; }
01774
01779 inline u_int32_t probeInterval()
01780 { return m_probeInterval; }
01781
01786 inline u_int32_t expireInterval()
01787 { return m_expireInterval; }
01788
01793 virtual void initialize(const NamedList& params);
01794
01800 virtual bool process();
01801
01807 virtual void checkTimeout(u_int64_t time);
01808
01813 virtual void processDisco(JBEvent* event);
01814
01819 virtual void processError(JBEvent* event);
01820
01825 virtual void processProbe(JBEvent* event);
01826
01832 virtual void processSubscribe(JBEvent* event, Presence presence);
01833
01838 virtual void processUnavailable(JBEvent* event);
01839
01844 virtual void processPresence(JBEvent* event);
01845
01851 virtual bool notifyProbe(JBEvent* event);
01852
01859 virtual bool notifySubscribe(JBEvent* event, Presence presence);
01860
01866 virtual void notifySubscribe(XMPPUser* user, Presence presence);
01867
01875 virtual bool notifyPresence(JBEvent* event, bool available);
01876
01882 virtual void notifyPresence(XMPPUser* user, JIDResource* resource);
01883
01889 virtual void notifyNewUser(XMPPUser* user);
01890
01899 XMPPUserRoster* getRoster(const JabberID& jid, bool add, bool* added);
01900
01912 XMPPUser* getRemoteUser(const JabberID& local, const JabberID& remote,
01913 bool addLocal, bool* addedLocal, bool addRemote, bool* addedRemote);
01914
01921 void removeRemoteUser(const JabberID& local, const JabberID& remote);
01922
01928 bool validDomain(const String& domain);
01929
01938 bool sendStanza(XMLElement* element, JBStream* stream);
01939
01947 static XMLElement* createPresence(const char* from,
01948 const char* to, Presence type = None);
01949
01958 static bool decodeError(const XMLElement* element,
01959 String& code, String& type, String& error);
01960
01966 static inline Presence presenceType(const char* text)
01967 { return (Presence)lookup(text,s_presence,None); }
01968
01974 static inline const char* presenceText(Presence presence)
01975 { return lookup(presence,s_presence,0); }
01976
01980 void cleanup();
01981
01982 protected:
01990 virtual bool accept(JBEvent* event, bool& processed, bool& insert);
01991
01992 static TokenDict s_presence[];
01993 XMPPDirVal m_autoSubscribe;
01994 bool m_delUnavailable;
01995 bool m_autoRoster;
01996 bool m_ignoreNonRoster;
01997 XMPPDirVal m_addOnSubscribe;
01998 XMPPDirVal m_addOnProbe;
01999 XMPPDirVal m_addOnPresence;
02000 bool m_autoProbe;
02001 u_int32_t m_probeInterval;
02002 u_int32_t m_expireInterval;
02003 ObjList m_rosters;
02004 JIDIdentity* m_defIdentity;
02005 JIDFeatureList m_defFeatures;
02006
02007 private:
02008
02009
02010 XMPPUser* recvGetRemoteUser(const char* type, const JabberID& local, const JabberID& remote,
02011 bool addLocal = false, bool* addedLocal = 0,
02012 bool addRemote = false, bool* addedRemote = 0);
02013 void addRoster(XMPPUserRoster* ur);
02014 void removeRoster(XMPPUserRoster* ur);
02015 };
02016
02017
02022 class YJINGLE_API JIDResource : public RefObject
02023 {
02024 public:
02028 enum Capability {
02029 CapChat = 1,
02030 CapAudio = 2,
02031 };
02032
02036 enum Presence {
02037 Unknown = 0,
02038 Available = 1,
02039 Unavailable = 2,
02040 };
02041
02045 enum Show {
02046 ShowAway,
02047 ShowChat,
02048 ShowDND,
02049 ShowXA,
02050 ShowNone,
02051 };
02052
02060 inline JIDResource(const char* name, Presence presence = Unknown,
02061 u_int32_t capability = CapChat, int prio = 0)
02062 : m_name(name), m_presence(presence), m_priority(prio),
02063 m_capability(capability), m_show(ShowNone)
02064 {}
02065
02069 inline virtual ~JIDResource()
02070 {}
02071
02076 inline const String& name() const
02077 { return m_name; }
02078
02083 inline void setName(const char* name)
02084 { m_name = name; }
02085
02090 inline Presence presence() const
02091 { return m_presence; }
02092
02097 inline bool available() const
02098 { return (m_presence == Available); }
02099
02104 inline Show show() const
02105 { return m_show; }
02106
02111 inline void show(Show s)
02112 { m_show = s; }
02113
02118 inline const String& status() const
02119 { return m_status; }
02120
02125 inline void status(const char* s)
02126 { m_status = s; }
02127
02132 inline int priority()
02133 { return m_priority; }
02134
02139 inline void priority(int value)
02140 { m_priority = value; }
02141
02146 inline JIDFeatureList& features()
02147 { return m_features; }
02148
02153 inline ObjList* infoXml()
02154 { return &m_info; }
02155
02161 bool setPresence(bool value);
02162
02168 inline bool hasCap(Capability capability) const
02169 { return (m_capability & capability) != 0; }
02170
02176 bool fromXML(XMLElement* element);
02177
02183 void addTo(XMLElement* element, bool addInfo = true);
02184
02190 static const char* getShow(XMLElement* element);
02191
02197 static const char* getStatus(XMLElement* element);
02198
02204 static inline Show showType(const char* text)
02205 { return (Show)lookup(text,s_show,ShowNone); }
02206
02212 static inline const char* showText(Show show)
02213 { return lookup(show,s_show,0); }
02214
02215 protected:
02216 static TokenDict s_show[];
02217
02218 private:
02219 String m_name;
02220 Presence m_presence;
02221 int m_priority;
02222 u_int32_t m_capability;
02223 Show m_show;
02224 String m_status;
02225 JIDFeatureList m_features;
02226 ObjList m_info;
02227 };
02228
02229
02234 class YJINGLE_API JIDResourceList : public Mutex
02235 {
02236 friend class XMPPUser;
02237 friend class JBPresence;
02238 public:
02242 inline JIDResourceList()
02243 : Mutex(true,"JIDResourceList")
02244 {}
02245
02252 inline bool add(const String& name)
02253 { return add(new JIDResource(name)); }
02254
02261 bool add(JIDResource* resource);
02262
02268 inline void remove(JIDResource* resource, bool del = true)
02269 { Lock lock(this); m_resources.remove(resource,del); }
02270
02274 inline void clear()
02275 { Lock lock(this); m_resources.clear(); }
02276
02282 JIDResource* get(const String& name);
02283
02288 inline JIDResource* getFirst() {
02289 Lock lock(this);
02290 ObjList* obj = m_resources.skipNull();
02291 return obj ? static_cast<JIDResource*>(obj->get()) : 0;
02292 }
02293
02299 JIDResource* getAudio(bool availableOnly = true);
02300
02301 private:
02302 ObjList m_resources;
02303 };
02304
02305
02310 class YJINGLE_API XMPPUser : public RefObject, public Mutex
02311 {
02312 friend class XMPPUserRoster;
02313 friend class JBPresence;
02314 public:
02324 XMPPUser(XMPPUserRoster* local, const char* node, const char* domain,
02325 XMPPDirVal sub, bool subTo = true, bool sendProbe = true);
02326
02331 virtual ~XMPPUser();
02332
02337 inline const JabberID& jid() const
02338 { return m_jid; }
02339
02344 inline XMPPUserRoster* local() const
02345 { return m_local; }
02346
02351 inline XMPPDirVal& subscription()
02352 { return m_subscription; }
02353
02358 inline JIDResourceList& localRes()
02359 { return m_localRes; }
02360
02365 inline JIDResourceList& remoteRes()
02366 { return m_remoteRes; }
02367
02376 bool addLocalRes(JIDResource* resource, bool send = true);
02377
02384 void removeLocalRes(JIDResource* resource);
02385
02391 void clearLocalRes();
02392
02398 bool addRemoteRes(JIDResource* resource);
02399
02404 void removeRemoteRes(JIDResource* resource);
02405
02412 inline JIDResource* getAudio(bool local, bool availableOnly = true) {
02413 return local ? m_localRes.getAudio(availableOnly) :
02414 m_remoteRes.getAudio(availableOnly);
02415 }
02416
02422 void processError(JBEvent* event);
02423
02430 void processProbe(JBEvent* event, const String* resName = 0);
02431
02439 bool processPresence(JBEvent* event, bool available);
02440
02447 void processSubscribe(JBEvent* event, JBPresence::Presence type);
02448
02456 bool probe(JBStream* stream, u_int64_t time = Time::msecNow());
02457
02465 bool sendSubscribe(JBPresence::Presence type, JBStream* stream);
02466
02473 bool sendUnavailable(JBStream* stream);
02474
02483 bool sendPresence(JIDResource* resource, JBStream* stream = 0, bool force = false);
02484
02491 bool timeout(u_int64_t time);
02492
02502 void notifyResource(bool remote, const String& name,
02503 JBStream* stream = 0, bool force = false);
02504
02513 void notifyResources(bool remote, JBStream* stream = 0, bool force = false);
02514
02515 protected:
02522 void updateSubscription(bool from, bool value, JBStream* stream);
02523
02529 void updateTimeout(bool from, u_int64_t time = Time::msecNow());
02530
02531 private:
02532 XMPPUserRoster* m_local;
02533 JabberID m_jid;
02534 XMPPDirVal m_subscription;
02535 JIDResourceList m_localRes;
02536 JIDResourceList m_remoteRes;
02537 u_int64_t m_nextProbe;
02538 u_int64_t m_expire;
02539 };
02540
02545 class YJINGLE_API XMPPUserRoster : public RefObject, public Mutex
02546 {
02547 friend class JBPresence;
02548 friend class JBClientStream;
02549 friend class XMPPUser;
02550 public:
02555 virtual ~XMPPUserRoster();
02556
02561 const JabberID& jid() const
02562 { return m_jid; }
02563
02568 JBPresence* engine()
02569 { return m_engine; }
02570
02575 inline JIDResourceList& resources()
02576 { return m_resources; }
02577
02582 inline ObjList& users()
02583 { return m_remote; }
02584
02593 XMPPUser* getUser(const JabberID& jid, bool add = false, bool* added = 0);
02594
02601 bool removeUser(const JabberID& remote);
02602
02606 inline void cleanup() {
02607 Lock lock(this);
02608 m_remote.clear();
02609 }
02610
02617 bool timeout(u_int64_t time);
02618
02626 inline XMLElement* createDiscoInfoResult(const char* from, const char* to,
02627 const char* id)
02628 { return XMPPUtils::createDiscoInfoRes(from,to,id,&m_features,m_identity); }
02629
02630 protected:
02638 XMPPUserRoster(JBPresence* engine, const char* node, const char* domain,
02639 JBEngine::Protocol proto = JBEngine::Component);
02640
02641 private:
02642 inline void addUser(XMPPUser* u) {
02643 Lock lock(this);
02644 m_remote.append(u);
02645 }
02646 void removeUser(XMPPUser* u) {
02647 Lock lock(this);
02648 m_remote.remove(u,false);
02649 }
02650
02651 JabberID m_jid;
02652 JIDFeatureList m_features;
02653 JIDIdentity* m_identity;
02654 ObjList m_remote;
02655 JIDResourceList m_resources;
02656 JBPresence* m_engine;
02657 };
02658
02659 };
02660
02661 #endif
02662
02663