# 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: 27149 $
    00027  * $Author: rjongbloed $
    00028  * $Date: 2012-03-07 18:32:36 -0600 (Wed, 07 Mar 2012) $
    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   protected:
    00416     virtual void InternalClose() { }
    00417 };
    00418
    00419 #endif // OPAL_HAS_IM
    00420
    00421 #endif // OPAL_IM_IM_H