OPAL  Version 3.10.4
pres_ent.h
Go to the documentation of this file.
00001 /*
00002  * prese_ent.h
00003  *
00004  * Presence Entity classes for Opal
00005  *
00006  * Open Phone Abstraction Library (OPAL)
00007  *
00008  * Copyright (c) 2009 Post Increment
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Open Phone Abstraction Library.
00021  *
00022  * The Initial Developer of the Original Code is Post Increment
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Revision: 26283 $
00027  * $Author: rjongbloed $
00028  * $Date: 2011-08-08 02:41:14 -0500 (Mon, 08 Aug 2011) $
00029  */
00030 
00031 #ifndef OPAL_IM_PRES_ENT_H
00032 #define OPAL_IM_PRES_ENT_H
00033 
00034 #include <ptlib.h>
00035 #include <opal/buildopts.h>
00036 
00037 #include <ptlib/pfactory.h>
00038 #include <ptlib/safecoll.h>
00039 #include <ptclib/url.h>
00040 #include <ptclib/guid.h>
00041 #include <ptclib/vcard.h>
00042 
00043 #include <im/im.h>
00044 
00045 #include <list>
00046 #include <queue>
00047 
00048 class OpalManager;
00049 class OpalPresentityCommand;
00050 
00051 
00053 
00056 class OpalPresenceInfo : public PObject
00057 {
00058   public:
00060     enum State {
00061       InternalError = -3,    // something bad happened
00062       Forbidden     = -2,    // access to presence information was specifically forbidden
00063       NoPresence    = -1,    // remove presence status - not the same as Unavailable or Away
00064 
00065       // basic states (from RFC 3863)
00066       Unchanged,
00067       Available,
00068       Unavailable,
00069 
00070       // extended states (from RFC 4480)
00071       // if this is changed, also change the tables in sippres.cxx and handlers.cxx - look for RFC 4480
00072       ExtendedBase    = 100,
00073       UnknownExtended = ExtendedBase,
00074       Appointment,
00075       Away,
00076       Breakfast,
00077       Busy,
00078       Dinner,
00079       Holiday,
00080       InTransit,
00081       LookingForWork,
00082       Lunch,
00083       Meal,
00084       Meeting,
00085       OnThePhone,
00086       Other,
00087       Performance,
00088       PermanentAbsence,
00089       Playing,
00090       Presentation,
00091       Shopping,
00092       Sleeping,
00093       Spectator,
00094       Steering,
00095       Travel,
00096       TV,
00097       Vacation,
00098       Working,
00099       Worship
00100     };
00101 
00102     State   m_state;    
00103     PString m_note;     
00104     PURL    m_entity;   
00105     PURL    m_target;   
00106     PTime   m_when;     
00107 
00108     OpalPresenceInfo(State state = Unchanged) : m_state(state) { }
00109 
00110     static PString AsString(State state);
00111     static State FromString(const PString & str);
00112     PString AsString() const;
00113 
00114     Comparison Compare(const PObject & other) const;
00115 };
00116 
00117 ostream & operator<<(ostream & strm, OpalPresenceInfo::State state);
00118 
00120 
00121 class OpalSetLocalPresenceCommand;
00122 class OpalSubscribeToPresenceCommand;
00123 class OpalAuthorisationRequestCommand;
00124 class OpalSendMessageToCommand;
00125 
00135 class OpalPresentity : public PSafeObject
00136 {
00137     PCLASSINFO(OpalPresentity, PSafeObject);
00138 
00141   protected:
00143     OpalPresentity();
00144     OpalPresentity(const OpalPresentity & other);
00145 
00146   public:
00147     ~OpalPresentity();
00148 
00151     static OpalPresentity * Create(
00152       OpalManager & manager, 
00153       const PURL & url,      
00154       const PString & scheme = PString::Empty() 
00155     );
00157 
00169     virtual bool Open() = 0;
00170 
00173     virtual bool IsOpen() const = 0;
00174 
00177     virtual bool Close() = 0;
00179 
00182 
00183     PStringOptions & GetAttributes() { return m_attributes; }
00184 
00186     virtual PStringArray GetAttributeNames() const = 0;
00187 
00189     virtual PStringArray GetAttributeTypes() const = 0;
00190 
00191     static const PCaselessString & AuthNameKey();         
00192     static const PCaselessString & AuthPasswordKey();     
00193     static const PCaselessString & TimeToLiveKey();       
00194 
00199     const PURL & GetAOR() const { return m_aor; }
00201 
00212     virtual bool SubscribeToPresence(
00213       const PURL & presentity,      
00214       bool subscribe = true,        
00215       const PString & note = PString::Empty() 
00216     );
00217 
00226     virtual bool UnsubscribeFromPresence(
00227       const PURL & presentity    
00228     );
00229 
00231     enum Authorisation {
00232       AuthorisationPermitted,
00233       AuthorisationDenied,
00234       AuthorisationDeniedPolitely,
00235       AuthorisationConfirming,
00236       AuthorisationRemove,
00237       NumAuthorisations
00238     };
00239 
00250     virtual bool SetPresenceAuthorisation(
00251       const PURL & presentity,        
00252       Authorisation authorisation     
00253     );
00254 
00262     virtual bool SetLocalPresence(
00263       OpalPresenceInfo::State state,            
00264       const PString & note = PString::Empty()   
00265     );
00266 
00269     virtual bool GetLocalPresence(
00270       OpalPresenceInfo::State & state, 
00271       PString & note
00272     );
00273 
00274 
00279     template <class cls>
00280     __inline cls * CreateCommand()
00281     {
00282       return dynamic_cast<cls *>(InternalCreateCommand(typeid(cls).name()));
00283     }
00284 
00296     virtual bool SendCommand(
00297       OpalPresentityCommand * cmd   
00298     );
00300 
00303     struct AuthorisationRequest
00304     {
00305       PURL    m_presentity; 
00306       PString m_note;       
00307     };
00308 
00316     virtual void OnAuthorisationRequest(
00317       const AuthorisationRequest & request  
00318     );
00319 
00320     typedef PNotifierTemplate<const AuthorisationRequest &> AuthorisationRequestNotifier;
00321 #define PDECLARE_AuthorisationRequestNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalPresentity, cls, fn, const OpalPresentity::AuthorisationRequest &)
00322     #define PCREATE_AuthorisationRequestNotifier(fn) PCREATE_NOTIFIER2(fn, const OpalPresentity::AuthorisationRequest &)
00323 
00325     void SetAuthorisationRequestNotifier(
00326       const AuthorisationRequestNotifier & notifier   
00327     );
00328 
00337     virtual void OnPresenceChange(
00338       const OpalPresenceInfo & info 
00339     );
00340 
00341     typedef PNotifierTemplate<const OpalPresenceInfo &> PresenceChangeNotifier;
00342     #define PDECLARE_PresenceChangeNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalPresentity, cls, fn, const OpalPresenceInfo &)
00343     #define PCREATE_PresenceChangeNotifier(fn) PCREATE_NOTIFIER2(fn, const OpalPresenceInfo &)
00344 
00346     void SetPresenceChangeNotifier(
00347       const PresenceChangeNotifier & notifier   
00348     );
00350 
00357     struct BuddyInfo {
00358       BuddyInfo(
00359         const PURL & presentity = PString::Empty(),
00360         const PString & displayName = PString::Empty()
00361       ) : m_presentity(presentity)
00362         , m_displayName(displayName)
00363       { }
00364 
00365       PURL    m_presentity;   
00366       PString m_displayName;  
00367 
00368       // RFC4482 contact fields, note most of these are duplicated
00369       // in the vCard structure
00370       PvCard  m_vCard;        
00374       PURL    m_icon;         
00378       PURL    m_map;          
00380       PURL    m_sound;        
00384       PURL    m_homePage;     
00385 
00386       // Extra field for protocol dependent "get out of gaol" card
00387       PString m_contentType;  
00388       PString m_rawXML;       
00389     };
00390 
00391     typedef std::list<BuddyInfo> BuddyList;
00392 
00393     enum BuddyStatus {
00394       BuddyStatus_GenericFailure             = -1,
00395       BuddyStatus_OK                         = 0,
00396       BuddyStatus_SpecifiedBuddyNotFound,
00397       BuddyStatus_ListFeatureNotImplemented,
00398       BuddyStatus_ListTemporarilyUnavailable,
00399       BuddyStatus_ListMayBeIncomplete,
00400       BuddyStatus_BadBuddySpecification,
00401       BuddyStatus_ListSubscribeFailed,
00402       BuddyStatus_AccountNotLoggedIn
00403     };
00404 
00407     virtual BuddyStatus GetBuddyListEx(
00408       BuddyList & buddies   
00409     );
00410     virtual bool GetBuddyList(
00411       BuddyList & buddies   
00412     )
00413     { return GetBuddyListEx(buddies) == BuddyStatus_OK; }
00414 
00417     virtual BuddyStatus SetBuddyListEx(
00418       const BuddyList & buddies   
00419     );
00420     virtual bool SetBuddyList(
00421       const BuddyList & buddies   
00422     )
00423     { return SetBuddyListEx(buddies) == BuddyStatus_OK; }
00424 
00425 
00428     virtual BuddyStatus DeleteBuddyListEx();
00429     virtual bool DeleteBuddyList() { return DeleteBuddyListEx() == BuddyStatus_OK; }
00430 
00435     virtual BuddyStatus GetBuddyEx(
00436       BuddyInfo & buddy
00437     );
00438     virtual bool GetBuddy(
00439       BuddyInfo & buddy
00440     )
00441     { return GetBuddyEx(buddy) == BuddyStatus_OK; }
00442 
00445     virtual BuddyStatus SetBuddyEx(
00446       const BuddyInfo & buddy
00447     );
00448     virtual bool SetBuddy(
00449       const BuddyInfo & buddy
00450     )
00451     { return SetBuddyEx(buddy) == BuddyStatus_OK; }
00452 
00455     virtual BuddyStatus DeleteBuddyEx(
00456       const PURL & presentity
00457     );
00458     virtual bool DeleteBuddy(
00459       const PURL & presentity
00460     )
00461     { return DeleteBuddyEx(presentity) == BuddyStatus_OK; }
00462 
00468     virtual BuddyStatus SubscribeBuddyListEx(
00469       PINDEX & successfulCount,
00470       bool subscribe = true
00471     );
00472     virtual bool SubscribeBuddyList(
00473       bool subscribe = true
00474     )
00475     { PINDEX successfulCount; return SubscribeBuddyListEx(successfulCount, subscribe) == BuddyStatus_OK; }
00476 
00482     virtual BuddyStatus UnsubscribeBuddyListEx();
00483     virtual bool UnsubscribeBuddyList()
00484     { return UnsubscribeBuddyListEx() == BuddyStatus_OK; }
00486   
00487   
00490     virtual bool SendMessageTo(
00491       const OpalIM & message
00492     );
00493 
00498     virtual void OnReceivedMessage(
00499       const OpalIM & message 
00500     );
00501 
00502     typedef PNotifierTemplate<const OpalIM &> ReceivedMessageNotifier;
00503     #define PDECLARE_ReceivedMessageNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalPresentity, cls, fn, const OpalIM &)
00504     #define PCREATE_ReceivedMessageNotifier(fn) PCREATE_NOTIFIER2(fn, const OpalIM &)
00505 
00507     void SetReceivedMessageNotifier(
00508       const ReceivedMessageNotifier & notifier   
00509     );
00511 
00516     virtual void SetAOR(
00517       const PURL & aor
00518     );
00519 
00520     void Internal_SendMessageToCommand(const OpalSendMessageToCommand & cmd);
00521 
00522     virtual PString GetID() const;
00523 
00524   protected:
00525     OpalPresentityCommand * InternalCreateCommand(const char * cmdName);
00526 
00527     OpalManager        * m_manager;
00528     PGloballyUniqueID    m_guid;
00529     PURL                 m_aor;
00530     PStringOptions       m_attributes;
00531 
00532     AuthorisationRequestNotifier m_onAuthorisationRequestNotifier;
00533     PresenceChangeNotifier       m_onPresenceChangeNotifier;
00534     ReceivedMessageNotifier      m_onReceivedMessageNotifier;
00535 
00536     PMutex m_notificationMutex;
00537     PAtomicInteger::IntegerType m_idNumber;
00538 
00539     bool m_temporarilyUnavailable;
00540     OpalPresenceInfo::State m_localState;      
00541     PString m_localStateNote;                  
00542 };
00543 
00544 
00546 
00550 class OpalPresentityWithCommandThread : public OpalPresentity
00551 {
00552     PCLASSINFO(OpalPresentityWithCommandThread, OpalPresentity);
00553 
00556   protected:
00558     OpalPresentityWithCommandThread();
00559     OpalPresentityWithCommandThread(const OpalPresentityWithCommandThread & other);
00560 
00561   public:
00565     ~OpalPresentityWithCommandThread();
00567 
00581     virtual bool SendCommand(
00582       OpalPresentityCommand * cmd   
00583     );
00585 
00598     void StartThread(
00599       bool startQueue = true
00600     );
00601 
00607     void StopThread();
00608 
00611     void StartQueue(
00612       bool startQueue = true
00613     );
00614     
00616 
00617   protected:
00618     void ThreadMain();
00619 
00620     typedef std::queue<OpalPresentityCommand *> CommandQueue;
00621     CommandQueue   m_commandQueue;
00622     PMutex         m_commandQueueMutex;
00623     PAtomicInteger m_commandSequence;
00624     PSyncPoint     m_commandQueueSync;
00625 
00626     bool      m_threadRunning;
00627     bool      m_queueRunning;
00628     PThread * m_thread;
00629 };
00630 
00632 
00635 class OpalPresentityCommand {
00636   public:
00637     OpalPresentityCommand(bool responseNeeded = false) 
00638       : m_responseNeeded(responseNeeded)
00639     { }
00640     virtual ~OpalPresentityCommand() { }
00641 
00645     virtual void Process(
00646       OpalPresentity & presentity
00647     ) = 0;
00648 
00649     typedef PAtomicInteger::IntegerType CmdSeqType;
00650     CmdSeqType m_sequence;
00651     bool       m_responseNeeded;
00652     PURL       m_presentity;
00653 };
00654 
00657 #define OPAL_DEFINE_COMMAND(command, entity, func) \
00658   class entity##_##command : public command \
00659   { \
00660     public: virtual void Process(OpalPresentity & presentity) { dynamic_cast<entity &>(presentity).func(*this); } \
00661   }; \
00662   static PFactory<OpalPresentityCommand>::Worker<entity##_##command> \
00663   s_##entity##_##command(PDefaultPFactoryKey(entity::Class())+typeid(command).name())
00664 
00665 
00668 class OpalSubscribeToPresenceCommand : public OpalPresentityCommand {
00669   public:
00670     OpalSubscribeToPresenceCommand(bool subscribe = true) : m_subscribe(subscribe) { }
00671 
00672     bool    m_subscribe;  
00673     PString m_note;       
00674 };
00675 
00676 
00683 class OpalAuthorisationRequestCommand : public OpalPresentityCommand {
00684   public:
00685     OpalAuthorisationRequestCommand() : m_authorisation(OpalPresentity::AuthorisationPermitted) { }
00686 
00687     OpalPresentity::Authorisation m_authorisation;  
00688     PString m_note;                                 
00689 };
00690 
00691 
00697 class OpalSetLocalPresenceCommand : public OpalPresentityCommand, public OpalPresenceInfo {
00698   public:
00699     OpalSetLocalPresenceCommand(State state = NoPresence) : OpalPresenceInfo(state) { }
00700 };
00701 
00702 
00705 class OpalSendMessageToCommand : public OpalPresentityCommand
00706 {
00707   public:
00708     OpalSendMessageToCommand() { }
00709 
00710     OpalIM m_message;
00711 };
00712 
00714 
00715 // Include concrete classes here so the factories are initialised
00716 #if OPAL_SIP && OPAL_PTLIB_EXPAT
00717 PFACTORY_LOAD(SIP_Presentity);
00718 #endif
00719 
00720 
00721 #endif  // OPAL_IM_PRES_ENT_H
00722