Yate

yatejabber.h

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