Yate
|
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; // A Jabber event 00036 class JBStream; // A Jabber stream 00037 class JBComponentStream; // A Jabber Component stream 00038 class JBClientStream; // A Jabber client to server stream 00039 class JBThread; // Base class for private threads 00040 class JBThreadList; // A list of threads 00041 class JBEngine; // A Jabber engine 00042 class JBService; // A Jabber service 00043 class JBPresence; // A Jabber presence service 00044 class JIDResource; // A JID resource 00045 class JIDResourceList; // Resource list 00046 class XMPPUser; // An XMPP user (JID, resources, capabilities etc) 00047 class XMPPUserRoster; // An XMPP user's roster 00048 00054 class YJINGLE_API JBEvent : public RefObject 00055 { 00056 friend class JBStream; 00057 friend class JBClientStream; 00058 public: 00062 enum Type { 00063 // Stream events 00064 Terminated = 1, // Stream terminated. Try to connect 00065 Destroy = 2, // Stream is destroying 00066 Running = 3, // Stream is running (stable state: can send/recv stanzas) 00067 // Result events 00068 WriteFail = 10, // Write failed. m_element is the element, m_id is the id set by the sender 00069 // Stanza events: m_element is always valid 00070 Presence = 20, // m_element is a 'presence' stanza 00071 Message = 30, // m_element is a 'message' stanza 00072 Iq = 50, // m_element is an 'iq' set/get, m_child is it's first child 00073 IqError = 51, // m_element is an 'iq' error, m_child is the 'iq' child if any 00074 IqResult = 52, // m_element is an 'iq' result, m_child is it's first child if any 00075 // Disco: m_child is a 'query' element qualified by DiscoInfo/DiscoItems namespaces 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 // Command: m_child is a 'command' element qualified by Command namespace 00085 IqCommandGet = 70, 00086 IqCommandSet = 71, 00087 IqCommandRes = 72, 00088 IqCommandErr = 73, 00089 // Jingle: m_child is a 'jingle' element qualified by Jingle namespace 00090 IqJingleGet = 80, 00091 IqJingleSet = 81, 00092 IqJingleRes = 82, 00093 IqJingleErr = 83, 00094 // Roster: m_child is a 'query' element qualified by Roster namespace 00095 IqRosterSet = 91, 00096 IqRosterRes = 92, 00097 IqRosterErr = 93, 00098 // Roster update (set or result) received by client streams: m_child is a 'query' element 00099 // qualified by Roster namespace 00100 IqClientRosterUpdate = 150, 00101 // Invalid 00102 Unhandled = 200, // m_element is an unhandled element 00103 Invalid = 500, // m_element is 0 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[]; // Event names 00241 JBEvent() {} // Don't use it! 00242 bool init(JBStream* stream, XMLElement* element); 00243 00244 Type m_type; // Type of this event 00245 JBStream* m_stream; // The stream that generated this event 00246 bool m_link; // Stream link state 00247 XMLElement* m_element; // Received XML element, if any 00248 XMLElement* m_child; // The first child element for 'iq' elements 00249 String m_stanzaType; // Stanza's 'type' attribute 00250 JabberID m_from; // Stanza's 'from' attribute 00251 JabberID m_to; // Stanza's 'to' attribute 00252 String m_id; // Sender's id for Write... events 00253 // 'id' attribute if the received stanza has one 00254 String m_text; // The stanza's text or termination reason for 00255 // Terminated/Destroy events 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; // The Jabber engine 00338 JBStream* m_stream; // Stream owning this socket 00339 Socket* m_socket; // The socket 00340 String m_remoteDomain; // Remote domain used to resolve before connecting 00341 SocketAddr m_address; // Remote address 00342 Mutex m_streamMutex; // Lock stream 00343 Mutex m_receiveMutex; // Lock receive 00344 String m_error; // Keep error string from send/receive/connect 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, // Stream is waiting to be connected or destroyed 00362 Connecting = 1, // Stream is waiting for the socket to connect 00363 Started = 2, // Stream start tag sent 00364 Securing = 3, // Stream is currently negotiating the TLS 00365 Register = 4, // A new user is currently registering 00366 Auth = 5, // Stream is currently authenticating 00367 Running = 6, // Established. Allow XML stanzas to pass over the stream 00368 Destroy = 7, // Stream is destroying. No more traffic allowed 00369 }; 00370 00374 enum Error { 00375 ErrorNone = 0, // No error (stanza enqueued/sent) 00376 ErrorContext, // Invalid stream context (state) or parameters 00377 ErrorPending, // The operation is pending in the stream's queue 00378 ErrorNoSocket, // Unrecoverable socket error. The stream will be terminated 00379 }; 00380 00384 enum Flags { 00385 AutoRestart = 0x0001, // Auto restart stream when down 00386 AllowPlainAuth = 0x0002, // Allow plain password authentication 00387 // If not allowed and this is the only method 00388 // offered by server the stream will be terminated 00389 NoVersion1 = 0x0004, // Don't support RFC 3920 TLS/SASL ... 00390 UseTls = 0x0008, // Use TLS if offered. Internally set if the remote server 00391 // always require encryption 00392 UseSasl = 0x0010, // Use SASL as authentication mechanism (RFC 3920) 00393 // If not set, the deprecated XEP-0078 will be used for authentication 00394 AllowUnsafeSetup = 0x0020, // Allow in-band user account setup on unsecured streams 00395 StreamSecured = 0x0100, // Stream already secured 00396 StreamAuthenticated = 0x0200, // Stream already authenticated 00397 NoRemoteVersion1 = 0x0400, // Remote doesn't support RFC 3920 TLS/SASL ... 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 { // Main state Wait 00573 WaitIdle, // Idle nothing 00574 WaitStart, // Started stream start response 00575 WaitFeatures, // Started stream features 00576 WaitBindRsp, // Started wait for bind response 00577 WaitSessionRsp, // Started wait for session response 00578 WaitTlsRsp, // Started wait response to starttls 00579 WaitChallenge, // Auth iq auth query with auth data sent, wait response 00580 WaitResponse, // Auth iq auth query sent, wait response 00581 WaitAborted, // Auth abort sent, wait confirmation to terminate stream 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 // Event termination notification 00852 // @param event The notifier. Ignored if it's not m_lastEvent 00853 void eventTerminated(const JBEvent* event); 00854 // Try sending pending stream element if any 00855 // Try to send the first element in pending outgoing stanzas list 00856 // If ErrorNoSocket is returned, stream termination was initiated 00857 Error sendPending(); 00858 // Remove pending elements with id if id is not 0 00859 // Remove all elements without id if id is 0 00860 // Set force to true to remove the first element even if partially sent 00861 void removePending(bool notify, const String* id, bool force); 00862 // Called when a setup state was completed 00863 // Set/reset some stream flags and data 00864 void resetStream(); 00865 00866 int m_type; // Stream type 00867 State m_state; // Stream state 00868 bool m_outgoing; // Stream direction 00869 unsigned int m_restart; // Remaining restart attempts 00870 unsigned int m_restartMax; // Max restart attempts 00871 u_int64_t m_timeToFillRestart; // Next time to increase the restart counter 00872 u_int64_t m_setupTimeout; // Stream setup timeout (interval allowed between Idle and Running states) 00873 u_int64_t m_idleTimeout; // Connection idle in state Running (send keep alive packet) 00874 String m_id; // Stream id 00875 JabberID m_local; // Local peer's jid 00876 JabberID m_remote; // Remote peer's jid 00877 JBEngine* m_engine; // The owner of this stream 00878 JBSocket m_socket; // The socket used by this stream 00879 XMLParser m_parser; // XML parser 00880 ObjList m_outXML; // Outgoing XML elements 00881 JBEvent* m_lastEvent; // Last generated event 00882 JBEvent* m_terminateEvent; // Destroy/Terminate event 00883 JBEvent* m_startEvent; // Running event 00884 int m_recvCount; // The number of bytes to read: -1: all, 0: nothing 1: 1 byte 00885 XMLElementOut* m_streamXML; // Pending (incomplete) stream element 00886 unsigned int m_declarationSent; // The number of declaration bytes sent 00887 // Auth data 00888 unsigned int m_nonceCount; // Nonce count 00889 String m_nc; // Nonce count string 00890 String m_nonce; // Server nonce 00891 String m_cnonce; // Client nonce 00892 String m_realm; // Client realm 00893 // Register data 00894 unsigned int m_registerId; // Id used when registering a new account 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 // Default constructor is private to avoid unwanted use 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 // Default constructor is private to avoid unwanted use 01057 JBClientStream() {} 01058 01059 XMPPUserRoster* m_roster; // Client's roster 01060 JIDResource* m_resource; // Client's resource 01061 String m_rosterReqId; // Roster request id 01062 }; 01063 01064 01069 class YJINGLE_API JBThread : public GenObject 01070 { 01071 public: 01075 enum Type { 01076 StreamConnect, // Asynchronously connect a stream's socket 01077 EngineReceive, // Read all streams sockets 01078 EngineProcess, // Get events from sockets and send them to 01079 // registered services 01080 Presence, // Presence service processor 01081 Jingle, // Jingle service processor 01082 Message // Message service processor 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; // Thread type 01139 JBThreadList* m_owner; // List owning this thread 01140 void* m_client; // The client to process 01141 int m_sleep; // Time to sleep if there is nothing to do 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; // Lock list operations 01187 DebugEnabler* m_owner; // The owner of this list 01188 ObjList m_threads; // Private threads list 01189 bool m_cancelling; // Cancelling threads operation in progress 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, // Use Jabber Component protocol 01207 Client = 2, // Use client streams 01208 }; 01209 01213 enum Service { 01214 ServiceJingle = 0, // Receive Jingle events 01215 ServiceIq = 1, // Receive generic Iq events 01216 ServiceMessage = 2, // Receive Message events 01217 ServicePresence = 3, // Receive Presence events 01218 ServiceCommand = 4, // Receive Command events 01219 ServiceDisco = 5, // Receive Disco events 01220 ServiceStream = 6, // Receive stream Terminated or Destroy events 01221 ServiceWriteFail = 7, // Receive WriteFail events 01222 ServiceRoster = 8, // Receive roster events 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 // Process a Disco... events 01456 bool processDisco(JBEvent* event); 01457 // Process a Command events 01458 bool processCommand(JBEvent* event); 01459 // Pass events to services 01460 bool received(Service service, JBEvent* event); 01461 static TokenDict s_protoName[]; // Protocol names 01462 01463 Protocol m_protocol; // The protocol to use 01464 u_int32_t m_restartUpdateInterval; // Update interval for restart counter of all streams 01465 u_int32_t m_restartCount; // The default restart counter value 01466 u_int64_t m_streamSetupInterval; // Timeout for stream setup 01467 u_int64_t m_streamIdleInterval; // Timeout for stream idle (nothing sent/received in Running state) 01468 int m_printXml; // Print XML data to output 01469 ObjList m_streams; // Streams belonging to this engine 01470 JIDIdentity* m_identity; // Engine's identity 01471 JIDFeatureList m_features; // Engine's features 01472 JabberID m_componentDomain; // Default server domain name 01473 String m_componentAddr; // Default server address 01474 int m_componentCheckFrom; // The behaviour when checking the 'from' attribute for a component stream 01475 // 0: no check 1: local identity 2: remote identity 01476 JabberID m_alternateDomain; // Alternate acceptable domain 01477 String m_defaultResource; // Default name for missing resources 01478 Mutex m_serverMutex; // Lock server info list 01479 ObjList m_server; // Server info list 01480 Mutex m_servicesMutex; // Lock service list 01481 ObjList m_services[ServiceCount]; // Services list 01482 bool m_initialized; // True if already 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() {} // Don't use it ! 01568 JBEngine* m_engine; // The Jabber Component engine 01569 int m_priority; // Service priority 01570 ObjList m_events; // Events received from engine 01571 }; 01572 01573 01578 class YJINGLE_API JBMessage : public JBService, public JBThreadList 01579 { 01580 public: 01584 enum MsgType { 01585 Chat, // chat 01586 GroupChat, // groupchat 01587 HeadLine, // headline 01588 Normal, // normal 01589 Error, // 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; // Process messages on accept 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, // error 01704 Probe = 1, // probe 01705 Subscribe = 2, // subscribe request 01706 Subscribed = 3, // subscribe accepted 01707 Unavailable = 4, // unavailable 01708 Unsubscribe = 5, // unsubscribe request 01709 Unsubscribed = 6, // unsubscribe accepted 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[]; // Keep the types of 'presence' 01993 XMPPDirVal m_autoSubscribe; // Auto subscribe state 01994 bool m_delUnavailable; // Delete unavailable user or resource 01995 bool m_autoRoster; // True if this service make an automatically roster management 01996 bool m_ignoreNonRoster; // Ignore all elements whose destination is not in roster 01997 XMPPDirVal m_addOnSubscribe; // Add new user on subscribe request 01998 XMPPDirVal m_addOnProbe; // Add new user on probe request 01999 XMPPDirVal m_addOnPresence; // Add new user on presence 02000 bool m_autoProbe; // Automatically respond to probe requests 02001 u_int32_t m_probeInterval; // Interval to probe a remote user 02002 u_int32_t m_expireInterval; // Expire interval after probe 02003 ObjList m_rosters; // The rosters 02004 JIDIdentity* m_defIdentity; // Default identity 02005 JIDFeatureList m_defFeatures; // Default features 02006 02007 private: 02008 // Wrapper for getRemoteUser() used when receiving presence 02009 // Show a debug message if not found 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, // Chat capability 02030 CapAudio = 2, // Jingle capability 02031 }; 02032 02036 enum Presence { 02037 Unknown = 0, // unknown 02038 Available = 1, // available 02039 Unavailable = 2, // unavailable 02040 }; 02041 02045 enum Show { 02046 ShowAway, // away : Temporarily away 02047 ShowChat, // chat : Actively interested in chatting 02048 ShowDND, // dnd : Busy 02049 ShowXA, // xa : Extended away 02050 ShowNone, // : Missing or no text 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[]; // Show texts 02217 02218 private: 02219 String m_name; // Resource name 02220 Presence m_presence; // Resorce presence 02221 int m_priority; // Resource priority 02222 u_int32_t m_capability; // Resource capabilities 02223 Show m_show; // Show attribute 02224 String m_status; // Status attribute 02225 JIDFeatureList m_features; // Resource features 02226 ObjList m_info; // XML elements containing additional info about this resource 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; // The resources list 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; // Local user 02533 JabberID m_jid; // User's JID 02534 XMPPDirVal m_subscription; // Subscription state 02535 JIDResourceList m_localRes; // Local user's resources 02536 JIDResourceList m_remoteRes; // Remote user's resources 02537 u_int64_t m_nextProbe; // Time to probe 02538 u_int64_t m_expire; // Expire time 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; // User's bare JID 02652 JIDFeatureList m_features; // Local user's resources 02653 JIDIdentity* m_identity; // JID's identity 02654 ObjList m_remote; // Remote users 02655 JIDResourceList m_resources; // Available resources of the user 02656 JBPresence* m_engine; // Presence engine 02657 }; 02658 02659 }; 02660 02661 #endif /* __YATEJABBER_H */ 02662 02663 /* vi: set ts=8 sw=4 sts=4 noet: */