D:/Storage/CVS_Head/h323plus/src/channels.cxx

00001 /*
00002  * channels.cxx
00003  *
00004  * H.323 protocol handler
00005  *
00006  * Open H323 Library
00007  *
00008  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
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 H323 Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions of this code were written with the assisance of funding from
00025  * Vovida Networks, Inc. http://www.vovida.com.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Log: channels.cxx,v $
00030  * Revision 1.1  2007/08/06 20:51:03  shorne
00031  * First commit of h323plus
00032  *
00033  * Revision 1.147.2.1  2007/05/23 06:58:02  shorne
00034  * Nat Support for EP's nested behind same NAT
00035  *
00036  * Revision 1.147  2006/03/21 10:42:25  csoutheren
00037  * Disable automatic payload type changes for video codecs
00038  *
00039  * Revision 1.146  2005/06/21 06:44:34  csoutheren
00040  * Added assert for capabilities that do not have codecs
00041  *
00042  * Revision 1.145  2005/01/03 06:25:54  csoutheren
00043  * Added extensive support for disabling code modules at compile time
00044  *
00045  * Revision 1.144  2004/07/27 05:28:45  csoutheren
00046  * Added ability to set priority of channel threads
00047  *
00048  * Revision 1.143  2004/07/17 03:10:06  rjongbloed
00049  * Fixed possible endless loop in RTP receive thread, thanks Gustavo García Bernardo
00050  *
00051  * Revision 1.142  2004/07/14 01:03:20  csoutheren
00052  * Ensure payload type is set before codec Read function is called
00053  *
00054  * Revision 1.141  2004/07/07 03:53:45  csoutheren
00055  * Fixed non-faststart comptibility problem with Cisco gateways. Apparently, they do not return a session ID in the OLCack in non-fastStart mode but they do in fastStart mode (who'da - guessed that !)
00056  *
00057  * Revision 1.140  2004/07/03 06:51:37  rjongbloed
00058  * Added PTRACE_PARAM() macro to fix warnings on parameters used in PTRACE
00059  *  macros only.
00060  *
00061  * Revision 1.139  2004/07/03 05:47:54  rjongbloed
00062  * Added virtual function for determining RTP payload type used in an H.323 channel,
00063  *    also some added bullet proofing for exception conditions, thanks Guilhem Tardy
00064  *
00065  * Revision 1.138  2004/05/23 12:03:04  rjongbloed
00066  * Fix problem with crashing on debug if change log level in mid call, thanks Ben Lear
00067  *
00068  * Revision 1.137  2004/04/03 08:28:06  csoutheren
00069  * Remove pseudo-RTTI and replaced with real RTTI
00070  *
00071  * Revision 1.136  2003/02/10 05:36:13  robertj
00072  * Fixed returning mediaControlChannel address in preference to mediaChannel
00073  *   address as Cisco's just feed your own address back at you.
00074  *
00075  * Revision 1.135  2002/12/18 11:20:49  craigs
00076  * Fixed problem with T.38 channels SEGVing thanks to Vyacheslav Frolov
00077  *
00078  * Revision 1.134  2002/12/17 08:48:09  robertj
00079  * Set silence suppression mode earlier in codec life so gets correct
00080  *   value for silenceSuppression in fast start OLC's.
00081  *
00082  * Revision 1.133  2002/12/16 08:20:04  robertj
00083  * Fixed problem where a spurious RTP packet full of zeros could be sent
00084  *   at the beginning of the transmission, thanks Bruce Fitzsimons
00085  *
00086  * Revision 1.132  2002/11/26 02:59:25  robertj
00087  * Added logging to help find logical channel thread stop failures.
00088  *
00089  * Revision 1.131  2002/10/31 00:37:47  robertj
00090  * Enhanced jitter buffer system so operates dynamically between minimum and
00091  *   maximum values. Altered API to assure app writers note the change!
00092  *
00093  * Revision 1.130  2002/08/05 10:03:47  robertj
00094  * Cosmetic changes to normalise the usage of pragma interface/implementation.
00095  *
00096  * Revision 1.129  2002/06/28 03:34:28  robertj
00097  * Fixed issues with address translation on gatekeeper RAS channel.
00098  *
00099  * Revision 1.128  2002/06/25 08:30:12  robertj
00100  * Changes to differentiate between stright G.723.1 and G.723.1 Annex A using
00101  *   the OLC dataType silenceSuppression field so does not send SID frames
00102  *   to receiver codecs that do not understand them.
00103  *
00104  * Revision 1.127  2002/06/24 00:07:31  robertj
00105  * Fixed bandwidth usage being exactly opposite (adding when it should
00106  *   be subtracting), thanks Saswat Praharaj.
00107  *
00108  * Revision 1.126  2002/05/23 04:53:57  robertj
00109  * Added function to remove a filter from logical channel.
00110  *
00111  * Revision 1.125  2002/05/10 05:47:15  robertj
00112  * Added session ID to the data logical channel class.
00113  *
00114  * Revision 1.124  2002/05/07 23:49:11  robertj
00115  * Fixed incorrect setting of session ID in data channel OLC, caused an
00116  *   incorrect optional field to be included, thanks Ulrich Findeisen.
00117  *
00118  * Revision 1.123  2002/05/03 00:07:24  robertj
00119  * Fixed missing setting of isRunning flag in external RTP channels.
00120  *
00121  * Revision 1.122  2002/05/02 07:56:27  robertj
00122  * Added automatic clearing of call if no media (RTP data) is transferred in a
00123  *   configurable (default 5 minutes) amount of time.
00124  *
00125  * Revision 1.121  2002/05/02 06:28:53  robertj
00126  * Fixed problem with external RTP channels not fast starting.
00127  *
00128  * Revision 1.120  2002/04/17 05:56:05  robertj
00129  * Added trace output of H323Channel::Direction enum.
00130  *
00131  * Revision 1.119  2002/02/25 08:42:26  robertj
00132  * Fixed comments on the real time requirements of the codec.
00133  *
00134  * Revision 1.118  2002/02/19 06:15:20  robertj
00135  * Allowed for RTP filter functions to force output of packet, or prevent it
00136  *   from being sent overriding the n frames per packet algorithm.
00137  *
00138  * Revision 1.117  2002/02/09 04:39:05  robertj
00139  * Changes to allow T.38 logical channels to use single transport which is
00140  *   now owned by the OpalT38Protocol object instead of H323Channel.
00141  *
00142  * Revision 1.116  2002/02/05 08:13:02  robertj
00143  * Added ability to not have addresses when external RTP channel created.
00144  *
00145  * Revision 1.115  2002/02/04 06:04:19  robertj
00146  * Fixed correct exit on terminating transmit channel, thanks Norwood Systems.
00147  *
00148  * Revision 1.114  2002/01/27 10:49:51  rogerh
00149  * Catch a division by zero case in a PTRACE()
00150  *
00151  * Revision 1.113  2002/01/24 03:33:07  robertj
00152  * Fixed payload type being incorrect for audio after sending RFC2833 packet.
00153  *
00154  * Revision 1.112  2002/01/22 22:48:25  robertj
00155  * Fixed RFC2833 support (transmitter) requiring large rewrite
00156  *
00157  * Revision 1.111  2002/01/22 07:08:26  robertj
00158  * Added IllegalPayloadType enum as need marker for none set
00159  *   and MaxPayloadType is a legal value.
00160  *
00161  * Revision 1.110  2002/01/22 06:05:03  robertj
00162  * Added ability for RTP payload type to be overridden at capability level.
00163  *
00164  * Revision 1.109  2002/01/17 07:05:03  robertj
00165  * Added support for RFC2833 embedded DTMF in the RTP stream.
00166  *
00167  * Revision 1.108  2002/01/17 00:10:37  robertj
00168  * Fixed double copy of rtpPayloadType in RTP channel, caused much confusion.
00169  *
00170  * Revision 1.107  2002/01/14 05:18:44  robertj
00171  * Fixed typo on external RTP channel constructor.
00172  *
00173  * Revision 1.106  2002/01/10 05:13:54  robertj
00174  * Added support for external RTP stacks, thanks NuMind Software Systems.
00175  *
00176  * Revision 1.105  2002/01/09 06:05:55  robertj
00177  * Rearranged transmitter timestamp calculation to allow for a codec that has
00178  *   variable number of timestamp units per call to Read().
00179  *
00180  * Revision 1.104  2001/12/22 01:50:47  robertj
00181  * Fixed bug in data channel (T.38) negotiations, using wrong PDU subclass.
00182  * Fixed using correct port number in data channel (T.38) negotiations.
00183  * Improved trace logging.
00184  *
00185  * Revision 1.103  2001/11/28 00:09:14  dereks
00186  * Additional information in PTRACE output.
00187  *
00188  * Revision 1.102  2001/11/09 05:39:54  craigs
00189  * Added initial T.38 support thanks to Adam Lazur
00190  *
00191  * Revision 1.101  2001/10/24 00:55:49  robertj
00192  * Made cosmetic changes to H.245 miscellaneous command function.
00193  *
00194  * Revision 1.100  2001/10/23 02:17:16  dereks
00195  * Initial release of cu30 video codec.
00196  *
00197  * Revision 1.99  2001/09/13 08:20:27  robertj
00198  * Fixed broken back out of rev 1.95, thanks Santiago Garcia Mantinan
00199  *
00200  * Revision 1.98  2001/09/11 00:21:23  robertj
00201  * Fixed missing stack sizes in endpoint for cleaner thread and jitter thread.
00202  *
00203  * Revision 1.97  2001/08/28 09:28:28  robertj
00204  * Backed out change in revision 1.95, not compatible with G.711
00205  *
00206  * Revision 1.96  2001/08/16 06:34:42  robertj
00207  * Plugged memory leak if using trace level 5.
00208  *
00209  * Revision 1.95  2001/08/10 01:34:41  robertj
00210  * Fixed problem with incorrect timestamp if codec returns more than one
00211  *    frame in read, thanks Lee Kirchhoff.
00212  *
00213  * Revision 1.94  2001/08/06 05:36:00  robertj
00214  * Fixed GNU warnings.
00215  *
00216  * Revision 1.93  2001/08/06 03:08:56  robertj
00217  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
00218  *
00219  * Revision 1.92  2001/07/24 02:26:44  robertj
00220  * Added start for handling reverse channels.
00221  *
00222  * Revision 1.91  2001/07/17 04:44:31  robertj
00223  * Partial implementation of T.120 and T.38 logical channels.
00224  *
00225  * Revision 1.90  2001/07/12 07:28:41  yurik
00226  * WinCE fix: Sleep(0) in Main to get system chance to digest
00227  *
00228  * Revision 1.89  2001/06/15 07:20:35  robertj
00229  * Moved OnClosedLogicalChannel() to be after channels threads halted.
00230  *
00231  * Revision 1.88  2001/06/02 01:35:32  robertj
00232  * Added thread names.
00233  *
00234  * Revision 1.87  2001/05/31 06:29:48  robertj
00235  * Changed trace of RTP mismatch so only displays for first n packets then
00236  *   does not dump messages any more. Was exactly the opposite.
00237  *
00238  * Revision 1.86  2001/04/20 02:32:07  robertj
00239  * Improved logging of bandwith, used more intuitive units.
00240  *
00241  * Revision 1.85  2001/04/02 04:12:53  robertj
00242  * Fixed trace output from packet transmit timing.
00243  *
00244  * Revision 1.84  2001/03/23 05:38:30  robertj
00245  * Added PTRACE_IF to output trace if a conditional is TRUE.
00246  *
00247  * Revision 1.83  2001/02/09 05:13:55  craigs
00248  * Added pragma implementation to (hopefully) reduce the executable image size
00249  * under Linux
00250  *
00251  * Revision 1.82  2001/02/07 05:04:45  robertj
00252  * Improved codec read analysis debug output.
00253  *
00254  * Revision 1.81  2001/02/06 07:40:46  robertj
00255  * Added debugging for timing of codec read.
00256  *
00257  * Revision 1.80  2001/01/25 07:27:16  robertj
00258  * Major changes to add more flexible OpalMediaFormat class to normalise
00259  *   all information about media types, especially codecs.
00260  *
00261  * Revision 1.79  2000/12/20 00:50:42  robertj
00262  * Fixed MSVC compatibility issues (No trace).
00263  *
00264  * Revision 1.78  2000/12/19 22:33:44  dereks
00265  * Adjust so that the video channel is used for reading/writing raw video
00266  * data, which better modularizes the video codec.
00267  *
00268  * Revision 1.77  2000/12/17 22:45:36  robertj
00269  * Set media stream threads to highest unprivileged priority.
00270  *
00271  * Revision 1.76  2000/11/24 10:52:50  robertj
00272  * Modified the ReadFrame/WriteFrame functions to allow for variable length codecs.
00273  * Added support for G.729 annex B packetisation scheme in RTP.
00274  * Fixed bug in fast started G.711 codec not working in one direction.
00275  *
00276  * Revision 1.75  2000/10/24 00:00:09  robertj
00277  * Improved memory hogging hash function for logical channels.
00278  *
00279  * Revision 1.74  2000/10/19 04:05:01  robertj
00280  * Added compare function for logical channel numbers, thanks Yuriy Ershov.
00281  *
00282  * Revision 1.73  2000/09/23 06:54:44  robertj
00283  * Prevented call of OnClose call back if channel was never opened.
00284  *
00285  * Revision 1.72  2000/09/22 01:35:49  robertj
00286  * Added support for handling LID's that only do symmetric codecs.
00287  *
00288  * Revision 1.71  2000/09/22 00:32:33  craigs
00289  * Added extra logging
00290  * Fixed problems with no fastConnect with tunelling
00291  *
00292  * Revision 1.70  2000/09/20 01:50:21  craigs
00293  * Added ability to set jitter buffer on a per-connection basis
00294  *
00295  * Revision 1.69  2000/09/14 23:03:45  robertj
00296  * Increased timeout on asserting because of driver lockup
00297  *
00298  * Revision 1.68  2000/08/31 08:15:40  robertj
00299  * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
00300  *
00301  * Revision 1.67  2000/08/30 06:33:01  craigs
00302  * Add fix to ignore small runs of consectuive mismatched payload types
00303  *
00304  * Revision 1.66  2000/08/25 01:10:28  robertj
00305  * Added assert if various thrads ever fail to terminate.
00306  *
00307  * Revision 1.65  2000/08/21 02:50:28  robertj
00308  * Fixed race condition if close call just as slow start media channels are opening.
00309  *
00310  * Revision 1.64  2000/07/14 14:04:49  robertj
00311  * Clarified a debug message.
00312  *
00313  * Revision 1.63  2000/07/14 12:47:36  robertj
00314  * Added clarification to some logging messags.
00315  *
00316  * Revision 1.62  2000/07/13 16:05:47  robertj
00317  * Removed time critical priority as it can totally slag a Win98 system.
00318  * Fixed trace message displaying mismatched codecs in RTP packet around the wrong way.
00319  *
00320  * Revision 1.61  2000/07/11 11:15:52  robertj
00321  * Fixed bug when terminating RTP receiver and not also terminating transmitter.
00322  *
00323  * Revision 1.60  2000/06/23 02:04:01  robertj
00324  * Increased the priority of the media channels, only relevent for Win32 at this time.
00325  *
00326  * Revision 1.59  2000/06/15 01:46:15  robertj
00327  * Added channel pause (aka mute) functions.
00328  *
00329  * Revision 1.58  2000/05/18 12:10:50  robertj
00330  * Removed all Sleep() calls in codec as timing innacuracies make it unusable. All
00331  *    codec implementations must thus have timing built into them, usually using I/O.
00332  *
00333  * Revision 1.57  2000/05/11 23:54:25  craigs
00334  * Fixed the Windows fix with another Linux fix. But it worked OK on the Alpha!
00335  *
00336  * Revision 1.56  2000/05/11 09:56:46  robertj
00337  * Win32 compatibility and addition of some extra debugging on codec timing.
00338  *
00339  * Revision 1.55  2000/05/11 02:27:18  robertj
00340  * Added "fail safe" timer sleep on codec writes when on output of jitter buffer.
00341  *
00342  * Revision 1.54  2000/05/04 11:52:34  robertj
00343  * Added Packets Too Late statistics, requiring major rearrangement of jitter
00344  *    buffer code, not also changes semantics of codec Write() function slightly.
00345  *
00346  * Revision 1.53  2000/05/02 04:32:26  robertj
00347  * Fixed copyright notice comment.
00348  *
00349  * Revision 1.52  2000/05/01 01:01:49  robertj
00350  * Added flag for what to do with out of orer packets (use if jitter, don't if not).
00351  *
00352  * Revision 1.51  2000/04/28 13:01:44  robertj
00353  * Fixed problem with adjusting tx/rx frame counts in capabilities during fast start.
00354  *
00355  * Revision 1.50  2000/04/10 19:45:49  robertj
00356  * Changed RTP data receive tp be more forgiving, will process packet even if payload type is wrong.
00357  *
00358  * Revision 1.49  2000/03/31 20:04:28  robertj
00359  * Fixed log message for start/end of transmitted talk burst.
00360  *
00361  * Revision 1.48  2000/03/29 04:36:38  robertj
00362  * Improved some trace logging messages.
00363  *
00364  * Revision 1.47  2000/03/22 01:31:36  robertj
00365  * Fixed transmitter loop so codec can return multiple frames (crash in G.711 mode)
00366  *
00367  * Revision 1.46  2000/03/21 03:58:00  robertj
00368  * Fixed stuffed up RTP transmit loop after previous change.
00369  *
00370  * Revision 1.45  2000/03/21 03:06:49  robertj
00371  * Changes to make RTP TX of exact numbers of frames in some codecs.
00372  *
00373  * Revision 1.44  2000/03/20 20:59:28  robertj
00374  * Fixed possible buffer overrun problem in RTP_DataFrames
00375  *
00376  * Revision 1.43  2000/02/24 00:34:25  robertj
00377  * Fixed possible endless loop on channel abort, thanks Yura Ershov
00378  *
00379  * Revision 1.42  2000/02/04 05:11:19  craigs
00380  * Updated for new Makefiles and for new video transmission code
00381  *
00382  * Revision 1.41  2000/01/13 04:03:45  robertj
00383  * Added video transmission
00384  *
00385  * Revision 1.40  2000/01/08 06:52:10  robertj
00386  * Removed invalid assert
00387  *
00388  * Revision 1.39  1999/12/23 23:02:35  robertj
00389  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
00390  *
00391  * Revision 1.38  1999/11/22 01:37:31  robertj
00392  * Fixed channel closure so OnClosedLogicalChannel() only called if channel was actually started.
00393  *
00394  * Revision 1.37  1999/11/20 05:35:26  robertj
00395  * Extra debugging
00396  *
00397  * Revision 1.36  1999/11/20 00:53:47  robertj
00398  * Fixed ability to have variable sized frames in single RTP packet under G.723.1
00399  *
00400  * Revision 1.35  1999/11/19 09:06:25  robertj
00401  * Changed to close down logical channel if get a transmit codec error.
00402  *
00403  * Revision 1.34  1999/11/11 23:28:46  robertj
00404  * Added first cut silence detection algorithm.
00405  *
00406  * Revision 1.33  1999/11/06 11:01:37  robertj
00407  * Extra debugging.
00408  *
00409  * Revision 1.32  1999/11/06 05:37:44  robertj
00410  * Complete rewrite of termination of connection to avoid numerous race conditions.
00411  *
00412  * Revision 1.31  1999/11/01 00:47:46  robertj
00413  * Added close of logical channel on write error
00414  *
00415  * Revision 1.30  1999/10/30 12:38:24  robertj
00416  * Added more tracing of channel threads.
00417  *
00418  * Revision 1.29  1999/10/08 09:59:03  robertj
00419  * Rewrite of capability for sending multiple audio frames
00420  *
00421  * Revision 1.28  1999/10/08 04:58:37  robertj
00422  * Added capability for sending multiple audio frames in single RTP packet
00423  *
00424  * Revision 1.27  1999/09/23 07:25:12  robertj
00425  * Added open audio and video function to connection and started multi-frame codec send functionality.
00426  *
00427  * Revision 1.26  1999/09/21 14:09:02  robertj
00428  * Removed warnings when no tracing enabled.
00429  *
00430  * Revision 1.25  1999/09/18 13:24:38  craigs
00431  * Added ability to disable jitter buffer
00432  * Added ability to access entire RTP packet in codec Write
00433  *
00434  * Revision 1.24  1999/09/08 04:05:48  robertj
00435  * Added support for video capabilities & codec, still needs the actual codec itself!
00436  *
00437  * Revision 1.23  1999/09/03 02:17:50  robertj
00438  * Added more debugging
00439  *
00440  * Revision 1.22  1999/08/31 12:34:18  robertj
00441  * Added gatekeeper support.
00442  *
00443  * Revision 1.21  1999/07/16 15:02:51  robertj
00444  * Changed jitter buffer to throw away old packets if jitter exceeded.
00445  *
00446  * Revision 1.20  1999/07/16 00:51:03  robertj
00447  * Some more debugging of fast start.
00448  *
00449  * Revision 1.19  1999/07/15 14:45:35  robertj
00450  * Added propagation of codec open error to shut down logical channel.
00451  * Fixed control channel start up bug introduced with tunnelling.
00452  *
00453  * Revision 1.18  1999/07/15 09:04:31  robertj
00454  * Fixed some fast start bugs
00455  *
00456  * Revision 1.17  1999/07/14 06:04:04  robertj
00457  * Fixed setting of channel number in fast start.
00458  *
00459  * Revision 1.16  1999/07/13 09:53:24  robertj
00460  * Fixed some problems with jitter buffer and added more debugging.
00461  *
00462  * Revision 1.15  1999/07/13 02:50:58  craigs
00463  * Changed semantics of SetPlayDevice/SetRecordDevice, only descendent
00464  *    endpoint assumes PSoundChannel devices for audio codec.
00465  *
00466  * Revision 1.14  1999/07/10 03:01:48  robertj
00467  * Removed debugging.
00468  *
00469  * Revision 1.13  1999/07/09 06:09:49  robertj
00470  * Major implementation. An ENORMOUS amount of stuff added everywhere.
00471  *
00472  * Revision 1.12  1999/06/25 14:19:40  robertj
00473  * Fixed termination race condition in logical channel tear down.
00474  *
00475  * Revision 1.11  1999/06/24 13:32:45  robertj
00476  * Fixed ability to change sound device on codec and fixed NM3 G.711 compatibility
00477  *
00478  * Revision 1.10  1999/06/22 13:49:40  robertj
00479  * Added GSM support and further RTP protocol enhancements.
00480  *
00481  * Revision 1.9  1999/06/14 05:15:55  robertj
00482  * Changes for using RTP sessions correctly in H323 Logical Channel context
00483  *
00484  * Revision 1.8  1999/06/13 12:41:14  robertj
00485  * Implement logical channel transmitter.
00486  * Fixed H245 connect on receiving call.
00487  *
00488  * Revision 1.7  1999/06/09 06:18:00  robertj
00489  * GCC compatibiltiy.
00490  *
00491  * Revision 1.6  1999/06/09 05:26:19  robertj
00492  * Major restructuring of classes.
00493  *
00494  * Revision 1.5  1999/06/07 00:54:30  robertj
00495  * Displayed error on SetOption for buffer size
00496  *
00497  * Revision 1.4  1999/06/06 06:06:36  robertj
00498  * Changes for new ASN compiler and v2 protocol ASN files.
00499  *
00500  * Revision 1.3  1999/04/26 06:14:46  craigs
00501  * Initial implementation for RTP decoding and lots of stuff
00502  * As a whole, these changes are called "First Noise"
00503  *
00504  * Revision 1.2  1999/02/25 03:26:02  robertj
00505  * BeOS compatibility
00506  *
00507  * Revision 1.1  1999/01/16 01:31:09  robertj
00508  * Initial revision
00509  *
00510  */
00511 
00512 #include <ptlib.h>
00513 
00514 #ifdef __GNUC__
00515 #pragma implementation "channels.h"
00516 #endif
00517 
00518 #include "channels.h"
00519 
00520 #include "h323pdu.h"
00521 #include "h323ep.h"
00522 #include "h323rtp.h"
00523 
00524 
00525 
00526 #define MAX_PAYLOAD_TYPE_MISMATCHES 8
00527 #define RTP_TRACE_DISPLAY_RATE 16000 // 2 seconds
00528 
00529 
00530 class H323LogicalChannelThread : public PThread
00531 {
00532     PCLASSINFO(H323LogicalChannelThread, PThread)
00533   public:
00534     H323LogicalChannelThread(H323EndPoint & endpoint, H323Channel & channel, BOOL rx);
00535     void Main();
00536   private:
00537     H323Channel & channel;
00538     BOOL receiver;
00539 };
00540 
00541 
00542 #define new PNEW
00543 
00544 
00545 #if PTRACING
00546 
00547 ostream & operator<<(ostream & out, H323Channel::Directions dir)
00548 {
00549   static const char * const DirNames[H323Channel::NumDirections] = {
00550     "IsBidirectional", "IsTransmitter", "IsReceiver"
00551   };
00552 
00553   if (dir < H323Channel::NumDirections && DirNames[dir] != NULL)
00554     out << DirNames[dir];
00555   else
00556     out << "Direction<" << (unsigned)dir << '>';
00557 
00558   return out;
00559 }
00560 
00561 #endif
00562 
00563 
00565 
00566 H323LogicalChannelThread::H323LogicalChannelThread(H323EndPoint & endpoint,
00567                                                    H323Channel & c,
00568                                                    BOOL rx)
00569   : PThread(endpoint.GetChannelThreadStackSize(),
00570             NoAutoDeleteThread,
00571             endpoint.GetChannelThreadPriority(),
00572             rx ? "LogChanRx:%0x" : "LogChanTx:%0x"),
00573     channel(c)
00574 {
00575   PTRACE(4, "LogChan\tStarting logical channel thread " << this);
00576   receiver = rx;
00577   Resume();
00578 }
00579 
00580 
00581 void H323LogicalChannelThread::Main()
00582 {
00583   PTRACE(4, "LogChan\tStarted logical channel thread " << this);
00584   if (receiver)
00585     channel.Receive();
00586   else
00587     channel.Transmit();
00588 
00589 #ifdef _WIN32_WCE
00590         Sleep(0); // Relinquish control to other thread
00591 #endif
00592 }
00593 
00594 
00596 
00597 H323ChannelNumber::H323ChannelNumber(unsigned num, BOOL fromRem)
00598 {
00599   PAssert(num < 0x10000, PInvalidParameter);
00600   number = num;
00601   fromRemote = fromRem;
00602 }
00603 
00604 
00605 PObject * H323ChannelNumber::Clone() const
00606 {
00607   return new H323ChannelNumber(number, fromRemote);
00608 }
00609 
00610 
00611 PINDEX H323ChannelNumber::HashFunction() const
00612 {
00613   PINDEX hash = (number%17) << 1;
00614   if (fromRemote)
00615     hash++;
00616   return hash;
00617 }
00618 
00619 
00620 void H323ChannelNumber::PrintOn(ostream & strm) const
00621 {
00622   strm << (fromRemote ? 'R' : 'T') << '-' << number;
00623 }
00624 
00625 
00626 PObject::Comparison H323ChannelNumber::Compare(const PObject & obj) const
00627 {
00628 #ifndef PASN_LEANANDMEAN
00629   PAssert(PIsDescendant(this, H323ChannelNumber), PInvalidCast);
00630 #endif
00631   const H323ChannelNumber & other = (const H323ChannelNumber &)obj;
00632   if (number < other.number)
00633     return LessThan;
00634   if (number > other.number)
00635     return GreaterThan;
00636   if (fromRemote && !other.fromRemote)
00637     return LessThan;
00638   if (!fromRemote && other.fromRemote)
00639     return GreaterThan;
00640   return EqualTo;
00641 }
00642 
00643 
00644 H323ChannelNumber & H323ChannelNumber::operator++(int)
00645 {
00646   number++;
00647   return *this;
00648 }
00649 
00650 
00652 
00653 H323Channel::H323Channel(H323Connection & conn, const H323Capability & cap)
00654   : endpoint(conn.GetEndPoint()),
00655     connection(conn)
00656 {
00657   capability = (H323Capability *)cap.Clone();
00658   codec = NULL;
00659   bandwidthUsed = 0;
00660   receiveThread = NULL;
00661   transmitThread = NULL;
00662   terminating = FALSE;
00663   opened = FALSE;
00664   paused = FALSE;
00665 }
00666 
00667 
00668 H323Channel::~H323Channel()
00669 {
00670   connection.UseBandwidth(bandwidthUsed, TRUE);
00671 
00672   delete codec;
00673   delete capability;
00674 }
00675 
00676 
00677 void H323Channel::PrintOn(ostream & strm) const
00678 {
00679   strm << number;
00680 }
00681 
00682 
00683 unsigned H323Channel::GetSessionID() const
00684 {
00685   return 0;
00686 }
00687 
00688 
00689 void H323Channel::CleanUpOnTermination()
00690 {
00691   if (!opened || terminating)
00692     return;
00693 
00694   PTRACE(3, "LogChan\tCleaning up " << number);
00695 
00696   terminating = TRUE;
00697 
00698   // If we have a codec, then close it, this allows the transmitThread to be
00699   // broken out of any I/O block on reading the codec.
00700   if (codec != NULL)
00701     codec->Close();
00702 
00703   // If we have a receiver thread, wait for it to die.
00704   if (receiveThread != NULL) {
00705     PTRACE(4, "LogChan\tAwaiting termination of " << receiveThread << ' ' << receiveThread->GetThreadName());
00706     PAssert(receiveThread->WaitForTermination(10000), "Receive media thread did not terminate");
00707     delete receiveThread;
00708     receiveThread = NULL;
00709   }
00710 
00711   // If we have a transmitter thread, wait for it to die.
00712   if (transmitThread != NULL) {
00713     PTRACE(4, "LogChan\tAwaiting termination of " << transmitThread << ' ' << transmitThread->GetThreadName());
00714     PAssert(transmitThread->WaitForTermination(10000), "Transmit media thread did not terminate");
00715     delete transmitThread;
00716     transmitThread = NULL;
00717   }
00718 
00719   // Signal to the connection that this channel is on the way out
00720   connection.OnClosedLogicalChannel(*this);
00721 
00722   PTRACE(3, "LogChan\tCleaned up " << number);
00723 }
00724 
00725 
00726 BOOL H323Channel::IsRunning() const
00727 {
00728   if (receiveThread  != NULL && !receiveThread ->IsTerminated())
00729     return TRUE;
00730 
00731   if (transmitThread != NULL && !transmitThread->IsTerminated())
00732     return TRUE;
00733 
00734   return FALSE;
00735 }
00736 
00737 
00738 BOOL H323Channel::OnReceivedPDU(const H245_OpenLogicalChannel & /*pdu*/,
00739                                 unsigned & /*errorCode*/)
00740 {
00741   return TRUE;
00742 }
00743 
00744 
00745 BOOL H323Channel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & /*pdu*/)
00746 {
00747   return TRUE;
00748 }
00749 
00750 
00751 void H323Channel::OnSendOpenAck(const H245_OpenLogicalChannel & /*pdu*/,
00752                                 H245_OpenLogicalChannelAck & /* pdu*/) const
00753 {
00754 }
00755 
00756 
00757 void H323Channel::OnFlowControl(long bitRateRestriction)
00758 {
00759   if (GetCodec() != NULL)
00760     codec->OnFlowControl(bitRateRestriction);
00761   else
00762     PTRACE(3, "LogChan\tOnFlowControl: " << bitRateRestriction);
00763 }
00764 
00765 
00766 void H323Channel::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
00767 {
00768   if (GetCodec() != NULL)
00769     codec->OnMiscellaneousCommand(type);
00770   else
00771     PTRACE(3, "LogChan\tOnMiscellaneousCommand: chan=" << number
00772            << ", type=" << type.GetTagName());
00773 }
00774 
00775 
00776 void H323Channel::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type)
00777 {
00778   if (GetCodec() != NULL)
00779     codec->OnMiscellaneousIndication(type);
00780   else
00781     PTRACE(3, "LogChan\tOnMiscellaneousIndication: chan=" << number
00782            << ", type=" << type.GetTagName());
00783 }
00784 
00785 
00786 void H323Channel::OnJitterIndication(DWORD PTRACE_PARAM(jitter),
00787                                      int   PTRACE_PARAM(skippedFrameCount),
00788                                      int   PTRACE_PARAM(additionalBuffer))
00789 {
00790   PTRACE(3, "LogChan\tOnJitterIndication:"
00791             " jitter=" << jitter <<
00792             " skippedFrameCount=" << skippedFrameCount <<
00793             " additionalBuffer=" << additionalBuffer);
00794 }
00795 
00796 
00797 BOOL H323Channel::SetInitialBandwidth()
00798 {
00799   if (GetCodec() == NULL)
00800     return TRUE;
00801 
00802   return SetBandwidthUsed(codec->GetMediaFormat().GetBandwidth()/100);
00803 }
00804 
00805 
00806 BOOL H323Channel::SetBandwidthUsed(unsigned bandwidth)
00807 {
00808   PTRACE(3, "LogChan\tBandwidth requested/used = "
00809          << bandwidth/10 << '.' << bandwidth%10 << '/'
00810          << bandwidthUsed/10 << '.' << bandwidthUsed%10
00811          << " kb/s");
00812   connection.UseBandwidth(bandwidthUsed, TRUE);
00813   bandwidthUsed = 0;
00814 
00815   if (!connection.UseBandwidth(bandwidth, FALSE))
00816     return FALSE;
00817 
00818   bandwidthUsed = bandwidth;
00819   return TRUE;
00820 }
00821 
00822 
00823 BOOL H323Channel::Open()
00824 {
00825   if (opened)
00826     return TRUE;
00827 
00828   // Give the connection (or endpoint) a chance to do something with
00829   // the opening of the codec. Default sets up various filters.
00830   if (!connection.OnStartLogicalChannel(*this)) {
00831     PTRACE(1, "LogChan\tOnStartLogicalChannel failed");
00832     return FALSE;
00833   }
00834   
00835   opened = TRUE;
00836   return TRUE;
00837 }
00838 
00839 
00840 H323Codec * H323Channel::GetCodec() const
00841 {
00842   if (codec == NULL) {
00843     ((H323Channel*)this)->codec = capability->CreateCodec(
00844                   GetDirection() == IsReceiver ? H323Codec::Decoder : H323Codec::Encoder);
00845 #ifdef H323_AUDIO_CODECS
00846     if (codec && PIsDescendant(codec, H323AudioCodec))
00847       ((H323AudioCodec*)codec)->SetSilenceDetectionMode(endpoint.GetSilenceDetectionMode()); 
00848 #endif
00849   }
00850 
00851   return codec;
00852 }
00853 
00854 
00855 void H323Channel::SendMiscCommand(unsigned command)
00856 { 
00857   connection.SendLogicalChannelMiscCommand(*this, command); 
00858 }
00859 
00860 
00862 
00863 H323UnidirectionalChannel::H323UnidirectionalChannel(H323Connection & conn,
00864                                                      const H323Capability & cap,
00865                                                      Directions direction)
00866   : H323Channel(conn, cap),
00867     receiver(direction == IsReceiver)
00868 {
00869 }
00870 
00871 
00872 H323Channel::Directions H323UnidirectionalChannel::GetDirection() const
00873 {
00874   return receiver ? IsReceiver : IsTransmitter;
00875 }
00876 
00877 
00878 BOOL H323UnidirectionalChannel::Start()
00879 {
00880   if (!Open())
00881     return FALSE;
00882 
00883   PThread * thread = new H323LogicalChannelThread(endpoint, *this, receiver);
00884 
00885   if (receiver)
00886     receiveThread  = thread;
00887   else
00888     transmitThread = thread;
00889   return TRUE;
00890 }
00891 
00892 
00894 
00895 H323BidirectionalChannel::H323BidirectionalChannel(H323Connection & conn,
00896                                                    const H323Capability & cap)
00897   : H323Channel(conn, cap)
00898 {
00899 }
00900 
00901 
00902 H323Channel::Directions H323BidirectionalChannel::GetDirection() const
00903 {
00904   return IsBidirectional;
00905 }
00906 
00907 
00908 BOOL H323BidirectionalChannel::Start()
00909 {
00910   receiveThread  = new H323LogicalChannelThread(endpoint, *this, TRUE);
00911   transmitThread = new H323LogicalChannelThread(endpoint, *this, FALSE);
00912   return TRUE;
00913 }
00914 
00915 
00917 
00918 H323_RealTimeChannel::H323_RealTimeChannel(H323Connection & connection,
00919                                            const H323Capability & capability,
00920                                            Directions direction)
00921   : H323UnidirectionalChannel(connection, capability, direction)
00922 {
00923   rtpPayloadType = RTP_DataFrame::IllegalPayloadType;
00924 }
00925 
00926 
00927 BOOL H323_RealTimeChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
00928 {
00929   PTRACE(3, "H323RTP\tOnSendingPDU");
00930 
00931   open.m_forwardLogicalChannelNumber = (unsigned)number;
00932 
00933   if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
00934     open.m_reverseLogicalChannelParameters.IncludeOptionalField(
00935             H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
00936     // Set the communications information for unicast IPv4
00937     open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
00938                 H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
00939                     ::e_h2250LogicalChannelParameters);
00940 
00941         if (connection.isSameNAT() && OnSendingAltPDU(open.m_genericInformation))
00942                 open.IncludeOptionalField(H245_OpenLogicalChannel::e_genericInformation);
00943 
00944     return OnSendingPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters);
00945   }
00946   else {
00947     // Set the communications information for unicast IPv4
00948     open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
00949                 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
00950                     ::e_h2250LogicalChannelParameters);
00951 
00952         if (connection.isSameNAT() && OnSendingAltPDU(open.m_genericInformation))
00953                 open.IncludeOptionalField(H245_OpenLogicalChannel::e_genericInformation);
00954 
00955     return OnSendingPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters);
00956   }
00957 }
00958 
00959 
00960 void H323_RealTimeChannel::OnSendOpenAck(const H245_OpenLogicalChannel & open,
00961                                          H245_OpenLogicalChannelAck & ack) const
00962 {
00963   PTRACE(3, "H323RTP\tOnSendOpenAck");
00964 
00965   // set forwardMultiplexAckParameters option
00966   ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
00967 
00968   // select H225 choice
00969   ack.m_forwardMultiplexAckParameters.SetTag(
00970           H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
00971 
00972   // get H225 parms
00973   H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
00974 
00975   // set session ID
00976   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
00977   const H245_H2250LogicalChannelParameters & openparam =
00978                           open.m_forwardLogicalChannelParameters.m_multiplexParameters;
00979   unsigned sessionID = openparam.m_sessionID;
00980   param.m_sessionID = sessionID;
00981 
00982   if (connection.isSameNAT()) {
00983                 ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_genericInformation);
00984                 OnSendOpenAckAlt(ack.m_genericInformation);
00985   }
00986 
00987   OnSendOpenAck(param);
00988 
00989   PTRACE(2, "H323RTP\tSending open logical channel ACK: sessionID=" << sessionID);
00990 }
00991 
00992 
00993 BOOL H323_RealTimeChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
00994                                          unsigned & errorCode)
00995 {
00996   if (receiver)
00997     number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
00998 
00999   PTRACE(3, "H323RTP\tOnReceivedPDU for channel: " << number);
01000 
01001   unsigned prevTxFrames = capability->GetTxFramesInPacket();
01002   unsigned prevRxFrames = capability->GetRxFramesInPacket();
01003   PString  prevFormat   = capability->GetFormatName();
01004 
01005   BOOL reverse = open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
01006   const H245_DataType & dataType = reverse ? open.m_reverseLogicalChannelParameters.m_dataType
01007                                            : open.m_forwardLogicalChannelParameters.m_dataType;
01008 
01009   if (!capability->OnReceivedPDU(dataType, receiver)) {
01010     PTRACE(1, "H323RTP\tData type not supported");
01011     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
01012     return FALSE;
01013   }
01014 
01015         if (open.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation))
01016                             OnReceivedAltPDU(open.m_genericInformation);
01017 
01018   // If we have already created a codec, and the new parameters indicate that
01019   // the capability limits have changed, then kill off the old codec it will
01020   // be wrongly constructed.
01021   if (codec != NULL &&
01022       (prevTxFrames != capability->GetTxFramesInPacket() ||
01023        prevRxFrames != capability->GetRxFramesInPacket() ||
01024        prevFormat   != capability->GetFormatName())) {
01025     delete codec;
01026     codec = NULL;
01027   }
01028 
01029   if (reverse) {
01030     if (open.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() ==
01031              H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
01032       return OnReceivedPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters, errorCode);
01033   }
01034   else {
01035     if (open.m_forwardLogicalChannelParameters.m_multiplexParameters.GetTag() ==
01036              H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
01037       return OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters, errorCode);
01038   }
01039 
01040   PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
01041   errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
01042   return FALSE;
01043 }
01044 
01045 
01046 BOOL H323_RealTimeChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
01047 {
01048   PTRACE(3, "H323RTP\tOnReceiveOpenAck");
01049 
01050   if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
01051     PTRACE(1, "H323RTP\tNo forwardMultiplexAckParameters");
01052     return FALSE;
01053   }
01054 
01055   if (ack.m_forwardMultiplexAckParameters.GetTag() !=
01056             H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
01057     PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
01058     return FALSE;
01059   }
01060 
01061   if (ack.HasOptionalField(H245_OpenLogicalChannel::e_genericInformation))
01062                                OnReceivedAckAltPDU(ack.m_genericInformation);
01063 
01064   return OnReceivedAckPDU(ack.m_forwardMultiplexAckParameters);
01065 }
01066 
01067 
01068 RTP_DataFrame::PayloadTypes H323_RealTimeChannel::GetRTPPayloadType() const
01069 {
01070   RTP_DataFrame::PayloadTypes pt = rtpPayloadType;
01071 
01072   if (pt == RTP_DataFrame::IllegalPayloadType) {
01073     pt = capability->GetPayloadType();
01074     if (pt == RTP_DataFrame::IllegalPayloadType) {
01075       PAssertNULL(codec);
01076       pt = codec->GetMediaFormat().GetPayloadType();
01077     }
01078   }
01079 
01080   return pt;
01081 }
01082 
01083 
01084 BOOL H323_RealTimeChannel::SetDynamicRTPPayloadType(int newType)
01085 {
01086   PTRACE(1, "H323RTP\tSetting dynamic RTP payload type: " << newType);
01087 
01088   // This is "no change"
01089   if (newType == -1)
01090     return TRUE;
01091 
01092   // Check for illegal type
01093   if (newType < RTP_DataFrame::DynamicBase || newType > RTP_DataFrame::MaxPayloadType)
01094     return FALSE;
01095 
01096   // Check for overwriting "known" type
01097   if (rtpPayloadType < RTP_DataFrame::DynamicBase)
01098     return FALSE;
01099 
01100   rtpPayloadType = (RTP_DataFrame::PayloadTypes)newType;
01101   PTRACE(3, "H323RTP\tSetting dynamic payload type to " << rtpPayloadType);
01102   return TRUE;
01103 }
01104 
01105 
01107 
01108 H323_RTPChannel::H323_RTPChannel(H323Connection & conn,
01109                                  const H323Capability & cap,
01110                                  Directions direction,
01111                                  RTP_Session & r)
01112   : H323_RealTimeChannel(conn, cap, direction),
01113     rtpSession(r),
01114     rtpCallbacks(*(H323_RTP_Session *)r.GetUserData())
01115 {
01116   PTRACE(3, "H323RTP\t" << (receiver ? "Receiver" : "Transmitter")
01117          << " created using session " << GetSessionID());
01118 }
01119 
01120 
01121 H323_RTPChannel::~H323_RTPChannel()
01122 {
01123   // Finished with the RTP session, this will delete the session if it is no
01124   // longer referenced by any logical channels.
01125   connection.ReleaseSession(GetSessionID());
01126 }
01127 
01128 
01129 void H323_RTPChannel::CleanUpOnTermination()
01130 {
01131   if (terminating)
01132     return;
01133 
01134   PTRACE(3, "H323RTP\tCleaning up RTP " << number);
01135 
01136   // Break any I/O blocks and wait for the thread that uses this object to
01137   // terminate before we allow it to be deleted.
01138   if ((receiver ? receiveThread : transmitThread) != NULL)
01139     rtpSession.Close(receiver);
01140 
01141   H323Channel::CleanUpOnTermination();
01142 }
01143 
01144 
01145 unsigned H323_RTPChannel::GetSessionID() const
01146 {
01147   return rtpSession.GetSessionID();
01148 }
01149 
01150 
01151 BOOL H323_RTPChannel::Open()
01152 {
01153   if (opened)
01154     return TRUE;
01155 
01156   if (GetCodec() == NULL) {
01157     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
01158            << " thread aborted (could not create codec)");
01159     return FALSE;
01160   }
01161 
01162   if (!codec->GetMediaFormat().IsValid()) {
01163     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
01164            << " thread aborted (invalid media format)");
01165     return FALSE;
01166   }
01167 
01168   codec->AttachLogicalChannel((H323Channel*)this);
01169 
01170   // Open the codec
01171   if (!codec->Open(connection)) {
01172     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
01173            << " thread aborted (open fail) for "<< *capability);
01174     return FALSE;
01175   }
01176 
01177   // Give the connection (or endpoint) a chance to do something with
01178   // the opening of the codec. Default sets up various filters.
01179   if (!connection.OnStartLogicalChannel(*this)) {
01180     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
01181            << " thread aborted (OnStartLogicalChannel fail)");
01182     return FALSE;
01183   }
01184 
01185   PTRACE(3, "LogChan\tOpened using capability " << *capability);
01186 
01187   opened = TRUE;
01188 
01189   return TRUE;
01190 }
01191 
01192 
01193 BOOL H323_RTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
01194 {
01195   return rtpCallbacks.OnSendingPDU(*this, param);
01196 }
01197 
01198 BOOL H323_RTPChannel::OnSendingAltPDU(H245_ArrayOf_GenericInformation & alternate) const
01199 {
01200   return rtpCallbacks.OnSendingAltPDU(*this, alternate);
01201 }
01202 
01203 void H323_RTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
01204 {
01205   rtpCallbacks.OnSendingAckPDU(*this, param);
01206 }
01207 
01208 void H323_RTPChannel::OnSendOpenAckAlt(H245_ArrayOf_GenericInformation & alternate) const
01209 {
01210   rtpCallbacks.OnSendOpenAckAlt(*this, alternate);
01211 }
01212 
01213 BOOL H323_RTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
01214                                     unsigned & errorCode)
01215 {
01216   return rtpCallbacks.OnReceivedPDU(*this, param, errorCode);
01217 }
01218 
01219 BOOL H323_RTPChannel::OnReceivedAltPDU(const H245_ArrayOf_GenericInformation & alternate)
01220 {
01221   return rtpCallbacks.OnReceivedAltPDU(*this, alternate);
01222 }
01223 
01224 
01225 BOOL H323_RTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
01226 {
01227   return rtpCallbacks.OnReceivedAckPDU(*this, param);
01228 }
01229 
01230 BOOL H323_RTPChannel::OnReceivedAckAltPDU(const H245_ArrayOf_GenericInformation & alternate)
01231 { 
01232   return rtpCallbacks.OnReceivedAckAltPDU(*this, alternate);
01233 }
01234 
01235 
01236 #if PTRACING
01237 class CodecReadAnalyser
01238 {
01239   enum { MaxSamples = 1000 };
01240   public:
01241     CodecReadAnalyser() { count = 0; }
01242     void AddSample(DWORD timestamp)
01243       {
01244         if (count < MaxSamples) {
01245           tick[count] = PTimer::Tick();
01246           rtp[count] = timestamp;
01247           count++;
01248         }
01249       }
01250     friend ostream & operator<<(ostream & strm, const CodecReadAnalyser & analysis)
01251       {
01252         PTimeInterval minimum = PMaxTimeInterval;
01253         PTimeInterval maximum;
01254         for (PINDEX i = 1; i < analysis.count; i++) {
01255           PTimeInterval delta = analysis.tick[i] - analysis.tick[i-1];
01256           strm << setw(6) << analysis.rtp[i] << ' '
01257                << setw(6) << (analysis.tick[i] - analysis.tick[0]) << ' '
01258                << setw(6) << delta
01259                << '\n';
01260           if (delta > maximum)
01261             maximum = delta;
01262           if (delta < minimum)
01263             minimum = delta;
01264         }
01265         strm << "Maximum delta time: " << maximum << "\n"
01266                 "Minimum delta time: " << minimum << '\n';
01267         return strm;
01268       }
01269   private:
01270     PTimeInterval tick[MaxSamples];
01271     DWORD rtp[MaxSamples];
01272     PINDEX count;
01273 };
01274 #endif
01275 
01276 
01277   void H323_RTPChannel::Transmit()
01278 {
01279   if (terminating) {
01280     PTRACE(3, "H323RTP\tTransmit thread terminated on start up");
01281     return;
01282   }
01283 
01284   const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
01285 
01286   // Get parameters from the codec on time and data sizes
01287   BOOL isAudio = mediaFormat.NeedsJitterBuffer();
01288   unsigned framesInPacket = capability->GetTxFramesInPacket();
01289   unsigned maxFrameSize = mediaFormat.GetFrameSize();
01290   if (maxFrameSize == 0)
01291     maxFrameSize = isAudio ? 8 : 2000;
01292   RTP_DataFrame frame(framesInPacket*maxFrameSize);
01293 
01294   rtpPayloadType = GetRTPPayloadType();
01295   if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
01296      PTRACE(1, "H323RTP\tReceive " << mediaFormat << " thread ended (illegal payload type)");
01297      return;
01298   }
01299   frame.SetPayloadType(rtpPayloadType); 
01300 
01301   PTRACE(2, "H323RTP\tTransmit " << mediaFormat << " thread started:"
01302             " rate=" << codec->GetFrameRate() <<
01303             " time=" << (codec->GetFrameRate()/(mediaFormat.GetTimeUnits() > 0 ? mediaFormat.GetTimeUnits() : 1)) << "ms" <<
01304             " size=" << framesInPacket << '*' << maxFrameSize << '='
01305                     << (framesInPacket*maxFrameSize) );
01306 
01307   // This is real time so need to keep track of elapsed milliseconds
01308   BOOL silent = TRUE;
01309   unsigned length;
01310   unsigned frameOffset = 0;
01311   unsigned frameCount = 0;
01312   DWORD rtpTimestamp = 0;
01313   frame.SetPayloadSize(0);
01314 
01315 #if PTRACING
01316   DWORD lastDisplayedTimestamp = 0;
01317   CodecReadAnalyser * codecReadAnalysis = NULL;
01318   if (PTrace::GetLevel() >= 5)
01319     codecReadAnalysis = new CodecReadAnalyser;
01320 #endif
01321 
01322   /* Now keep getting encoded frames from the codec, it is expected that the
01323      Read() function will maintain the Real Time aspects of the transmission.
01324      That is for GSM codec say with a single frame, this function will take
01325      20 milliseconds to complete.
01326    */
01327   while (codec->Read(frame.GetPayloadPtr()+frameOffset, length, frame)) {
01328     // Calculate the timestamp and real time to take in processing
01329     rtpTimestamp += codec->GetFrameRate();
01330 
01331 #if PTRACING
01332     if (rtpTimestamp - lastDisplayedTimestamp > RTP_TRACE_DISPLAY_RATE) {
01333       PTRACE(3, "H323RTP\tTransmitter sent timestamp " << rtpTimestamp);
01334       lastDisplayedTimestamp = rtpTimestamp;
01335     }
01336 
01337     if (codecReadAnalysis != NULL)
01338       codecReadAnalysis->AddSample(rtpTimestamp);
01339 #endif
01340 
01341     if (paused)
01342       length = 0; // Act as though silent/no video
01343 
01344     // Handle marker bit for audio codec
01345     if (isAudio) {
01346       // If switching from silence to signal
01347       if (silent && length > 0) {
01348         silent = FALSE;
01349         frame.SetMarker(TRUE);  // Set flag for start of sound
01350         PTRACE(3, "H323RTP\tTransmit start of talk burst: " << rtpTimestamp);
01351       }
01352       // If switching from signal to silence
01353       else if (!silent && length == 0) {
01354         silent = TRUE;
01355         // If had some data waiting to go out
01356         if (frameOffset > 0)
01357           frameCount = framesInPacket;  // Force the RTP write
01358         PTRACE(3, "H323RTP\tTransmit  end  of talk burst: " << rtpTimestamp);
01359       }
01360     }
01361 
01362     // See if is silence or have some audio data to stuff in the RTP packet
01363     if (length == 0)
01364       frame.SetTimestamp(rtpTimestamp);
01365     else {
01366       silenceStartTick = PTimer::Tick();
01367 
01368       // If first read frame in packet, set timestamp for it
01369       if (frameOffset == 0)
01370         frame.SetTimestamp(rtpTimestamp);
01371       frameOffset += length;
01372 
01373       // Look for special cases
01374       if (rtpPayloadType == RTP_DataFrame::G729 && length == 2) {
01375         /* If we have a G729 sid frame (ie 2 bytes instead of 10) then we must
01376            not send any more frames in the RTP packet.
01377          */
01378         frameCount = framesInPacket;
01379       }
01380       else {
01381         /* Increment by number of frames that were read in one hit Note a
01382            codec that does variable length frames should never return more
01383            than one frame per Read() call or confusion will result.
01384          */
01385         frameCount += (length + maxFrameSize - 1)/maxFrameSize;
01386       }
01387     }
01388 
01389     BOOL sendPacket = FALSE;
01390 
01391     // Have read number of frames for packet (or just went silent)
01392     if (frameCount >= framesInPacket) {
01393       // Set payload size to frame offset, now length of frame.
01394       frame.SetPayloadSize(frameOffset);
01395       frame.SetPayloadType(rtpPayloadType);
01396 
01397       frameOffset = 0;
01398       frameCount = 0;
01399 
01400       sendPacket = TRUE;
01401     }
01402 
01403     filterMutex.Wait();
01404     for (PINDEX i = 0; i < filters.GetSize(); i++)
01405       filters[i](frame, (INT)&sendPacket);
01406     filterMutex.Signal();
01407 
01408     if (sendPacket || (silent && frame.GetPayloadSize() > 0)) {
01409       // Send the frame of coded data we have so far to RTP transport
01410       if (!rtpSession.WriteData(frame))
01411          break;
01412 
01413       // Reset flag for in talk burst
01414       if (isAudio)
01415         frame.SetMarker(FALSE); 
01416 
01417       frame.SetPayloadSize(0);
01418       frameOffset = 0;
01419       frameCount = 0;
01420     }
01421 
01422     if (terminating)
01423       break;
01424   }
01425 
01426 #if PTRACING
01427   PTRACE_IF(5, codecReadAnalysis != NULL, "Codec read timing:\n" << *codecReadAnalysis);
01428   delete codecReadAnalysis;
01429 #endif
01430 
01431   if (!terminating)
01432     connection.CloseLogicalChannelNumber(number);
01433 
01434   PTRACE(2, "H323RTP\tTransmit " << mediaFormat << " thread ended");
01435 }
01436 
01437 
01438 void H323_RTPChannel::Receive()
01439 {
01440   if (terminating) {
01441     PTRACE(3, "H323RTP\tReceive thread terminated on start up");
01442     return;
01443   }
01444 
01445   const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
01446 
01447   PTRACE(2, "H323RTP\tReceive " << mediaFormat << " thread started.");
01448 
01449   // if jitter buffer required, start the thread that is on the other end of it
01450   if (mediaFormat.NeedsJitterBuffer())
01451     rtpSession.SetJitterBufferSize(connection.GetMinAudioJitterDelay()*mediaFormat.GetTimeUnits(),
01452                                    connection.GetMaxAudioJitterDelay()*mediaFormat.GetTimeUnits(),
01453                                    endpoint.GetJitterThreadStackSize());
01454 
01455   // Keep time using th RTP timestamps.
01456   DWORD codecFrameRate = codec->GetFrameRate();
01457   DWORD rtpTimestamp = 0;
01458 #if PTRACING
01459   DWORD lastDisplayedTimestamp = 0;
01460 #endif
01461 
01462   // keep track of consecutive payload type mismatches
01463   int consecutiveMismatches = 0;
01464 
01465   rtpPayloadType = GetRTPPayloadType();
01466   if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
01467      PTRACE(1, "H323RTP\tTransmit " << mediaFormat << " thread ended (illegal payload type)");
01468      return;
01469   }
01470 
01471   BOOL allowRtpPayloadChange = codec->GetMediaFormat().GetDefaultSessionID() == OpalMediaFormat::DefaultAudioSessionID;
01472 
01473   RTP_DataFrame frame;
01474   while (rtpSession.ReadBufferedData(rtpTimestamp, frame)) {
01475 
01476     filterMutex.Wait();
01477     for (PINDEX i = 0; i < filters.GetSize(); i++)
01478       filters[i](frame, 0);
01479     filterMutex.Signal();
01480 
01481     int size = frame.GetPayloadSize();
01482     rtpTimestamp = frame.GetTimestamp();
01483 
01484 #if PTRACING
01485     if (rtpTimestamp - lastDisplayedTimestamp > RTP_TRACE_DISPLAY_RATE) {
01486       PTRACE(3, "H323RTP\tReceiver written timestamp " << rtpTimestamp);
01487       lastDisplayedTimestamp = rtpTimestamp;
01488     }
01489 #endif
01490 
01491     unsigned written;
01492     BOOL ok = TRUE;
01493     if (size == 0) {
01494       ok = codec->Write(NULL, 0, frame, written);
01495       rtpTimestamp += codecFrameRate;
01496     } else {
01497       silenceStartTick = PTimer::Tick();
01498 
01499       BOOL isCodecPacket = TRUE;
01500 
01501       if (frame.GetPayloadType() == rtpPayloadType) {
01502         PTRACE_IF(2, consecutiveMismatches > 0,
01503                   "H323RTP\tPayload type matched again " << rtpPayloadType);
01504         consecutiveMismatches = 0;
01505       }
01506       else {
01507         consecutiveMismatches++;
01508         if (allowRtpPayloadChange && consecutiveMismatches >= MAX_PAYLOAD_TYPE_MISMATCHES) {
01509           rtpPayloadType = frame.GetPayloadType();
01510           consecutiveMismatches = 0;
01511           PTRACE(1, "H323RTP\tResetting expected payload type to " << rtpPayloadType);
01512         }
01513         PTRACE_IF(2, consecutiveMismatches < MAX_PAYLOAD_TYPE_MISMATCHES, "H323RTP\tPayload type mismatch: expected "
01514               << rtpPayloadType << ", got " << frame.GetPayloadType()
01515               << ". Ignoring packet.");
01516       }
01517 
01518       if (isCodecPacket && consecutiveMismatches == 0) {
01519         const BYTE * ptr = frame.GetPayloadPtr();
01520         while (ok && size > 0) {
01521           /* Now write data to the codec, it is expected that the Write()
01522              function will maintain the Real Time aspects of the system. That
01523              is for GSM codec, say with a single frame, this function will take
01524              20 milliseconds to complete. It is very important that this occurs
01525              for audio codecs or the jitter buffer will not operate correctly.
01526            */
01527           ok = codec->Write(ptr, paused ? 0 : size, frame, written);
01528           rtpTimestamp += codecFrameRate;
01529           size -= written != 0 ? written : size;
01530           ptr += written;
01531         }
01532         PTRACE_IF(1, size < 0, "H323RTP\tPayload size too small, short " << -size << " bytes.");
01533       }
01534     }
01535 
01536     if (terminating)
01537       break;
01538 
01539     if (!ok) {
01540       connection.CloseLogicalChannelNumber(number);
01541       break;
01542     }
01543   }
01544 
01545   PTRACE(2, "H323RTP\tReceive " << mediaFormat << " thread ended");
01546 }
01547 
01548 
01549 void H323_RTPChannel::AddFilter(const PNotifier & filterFunction)
01550 {
01551   filterMutex.Wait();
01552   filters.Append(new PNotifier(filterFunction));
01553   filterMutex.Signal();
01554 }
01555 
01556 
01557 void H323_RTPChannel::RemoveFilter(const PNotifier & filterFunction)
01558 {
01559   filterMutex.Wait();
01560   PINDEX idx = filters.GetValuesIndex(filterFunction);
01561   if (idx != P_MAX_INDEX)
01562     filters.RemoveAt(idx);
01563   filterMutex.Signal();
01564 }
01565 
01566 
01567 PTimeInterval H323_RTPChannel::GetSilenceDuration() const
01568 {
01569   if (silenceStartTick == 0)
01570     return silenceStartTick;
01571 
01572   return PTimer::Tick() - silenceStartTick;
01573 }
01574 
01575 
01577 
01578 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
01579                                                  const H323Capability & capability,
01580                                                  Directions direction,
01581                                                  unsigned id)
01582   : H323_RealTimeChannel(connection, capability, direction)
01583 {
01584   sessionID = id;
01585   isRunning = FALSE;
01586 }
01587 
01588 
01589 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
01590                                                  const H323Capability & capability,
01591                                                  Directions direction,
01592                                                  unsigned id,
01593                                                  const H323TransportAddress & data,
01594                                                  const H323TransportAddress & control)
01595   : H323_RealTimeChannel(connection, capability, direction),
01596     externalMediaAddress(data),
01597     externalMediaControlAddress(control)
01598 {
01599   sessionID = id;
01600   isRunning = FALSE;
01601 }
01602 
01603 
01604 H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
01605                                                  const H323Capability & capability,
01606                                                  Directions direction,
01607                                                  unsigned id,
01608                                                  const PIPSocket::Address & ip,
01609                                                  WORD dataPort)
01610   : H323_RealTimeChannel(connection, capability, direction),
01611     externalMediaAddress(ip, dataPort),
01612     externalMediaControlAddress(ip, (WORD)(dataPort+1))
01613 {
01614   sessionID = id;
01615   isRunning = FALSE;
01616 }
01617 
01618 
01619 unsigned H323_ExternalRTPChannel::GetSessionID() const
01620 {
01621   return sessionID;
01622 }
01623 
01624 
01625 BOOL H323_ExternalRTPChannel::Start()
01626 {
01627   isRunning = TRUE;
01628   return Open();
01629 }
01630 
01631 
01632 BOOL H323_ExternalRTPChannel::IsRunning() const
01633 {
01634   return opened && isRunning;
01635 }
01636 
01637 
01638 void H323_ExternalRTPChannel::Receive()
01639 {
01640   // Do nothing
01641 }
01642 
01643 
01644 void H323_ExternalRTPChannel::Transmit()
01645 {
01646   // Do nothing
01647 }
01648 
01649 
01650 BOOL H323_ExternalRTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
01651 {
01652   param.m_sessionID = sessionID;
01653 
01654   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaGuaranteedDelivery);
01655   param.m_mediaGuaranteedDelivery = FALSE;
01656 
01657   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_silenceSuppression);
01658   param.m_silenceSuppression = FALSE;
01659 
01660   // unicast must have mediaControlChannel
01661   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel);
01662   externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
01663 
01664   if (receiver) {
01665     // set mediaChannel
01666     param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
01667     externalMediaAddress.SetPDU(param.m_mediaChannel);
01668   }
01669 
01670   return TRUE;
01671 }
01672 
01673 
01674 void H323_ExternalRTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
01675 {
01676   // set mediaControlChannel
01677   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel);
01678   externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
01679 
01680   // set mediaChannel
01681   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
01682   externalMediaAddress.SetPDU(param.m_mediaChannel);
01683 }
01684 
01685 
01686 BOOL H323_ExternalRTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
01687                                           unsigned & errorCode)
01688 {
01689   // Only support a single audio session
01690   if (param.m_sessionID != sessionID) {
01691     PTRACE(1, "LogChan\tOpen for invalid session: " << param.m_sessionID);
01692     errorCode = H245_OpenLogicalChannelReject_cause::e_invalidSessionID;
01693     return FALSE;
01694   }
01695 
01696   if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
01697     PTRACE(1, "LogChan\tNo mediaControlChannel specified");
01698     errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
01699     return FALSE;
01700   }
01701 
01702   remoteMediaControlAddress = param.m_mediaControlChannel;
01703   if (remoteMediaControlAddress.IsEmpty())
01704     return FALSE;
01705 
01706   if (param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
01707     remoteMediaAddress = param.m_mediaChannel;
01708     if (remoteMediaAddress.IsEmpty())
01709       return FALSE;
01710   }
01711 
01712   return TRUE;
01713 }
01714 
01715 
01716 BOOL H323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
01717 {
01718   if (param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID) && (param.m_sessionID != sessionID)) {
01719     PTRACE(1, "LogChan\twarning: Ack for invalid session: " << param.m_sessionID);
01720   }
01721 
01722   if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel)) {
01723     PTRACE(1, "LogChan\tNo mediaControlChannel specified");
01724     return FALSE;
01725   }
01726 
01727   remoteMediaControlAddress = param.m_mediaControlChannel;
01728   if (remoteMediaControlAddress.IsEmpty())
01729     return FALSE;
01730 
01731   if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
01732     PTRACE(1, "LogChan\tNo mediaChannel specified");
01733     return FALSE;
01734   }
01735 
01736   remoteMediaAddress = param.m_mediaChannel;
01737   if (remoteMediaAddress.IsEmpty())
01738     return FALSE;
01739 
01740   return TRUE;
01741 }
01742 
01743 
01744 void H323_ExternalRTPChannel::SetExternalAddress(const H323TransportAddress & data,
01745                                                  const H323TransportAddress & control)
01746 {
01747   externalMediaAddress = data;
01748   externalMediaControlAddress = control;
01749 
01750   if (data.IsEmpty() || control.IsEmpty()) {
01751     PIPSocket::Address ip;
01752     WORD port;
01753     if (data.GetIpAndPort(ip, port))
01754       externalMediaControlAddress = H323TransportAddress(ip, (WORD)(port+1));
01755     else if (control.GetIpAndPort(ip, port))
01756       externalMediaAddress = H323TransportAddress(ip, (WORD)(port-1));
01757   }
01758 }
01759 
01760 
01761 BOOL H323_ExternalRTPChannel::GetRemoteAddress(PIPSocket::Address & ip,
01762                                                WORD & dataPort) const
01763 {
01764   if (!remoteMediaControlAddress) {
01765     if (remoteMediaControlAddress.GetIpAndPort(ip, dataPort)) {
01766       dataPort--;
01767       return TRUE;
01768     }
01769   }
01770 
01771   if (!remoteMediaAddress)
01772     return remoteMediaAddress.GetIpAndPort(ip, dataPort);
01773 
01774   return FALSE;
01775 }
01776 
01777 
01779 
01780 H323DataChannel::H323DataChannel(H323Connection & conn,
01781                                  const H323Capability & cap,
01782                                  Directions dir,
01783                                  unsigned id)
01784   : H323UnidirectionalChannel(conn, cap, dir)
01785 {
01786   sessionID = id;
01787   listener = NULL;
01788   autoDeleteListener = TRUE;
01789   transport = NULL;
01790   autoDeleteTransport = TRUE;
01791   separateReverseChannel = FALSE;
01792 }
01793 
01794 
01795 H323DataChannel::~H323DataChannel()
01796 {
01797   if (autoDeleteListener)
01798     delete listener;
01799   if (autoDeleteTransport)
01800     delete transport;
01801 }
01802 
01803 
01804 void H323DataChannel::CleanUpOnTermination()
01805 {
01806   if (terminating)
01807     return;
01808 
01809   PTRACE(3, "LogChan\tCleaning up data channel " << number);
01810 
01811   // Break any I/O blocks and wait for the thread that uses this object to
01812   // terminate before we allow it to be deleted.
01813   if (listener != NULL)
01814     listener->Close();
01815   if (transport != NULL)
01816     transport->Close();
01817 
01818   H323UnidirectionalChannel::CleanUpOnTermination();
01819 }
01820 
01821 
01822 unsigned H323DataChannel::GetSessionID() const
01823 {
01824   return sessionID;
01825 }
01826 
01827 
01828 BOOL H323DataChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
01829 {
01830   PTRACE(3, "LogChan\tOnSendingPDU for channel: " << number);
01831 
01832   open.m_forwardLogicalChannelNumber = (unsigned)number;
01833 
01834   open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
01835               H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
01836                   ::e_h2250LogicalChannelParameters);
01837   H245_H2250LogicalChannelParameters & fparam = open.m_forwardLogicalChannelParameters.m_multiplexParameters;
01838   fparam.m_sessionID = GetSessionID();
01839 
01840   if (separateReverseChannel)
01841     return TRUE;
01842 
01843   open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
01844   open.m_reverseLogicalChannelParameters.IncludeOptionalField(
01845               H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
01846   open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
01847               H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
01848                   ::e_h2250LogicalChannelParameters);
01849   H245_H2250LogicalChannelParameters & rparam = open.m_reverseLogicalChannelParameters.m_multiplexParameters;
01850   rparam.m_sessionID = GetSessionID();
01851 
01852   return capability->OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType);
01853 }
01854 
01855 
01856 void H323DataChannel::OnSendOpenAck(const H245_OpenLogicalChannel & /*open*/,
01857                                     H245_OpenLogicalChannelAck & ack) const
01858 {
01859   if (listener == NULL && transport == NULL) {
01860     PTRACE(2, "LogChan\tOnSendOpenAck without a listener or transport");
01861     return;
01862   }
01863 
01864   PTRACE(3, "LogChan\tOnSendOpenAck for channel: " << number);
01865 
01866   H245_H2250LogicalChannelAckParameters * param;
01867 
01868   if (separateReverseChannel) {
01869     ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
01870     ack.m_forwardMultiplexAckParameters.SetTag(
01871               H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
01872     param = (H245_H2250LogicalChannelAckParameters*)&ack.m_forwardMultiplexAckParameters.GetObject();
01873   }
01874   else {
01875     ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters);
01876     ack.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
01877               H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
01878                   ::e_h2250LogicalChannelParameters);
01879     param = (H245_H2250LogicalChannelAckParameters*)
01880                 &ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetObject();
01881   }
01882 
01883   unsigned session = GetSessionID();
01884   if (session != 0) {
01885     param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
01886     param->m_sessionID = GetSessionID();
01887   }
01888 
01889   param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
01890   if (listener != NULL)
01891     listener->SetUpTransportPDU(param->m_mediaChannel, connection.GetControlChannel());
01892   else
01893     transport->SetUpTransportPDU(param->m_mediaChannel, H323Transport::UseLocalTSAP);
01894 }
01895 
01896 
01897 BOOL H323DataChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
01898                                     unsigned & errorCode)
01899 {
01900   number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
01901 
01902   PTRACE(3, "LogChan\tOnReceivedPDU for data channel: " << number);
01903 
01904   if (!CreateListener()) {
01905     PTRACE(1, "LogChan\tCould not create listener");
01906     errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
01907     return FALSE;
01908   }
01909 
01910   if (separateReverseChannel &&
01911       open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
01912     errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
01913     PTRACE(2, "LogChan\tOnReceivedPDU has unexpected reverse parameters");
01914     return FALSE;
01915   }
01916 
01917   if (!capability->OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_dataType, receiver)) {
01918     PTRACE(1, "H323RTP\tData type not supported");
01919     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
01920     return FALSE;
01921   }
01922 
01923   return TRUE;
01924 }
01925 
01926 
01927 BOOL H323DataChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
01928 {
01929   PTRACE(3, "LogChan\tOnReceivedAckPDU");
01930 
01931   const H245_TransportAddress * address;
01932 
01933   if (separateReverseChannel) {
01934       PTRACE(3, "LogChan\tseparateReverseChannels");
01935     if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
01936       PTRACE(1, "LogChan\tNo forwardMultiplexAckParameters");
01937       return FALSE;
01938     }
01939 
01940     if (ack.m_forwardMultiplexAckParameters.GetTag() !=
01941               H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
01942       PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
01943       return FALSE;
01944     }
01945 
01946     const H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
01947 
01948     if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
01949       PTRACE(1, "LogChan\tNo media channel address provided");
01950       return FALSE;
01951     }
01952 
01953     address = &param.m_mediaChannel;
01954 
01955     if (ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
01956       PTRACE(3, "LogChan\treverseLogicalChannelParameters set");
01957       reverseChannel = H323ChannelNumber(ack.m_reverseLogicalChannelParameters.m_reverseLogicalChannelNumber, TRUE);
01958     }
01959   }
01960   else {
01961     if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
01962       PTRACE(1, "LogChan\tNo reverseLogicalChannelParameters");
01963       return FALSE;
01964     }
01965 
01966     if (ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() !=
01967               H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
01968                               ::e_h2250LogicalChannelParameters) {
01969       PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
01970       return FALSE;
01971     }
01972 
01973     const H245_H2250LogicalChannelParameters & param = ack.m_reverseLogicalChannelParameters.m_multiplexParameters;
01974 
01975     if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
01976       PTRACE(1, "LogChan\tNo media channel address provided");
01977       return FALSE;
01978     }
01979 
01980     address = &param.m_mediaChannel;
01981   }
01982 
01983   if (!CreateTransport()) {
01984     PTRACE(1, "LogChan\tCould not create transport");
01985     return FALSE;
01986   }
01987 
01988   if (!transport->ConnectTo(*address)) {
01989     PTRACE(1, "LogChan\tCould not connect to remote transport address: " << *address);
01990     return FALSE;
01991   }
01992 
01993   return TRUE;
01994 }
01995 
01996 
01997 BOOL H323DataChannel::CreateListener()
01998 {
01999   if (listener == NULL) {
02000     listener = connection.GetControlChannel().GetLocalAddress().CreateCompatibleListener(connection.GetEndPoint());
02001     if (listener == NULL)
02002       return FALSE;
02003 
02004     PTRACE(3, "LogChan\tCreated listener for data channel: " << *listener);
02005   }
02006 
02007   return listener->Open();
02008 }
02009 
02010 
02011 BOOL H323DataChannel::CreateTransport()
02012 {
02013   if (transport == NULL) {
02014     transport = connection.GetControlChannel().GetLocalAddress().CreateTransport(connection.GetEndPoint());
02015     if (transport == NULL)
02016       return FALSE;
02017 
02018     PTRACE(3, "LogChan\tCreated transport for data channel: " << *transport);
02019   }
02020 
02021   return transport != NULL;
02022 }
02023 
02024 

Generated on Thu Oct 25 13:42:38 2007 for h323plus by  doxygen 1.5.2