OPAL Version 3.10.4

- Main Page
- Related Pages
- Namespaces
- Data Structures
- Files

- File List
- Globals

im.h
Go to the documentation of this file.
1 /*
2 * im_mf.h
3 *
4 * Media formats for Instant Messaging
5 *
6 * Open Phone Abstraction Library (OPAL)
7 *
8 * Copyright (c) 2008 Post Increment
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Open Phone Abstraction Library.
21 *
22 * The Initial Developer of the Original Code is Post Increment
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Revision: 26270 $
27 * $Author: rjongbloed $
28 * $Date: 2011-08-03 03:29:01 -0500 (Wed, 03 Aug 2011) $
29 */
30
31 #ifndef OPAL_IM_IM_H
32 #define OPAL_IM_IM_H
33
34 #include <ptlib.h>
35 #include <opal/buildopts.h>
36
37 #include <ptclib/url.h>
38 #include <ptclib/threadpool.h>
39
40 #include <opal/transports.h>
41
42 class OpalIM : public PObject
43 {
44 public:
45 OpalIM();
46
47 enum Type {
48 Text,
49 CompositionIndication_Idle, // aka RFC 3994
50 CompositionIndication_Active, // aka RFC 3994
51 Disposition // aka RFC 5438
52 } m_type;
53
54 PURL m_to;
55 PURL m_from;
56 PString m_fromName;
57 PString m_mimeType;
58 PString m_body;
59 PString m_conversationId;
60
61 OpalTransportAddress m_fromAddr;
62 OpalTransportAddress m_toAddr;
63
64 PAtomicInteger::IntegerType m_messageId;
65
66 static PAtomicInteger::IntegerType GetNextMessageId();
67 };
68
69 #if OPAL_HAS_IM
70
71 #include <opal/mediastrm.h>
72 #include <im/rfc4103.h>
73
74 class OpalIMMediaType : public OpalMediaTypeDefinition
75 {
76 public:
77 OpalIMMediaType(
78 const char * mediaType,
79 const char * sdpType
80 )
81 : OpalMediaTypeDefinition(mediaType, sdpType, 0, OpalMediaType::DontOffer)
82 { }
83
84 PString GetRTPEncoding() const { return PString::Empty(); }
85 RTP_UDP * CreateRTPSession(OpalRTPConnection & , unsigned , bool ) { return NULL; }
86 virtual bool UsesRTP() const { return false; }
87 };
88
90
91 class OpalIMManager;
92 class OpalPresentity;
93
94 class OpalIMContext : public PSafeObject
95 {
96 PCLASSINFO(OpalIMContext, PSafeObject);
97
98 public:
99 friend class OpalIMManager;
100
101 OpalIMContext();
102 ~OpalIMContext();
103
104 static PSafePtr<OpalIMContext> Create(
105 OpalManager & manager,
106 const PURL & localURL,
107 const PURL & remoteURL
108 );
109
110 static PSafePtr<OpalIMContext> Create(
111 OpalManager & manager,
112 PSafePtr<OpalConnection> conn
113 );
114
115 static PSafePtr<OpalIMContext> Create(
116 OpalManager & manager,
117 PSafePtr<OpalPresentity> presentity,
118 const PURL & remoteURL
119 );
120
121 enum SentStatus {
122 SentOK,
123 SentPending,
124 SentAccepted,
125 SentUnacceptableContent,
126 SentInvalidContent,
127 SentConnectionClosed,
128 SentNoTransport,
129 SentNoAnswer,
130 SentDestinationUnknown,
131 SentFailedGeneric,
132 };
133
134 // send text message in this conversation
135 virtual SentStatus Send(OpalIM * message);
136 virtual SentStatus SendCompositionIndication(bool active = true);
137
140 struct MessageSentInfo {
141 PAtomicInteger::IntegerType messageId;
142 OpalIMContext::SentStatus status;
143 };
144 virtual void OnMessageSent(const MessageSentInfo & info);
145
146 typedef PNotifierTemplate<const MessageSentInfo &> MessageSentNotifier;
147 #define PDECLARE_MessageSentNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const MessageSentInfo &)
148 #define PCREATE_MessageSentNotifier(fn) PCREATE_NOTIFIER2(fn, const MessageSentInfo &)
149
151 void SetMessageSentNotifier(
152 const MessageSentNotifier & notifier
153 );
154
157 virtual SentStatus OnIncomingIM(OpalIM & message);
158
159 typedef PNotifierTemplate<const OpalIM &> IncomingIMNotifier;
160 #define PDECLARE_IncomingIMNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const OpalIM &)
161 #define PCREATE_IncomingIMNotifier(fn) PCREATE_NOTIFIER2(fn, const OpalIM &)
162
164 void SetIncomingIMNotifier(
165 const IncomingIMNotifier & notifier
166 );
167
170 virtual void OnCompositionIndicationChanged(const PString & state);
171
172 typedef PNotifierTemplate<const PString &> CompositionIndicationChangedNotifier;
173 #define PDECLARE_CompositionIndicationChangedNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMContext, cls, fn, const PString &)
174 #define PCREATE_CompositionIndicationChangedNotifier(fn) PCREATE_NOTIFIER2(fn, const PString &)
175
177 void SetCompositionIndicationChangedNotifier(
178 const CompositionIndicationChangedNotifier & notifier
179 );
180
181 virtual bool CheckContentType(const PString & contentType) const;
182 virtual PStringArray GetContentTypes() const;
183
184 // start of internal functions
185
186 PString GetID() const { return m_id; }
187 void SetID(const PString & id) { m_id = id; }
188 PString GetKey() const { return m_key; }
189 PString GetLocalURL() const { return m_localURL; }
190 PString GetRemoteURL() const { return m_remoteURL; }
191
194
195 PStringOptions & GetAttributes() { return m_attributes; }
196 const PStringOptions & GetAttributes() const { return m_attributes; }
197
198 virtual bool OnNewIncomingIM();
199
200 virtual bool AddIncomingIM(OpalIM * message);
201
202 virtual void OnCompositionIndicationTimeout();
203
204 OpalIM * GetIncomingMessage();
205
206 virtual void InternalOnMessageSent(const MessageSentInfo & info);
207
208 static PString CreateKey(const PString & from, const PString & to);
209
210 void ResetLastUsed();
211
212 protected:
213 virtual SentStatus InternalSend();
214 virtual SentStatus InternalSendOutsideCall(OpalIM * message);
215 virtual SentStatus InternalSendInsideCall(OpalIM * message);
216
217 PMutex m_notificationMutex;
218 IncomingIMNotifier m_incomingMessageNotifier;
219 MessageSentNotifier m_messageSentNotifier;
220 CompositionIndicationChangedNotifier m_compositionIndicationChangedNotifier;
221
222 OpalManager * m_manager;
223 PStringOptions m_attributes;
224
225 PSafePtr<OpalConnection> m_connection;
226 PSafePtr<OpalPresentity> m_presentity;
227
228 PMutex m_incomingMessagesMutex;
229 PQueue<OpalIM> m_incomingMessages;
230
231 PMutex m_outgoingMessagesMutex;
232 OpalIM * m_currentOutgoingMessage;
233 PQueue<OpalIM> m_outgoingMessages;
234
235 PMutex m_lastUsedMutex;
236 PTime m_lastUsed;
237
238 private:
239 PString m_id, m_localURL, m_remoteURL, m_key;
240
241 };
242
243 class OpalConnectionIMContext : public OpalIMContext
244 {
245 public:
246 OpalConnectionIMContext();
247 };
248
249 class OpalPresentityIMContext : public OpalIMContext
250 {
251 public:
252 OpalPresentityIMContext();
253 };
254
256
257 class OpalIMManager : public PObject
258 {
259 public:
260 OpalIMManager(OpalManager & manager);
261 ~OpalIMManager();
262
263 class IM_Work;
264
265 OpalIMContext::SentStatus OnIncomingMessage(OpalIM * im, PString & conversationId, PSafePtr<OpalConnection> conn = NULL);
266 void OnCompositionIndicationTimeout(const PString & conversationId);
267
268 void AddContext(PSafePtr<OpalIMContext> context);
269 void RemoveContext(OpalIMContext * context);
270
271 void GarbageCollection();
272
273 PSafePtr<OpalIMContext> FindContextByIdWithLock(
274 const PString & key,
275 PSafetyMode mode = PSafeReadWrite
276 );
277
278 PSafePtr<OpalIMContext> FindContextByNamesWithLock(
279 const PString & local,
280 const PString & remote,
281 PSafetyMode mode = PSafeReadWrite
282 );
283
284 PSafePtr<OpalIMContext> FindContextForMessageWithLock(OpalIM & im, OpalConnection * conn = NULL);
285
286 typedef PNotifierTemplate<OpalIMContext &> NewConversationNotifier;
287 #define PDECLARE_NewConversationNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalIMManager, cls, fn, OpalIMContext &)
288 #define PCREATE_NewConversationNotifier(fn) PCREATE_NOTIFIER2(fn, OpalIMContext &)
289
290 class NewConversationCallBack : public PObject {
291 public:
292 NewConversationNotifier m_notifier;
293 PString m_scheme;
294 };
295
296 void AddNotifier(const NewConversationNotifier & notifier, const PString & scheme);
297 bool RemoveNotifier(const NewConversationNotifier & notifier, const PString & scheme);
298
299
300 // thread pool declarations
301 class IM_Work
302 {
303 public:
304 IM_Work(OpalIMManager & mgr, const PString & conversationId);
305 virtual ~IM_Work();
306
307 virtual void Work() = 0;
308
309 OpalIMManager & m_mgr;
310 PString m_conversationId;
311 };
312
313 class NewIncomingIM_Work : public IM_Work
314 {
315 public:
316 NewIncomingIM_Work(OpalIMManager & mgr, const PString & conversationId)
317 : IM_Work(mgr, conversationId)
318 { }
319 virtual void Work()
320 { m_mgr.InternalOnNewIncomingIM(m_conversationId); }
321 };
322
323 class NewConversation_Work : public IM_Work
324 {
325 public:
326 NewConversation_Work(OpalIMManager & mgr, const PString & conversationId)
327 : IM_Work(mgr, conversationId)
328 { }
329 virtual void Work()
330 { m_mgr.InternalOnNewConversation(m_conversationId); }
331 };
332
333 class MessageSent_Work : public IM_Work
334 {
335 public:
336 MessageSent_Work(OpalIMManager & mgr, const PString & conversationId, const OpalIMContext::MessageSentInfo & info)
337 : IM_Work(mgr, conversationId)
338 , m_info(info)
339 { }
340 virtual void Work()
341 { m_mgr.InternalOnMessageSent(m_conversationId, m_info); }
342
343 OpalIMContext::MessageSentInfo m_info;
344 };
345
346 class CompositionIndicationTimeout_Work : public IM_Work
347 {
348 public:
349 CompositionIndicationTimeout_Work(OpalIMManager & mgr, const PString & conversationId)
350 : IM_Work(mgr, conversationId)
351 { }
352 virtual void Work()
353 { m_mgr.InternalOnCompositionIndicationTimeout(m_conversationId); }
354 };
355
356
357 void AddWork(IM_Work * work);
358 virtual void InternalOnNewConversation(const PString & conversation);
359 virtual void InternalOnNewIncomingIM(const PString & conversation);
360 virtual void InternalOnMessageSent(const PString & conversation, const OpalIMContext::MessageSentInfo & info);
361 virtual void InternalOnCompositionIndicationTimeout(const PString & conversationId);
362
363 protected:
364 PQueuedThreadPool<IM_Work> m_imThreadPool;
365
366 PTime m_lastGarbageCollection;
367 OpalManager & m_manager;
368 bool m_deleting;
369 typedef PSafeDictionary<PString, OpalIMContext> ContextsByConversationId;
370 ContextsByConversationId m_contextsByConversationId;
371
372 PMutex m_contextsByNamesMutex;
373 typedef std::multimap<std::string, PString> ContextsByNames;
374 ContextsByNames m_contextsByNames;
375
376 PMutex m_notifierMutex;
377 PList<NewConversationCallBack> m_callbacks;
378 };
379
381
382 class RTP_IMFrame : public RTP_DataFrame
383 {
384 public:
385 RTP_IMFrame();
386 RTP_IMFrame(const PString & contentType);
387 RTP_IMFrame(const PString & contentType, const T140String & content);
388 RTP_IMFrame(const BYTE * data, PINDEX len, PBoolean dynamic = true);
389
390 void SetContentType(const PString & contentType);
391 PString GetContentType() const;
392
393 void SetContent(const T140String & text);
394 bool GetContent(T140String & text) const;
395
396 PString AsString() const { return PString((const char *)GetPayloadPtr(), GetPayloadSize()); }
397 };
398
399 class OpalIMMediaStream : public OpalMediaStream
400 {
401 public:
402 OpalIMMediaStream(
403 OpalConnection & conn,
404 const OpalMediaFormat & mediaFormat,
405 unsigned sessionID,
406 bool isSource
407 );
408
409 virtual PBoolean IsSynchronous() const { return false; }
410 virtual PBoolean RequiresPatchThread() const { return false; }
411
412 bool ReadPacket(RTP_DataFrame & packet);
413 bool WritePacket(RTP_DataFrame & packet);
414 };
415
416 #endif // OPAL_HAS_IM
417
418 #endif // OPAL_IM_IM_H