00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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,
00050 CompositionIndication_Active,
00051 Disposition
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
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
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
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