OPAL  Version 3.10.4
im.h
Go to the documentation of this file.
00001 /*
00002  * im_mf.h
00003  *
00004  * Media formats for Instant Messaging
00005  *
00006  * Open Phone Abstraction Library (OPAL)
00007  *
00008  * Copyright (c) 2008 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: 26270 $
00027  * $Author: rjongbloed $
00028  * $Date: 2011-08-03 03:29:01 -0500 (Wed, 03 Aug 2011) $
00029  */
00030 
00031 #ifndef OPAL_IM_IM_H
00032 #define OPAL_IM_IM_H
00033 
00034 #include <ptlib.h>
00035 #include <opal/buildopts.h>
00036 
00037 #include <ptclib/url.h>
00038 #include <ptclib/threadpool.h>
00039 
00040 #include <opal/transports.h>
00041 
00042 class OpalIM : public PObject
00043 {
00044   public:
00045     OpalIM();
00046 
00047     enum Type {
00048       Text,
00049       CompositionIndication_Idle,   // aka RFC 3994
00050       CompositionIndication_Active, // aka RFC 3994
00051       Disposition                   // aka RFC 5438
00052     } m_type;
00053 
00054     PURL    m_to;
00055     PURL    m_from;
00056     PString m_fromName;
00057     PString m_mimeType;
00058     PString m_body;
00059     PString m_conversationId;
00060 
00061     OpalTransportAddress m_fromAddr;
00062     OpalTransportAddress m_toAddr;
00063 
00064     PAtomicInteger::IntegerType m_messageId;
00065 
00066     static PAtomicInteger::IntegerType GetNextMessageId();
00067 };
00068 
00069 #if OPAL_HAS_IM
00070 
00071 #include <opal/mediastrm.h>
00072 #include <im/rfc4103.h>
00073 
00074 class OpalIMMediaType : public OpalMediaTypeDefinition 
00075 {
00076   public:
00077     OpalIMMediaType(
00078       const char * mediaType, 
00079       const char * sdpType    
00080     )
00081       : OpalMediaTypeDefinition(mediaType, sdpType, 0, OpalMediaType::DontOffer)
00082     { }
00083 
00084     PString GetRTPEncoding() const { return PString::Empty(); }
00085     RTP_UDP * CreateRTPSession(OpalRTPConnection & , unsigned , bool ) { return NULL; }
00086     virtual bool UsesRTP() const { return false; }
00087 };
00088 
00090 
00091 class OpalIMManager;
00092 class OpalPresentity;
00093 
00094 class OpalIMContext : public PSafeObject
00095 {
00096   PCLASSINFO(OpalIMContext, PSafeObject);
00097 
00098   public:
00099     friend class OpalIMManager;
00100 
00101     OpalIMContext();
00102     ~OpalIMContext();
00103 
00104     static PSafePtr<OpalIMContext> Create(
00105       OpalManager & manager, 
00106       const PURL & localURL, 
00107       const PURL & remoteURL
00108     );
00109 
00110     static PSafePtr<OpalIMContext> Create(
00111       OpalManager & manager,
00112       PSafePtr<OpalConnection> conn
00113     );
00114 
00115     static PSafePtr<OpalIMContext> Create(
00116       OpalManager & manager,
00117       PSafePtr<OpalPresentity> presentity,
00118       const PURL & remoteURL
00119     );
00120 
00121     enum SentStatus {
00122       SentOK,
00123       SentPending,
00124       SentAccepted,
00125       SentUnacceptableContent,
00126       SentInvalidContent,
00127       SentConnectionClosed,
00128       SentNoTransport,
00129       SentNoAnswer,
00130       SentDestinationUnknown,
00131       SentFailedGeneric,
00132     };
00133 
00134     // send text message in this conversation
00135     virtual SentStatus Send(OpalIM * message);
00136     virtual SentStatus SendCompositionIndication(bool active = true);
00137 
00140     struct MessageSentInfo {
00141       PAtomicInteger::IntegerType messageId;
00142       OpalIMContext::SentStatus status;
00143     };
00144     virtual void OnMessageSent(const MessageSentInfo & info);
00145 
00146     typedef PNotifierTemplate<const MessageSentInfo &> MessageSentNotifier;
00147     #define PDECLARE_MessageSentNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const MessageSentInfo &)
00148     #define PCREATE_MessageSentNotifier(fn) PCREATE_NOTIFIER2(fn, const MessageSentInfo &)
00149 
00151     void SetMessageSentNotifier(
00152       const MessageSentNotifier & notifier   
00153     );
00154 
00157     virtual SentStatus OnIncomingIM(OpalIM & message);
00158 
00159     typedef PNotifierTemplate<const OpalIM &> IncomingIMNotifier;
00160     #define PDECLARE_IncomingIMNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const OpalIM &)
00161     #define PCREATE_IncomingIMNotifier(fn) PCREATE_NOTIFIER2(fn, const OpalIM &)
00162 
00164     void SetIncomingIMNotifier(
00165       const IncomingIMNotifier & notifier   
00166     );
00167 
00170     virtual void OnCompositionIndicationChanged(const PString & state);
00171 
00172     typedef PNotifierTemplate<const PString &> CompositionIndicationChangedNotifier;
00173     #define PDECLARE_CompositionIndicationChangedNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const PString &)
00174     #define PCREATE_CompositionIndicationChangedNotifier(fn) PCREATE_NOTIFIER2(fn, const PString &)
00175 
00177     void SetCompositionIndicationChangedNotifier(
00178       const CompositionIndicationChangedNotifier & notifier   
00179     );
00180 
00181     virtual bool CheckContentType(const PString & contentType) const;
00182     virtual PStringArray GetContentTypes() const;
00183 
00184     // start of internal functions
00185 
00186     PString GetID() const          { return m_id; }
00187     void SetID(const PString & id) { m_id = id; }
00188     PString GetKey() const         { return m_key; }
00189     PString GetLocalURL() const    { return m_localURL; }
00190     PString GetRemoteURL() const   { return m_remoteURL; }
00191 
00194 
00195     PStringOptions & GetAttributes() { return m_attributes; }
00196     const PStringOptions & GetAttributes() const { return m_attributes; }
00197 
00198     virtual bool OnNewIncomingIM();
00199 
00200     virtual bool AddIncomingIM(OpalIM * message);
00201 
00202     virtual void OnCompositionIndicationTimeout();
00203 
00204     OpalIM * GetIncomingMessage();
00205 
00206     virtual void InternalOnMessageSent(const MessageSentInfo & info);
00207 
00208     static PString CreateKey(const PString & from, const PString & to);
00209 
00210     void ResetLastUsed();
00211 
00212   protected:
00213     virtual SentStatus InternalSend();
00214     virtual SentStatus InternalSendOutsideCall(OpalIM * message);
00215     virtual SentStatus InternalSendInsideCall(OpalIM * message);
00216 
00217     PMutex m_notificationMutex;
00218     IncomingIMNotifier                   m_incomingMessageNotifier;
00219     MessageSentNotifier                  m_messageSentNotifier;
00220     CompositionIndicationChangedNotifier m_compositionIndicationChangedNotifier;
00221 
00222     OpalManager  * m_manager;
00223     PStringOptions m_attributes;
00224 
00225     PSafePtr<OpalConnection> m_connection;
00226     PSafePtr<OpalPresentity> m_presentity;
00227 
00228     PMutex m_incomingMessagesMutex;
00229     PQueue<OpalIM> m_incomingMessages;
00230 
00231     PMutex m_outgoingMessagesMutex;
00232     OpalIM * m_currentOutgoingMessage;
00233     PQueue<OpalIM> m_outgoingMessages;
00234 
00235     PMutex m_lastUsedMutex;
00236     PTime m_lastUsed;
00237 
00238   private:    
00239     PString m_id, m_localURL, m_remoteURL, m_key;
00240 
00241 };
00242 
00243 class OpalConnectionIMContext : public OpalIMContext
00244 {
00245   public:
00246     OpalConnectionIMContext();
00247 };
00248 
00249 class OpalPresentityIMContext : public OpalIMContext
00250 {
00251   public:
00252     OpalPresentityIMContext();
00253 };
00254 
00256 
00257 class OpalIMManager : public PObject
00258 {
00259   public:
00260     OpalIMManager(OpalManager & manager);
00261     ~OpalIMManager();
00262 
00263     class IM_Work;
00264 
00265     OpalIMContext::SentStatus OnIncomingMessage(OpalIM * im, PString & conversationId, PSafePtr<OpalConnection> conn = NULL);
00266     void OnCompositionIndicationTimeout(const PString & conversationId);
00267 
00268     void AddContext(PSafePtr<OpalIMContext> context);
00269     void RemoveContext(OpalIMContext * context);
00270 
00271     void GarbageCollection();
00272 
00273     PSafePtr<OpalIMContext> FindContextByIdWithLock(
00274       const PString & key,
00275       PSafetyMode mode = PSafeReadWrite
00276     );
00277 
00278     PSafePtr<OpalIMContext> FindContextByNamesWithLock(
00279       const PString & local, 
00280       const PString & remote, 
00281       PSafetyMode mode = PSafeReadWrite
00282     );
00283 
00284     PSafePtr<OpalIMContext> FindContextForMessageWithLock(OpalIM & im, OpalConnection * conn = NULL);
00285 
00286     typedef PNotifierTemplate<OpalIMContext &> NewConversationNotifier;
00287     #define PDECLARE_NewConversationNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMManager, cls, fn, OpalIMContext &)
00288     #define PCREATE_NewConversationNotifier(fn) PCREATE_NOTIFIER2(fn, OpalIMContext &)
00289 
00290     class NewConversationCallBack : public PObject {
00291       public:
00292         NewConversationNotifier m_notifier;
00293         PString m_scheme;
00294     };
00295 
00296     void AddNotifier(const NewConversationNotifier & notifier, const PString & scheme);
00297     bool RemoveNotifier(const NewConversationNotifier & notifier, const PString & scheme);
00298 
00299 
00300     // thread pool declarations
00301     class IM_Work
00302     {
00303       public:
00304         IM_Work(OpalIMManager & mgr, const PString & conversationId);
00305         virtual ~IM_Work();
00306 
00307         virtual void Work() = 0;
00308 
00309         OpalIMManager & m_mgr;
00310         PString m_conversationId;
00311     };
00312 
00313     class NewIncomingIM_Work : public IM_Work 
00314     {
00315       public:
00316         NewIncomingIM_Work(OpalIMManager & mgr, const PString & conversationId)
00317           : IM_Work(mgr, conversationId)
00318         { }
00319         virtual void Work()
00320         { m_mgr.InternalOnNewIncomingIM(m_conversationId); }
00321     };
00322 
00323     class NewConversation_Work : public IM_Work 
00324     {
00325       public:
00326         NewConversation_Work(OpalIMManager & mgr, const PString & conversationId)
00327           : IM_Work(mgr, conversationId)
00328         { }
00329         virtual void Work()
00330         { m_mgr.InternalOnNewConversation(m_conversationId); }
00331     };
00332 
00333     class MessageSent_Work : public IM_Work 
00334     {
00335       public:
00336         MessageSent_Work(OpalIMManager & mgr, const PString & conversationId, const OpalIMContext::MessageSentInfo & info)
00337           : IM_Work(mgr, conversationId)
00338           , m_info(info)
00339         { }
00340         virtual void Work()
00341         { m_mgr.InternalOnMessageSent(m_conversationId, m_info); }
00342 
00343         OpalIMContext::MessageSentInfo m_info;
00344     };
00345 
00346     class CompositionIndicationTimeout_Work : public IM_Work 
00347     {
00348       public:
00349         CompositionIndicationTimeout_Work(OpalIMManager & mgr, const PString & conversationId)
00350           : IM_Work(mgr, conversationId)
00351         { }
00352         virtual void Work()
00353         { m_mgr.InternalOnCompositionIndicationTimeout(m_conversationId); }
00354     };
00355 
00356 
00357     void AddWork(IM_Work * work);
00358     virtual void InternalOnNewConversation(const PString & conversation);
00359     virtual void InternalOnNewIncomingIM(const PString & conversation);
00360     virtual void InternalOnMessageSent(const PString & conversation, const OpalIMContext::MessageSentInfo & info);
00361     virtual void InternalOnCompositionIndicationTimeout(const PString & conversationId);
00362 
00363   protected:
00364     PQueuedThreadPool<IM_Work> m_imThreadPool;
00365 
00366     PTime m_lastGarbageCollection;
00367     OpalManager & m_manager;
00368     bool m_deleting;
00369     typedef PSafeDictionary<PString, OpalIMContext> ContextsByConversationId;
00370     ContextsByConversationId m_contextsByConversationId;
00371 
00372     PMutex m_contextsByNamesMutex;
00373     typedef std::multimap<std::string, PString> ContextsByNames;
00374     ContextsByNames m_contextsByNames;
00375 
00376     PMutex m_notifierMutex;
00377     PList<NewConversationCallBack> m_callbacks;
00378 };
00379 
00381 
00382 class RTP_IMFrame : public RTP_DataFrame
00383 {
00384   public:
00385     RTP_IMFrame();
00386     RTP_IMFrame(const PString & contentType);
00387     RTP_IMFrame(const PString & contentType, const T140String & content);
00388     RTP_IMFrame(const BYTE * data, PINDEX len, PBoolean dynamic = true);
00389 
00390     void SetContentType(const PString & contentType);
00391     PString GetContentType() const;
00392 
00393     void SetContent(const T140String & text);
00394     bool GetContent(T140String & text) const;
00395 
00396     PString AsString() const { return PString((const char *)GetPayloadPtr(), GetPayloadSize()); }
00397 };
00398 
00399 class OpalIMMediaStream : public OpalMediaStream
00400 {
00401   public:
00402     OpalIMMediaStream(
00403       OpalConnection & conn,
00404       const OpalMediaFormat & mediaFormat, 
00405       unsigned sessionID,                  
00406       bool isSource                        
00407     );
00408 
00409     virtual PBoolean IsSynchronous() const         { return false; }
00410     virtual PBoolean RequiresPatchThread() const   { return false; }
00411 
00412     bool ReadPacket(RTP_DataFrame & packet);
00413     bool WritePacket(RTP_DataFrame & packet);
00414 };
00415 
00416 #endif // OPAL_HAS_IM
00417 
00418 #endif // OPAL_IM_IM_H