Fixed previous check in which mysteriously changed a flag.
[opal.git] / src / h323 / channels.cxx
blob98ac7c6641dc9cbd2e9d309ed8a26d4e3c3d6926
1 /*
2 * channels.cxx
4 * H.323 protocol handler
6 * Open H323 Library
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
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/
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.
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
27 * Contributor(s): ______________________________________.
29 * $Log$
30 * Revision 2.44 2007/08/21 00:19:46 rjongbloed
31 * Fixed previous check in which mysteriously changed a flag.
33 * Revision 2.43 2007/08/17 09:00:40 csoutheren
34 * Remove commented-out code
36 * Revision 2.42 2007/08/16 03:10:35 rjongbloed
37 * Fixed setting of dynamic RTP in OLC on rx channel for slow start, only worked for fast cononect.
38 * Also fixed sending dynamic RTP type in OLC for Tx channel.
40 * Revision 2.41 2007/08/13 16:19:08 csoutheren
41 * Ensure CreateMediaStream is only called *once* for each stream in H.323 calls
43 * Revision 2.40 2007/06/28 12:08:26 rjongbloed
44 * Simplified mutex strategy to avoid some wierd deadlocks. All locking of access
45 * to an OpalConnection must be via the PSafeObject locks.
47 * Revision 2.39 2007/04/04 02:12:00 rjongbloed
48 * Reviewed and adjusted PTRACE log levels
49 * Now follows 1=error,2=warn,3=info,4+=debug
51 * Revision 2.38 2007/03/29 05:16:49 csoutheren
52 * Pass OpalConnection to OpalMediaSream constructor
53 * Add ID to OpalMediaStreams so that transcoders can match incoming and outgoing codecs
55 * Revision 2.37 2007/03/13 02:17:46 csoutheren
56 * Remove warnings/errors when compiling with various turned off
58 * Revision 2.36 2007/03/01 03:36:28 csoutheren
59 * Use local jitter buffer values rather than getting direct from OpalManager
61 * Revision 2.35 2007/01/10 09:16:55 csoutheren
62 * Allow compilation with video disabled
64 * Revision 2.34 2006/08/10 05:10:30 csoutheren
65 * Various H.323 stability patches merged in from DeimosPrePLuginBranch
67 * Revision 2.33 2006/07/24 14:03:40 csoutheren
68 * Merged in audio and video plugins from CVS branch PluginBranch
70 * Revision 2.32.2.1 2006/08/09 12:49:21 csoutheren
71 * Improve stablity under heavy H.323 load
73 * Revision 2.32 2006/04/10 05:16:09 csoutheren
74 * Populate media stream info even when OLCack only contains media control information
76 * Revision 2.31 2006/03/29 23:57:52 csoutheren
77 * Added patches from Paul Caswell to provide correct operation when using
78 * external RTP with H.323
80 * Revision 2.30 2006/01/02 15:51:44 dsandras
81 * Merged changes from OpenH323 Atlas_devel_2.
83 * Revision 2.29 2005/09/04 06:51:52 rjongbloed
84 * Added OpalMediaCommand mechanism (via PNotifier) for media streams
85 * and media transcoders to send commands back to remote.
87 * Revision 2.28 2005/09/04 06:23:39 rjongbloed
88 * Added OpalMediaCommand mechanism (via PNotifier) for media streams
89 * and media transcoders to send commands back to remote.
91 * Revision 2.27 2005/08/31 13:19:25 rjongbloed
92 * Added mechanism for controlling media (especially codecs) including
93 * changing the OpalMediaFormat option list (eg bit rate) and a completely
94 * new OpalMediaCommand abstraction for things like video fast update.
96 * Revision 2.26 2005/07/11 01:52:24 csoutheren
97 * Extended AnsweringCall to work for SIP as well as H.323
98 * Fixed problems with external RTP connection in H.323
99 * Added call to OnClosedMediaStream
101 * Revision 2.25 2004/04/07 08:21:01 rjongbloed
102 * Changes for new RTTI system.
104 * Revision 2.24 2004/02/19 10:47:02 rjongbloed
105 * Merged OpenH323 version 1.13.1 changes.
107 * Revision 2.23 2003/03/17 10:26:59 robertj
108 * Added video support.
110 * Revision 2.22 2003/01/07 04:39:53 robertj
111 * Updated to OpenH323 v1.11.2
113 * Revision 2.21 2002/11/10 11:33:18 robertj
114 * Updated to OpenH323 v1.10.3
116 * Revision 2.20 2002/09/04 06:01:47 robertj
117 * Updated to OpenH323 v1.9.6
119 * Revision 2.19 2002/07/01 04:56:31 robertj
120 * Updated to OpenH323 v1.9.1
122 * Revision 2.18 2002/04/18 03:41:54 robertj
123 * Fixed logical channel so does not delete media stream too early.
125 * Revision 2.17 2002/04/15 08:51:42 robertj
126 * Fixed correct setting of jitter buffer size in RTP media stream.
128 * Revision 2.16 2002/03/22 06:57:49 robertj
129 * Updated to OpenH323 version 1.8.2
131 * Revision 2.15 2002/02/19 07:45:28 robertj
132 * Restructured media bypass functions to fix problems with RFC2833.
134 * Revision 2.14 2002/02/13 04:17:53 robertj
135 * Fixed return of both data and control if only have one from OLC.
137 * Revision 2.13 2002/02/11 09:32:12 robertj
138 * Updated to openH323 v1.8.0
140 * Revision 2.12 2002/02/11 07:40:02 robertj
141 * Added media bypass for streams between compatible protocols.
143 * Revision 2.11 2002/01/22 05:24:36 robertj
144 * Added enum for illegal payload type value.
145 * Update from OpenH323
147 * Revision 2.10 2002/01/14 06:35:57 robertj
148 * Updated to OpenH323 v1.7.9
150 * Revision 2.9 2001/11/13 04:29:47 robertj
151 * Changed OpalTransportAddress CreateTransport and CreateListsner functions
152 * to have extra parameter to control local binding of sockets.
154 * Revision 2.8 2001/11/02 10:45:19 robertj
155 * Updated to OpenH323 v1.7.3
157 * Revision 2.7 2001/10/15 04:34:42 robertj
158 * Added delayed start of media patch threads.
160 * Revision 2.6 2001/10/05 00:22:13 robertj
161 * Updated to PWLib 1.2.0 and OpenH323 1.7.0
163 * Revision 2.5 2001/10/03 05:56:15 robertj
164 * Changes abndwidth management API.
166 * Revision 2.4 2001/08/17 08:32:17 robertj
167 * Update from OpenH323
169 * Revision 2.3 2001/08/13 05:10:39 robertj
170 * Updates from OpenH323 v1.6.0 release.
172 * Revision 2.2 2001/08/01 05:17:45 robertj
173 * Made OpalMediaFormatList class global to help with documentation.
175 * Revision 2.1 2001/07/30 01:40:01 robertj
176 * Fixed GNU C++ warnings.
178 * Revision 2.0 2001/07/27 15:48:25 robertj
179 * Conversion of OpenH323 to Open Phone Abstraction Library (OPAL)
181 * Revision 1.136 2003/02/10 05:36:13 robertj
182 * Fixed returning mediaControlChannel address in preference to mediaChannel
183 * address as Cisco's just feed your own address back at you.
185 * Revision 1.135 2002/12/18 11:20:49 craigs
186 * Fixed problem with T.38 channels SEGVing thanks to Vyacheslav Frolov
188 * Revision 1.134 2002/12/17 08:48:09 robertj
189 * Set silence suppression mode earlier in codec life so gets correct
190 * value for silenceSuppression in fast start OLC's.
192 * Revision 1.133 2002/12/16 08:20:04 robertj
193 * Fixed problem where a spurious RTP packet full of zeros could be sent
194 * at the beginning of the transmission, thanks Bruce Fitzsimons
196 * Revision 1.132 2002/11/26 02:59:25 robertj
197 * Added logging to help find logical channel thread stop failures.
199 * Revision 1.131 2002/10/31 00:37:47 robertj
200 * Enhanced jitter buffer system so operates dynamically between minimum and
201 * maximum values. Altered API to assure app writers note the change!
203 * Revision 1.130 2002/08/05 10:03:47 robertj
204 * Cosmetic changes to normalise the usage of pragma interface/implementation.
206 * Revision 1.129 2002/06/28 03:34:28 robertj
207 * Fixed issues with address translation on gatekeeper RAS channel.
209 * Revision 1.128 2002/06/25 08:30:12 robertj
210 * Changes to differentiate between stright G.723.1 and G.723.1 Annex A using
211 * the OLC dataType silenceSuppression field so does not send SID frames
212 * to receiver codecs that do not understand them.
214 * Revision 1.127 2002/06/24 00:07:31 robertj
215 * Fixed bandwidth usage being exactly opposite (adding when it should
216 * be subtracting), thanks Saswat Praharaj.
218 * Revision 1.126 2002/05/23 04:53:57 robertj
219 * Added function to remove a filter from logical channel.
221 * Revision 1.125 2002/05/10 05:47:15 robertj
222 * Added session ID to the data logical channel class.
224 * Revision 1.124 2002/05/07 23:49:11 robertj
225 * Fixed incorrect setting of session ID in data channel OLC, caused an
226 * incorrect optional field to be included, thanks Ulrich Findeisen.
228 * Revision 1.123 2002/05/03 00:07:24 robertj
229 * Fixed missing setting of isRunning flag in external RTP channels.
231 * Revision 1.122 2002/05/02 07:56:27 robertj
232 * Added automatic clearing of call if no media (RTP data) is transferred in a
233 * configurable (default 5 minutes) amount of time.
235 * Revision 1.121 2002/05/02 06:28:53 robertj
236 * Fixed problem with external RTP channels not fast starting.
238 * Revision 1.120 2002/04/17 05:56:05 robertj
239 * Added trace output of H323Channel::Direction enum.
241 * Revision 1.119 2002/02/25 08:42:26 robertj
242 * Fixed comments on the real time requirements of the codec.
244 * Revision 1.118 2002/02/19 06:15:20 robertj
245 * Allowed for RTP filter functions to force output of packet, or prevent it
246 * from being sent overriding the n frames per packet algorithm.
248 * Revision 1.117 2002/02/09 04:39:05 robertj
249 * Changes to allow T.38 logical channels to use single transport which is
250 * now owned by the OpalT38Protocol object instead of H323Channel.
252 * Revision 1.116 2002/02/05 08:13:02 robertj
253 * Added ability to not have addresses when external RTP channel created.
255 * Revision 1.115 2002/02/04 06:04:19 robertj
256 * Fixed correct exit on terminating transmit channel, thanks Norwood Systems.
258 * Revision 1.114 2002/01/27 10:49:51 rogerh
259 * Catch a division by zero case in a PTRACE()
261 * Revision 1.113 2002/01/24 03:33:07 robertj
262 * Fixed payload type being incorrect for audio after sending RFC2833 packet.
264 * Revision 1.112 2002/01/22 22:48:25 robertj
265 * Fixed RFC2833 support (transmitter) requiring large rewrite
267 * Revision 1.111 2002/01/22 07:08:26 robertj
268 * Added IllegalPayloadType enum as need marker for none set
269 * and MaxPayloadType is a legal value.
271 * Revision 1.110 2002/01/22 06:05:03 robertj
272 * Added ability for RTP payload type to be overridden at capability level.
274 * Revision 1.109 2002/01/17 07:05:03 robertj
275 * Added support for RFC2833 embedded DTMF in the RTP stream.
277 * Revision 1.108 2002/01/17 00:10:37 robertj
278 * Fixed double copy of rtpPayloadType in RTP channel, caused much confusion.
280 * Revision 1.107 2002/01/14 05:18:44 robertj
281 * Fixed typo on external RTP channel constructor.
283 * Revision 1.106 2002/01/10 05:13:54 robertj
284 * Added support for external RTP stacks, thanks NuMind Software Systems.
286 * Revision 1.105 2002/01/09 06:05:55 robertj
287 * Rearranged transmitter timestamp calculation to allow for a codec that has
288 * variable number of timestamp units per call to Read().
290 * Revision 1.104 2001/12/22 01:50:47 robertj
291 * Fixed bug in data channel (T.38) negotiations, using wrong PDU subclass.
292 * Fixed using correct port number in data channel (T.38) negotiations.
293 * Improved trace logging.
295 * Revision 1.103 2001/11/28 00:09:14 dereks
296 * Additional information in PTRACE output.
298 * Revision 1.102 2001/11/09 05:39:54 craigs
299 * Added initial T.38 support thanks to Adam Lazur
301 * Revision 1.101 2001/10/24 00:55:49 robertj
302 * Made cosmetic changes to H.245 miscellaneous command function.
304 * Revision 1.100 2001/10/23 02:17:16 dereks
305 * Initial release of cu30 video codec.
307 * Revision 1.99 2001/09/13 08:20:27 robertj
308 * Fixed broken back out of rev 1.95, thanks Santiago Garcia Mantinan
310 * Revision 1.98 2001/09/11 00:21:23 robertj
311 * Fixed missing stack sizes in endpoint for cleaner thread and jitter thread.
313 * Revision 1.97 2001/08/28 09:28:28 robertj
314 * Backed out change in revision 1.95, not compatible with G.711
316 * Revision 1.96 2001/08/16 06:34:42 robertj
317 * Plugged memory leak if using trace level 5.
319 * Revision 1.95 2001/08/10 01:34:41 robertj
320 * Fixed problem with incorrect timestamp if codec returns more than one
321 * frame in read, thanks Lee Kirchhoff.
323 * Revision 1.94 2001/08/06 05:36:00 robertj
324 * Fixed GNU warnings.
326 * Revision 1.93 2001/08/06 03:08:56 robertj
327 * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
329 * Revision 1.92 2001/07/24 02:26:44 robertj
330 * Added start for handling reverse channels.
332 * Revision 1.91 2001/07/17 04:44:31 robertj
333 * Partial implementation of T.120 and T.38 logical channels.
335 * Revision 1.90 2001/07/12 07:28:41 yurik
336 * WinCE fix: Sleep(0) in Main to get system chance to digest
338 * Revision 1.89 2001/06/15 07:20:35 robertj
339 * Moved OnClosedLogicalChannel() to be after channels threads halted.
341 * Revision 1.88 2001/06/02 01:35:32 robertj
342 * Added thread names.
344 * Revision 1.87 2001/05/31 06:29:48 robertj
345 * Changed trace of RTP mismatch so only displays for first n packets then
346 * does not dump messages any more. Was exactly the opposite.
348 * Revision 1.86 2001/04/20 02:32:07 robertj
349 * Improved logging of bandwith, used more intuitive units.
351 * Revision 1.85 2001/04/02 04:12:53 robertj
352 * Fixed trace output from packet transmit timing.
354 * Revision 1.84 2001/03/23 05:38:30 robertj
355 * Added PTRACE_IF to output trace if a conditional is TRUE.
357 * Revision 1.83 2001/02/09 05:13:55 craigs
358 * Added pragma implementation to (hopefully) reduce the executable image size
359 * under Linux
361 * Revision 1.82 2001/02/07 05:04:45 robertj
362 * Improved codec read analysis debug output.
364 * Revision 1.81 2001/02/06 07:40:46 robertj
365 * Added debugging for timing of codec read.
367 * Revision 1.80 2001/01/25 07:27:16 robertj
368 * Major changes to add more flexible OpalMediaFormat class to normalise
369 * all information about media types, especially codecs.
371 * Revision 1.79 2000/12/20 00:50:42 robertj
372 * Fixed MSVC compatibility issues (No trace).
374 * Revision 1.78 2000/12/19 22:33:44 dereks
375 * Adjust so that the video channel is used for reading/writing raw video
376 * data, which better modularizes the video codec.
378 * Revision 1.77 2000/12/17 22:45:36 robertj
379 * Set media stream threads to highest unprivileged priority.
381 * Revision 1.76 2000/11/24 10:52:50 robertj
382 * Modified the ReadFrame/WriteFrame functions to allow for variable length codecs.
383 * Added support for G.729 annex B packetisation scheme in RTP.
384 * Fixed bug in fast started G.711 codec not working in one direction.
386 * Revision 1.75 2000/10/24 00:00:09 robertj
387 * Improved memory hogging hash function for logical channels.
389 * Revision 1.74 2000/10/19 04:05:01 robertj
390 * Added compare function for logical channel numbers, thanks Yuriy Ershov.
392 * Revision 1.73 2000/09/23 06:54:44 robertj
393 * Prevented call of OnClose call back if channel was never opened.
395 * Revision 1.72 2000/09/22 01:35:49 robertj
396 * Added support for handling LID's that only do symmetric codecs.
398 * Revision 1.71 2000/09/22 00:32:33 craigs
399 * Added extra logging
400 * Fixed problems with no fastConnect with tunelling
402 * Revision 1.70 2000/09/20 01:50:21 craigs
403 * Added ability to set jitter buffer on a per-connection basis
405 * Revision 1.69 2000/09/14 23:03:45 robertj
406 * Increased timeout on asserting because of driver lockup
408 * Revision 1.68 2000/08/31 08:15:40 robertj
409 * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
411 * Revision 1.67 2000/08/30 06:33:01 craigs
412 * Add fix to ignore small runs of consectuive mismatched payload types
414 * Revision 1.66 2000/08/25 01:10:28 robertj
415 * Added assert if various thrads ever fail to terminate.
417 * Revision 1.65 2000/08/21 02:50:28 robertj
418 * Fixed race condition if close call just as slow start media channels are opening.
420 * Revision 1.64 2000/07/14 14:04:49 robertj
421 * Clarified a debug message.
423 * Revision 1.63 2000/07/14 12:47:36 robertj
424 * Added clarification to some logging messags.
426 * Revision 1.62 2000/07/13 16:05:47 robertj
427 * Removed time critical priority as it can totally slag a Win98 system.
428 * Fixed trace message displaying mismatched codecs in RTP packet around the wrong way.
430 * Revision 1.61 2000/07/11 11:15:52 robertj
431 * Fixed bug when terminating RTP receiver and not also terminating transmitter.
433 * Revision 1.60 2000/06/23 02:04:01 robertj
434 * Increased the priority of the media channels, only relevent for Win32 at this time.
436 * Revision 1.59 2000/06/15 01:46:15 robertj
437 * Added channel pause (aka mute) functions.
439 * Revision 1.58 2000/05/18 12:10:50 robertj
440 * Removed all Sleep() calls in codec as timing innacuracies make it unusable. All
441 * codec implementations must thus have timing built into them, usually using I/O.
443 * Revision 1.57 2000/05/11 23:54:25 craigs
444 * Fixed the Windows fix with another Linux fix. But it worked OK on the Alpha!
446 * Revision 1.56 2000/05/11 09:56:46 robertj
447 * Win32 compatibility and addition of some extra debugging on codec timing.
449 * Revision 1.55 2000/05/11 02:27:18 robertj
450 * Added "fail safe" timer sleep on codec writes when on output of jitter buffer.
452 * Revision 1.54 2000/05/04 11:52:34 robertj
453 * Added Packets Too Late statistics, requiring major rearrangement of jitter
454 * buffer code, not also changes semantics of codec Write() function slightly.
456 * Revision 1.53 2000/05/02 04:32:26 robertj
457 * Fixed copyright notice comment.
459 * Revision 1.52 2000/05/01 01:01:49 robertj
460 * Added flag for what to do with out of orer packets (use if jitter, don't if not).
462 * Revision 1.51 2000/04/28 13:01:44 robertj
463 * Fixed problem with adjusting tx/rx frame counts in capabilities during fast start.
465 * Revision 1.50 2000/04/10 19:45:49 robertj
466 * Changed RTP data receive tp be more forgiving, will process packet even if payload type is wrong.
468 * Revision 1.49 2000/03/31 20:04:28 robertj
469 * Fixed log message for start/end of transmitted talk burst.
471 * Revision 1.48 2000/03/29 04:36:38 robertj
472 * Improved some trace logging messages.
474 * Revision 1.47 2000/03/22 01:31:36 robertj
475 * Fixed transmitter loop so codec can return multiple frames (crash in G.711 mode)
477 * Revision 1.46 2000/03/21 03:58:00 robertj
478 * Fixed stuffed up RTP transmit loop after previous change.
480 * Revision 1.45 2000/03/21 03:06:49 robertj
481 * Changes to make RTP TX of exact numbers of frames in some codecs.
483 * Revision 1.44 2000/03/20 20:59:28 robertj
484 * Fixed possible buffer overrun problem in RTP_DataFrames
486 * Revision 1.43 2000/02/24 00:34:25 robertj
487 * Fixed possible endless loop on channel abort, thanks Yura Ershov
489 * Revision 1.42 2000/02/04 05:11:19 craigs
490 * Updated for new Makefiles and for new video transmission code
492 * Revision 1.41 2000/01/13 04:03:45 robertj
493 * Added video transmission
495 * Revision 1.40 2000/01/08 06:52:10 robertj
496 * Removed invalid assert
498 * Revision 1.39 1999/12/23 23:02:35 robertj
499 * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
501 * Revision 1.38 1999/11/22 01:37:31 robertj
502 * Fixed channel closure so OnClosedLogicalChannel() only called if channel was actually started.
504 * Revision 1.37 1999/11/20 05:35:26 robertj
505 * Extra debugging
507 * Revision 1.36 1999/11/20 00:53:47 robertj
508 * Fixed ability to have variable sized frames in single RTP packet under G.723.1
510 * Revision 1.35 1999/11/19 09:06:25 robertj
511 * Changed to close down logical channel if get a transmit codec error.
513 * Revision 1.34 1999/11/11 23:28:46 robertj
514 * Added first cut silence detection algorithm.
516 * Revision 1.33 1999/11/06 11:01:37 robertj
517 * Extra debugging.
519 * Revision 1.32 1999/11/06 05:37:44 robertj
520 * Complete rewrite of termination of connection to avoid numerous race conditions.
522 * Revision 1.31 1999/11/01 00:47:46 robertj
523 * Added close of logical channel on write error
525 * Revision 1.30 1999/10/30 12:38:24 robertj
526 * Added more tracing of channel threads.
528 * Revision 1.29 1999/10/08 09:59:03 robertj
529 * Rewrite of capability for sending multiple audio frames
531 * Revision 1.28 1999/10/08 04:58:37 robertj
532 * Added capability for sending multiple audio frames in single RTP packet
534 * Revision 1.27 1999/09/23 07:25:12 robertj
535 * Added open audio and video function to connection and started multi-frame codec send functionality.
537 * Revision 1.26 1999/09/21 14:09:02 robertj
538 * Removed warnings when no tracing enabled.
540 * Revision 1.25 1999/09/18 13:24:38 craigs
541 * Added ability to disable jitter buffer
542 * Added ability to access entire RTP packet in codec Write
544 * Revision 1.24 1999/09/08 04:05:48 robertj
545 * Added support for video capabilities & codec, still needs the actual codec itself!
547 * Revision 1.23 1999/09/03 02:17:50 robertj
548 * Added more debugging
550 * Revision 1.22 1999/08/31 12:34:18 robertj
551 * Added gatekeeper support.
553 * Revision 1.21 1999/07/16 15:02:51 robertj
554 * Changed jitter buffer to throw away old packets if jitter exceeded.
556 * Revision 1.20 1999/07/16 00:51:03 robertj
557 * Some more debugging of fast start.
559 * Revision 1.19 1999/07/15 14:45:35 robertj
560 * Added propagation of codec open error to shut down logical channel.
561 * Fixed control channel start up bug introduced with tunnelling.
563 * Revision 1.18 1999/07/15 09:04:31 robertj
564 * Fixed some fast start bugs
566 * Revision 1.17 1999/07/14 06:04:04 robertj
567 * Fixed setting of channel number in fast start.
569 * Revision 1.16 1999/07/13 09:53:24 robertj
570 * Fixed some problems with jitter buffer and added more debugging.
572 * Revision 1.15 1999/07/13 02:50:58 craigs
573 * Changed semantics of SetPlayDevice/SetRecordDevice, only descendent
574 * endpoint assumes PSoundChannel devices for audio codec.
576 * Revision 1.14 1999/07/10 03:01:48 robertj
577 * Removed debugging.
579 * Revision 1.13 1999/07/09 06:09:49 robertj
580 * Major implementation. An ENORMOUS amount of stuff added everywhere.
582 * Revision 1.12 1999/06/25 14:19:40 robertj
583 * Fixed termination race condition in logical channel tear down.
585 * Revision 1.11 1999/06/24 13:32:45 robertj
586 * Fixed ability to change sound device on codec and fixed NM3 G.711 compatibility
588 * Revision 1.10 1999/06/22 13:49:40 robertj
589 * Added GSM support and further RTP protocol enhancements.
591 * Revision 1.9 1999/06/14 05:15:55 robertj
592 * Changes for using RTP sessions correctly in H323 Logical Channel context
594 * Revision 1.8 1999/06/13 12:41:14 robertj
595 * Implement logical channel transmitter.
596 * Fixed H245 connect on receiving call.
598 * Revision 1.7 1999/06/09 06:18:00 robertj
599 * GCC compatibiltiy.
601 * Revision 1.6 1999/06/09 05:26:19 robertj
602 * Major restructuring of classes.
604 * Revision 1.5 1999/06/07 00:54:30 robertj
605 * Displayed error on SetOption for buffer size
607 * Revision 1.4 1999/06/06 06:06:36 robertj
608 * Changes for new ASN compiler and v2 protocol ASN files.
610 * Revision 1.3 1999/04/26 06:14:46 craigs
611 * Initial implementation for RTP decoding and lots of stuff
612 * As a whole, these changes are called "First Noise"
614 * Revision 1.2 1999/02/25 03:26:02 robertj
615 * BeOS compatibility
617 * Revision 1.1 1999/01/16 01:31:09 robertj
618 * Initial revision
622 #include <ptlib.h>
624 #ifdef __GNUC__
625 #pragma implementation "channels.h"
626 #endif
628 #include <h323/channels.h>
630 #include <opal/transports.h>
632 #if OPAL_VIDEO
633 #include <codec/vidcodec.h>
634 #endif
636 #include <h323/h323ep.h>
637 #include <h323/h323con.h>
638 #include <h323/h323rtp.h>
639 #include <h323/transaddr.h>
640 #include <h323/h323pdu.h>
643 #define new PNEW
646 #define MAX_PAYLOAD_TYPE_MISMATCHES 8
647 #define RTP_TRACE_DISPLAY_RATE 16000 // 2 seconds
650 #if PTRACING
652 ostream & operator<<(ostream & out, H323Channel::Directions dir)
654 static const char * const DirNames[H323Channel::NumDirections] = {
655 "IsBidirectional", "IsTransmitter", "IsReceiver"
658 if (dir < H323Channel::NumDirections && DirNames[dir] != NULL)
659 out << DirNames[dir];
660 else
661 out << "Direction<" << (unsigned)dir << '>';
663 return out;
666 #endif
669 /////////////////////////////////////////////////////////////////////////////
671 H323ChannelNumber::H323ChannelNumber(unsigned num, BOOL fromRem)
673 PAssert(num < 0x10000, PInvalidParameter);
674 number = num;
675 fromRemote = fromRem;
679 PObject * H323ChannelNumber::Clone() const
681 return new H323ChannelNumber(number, fromRemote);
685 PINDEX H323ChannelNumber::HashFunction() const
687 PINDEX hash = (number%17) << 1;
688 if (fromRemote)
689 hash++;
690 return hash;
694 void H323ChannelNumber::PrintOn(ostream & strm) const
696 strm << (fromRemote ? 'R' : 'T') << '-' << number;
700 PObject::Comparison H323ChannelNumber::Compare(const PObject & obj) const
702 #ifndef PASN_LEANANDMEAN
703 PAssert(PIsDescendant(&obj, H323ChannelNumber), PInvalidCast);
704 #endif
705 const H323ChannelNumber & other = (const H323ChannelNumber &)obj;
706 if (number < other.number)
707 return LessThan;
708 if (number > other.number)
709 return GreaterThan;
710 if (fromRemote && !other.fromRemote)
711 return LessThan;
712 if (!fromRemote && other.fromRemote)
713 return GreaterThan;
714 return EqualTo;
718 H323ChannelNumber & H323ChannelNumber::operator++(int)
720 number++;
721 return *this;
725 /////////////////////////////////////////////////////////////////////////////
727 H323Channel::H323Channel(H323Connection & conn, const H323Capability & cap)
728 : endpoint(conn.GetEndPoint()),
729 connection(conn)
731 capability = (H323Capability *)cap.Clone();
732 bandwidthUsed = 0;
733 terminating = FALSE;
734 opened = FALSE;
735 paused = TRUE;
739 H323Channel::~H323Channel()
741 connection.SetBandwidthUsed(bandwidthUsed, 0);
743 delete capability;
747 void H323Channel::PrintOn(ostream & strm) const
749 strm << number;
753 unsigned H323Channel::GetSessionID() const
755 return 0;
759 BOOL H323Channel::GetMediaTransportAddress(OpalTransportAddress & /*data*/,
760 OpalTransportAddress & /*control*/) const
762 return FALSE;
766 void H323Channel::Close()
768 if (!opened || terminating)
769 return;
771 terminating = TRUE;
773 // Signal to the connection that this channel is on the way out
774 connection.OnClosedLogicalChannel(*this);
776 PTRACE(4, "LogChan\tCleaned up " << number);
780 BOOL H323Channel::OnReceivedPDU(const H245_OpenLogicalChannel & /*pdu*/,
781 unsigned & /*errorCode*/)
783 return TRUE;
787 BOOL H323Channel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & /*pdu*/)
789 return TRUE;
793 void H323Channel::OnSendOpenAck(const H245_OpenLogicalChannel & /*pdu*/,
794 H245_OpenLogicalChannelAck & /* pdu*/) const
799 void H323Channel::OnFlowControl(long PTRACE_PARAM(bitRateRestriction))
801 PTRACE(3, "LogChan\tOnFlowControl: " << bitRateRestriction);
805 void H323Channel::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & PTRACE_PARAM(type))
807 PTRACE(3, "LogChan\tOnMiscellaneousCommand: chan=" << number << ", type=" << type.GetTagName());
811 void H323Channel::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & PTRACE_PARAM(type))
813 PTRACE(3, "LogChan\tOnMiscellaneousIndication: chan=" << number
814 << ", type=" << type.GetTagName());
818 void H323Channel::OnJitterIndication(DWORD PTRACE_PARAM(jitter),
819 int PTRACE_PARAM(skippedFrameCount),
820 int PTRACE_PARAM(additionalBuffer))
822 PTRACE(3, "LogChan\tOnJitterIndication:"
823 " jitter=" << jitter <<
824 " skippedFrameCount=" << skippedFrameCount <<
825 " additionalBuffer=" << additionalBuffer);
829 BOOL H323Channel::SetBandwidthUsed(unsigned bandwidth)
831 PTRACE(3, "LogChan\tBandwidth requested/used = "
832 << bandwidth/10 << '.' << bandwidth%10 << '/'
833 << bandwidthUsed/10 << '.' << bandwidthUsed%10
834 << " kb/s");
835 if (!connection.SetBandwidthUsed(bandwidthUsed, bandwidth)) {
836 bandwidthUsed = 0;
837 return FALSE;
840 bandwidthUsed = bandwidth;
841 return TRUE;
845 BOOL H323Channel::Open()
847 if (opened)
848 return TRUE;
850 // Give the connection (or endpoint) a chance to do something with
851 // the opening of the codec.
852 if (!connection.OnStartLogicalChannel(*this)) {
853 PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
854 << " open failed (OnStartLogicalChannel fail)");
855 return FALSE;
858 opened = TRUE;
859 return TRUE;
863 /////////////////////////////////////////////////////////////////////////////
865 H323UnidirectionalChannel::H323UnidirectionalChannel(H323Connection & conn,
866 const H323Capability & cap,
867 Directions direction)
868 : H323Channel(conn, cap),
869 receiver(direction == IsReceiver)
871 mediaStream = NULL;
874 H323UnidirectionalChannel::~H323UnidirectionalChannel()
876 if (!connection.RemoveMediaStream(mediaStream)) {
877 delete mediaStream;
878 mediaStream = NULL;
883 H323Channel::Directions H323UnidirectionalChannel::GetDirection() const
885 return receiver ? IsReceiver : IsTransmitter;
889 BOOL H323UnidirectionalChannel::SetInitialBandwidth()
891 return SetBandwidthUsed(capability->GetMediaFormat().GetBandwidth()/100);
895 BOOL H323UnidirectionalChannel::Open()
897 if (opened)
898 return TRUE;
900 if (PAssertNULL(mediaStream) == NULL)
901 return FALSE;
903 if (!mediaStream->Open()) {
904 PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
905 << " open failed (OpalMediaStream::Open fail)");
906 return FALSE;
909 if (!H323Channel::Open())
910 return FALSE;
912 if (!mediaStream->IsSource())
913 return TRUE;
915 return connection.OnOpenMediaStream(*mediaStream);
919 BOOL H323UnidirectionalChannel::Start()
921 if (!Open())
922 return FALSE;
924 if (!mediaStream->Start())
925 return FALSE;
927 //mediaStream->SetCommandNotifier(PCREATE_NOTIFIER(OnMediaCommand)); // TODO: HERE
929 paused = FALSE;
930 return TRUE;
934 void H323UnidirectionalChannel::Close()
936 if (terminating)
937 return;
939 PTRACE(4, "H323RTP\tCleaning up media stream on " << number);
941 // If we have source media stream close it
942 if (mediaStream != NULL)
943 mediaStream->Close();
945 H323Channel::Close();
949 void H323UnidirectionalChannel::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
951 H323Channel::OnMiscellaneousCommand(type);
953 if (mediaStream == NULL)
954 return;
956 #if OPAL_VIDEO
957 switch (type.GetTag())
959 case H245_MiscellaneousCommand_type::e_videoFreezePicture :
960 mediaStream->ExecuteCommand(OpalVideoFreezePicture());
961 break;
963 case H245_MiscellaneousCommand_type::e_videoFastUpdatePicture:
964 mediaStream->ExecuteCommand(OpalVideoUpdatePicture());
965 break;
967 case H245_MiscellaneousCommand_type::e_videoFastUpdateGOB :
969 const H245_MiscellaneousCommand_type_videoFastUpdateGOB & fuGOB = type;
970 mediaStream->ExecuteCommand(OpalVideoUpdatePicture(fuGOB.m_firstGOB, -1, fuGOB.m_numberOfGOBs));
972 break;
974 case H245_MiscellaneousCommand_type::e_videoFastUpdateMB :
976 const H245_MiscellaneousCommand_type_videoFastUpdateMB & vfuMB = type;
977 mediaStream->ExecuteCommand(OpalVideoUpdatePicture(vfuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstGOB) ? (int)vfuMB.m_firstGOB : -1,
978 vfuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstMB) ? (int)vfuMB.m_firstMB : -1,
979 vfuMB.m_numberOfMBs));
981 break;
983 case H245_MiscellaneousCommand_type::e_videoTemporalSpatialTradeOff :
984 mediaStream->ExecuteCommand(OpalTemporalSpatialTradeOff((const PASN_Integer &)type));
985 break;
986 default:
987 break;
989 #endif
993 void H323UnidirectionalChannel::OnMediaCommand(
994 #if OPAL_VIDEO
995 OpalMediaCommand & command,
996 #else
997 OpalMediaCommand & ,
998 #endif
999 INT)
1001 #if OPAL_VIDEO
1002 if (PIsDescendant(&command, OpalVideoUpdatePicture)) {
1003 H323ControlPDU pdu;
1004 const OpalVideoUpdatePicture & updatePicture = (const OpalVideoUpdatePicture &)command;
1006 if (updatePicture.GetNumBlocks() < 0)
1007 pdu.BuildMiscellaneousCommand(GetNumber(), H245_MiscellaneousCommand_type::e_videoFastUpdatePicture);
1008 else if (updatePicture.GetFirstMB() < 0) {
1009 H245_MiscellaneousCommand_type_videoFastUpdateGOB & fuGOB =
1010 pdu.BuildMiscellaneousCommand(GetNumber(), H245_MiscellaneousCommand_type::e_videoFastUpdateGOB).m_type;
1011 fuGOB.m_firstGOB = updatePicture.GetFirstGOB();
1012 fuGOB.m_numberOfGOBs = updatePicture.GetNumBlocks();
1014 else {
1015 H245_MiscellaneousCommand_type_videoFastUpdateMB & vfuMB =
1016 pdu.BuildMiscellaneousCommand(GetNumber(), H245_MiscellaneousCommand_type::e_videoFastUpdateMB).m_type;
1017 if (updatePicture.GetFirstGOB() >= 0) {
1018 vfuMB.IncludeOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstGOB);
1019 vfuMB.m_firstGOB = updatePicture.GetFirstGOB();
1021 if (updatePicture.GetFirstMB() >= 0) {
1022 vfuMB.IncludeOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstMB);
1023 vfuMB.m_firstMB = updatePicture.GetFirstMB();
1025 vfuMB.m_numberOfMBs = updatePicture.GetNumBlocks();
1028 connection.WriteControlPDU(pdu);
1029 return;
1031 #endif
1035 OpalMediaStream * H323UnidirectionalChannel::GetMediaStream(BOOL deleted) const
1037 OpalMediaStream * t = mediaStream;
1038 if (deleted)
1039 mediaStream = NULL;
1040 return t;
1044 /////////////////////////////////////////////////////////////////////////////
1046 H323BidirectionalChannel::H323BidirectionalChannel(H323Connection & conn,
1047 const H323Capability & cap)
1048 : H323Channel(conn, cap)
1053 H323Channel::Directions H323BidirectionalChannel::GetDirection() const
1055 return IsBidirectional;
1059 BOOL H323BidirectionalChannel::Start()
1061 return TRUE;
1065 /////////////////////////////////////////////////////////////////////////////
1067 H323_RealTimeChannel::H323_RealTimeChannel(H323Connection & connection,
1068 const H323Capability & capability,
1069 Directions direction)
1070 : H323UnidirectionalChannel(connection, capability, direction)
1072 rtpPayloadType = capability.GetMediaFormat().GetPayloadType();
1076 BOOL H323_RealTimeChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
1078 PTRACE(3, "H323RTP\tOnSendingPDU");
1080 open.m_forwardLogicalChannelNumber = (unsigned)number;
1082 if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
1083 open.m_reverseLogicalChannelParameters.IncludeOptionalField(
1084 H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
1085 // Set the communications information for unicast IPv4
1086 open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
1087 H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
1088 ::e_h2250LogicalChannelParameters);
1090 return OnSendingPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters);
1092 else {
1093 // Set the communications information for unicast IPv4
1094 open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
1095 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
1096 ::e_h2250LogicalChannelParameters);
1098 return OnSendingPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters);
1103 void H323_RealTimeChannel::OnSendOpenAck(const H245_OpenLogicalChannel & open,
1104 H245_OpenLogicalChannelAck & ack) const
1106 PTRACE(3, "H323RTP\tOnSendOpenAck");
1108 // set forwardMultiplexAckParameters option
1109 ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
1111 // select H225 choice
1112 ack.m_forwardMultiplexAckParameters.SetTag(
1113 H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
1115 // get H225 parms
1116 H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
1118 // set session ID
1119 param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
1120 const H245_H2250LogicalChannelParameters & openparam =
1121 open.m_forwardLogicalChannelParameters.m_multiplexParameters;
1122 unsigned sessionID = openparam.m_sessionID;
1123 param.m_sessionID = sessionID;
1125 OnSendOpenAck(param);
1127 PTRACE(3, "H323RTP\tSending open logical channel ACK: sessionID=" << sessionID);
1131 BOOL H323_RealTimeChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
1132 unsigned & errorCode)
1134 if (receiver)
1135 number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
1137 PTRACE(3, "H323RTP\tOnReceivedPDU for channel: " << number);
1139 BOOL reverse = open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
1140 const H245_DataType & dataType = reverse ? open.m_reverseLogicalChannelParameters.m_dataType
1141 : open.m_forwardLogicalChannelParameters.m_dataType;
1143 if (!capability->OnReceivedPDU(dataType, receiver)) {
1144 PTRACE(1, "H323RTP\tData type not supported");
1145 errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
1146 return FALSE;
1149 if (reverse) {
1150 if (open.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() ==
1151 H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
1152 return OnReceivedPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters, errorCode);
1154 else {
1155 if (open.m_forwardLogicalChannelParameters.m_multiplexParameters.GetTag() ==
1156 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
1157 return OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters, errorCode);
1160 PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
1161 errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
1162 return FALSE;
1166 BOOL H323_RealTimeChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
1168 PTRACE(3, "H323RTP\tOnReceiveOpenAck");
1170 if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
1171 PTRACE(1, "H323RTP\tNo forwardMultiplexAckParameters");
1172 return FALSE;
1175 if (ack.m_forwardMultiplexAckParameters.GetTag() !=
1176 H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
1177 PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
1178 return FALSE;
1181 return OnReceivedAckPDU(ack.m_forwardMultiplexAckParameters);
1185 BOOL H323_RealTimeChannel::SetDynamicRTPPayloadType(int newType)
1187 PTRACE(4, "H323RTP\tAttempting to set dynamic RTP payload type: " << newType);
1189 // This is "no change"
1190 if (newType == -1)
1191 return TRUE;
1193 // Check for illegal type
1194 if (newType < RTP_DataFrame::DynamicBase || newType >= RTP_DataFrame::IllegalPayloadType)
1195 return FALSE;
1197 // Check for overwriting "known" type
1198 if (rtpPayloadType < RTP_DataFrame::DynamicBase)
1199 return FALSE;
1201 rtpPayloadType = (RTP_DataFrame::PayloadTypes)newType;
1202 PTRACE(3, "H323RTP\tSet dynamic payload type to " << rtpPayloadType);
1203 return TRUE;
1207 /////////////////////////////////////////////////////////////////////////////
1209 H323_RTPChannel::H323_RTPChannel(H323Connection & conn,
1210 const H323Capability & cap,
1211 Directions direction,
1212 RTP_Session & r)
1213 : H323_RealTimeChannel(conn, cap, direction),
1214 rtpSession(r),
1215 rtpCallbacks(*(H323_RTP_Session *)r.GetUserData())
1217 // If we are the receiver of RTP data then we create a source media stream
1218 mediaStream = conn.CreateMediaStream(capability->GetMediaFormat(), GetSessionID(), receiver);
1219 PTRACE(3, "H323RTP\t" << (receiver ? "Receiver" : "Transmitter")
1220 << " created using session " << GetSessionID());
1224 H323_RTPChannel::~H323_RTPChannel()
1226 // Finished with the RTP session, this will delete the session if it is no
1227 // longer referenced by any logical channels.
1228 connection.ReleaseSession(GetSessionID());
1232 unsigned H323_RTPChannel::GetSessionID() const
1234 return rtpSession.GetSessionID();
1238 BOOL H323_RTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
1240 return rtpCallbacks.OnSendingPDU(*this, param);
1244 void H323_RTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
1246 rtpCallbacks.OnSendingAckPDU(*this, param);
1250 BOOL H323_RTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
1251 unsigned & errorCode)
1253 return rtpCallbacks.OnReceivedPDU(*this, param, errorCode);
1257 BOOL H323_RTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
1259 return rtpCallbacks.OnReceivedAckPDU(*this, param);
1263 /////////////////////////////////////////////////////////////////////////////
1265 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
1266 const H323Capability & capability,
1267 Directions direction,
1268 unsigned id)
1269 : H323_RealTimeChannel(connection, capability, direction)
1271 Construct(connection, id);
1275 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
1276 const H323Capability & capability,
1277 Directions direction,
1278 unsigned id,
1279 const H323TransportAddress & data,
1280 const H323TransportAddress & control)
1281 : H323_RealTimeChannel(connection, capability, direction),
1282 externalMediaAddress(data),
1283 externalMediaControlAddress(control)
1285 Construct(connection, id);
1289 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
1290 const H323Capability & capability,
1291 Directions direction,
1292 unsigned id,
1293 const PIPSocket::Address & ip,
1294 WORD dataPort)
1295 : H323_RealTimeChannel(connection, capability, direction),
1296 externalMediaAddress(ip, dataPort),
1297 externalMediaControlAddress(ip, (WORD)(dataPort+1))
1299 Construct(connection, id);
1302 void H323_ExternalRTPChannel::Construct(H323Connection & conn, unsigned id)
1304 mediaStream = new OpalNullMediaStream(conn, capability->GetMediaFormat(), id, receiver);
1305 sessionID = id;
1307 PTRACE(3, "H323RTP\tExternal " << (receiver ? "receiver" : "transmitter")
1308 << " created using session " << GetSessionID());
1312 unsigned H323_ExternalRTPChannel::GetSessionID() const
1314 return sessionID;
1318 BOOL H323_ExternalRTPChannel::GetMediaTransportAddress(OpalTransportAddress & data,
1319 OpalTransportAddress & control) const
1321 data = remoteMediaAddress;
1322 control = remoteMediaControlAddress;
1324 if (data.IsEmpty() && control.IsEmpty())
1325 return FALSE;
1327 PIPSocket::Address ip;
1328 WORD port;
1329 if (data.IsEmpty()) {
1330 if (control.GetIpAndPort(ip, port))
1331 data = OpalTransportAddress(ip, (WORD)(port-1));
1333 else if (control.IsEmpty()) {
1334 if (data.GetIpAndPort(ip, port))
1335 control = OpalTransportAddress(ip, (WORD)(port+1));
1338 return TRUE;
1342 BOOL H323_ExternalRTPChannel::Start()
1344 OpalConnection * otherParty = connection.GetCall().GetOtherPartyConnection(connection);
1345 if (otherParty == NULL)
1346 return FALSE;
1348 OpalConnection::MediaInformation info;
1349 if (!otherParty->GetMediaInformation(sessionID, info))
1350 return FALSE;
1352 externalMediaAddress = info.data;
1353 externalMediaControlAddress = info.control;
1354 return Open();
1358 void H323_ExternalRTPChannel::Receive()
1360 // Do nothing
1364 void H323_ExternalRTPChannel::Transmit()
1366 // Do nothing
1370 BOOL H323_ExternalRTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
1372 param.m_sessionID = sessionID;
1374 param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaGuaranteedDelivery);
1375 param.m_mediaGuaranteedDelivery = FALSE;
1377 param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_silenceSuppression);
1378 param.m_silenceSuppression = FALSE;
1380 // unicast must have mediaControlChannel
1381 param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel);
1382 externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
1384 if (receiver) {
1385 // set mediaChannel
1386 param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
1387 externalMediaAddress.SetPDU(param.m_mediaChannel);
1390 return TRUE;
1394 void H323_ExternalRTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
1396 // set mediaControlChannel
1397 param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel);
1398 externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
1400 // set mediaChannel
1401 param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
1402 externalMediaAddress.SetPDU(param.m_mediaChannel);
1406 BOOL H323_ExternalRTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
1407 unsigned & errorCode)
1409 // Only support a single audio session
1410 if (param.m_sessionID != sessionID) {
1411 PTRACE(1, "LogChan\tOpen for invalid session: " << param.m_sessionID);
1412 errorCode = H245_OpenLogicalChannelReject_cause::e_invalidSessionID;
1413 return FALSE;
1416 if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
1417 PTRACE(1, "LogChan\tNo mediaControlChannel specified");
1418 errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
1419 return FALSE;
1422 remoteMediaControlAddress = param.m_mediaControlChannel;
1423 if (remoteMediaControlAddress.IsEmpty())
1424 return FALSE;
1426 if (param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
1427 remoteMediaAddress = param.m_mediaChannel;
1428 if (remoteMediaAddress.IsEmpty())
1429 return FALSE;
1431 else {
1432 PIPSocket::Address addr;
1433 WORD port;
1434 if (!remoteMediaControlAddress.GetIpAndPort(addr, port))
1435 return FALSE;
1436 remoteMediaAddress = OpalTransportAddress(addr, port-1);
1439 unsigned id = param.m_sessionID;
1440 if (!remoteMediaAddress.IsEmpty() && (connection.GetMediaTransportAddresses().GetAt(id) == NULL))
1441 connection.GetMediaTransportAddresses().SetAt(id, new OpalTransportAddress(remoteMediaAddress));
1443 return TRUE;
1447 BOOL H323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
1449 if (param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID) && (param.m_sessionID != sessionID)) {
1450 PTRACE(2, "LogChan\tAck for invalid session: " << param.m_sessionID);
1454 if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel)) {
1455 PTRACE(1, "LogChan\tNo mediaControlChannel specified");
1456 return FALSE;
1459 remoteMediaControlAddress = param.m_mediaControlChannel;
1460 if (remoteMediaControlAddress.IsEmpty())
1461 return FALSE;
1463 if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
1464 PTRACE(1, "LogChan\tNo mediaChannel specified");
1465 return FALSE;
1468 remoteMediaAddress = param.m_mediaChannel;
1469 if (remoteMediaAddress.IsEmpty())
1470 return FALSE;
1472 unsigned id = param.m_sessionID;
1473 if (!remoteMediaAddress.IsEmpty() && (connection.GetMediaTransportAddresses().GetAt(id) == NULL))
1474 connection.GetMediaTransportAddresses().SetAt(id, new OpalTransportAddress(remoteMediaAddress));
1476 return TRUE;
1480 void H323_ExternalRTPChannel::SetExternalAddress(const H323TransportAddress & data,
1481 const H323TransportAddress & control)
1483 externalMediaAddress = data;
1484 externalMediaControlAddress = control;
1486 if (data.IsEmpty() || control.IsEmpty()) {
1487 PIPSocket::Address ip;
1488 WORD port;
1489 if (data.GetIpAndPort(ip, port))
1490 externalMediaControlAddress = H323TransportAddress(ip, (WORD)(port+1));
1491 else if (control.GetIpAndPort(ip, port))
1492 externalMediaAddress = H323TransportAddress(ip, (WORD)(port-1));
1497 BOOL H323_ExternalRTPChannel::GetRemoteAddress(PIPSocket::Address & ip,
1498 WORD & dataPort) const
1500 if (!remoteMediaControlAddress) {
1501 if (remoteMediaControlAddress.GetIpAndPort(ip, dataPort)) {
1502 dataPort--;
1503 return TRUE;
1507 if (!remoteMediaAddress)
1508 return remoteMediaAddress.GetIpAndPort(ip, dataPort);
1510 return FALSE;
1514 /////////////////////////////////////////////////////////////////////////////
1516 H323DataChannel::H323DataChannel(H323Connection & conn,
1517 const H323Capability & cap,
1518 Directions dir,
1519 unsigned id)
1520 : H323UnidirectionalChannel(conn, cap, dir)
1522 sessionID = id;
1523 listener = NULL;
1524 autoDeleteListener = TRUE;
1525 transport = NULL;
1526 autoDeleteTransport = TRUE;
1527 separateReverseChannel = FALSE;
1531 H323DataChannel::~H323DataChannel()
1533 if (autoDeleteListener)
1534 delete listener;
1535 if (autoDeleteTransport)
1536 delete transport;
1540 void H323DataChannel::Close()
1542 if (terminating)
1543 return;
1545 PTRACE(4, "LogChan\tCleaning up data channel " << number);
1547 // Break any I/O blocks and wait for the thread that uses this object to
1548 // terminate before we allow it to be deleted.
1549 if (listener != NULL)
1550 listener->Close();
1551 if (transport != NULL)
1552 transport->Close();
1554 H323UnidirectionalChannel::Close();
1558 unsigned H323DataChannel::GetSessionID() const
1560 return sessionID;
1564 BOOL H323DataChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
1566 PTRACE(3, "LogChan\tOnSendingPDU for channel: " << number);
1568 open.m_forwardLogicalChannelNumber = (unsigned)number;
1570 open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
1571 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
1572 ::e_h2250LogicalChannelParameters);
1573 H245_H2250LogicalChannelParameters & fparam = open.m_forwardLogicalChannelParameters.m_multiplexParameters;
1574 fparam.m_sessionID = GetSessionID();
1576 if (separateReverseChannel)
1577 return TRUE;
1579 open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
1580 open.m_reverseLogicalChannelParameters.IncludeOptionalField(
1581 H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
1582 open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
1583 H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
1584 ::e_h2250LogicalChannelParameters);
1585 H245_H2250LogicalChannelParameters & rparam = open.m_reverseLogicalChannelParameters.m_multiplexParameters;
1586 rparam.m_sessionID = GetSessionID();
1588 return capability->OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType);
1592 void H323DataChannel::OnSendOpenAck(const H245_OpenLogicalChannel & /*open*/,
1593 H245_OpenLogicalChannelAck & ack) const
1595 if (listener == NULL && transport == NULL) {
1596 PTRACE(2, "LogChan\tOnSendOpenAck without a listener or transport");
1597 return;
1600 PTRACE(3, "LogChan\tOnSendOpenAck for channel: " << number);
1602 H245_H2250LogicalChannelAckParameters * param;
1604 if (separateReverseChannel) {
1605 ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
1606 ack.m_forwardMultiplexAckParameters.SetTag(
1607 H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
1608 param = (H245_H2250LogicalChannelAckParameters*)&ack.m_forwardMultiplexAckParameters.GetObject();
1610 else {
1611 ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters);
1612 ack.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
1613 H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
1614 ::e_h2250LogicalChannelParameters);
1615 param = (H245_H2250LogicalChannelAckParameters*)
1616 &ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetObject();
1619 unsigned session = GetSessionID();
1620 if (session != 0) {
1621 param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
1622 param->m_sessionID = GetSessionID();
1625 H323TransportAddress address;
1626 param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
1627 if (listener != NULL)
1628 address = listener->GetLocalAddress(connection.GetControlChannel().GetLocalAddress());
1629 else
1630 address = transport->GetLocalAddress();
1632 address.SetPDU(param->m_mediaChannel);
1636 BOOL H323DataChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
1637 unsigned & errorCode)
1639 number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
1641 PTRACE(3, "LogChan\tOnReceivedPDU for data channel: " << number);
1643 if (!CreateListener()) {
1644 PTRACE(1, "LogChan\tCould not create listener");
1645 errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
1646 return FALSE;
1649 if (separateReverseChannel &&
1650 open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
1651 errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
1652 PTRACE(1, "LogChan\tOnReceivedPDU has unexpected reverse parameters");
1653 return FALSE;
1656 if (!capability->OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_dataType, receiver)) {
1657 PTRACE(1, "H323RTP\tData type not supported");
1658 errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
1659 return FALSE;
1662 return TRUE;
1666 BOOL H323DataChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
1668 PTRACE(3, "LogChan\tOnReceivedAckPDU");
1670 const H245_TransportAddress * address;
1672 if (separateReverseChannel) {
1673 PTRACE(3, "LogChan\tseparateReverseChannels");
1674 if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
1675 PTRACE(1, "LogChan\tNo forwardMultiplexAckParameters");
1676 return FALSE;
1679 if (ack.m_forwardMultiplexAckParameters.GetTag() !=
1680 H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
1681 PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
1682 return FALSE;
1685 const H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
1687 if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
1688 PTRACE(1, "LogChan\tNo media channel address provided");
1689 return FALSE;
1692 address = &param.m_mediaChannel;
1694 if (ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
1695 PTRACE(3, "LogChan\treverseLogicalChannelParameters set");
1696 reverseChannel = H323ChannelNumber(ack.m_reverseLogicalChannelParameters.m_reverseLogicalChannelNumber, TRUE);
1699 else {
1700 if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
1701 PTRACE(1, "LogChan\tNo reverseLogicalChannelParameters");
1702 return FALSE;
1705 if (ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() !=
1706 H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
1707 ::e_h2250LogicalChannelParameters) {
1708 PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
1709 return FALSE;
1712 const H245_H2250LogicalChannelParameters & param = ack.m_reverseLogicalChannelParameters.m_multiplexParameters;
1714 if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
1715 PTRACE(1, "LogChan\tNo media channel address provided");
1716 return FALSE;
1719 address = &param.m_mediaChannel;
1722 if (!CreateTransport()) {
1723 PTRACE(1, "LogChan\tCould not create transport");
1724 return FALSE;
1727 if (!transport->ConnectTo(H323TransportAddress(*address))) {
1728 PTRACE(1, "LogChan\tCould not connect to remote transport address: " << *address);
1729 return FALSE;
1732 return TRUE;
1736 BOOL H323DataChannel::CreateListener()
1738 if (listener == NULL) {
1739 listener = connection.GetControlChannel().GetLocalAddress().CreateListener(
1740 connection.GetEndPoint(), OpalTransportAddress::HostOnly);
1741 if (listener == NULL)
1742 return FALSE;
1744 PTRACE(3, "LogChan\tCreated listener for data channel: " << *listener);
1747 return listener->Open(NULL);
1751 BOOL H323DataChannel::CreateTransport()
1753 if (transport == NULL) {
1754 transport = connection.GetControlChannel().GetLocalAddress().CreateTransport(
1755 connection.GetEndPoint(), OpalTransportAddress::HostOnly);
1756 if (transport == NULL)
1757 return FALSE;
1759 PTRACE(3, "LogChan\tCreated transport for data channel: " << *transport);
1762 return transport != NULL;
1766 /////////////////////////////////////////////////////////////////////////////