OPAL
Version 3.10.4
|
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