home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / openh323.tar.gz / openh323.tar / openh323 / src / channels.cxx < prev    next >
Text File  |  2003-02-10  |  62KB  |  1,945 lines

  1. /*
  2.  * channels.cxx
  3.  *
  4.  * H.323 protocol handler
  5.  *
  6.  * Open H323 Library
  7.  *
  8.  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Open H323 Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions of this code were written with the assisance of funding from
  25.  * Vovida Networks, Inc. http://www.vovida.com.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: channels.cxx,v $
  30.  * Revision 1.136  2003/02/10 05:36:13  robertj
  31.  * Fixed returning mediaControlChannel address in preference to mediaChannel
  32.  *   address as Cisco's just feed your own address back at you.
  33.  *
  34.  * Revision 1.135  2002/12/18 11:20:49  craigs
  35.  * Fixed problem with T.38 channels SEGVing thanks to Vyacheslav Frolov
  36.  *
  37.  * Revision 1.134  2002/12/17 08:48:09  robertj
  38.  * Set silence suppression mode earlier in codec life so gets correct
  39.  *   value for silenceSuppression in fast start OLC's.
  40.  *
  41.  * Revision 1.133  2002/12/16 08:20:04  robertj
  42.  * Fixed problem where a spurious RTP packet full of zeros could be sent
  43.  *   at the beginning of the transmission, thanks Bruce Fitzsimons
  44.  *
  45.  * Revision 1.132  2002/11/26 02:59:25  robertj
  46.  * Added logging to help find logical channel thread stop failures.
  47.  *
  48.  * Revision 1.131  2002/10/31 00:37:47  robertj
  49.  * Enhanced jitter buffer system so operates dynamically between minimum and
  50.  *   maximum values. Altered API to assure app writers note the change!
  51.  *
  52.  * Revision 1.130  2002/08/05 10:03:47  robertj
  53.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  54.  *
  55.  * Revision 1.129  2002/06/28 03:34:28  robertj
  56.  * Fixed issues with address translation on gatekeeper RAS channel.
  57.  *
  58.  * Revision 1.128  2002/06/25 08:30:12  robertj
  59.  * Changes to differentiate between stright G.723.1 and G.723.1 Annex A using
  60.  *   the OLC dataType silenceSuppression field so does not send SID frames
  61.  *   to receiver codecs that do not understand them.
  62.  *
  63.  * Revision 1.127  2002/06/24 00:07:31  robertj
  64.  * Fixed bandwidth usage being exactly opposite (adding when it should
  65.  *   be subtracting), thanks Saswat Praharaj.
  66.  *
  67.  * Revision 1.126  2002/05/23 04:53:57  robertj
  68.  * Added function to remove a filter from logical channel.
  69.  *
  70.  * Revision 1.125  2002/05/10 05:47:15  robertj
  71.  * Added session ID to the data logical channel class.
  72.  *
  73.  * Revision 1.124  2002/05/07 23:49:11  robertj
  74.  * Fixed incorrect setting of session ID in data channel OLC, caused an
  75.  *   incorrect optional field to be included, thanks Ulrich Findeisen.
  76.  *
  77.  * Revision 1.123  2002/05/03 00:07:24  robertj
  78.  * Fixed missing setting of isRunning flag in external RTP channels.
  79.  *
  80.  * Revision 1.122  2002/05/02 07:56:27  robertj
  81.  * Added automatic clearing of call if no media (RTP data) is transferred in a
  82.  *   configurable (default 5 minutes) amount of time.
  83.  *
  84.  * Revision 1.121  2002/05/02 06:28:53  robertj
  85.  * Fixed problem with external RTP channels not fast starting.
  86.  *
  87.  * Revision 1.120  2002/04/17 05:56:05  robertj
  88.  * Added trace output of H323Channel::Direction enum.
  89.  *
  90.  * Revision 1.119  2002/02/25 08:42:26  robertj
  91.  * Fixed comments on the real time requirements of the codec.
  92.  *
  93.  * Revision 1.118  2002/02/19 06:15:20  robertj
  94.  * Allowed for RTP filter functions to force output of packet, or prevent it
  95.  *   from being sent overriding the n frames per packet algorithm.
  96.  *
  97.  * Revision 1.117  2002/02/09 04:39:05  robertj
  98.  * Changes to allow T.38 logical channels to use single transport which is
  99.  *   now owned by the OpalT38Protocol object instead of H323Channel.
  100.  *
  101.  * Revision 1.116  2002/02/05 08:13:02  robertj
  102.  * Added ability to not have addresses when external RTP channel created.
  103.  *
  104.  * Revision 1.115  2002/02/04 06:04:19  robertj
  105.  * Fixed correct exit on terminating transmit channel, thanks Norwood Systems.
  106.  *
  107.  * Revision 1.114  2002/01/27 10:49:51  rogerh
  108.  * Catch a division by zero case in a PTRACE()
  109.  *
  110.  * Revision 1.113  2002/01/24 03:33:07  robertj
  111.  * Fixed payload type being incorrect for audio after sending RFC2833 packet.
  112.  *
  113.  * Revision 1.112  2002/01/22 22:48:25  robertj
  114.  * Fixed RFC2833 support (transmitter) requiring large rewrite
  115.  *
  116.  * Revision 1.111  2002/01/22 07:08:26  robertj
  117.  * Added IllegalPayloadType enum as need marker for none set
  118.  *   and MaxPayloadType is a legal value.
  119.  *
  120.  * Revision 1.110  2002/01/22 06:05:03  robertj
  121.  * Added ability for RTP payload type to be overridden at capability level.
  122.  *
  123.  * Revision 1.109  2002/01/17 07:05:03  robertj
  124.  * Added support for RFC2833 embedded DTMF in the RTP stream.
  125.  *
  126.  * Revision 1.108  2002/01/17 00:10:37  robertj
  127.  * Fixed double copy of rtpPayloadType in RTP channel, caused much confusion.
  128.  *
  129.  * Revision 1.107  2002/01/14 05:18:44  robertj
  130.  * Fixed typo on external RTP channel constructor.
  131.  *
  132.  * Revision 1.106  2002/01/10 05:13:54  robertj
  133.  * Added support for external RTP stacks, thanks NuMind Software Systems.
  134.  *
  135.  * Revision 1.105  2002/01/09 06:05:55  robertj
  136.  * Rearranged transmitter timestamp calculation to allow for a codec that has
  137.  *   variable number of timestamp units per call to Read().
  138.  *
  139.  * Revision 1.104  2001/12/22 01:50:47  robertj
  140.  * Fixed bug in data channel (T.38) negotiations, using wrong PDU subclass.
  141.  * Fixed using correct port number in data channel (T.38) negotiations.
  142.  * Improved trace logging.
  143.  *
  144.  * Revision 1.103  2001/11/28 00:09:14  dereks
  145.  * Additional information in PTRACE output.
  146.  *
  147.  * Revision 1.102  2001/11/09 05:39:54  craigs
  148.  * Added initial T.38 support thanks to Adam Lazur
  149.  *
  150.  * Revision 1.101  2001/10/24 00:55:49  robertj
  151.  * Made cosmetic changes to H.245 miscellaneous command function.
  152.  *
  153.  * Revision 1.100  2001/10/23 02:17:16  dereks
  154.  * Initial release of cu30 video codec.
  155.  *
  156.  * Revision 1.99  2001/09/13 08:20:27  robertj
  157.  * Fixed broken back out of rev 1.95, thanks Santiago Garcia Mantinan
  158.  *
  159.  * Revision 1.98  2001/09/11 00:21:23  robertj
  160.  * Fixed missing stack sizes in endpoint for cleaner thread and jitter thread.
  161.  *
  162.  * Revision 1.97  2001/08/28 09:28:28  robertj
  163.  * Backed out change in revision 1.95, not compatible with G.711
  164.  *
  165.  * Revision 1.96  2001/08/16 06:34:42  robertj
  166.  * Plugged memory leak if using trace level 5.
  167.  *
  168.  * Revision 1.95  2001/08/10 01:34:41  robertj
  169.  * Fixed problem with incorrect timestamp if codec returns more than one
  170.  *    frame in read, thanks Lee Kirchhoff.
  171.  *
  172.  * Revision 1.94  2001/08/06 05:36:00  robertj
  173.  * Fixed GNU warnings.
  174.  *
  175.  * Revision 1.93  2001/08/06 03:08:56  robertj
  176.  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
  177.  *
  178.  * Revision 1.92  2001/07/24 02:26:44  robertj
  179.  * Added start for handling reverse channels.
  180.  *
  181.  * Revision 1.91  2001/07/17 04:44:31  robertj
  182.  * Partial implementation of T.120 and T.38 logical channels.
  183.  *
  184.  * Revision 1.90  2001/07/12 07:28:41  yurik
  185.  * WinCE fix: Sleep(0) in Main to get system chance to digest
  186.  *
  187.  * Revision 1.89  2001/06/15 07:20:35  robertj
  188.  * Moved OnClosedLogicalChannel() to be after channels threads halted.
  189.  *
  190.  * Revision 1.88  2001/06/02 01:35:32  robertj
  191.  * Added thread names.
  192.  *
  193.  * Revision 1.87  2001/05/31 06:29:48  robertj
  194.  * Changed trace of RTP mismatch so only displays for first n packets then
  195.  *   does not dump messages any more. Was exactly the opposite.
  196.  *
  197.  * Revision 1.86  2001/04/20 02:32:07  robertj
  198.  * Improved logging of bandwith, used more intuitive units.
  199.  *
  200.  * Revision 1.85  2001/04/02 04:12:53  robertj
  201.  * Fixed trace output from packet transmit timing.
  202.  *
  203.  * Revision 1.84  2001/03/23 05:38:30  robertj
  204.  * Added PTRACE_IF to output trace if a conditional is TRUE.
  205.  *
  206.  * Revision 1.83  2001/02/09 05:13:55  craigs
  207.  * Added pragma implementation to (hopefully) reduce the executable image size
  208.  * under Linux
  209.  *
  210.  * Revision 1.82  2001/02/07 05:04:45  robertj
  211.  * Improved codec read analysis debug output.
  212.  *
  213.  * Revision 1.81  2001/02/06 07:40:46  robertj
  214.  * Added debugging for timing of codec read.
  215.  *
  216.  * Revision 1.80  2001/01/25 07:27:16  robertj
  217.  * Major changes to add more flexible OpalMediaFormat class to normalise
  218.  *   all information about media types, especially codecs.
  219.  *
  220.  * Revision 1.79  2000/12/20 00:50:42  robertj
  221.  * Fixed MSVC compatibility issues (No trace).
  222.  *
  223.  * Revision 1.78  2000/12/19 22:33:44  dereks
  224.  * Adjust so that the video channel is used for reading/writing raw video
  225.  * data, which better modularizes the video codec.
  226.  *
  227.  * Revision 1.77  2000/12/17 22:45:36  robertj
  228.  * Set media stream threads to highest unprivileged priority.
  229.  *
  230.  * Revision 1.76  2000/11/24 10:52:50  robertj
  231.  * Modified the ReadFrame/WriteFrame functions to allow for variable length codecs.
  232.  * Added support for G.729 annex B packetisation scheme in RTP.
  233.  * Fixed bug in fast started G.711 codec not working in one direction.
  234.  *
  235.  * Revision 1.75  2000/10/24 00:00:09  robertj
  236.  * Improved memory hogging hash function for logical channels.
  237.  *
  238.  * Revision 1.74  2000/10/19 04:05:01  robertj
  239.  * Added compare function for logical channel numbers, thanks Yuriy Ershov.
  240.  *
  241.  * Revision 1.73  2000/09/23 06:54:44  robertj
  242.  * Prevented call of OnClose call back if channel was never opened.
  243.  *
  244.  * Revision 1.72  2000/09/22 01:35:49  robertj
  245.  * Added support for handling LID's that only do symmetric codecs.
  246.  *
  247.  * Revision 1.71  2000/09/22 00:32:33  craigs
  248.  * Added extra logging
  249.  * Fixed problems with no fastConnect with tunelling
  250.  *
  251.  * Revision 1.70  2000/09/20 01:50:21  craigs
  252.  * Added ability to set jitter buffer on a per-connection basis
  253.  *
  254.  * Revision 1.69  2000/09/14 23:03:45  robertj
  255.  * Increased timeout on asserting because of driver lockup
  256.  *
  257.  * Revision 1.68  2000/08/31 08:15:40  robertj
  258.  * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
  259.  *
  260.  * Revision 1.67  2000/08/30 06:33:01  craigs
  261.  * Add fix to ignore small runs of consectuive mismatched payload types
  262.  *
  263.  * Revision 1.66  2000/08/25 01:10:28  robertj
  264.  * Added assert if various thrads ever fail to terminate.
  265.  *
  266.  * Revision 1.65  2000/08/21 02:50:28  robertj
  267.  * Fixed race condition if close call just as slow start media channels are opening.
  268.  *
  269.  * Revision 1.64  2000/07/14 14:04:49  robertj
  270.  * Clarified a debug message.
  271.  *
  272.  * Revision 1.63  2000/07/14 12:47:36  robertj
  273.  * Added clarification to some logging messags.
  274.  *
  275.  * Revision 1.62  2000/07/13 16:05:47  robertj
  276.  * Removed time critical priority as it can totally slag a Win98 system.
  277.  * Fixed trace message displaying mismatched codecs in RTP packet around the wrong way.
  278.  *
  279.  * Revision 1.61  2000/07/11 11:15:52  robertj
  280.  * Fixed bug when terminating RTP receiver and not also terminating transmitter.
  281.  *
  282.  * Revision 1.60  2000/06/23 02:04:01  robertj
  283.  * Increased the priority of the media channels, only relevent for Win32 at this time.
  284.  *
  285.  * Revision 1.59  2000/06/15 01:46:15  robertj
  286.  * Added channel pause (aka mute) functions.
  287.  *
  288.  * Revision 1.58  2000/05/18 12:10:50  robertj
  289.  * Removed all Sleep() calls in codec as timing innacuracies make it unusable. All
  290.  *    codec implementations must thus have timing built into them, usually using I/O.
  291.  *
  292.  * Revision 1.57  2000/05/11 23:54:25  craigs
  293.  * Fixed the Windows fix with another Linux fix. But it worked OK on the Alpha!
  294.  *
  295.  * Revision 1.56  2000/05/11 09:56:46  robertj
  296.  * Win32 compatibility and addition of some extra debugging on codec timing.
  297.  *
  298.  * Revision 1.55  2000/05/11 02:27:18  robertj
  299.  * Added "fail safe" timer sleep on codec writes when on output of jitter buffer.
  300.  *
  301.  * Revision 1.54  2000/05/04 11:52:34  robertj
  302.  * Added Packets Too Late statistics, requiring major rearrangement of jitter
  303.  *    buffer code, not also changes semantics of codec Write() function slightly.
  304.  *
  305.  * Revision 1.53  2000/05/02 04:32:26  robertj
  306.  * Fixed copyright notice comment.
  307.  *
  308.  * Revision 1.52  2000/05/01 01:01:49  robertj
  309.  * Added flag for what to do with out of orer packets (use if jitter, don't if not).
  310.  *
  311.  * Revision 1.51  2000/04/28 13:01:44  robertj
  312.  * Fixed problem with adjusting tx/rx frame counts in capabilities during fast start.
  313.  *
  314.  * Revision 1.50  2000/04/10 19:45:49  robertj
  315.  * Changed RTP data receive tp be more forgiving, will process packet even if payload type is wrong.
  316.  *
  317.  * Revision 1.49  2000/03/31 20:04:28  robertj
  318.  * Fixed log message for start/end of transmitted talk burst.
  319.  *
  320.  * Revision 1.48  2000/03/29 04:36:38  robertj
  321.  * Improved some trace logging messages.
  322.  *
  323.  * Revision 1.47  2000/03/22 01:31:36  robertj
  324.  * Fixed transmitter loop so codec can return multiple frames (crash in G.711 mode)
  325.  *
  326.  * Revision 1.46  2000/03/21 03:58:00  robertj
  327.  * Fixed stuffed up RTP transmit loop after previous change.
  328.  *
  329.  * Revision 1.45  2000/03/21 03:06:49  robertj
  330.  * Changes to make RTP TX of exact numbers of frames in some codecs.
  331.  *
  332.  * Revision 1.44  2000/03/20 20:59:28  robertj
  333.  * Fixed possible buffer overrun problem in RTP_DataFrames
  334.  *
  335.  * Revision 1.43  2000/02/24 00:34:25  robertj
  336.  * Fixed possible endless loop on channel abort, thanks Yura Ershov
  337.  *
  338.  * Revision 1.42  2000/02/04 05:11:19  craigs
  339.  * Updated for new Makefiles and for new video transmission code
  340.  *
  341.  * Revision 1.41  2000/01/13 04:03:45  robertj
  342.  * Added video transmission
  343.  *
  344.  * Revision 1.40  2000/01/08 06:52:10  robertj
  345.  * Removed invalid assert
  346.  *
  347.  * Revision 1.39  1999/12/23 23:02:35  robertj
  348.  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
  349.  *
  350.  * Revision 1.38  1999/11/22 01:37:31  robertj
  351.  * Fixed channel closure so OnClosedLogicalChannel() only called if channel was actually started.
  352.  *
  353.  * Revision 1.37  1999/11/20 05:35:26  robertj
  354.  * Extra debugging
  355.  *
  356.  * Revision 1.36  1999/11/20 00:53:47  robertj
  357.  * Fixed ability to have variable sized frames in single RTP packet under G.723.1
  358.  *
  359.  * Revision 1.35  1999/11/19 09:06:25  robertj
  360.  * Changed to close down logical channel if get a transmit codec error.
  361.  *
  362.  * Revision 1.34  1999/11/11 23:28:46  robertj
  363.  * Added first cut silence detection algorithm.
  364.  *
  365.  * Revision 1.33  1999/11/06 11:01:37  robertj
  366.  * Extra debugging.
  367.  *
  368.  * Revision 1.32  1999/11/06 05:37:44  robertj
  369.  * Complete rewrite of termination of connection to avoid numerous race conditions.
  370.  *
  371.  * Revision 1.31  1999/11/01 00:47:46  robertj
  372.  * Added close of logical channel on write error
  373.  *
  374.  * Revision 1.30  1999/10/30 12:38:24  robertj
  375.  * Added more tracing of channel threads.
  376.  *
  377.  * Revision 1.29  1999/10/08 09:59:03  robertj
  378.  * Rewrite of capability for sending multiple audio frames
  379.  *
  380.  * Revision 1.28  1999/10/08 04:58:37  robertj
  381.  * Added capability for sending multiple audio frames in single RTP packet
  382.  *
  383.  * Revision 1.27  1999/09/23 07:25:12  robertj
  384.  * Added open audio and video function to connection and started multi-frame codec send functionality.
  385.  *
  386.  * Revision 1.26  1999/09/21 14:09:02  robertj
  387.  * Removed warnings when no tracing enabled.
  388.  *
  389.  * Revision 1.25  1999/09/18 13:24:38  craigs
  390.  * Added ability to disable jitter buffer
  391.  * Added ability to access entire RTP packet in codec Write
  392.  *
  393.  * Revision 1.24  1999/09/08 04:05:48  robertj
  394.  * Added support for video capabilities & codec, still needs the actual codec itself!
  395.  *
  396.  * Revision 1.23  1999/09/03 02:17:50  robertj
  397.  * Added more debugging
  398.  *
  399.  * Revision 1.22  1999/08/31 12:34:18  robertj
  400.  * Added gatekeeper support.
  401.  *
  402.  * Revision 1.21  1999/07/16 15:02:51  robertj
  403.  * Changed jitter buffer to throw away old packets if jitter exceeded.
  404.  *
  405.  * Revision 1.20  1999/07/16 00:51:03  robertj
  406.  * Some more debugging of fast start.
  407.  *
  408.  * Revision 1.19  1999/07/15 14:45:35  robertj
  409.  * Added propagation of codec open error to shut down logical channel.
  410.  * Fixed control channel start up bug introduced with tunnelling.
  411.  *
  412.  * Revision 1.18  1999/07/15 09:04:31  robertj
  413.  * Fixed some fast start bugs
  414.  *
  415.  * Revision 1.17  1999/07/14 06:04:04  robertj
  416.  * Fixed setting of channel number in fast start.
  417.  *
  418.  * Revision 1.16  1999/07/13 09:53:24  robertj
  419.  * Fixed some problems with jitter buffer and added more debugging.
  420.  *
  421.  * Revision 1.15  1999/07/13 02:50:58  craigs
  422.  * Changed semantics of SetPlayDevice/SetRecordDevice, only descendent
  423.  *    endpoint assumes PSoundChannel devices for audio codec.
  424.  *
  425.  * Revision 1.14  1999/07/10 03:01:48  robertj
  426.  * Removed debugging.
  427.  *
  428.  * Revision 1.13  1999/07/09 06:09:49  robertj
  429.  * Major implementation. An ENORMOUS amount of stuff added everywhere.
  430.  *
  431.  * Revision 1.12  1999/06/25 14:19:40  robertj
  432.  * Fixed termination race condition in logical channel tear down.
  433.  *
  434.  * Revision 1.11  1999/06/24 13:32:45  robertj
  435.  * Fixed ability to change sound device on codec and fixed NM3 G.711 compatibility
  436.  *
  437.  * Revision 1.10  1999/06/22 13:49:40  robertj
  438.  * Added GSM support and further RTP protocol enhancements.
  439.  *
  440.  * Revision 1.9  1999/06/14 05:15:55  robertj
  441.  * Changes for using RTP sessions correctly in H323 Logical Channel context
  442.  *
  443.  * Revision 1.8  1999/06/13 12:41:14  robertj
  444.  * Implement logical channel transmitter.
  445.  * Fixed H245 connect on receiving call.
  446.  *
  447.  * Revision 1.7  1999/06/09 06:18:00  robertj
  448.  * GCC compatibiltiy.
  449.  *
  450.  * Revision 1.6  1999/06/09 05:26:19  robertj
  451.  * Major restructuring of classes.
  452.  *
  453.  * Revision 1.5  1999/06/07 00:54:30  robertj
  454.  * Displayed error on SetOption for buffer size
  455.  *
  456.  * Revision 1.4  1999/06/06 06:06:36  robertj
  457.  * Changes for new ASN compiler and v2 protocol ASN files.
  458.  *
  459.  * Revision 1.3  1999/04/26 06:14:46  craigs
  460.  * Initial implementation for RTP decoding and lots of stuff
  461.  * As a whole, these changes are called "First Noise"
  462.  *
  463.  * Revision 1.2  1999/02/25 03:26:02  robertj
  464.  * BeOS compatibility
  465.  *
  466.  * Revision 1.1  1999/01/16 01:31:09  robertj
  467.  * Initial revision
  468.  *
  469.  */
  470.  
  471. #include <ptlib.h>
  472.  
  473. #ifdef __GNUC__
  474. #pragma implementation "channels.h"
  475. #endif
  476.  
  477. #include "channels.h"
  478.  
  479. #include "h323pdu.h"
  480. #include "h323ep.h"
  481. #include "h323rtp.h"
  482.  
  483.  
  484.  
  485. #define    MAX_PAYLOAD_TYPE_MISMATCHES 8
  486. #define RTP_TRACE_DISPLAY_RATE 16000 // 2 seconds
  487.  
  488.  
  489. class H323LogicalChannelThread : public PThread
  490. {
  491.     PCLASSINFO(H323LogicalChannelThread, PThread)
  492.   public:
  493.     H323LogicalChannelThread(H323EndPoint & endpoint, H323Channel & channel, BOOL rx);
  494.     void Main();
  495.   private:
  496.     H323Channel & channel;
  497.     BOOL receiver;
  498. };
  499.  
  500.  
  501. #define new PNEW
  502.  
  503.  
  504. #if PTRACING
  505.  
  506. ostream & operator<<(ostream & out, H323Channel::Directions dir)
  507. {
  508.   static const char * const DirNames[H323Channel::NumDirections] = {
  509.     "IsBidirectional", "IsTransmitter", "IsReceiver"
  510.   };
  511.  
  512.   if (dir < H323Channel::NumDirections && DirNames[dir] != NULL)
  513.     out << DirNames[dir];
  514.   else
  515.     out << "Direction<" << (unsigned)dir << '>';
  516.  
  517.   return out;
  518. }
  519.  
  520. #else // Stuff to remove unused parameters warning
  521.  
  522. #define PTRACE_jitter
  523. #define PTRACE_skippedFrameCount
  524. #define PTRACE_additionalBuffer
  525. #define PTRACE_direction
  526.  
  527. #endif
  528.  
  529.  
  530. /////////////////////////////////////////////////////////////////////////////
  531.  
  532. H323LogicalChannelThread::H323LogicalChannelThread(H323EndPoint & endpoint,
  533.                                                    H323Channel & c,
  534.                                                    BOOL rx)
  535.   : PThread(endpoint.GetChannelThreadStackSize(),
  536.             NoAutoDeleteThread,
  537.             HighestPriority,
  538.             rx ? "LogChanRx:%0x" : "LogChanTx:%0x"),
  539.     channel(c)
  540. {
  541.   PTRACE(4, "LogChan\tStarting logical channel thread " << this);
  542.   receiver = rx;
  543.   Resume();
  544. }
  545.  
  546.  
  547. void H323LogicalChannelThread::Main()
  548. {
  549.   PTRACE(4, "LogChan\tStarted logical channel thread " << this);
  550.   if (receiver)
  551.     channel.Receive();
  552.   else
  553.     channel.Transmit();
  554.  
  555. #ifdef _WIN32_WCE
  556.     Sleep(0); // Relinquish control to other thread
  557. #endif
  558. }
  559.  
  560.  
  561. /////////////////////////////////////////////////////////////////////////////
  562.  
  563. H323ChannelNumber::H323ChannelNumber(unsigned num, BOOL fromRem)
  564. {
  565.   PAssert(num < 0x10000, PInvalidParameter);
  566.   number = num;
  567.   fromRemote = fromRem;
  568. }
  569.  
  570.  
  571. PObject * H323ChannelNumber::Clone() const
  572. {
  573.   return new H323ChannelNumber(number, fromRemote);
  574. }
  575.  
  576.  
  577. PINDEX H323ChannelNumber::HashFunction() const
  578. {
  579.   PINDEX hash = (number%17) << 1;
  580.   if (fromRemote)
  581.     hash++;
  582.   return hash;
  583. }
  584.  
  585.  
  586. void H323ChannelNumber::PrintOn(ostream & strm) const
  587. {
  588.   strm << (fromRemote ? 'R' : 'T') << '-' << number;
  589. }
  590.  
  591.  
  592. PObject::Comparison H323ChannelNumber::Compare(const PObject & obj) const
  593. {
  594. #ifndef PASN_LEANANDMEAN
  595.   PAssert(IsDescendant(Class()), PInvalidCast);
  596. #endif
  597.   const H323ChannelNumber & other = (const H323ChannelNumber &)obj;
  598.   if (number < other.number)
  599.     return LessThan;
  600.   if (number > other.number)
  601.     return GreaterThan;
  602.   if (fromRemote && !other.fromRemote)
  603.     return LessThan;
  604.   if (!fromRemote && other.fromRemote)
  605.     return GreaterThan;
  606.   return EqualTo;
  607. }
  608.  
  609.  
  610. H323ChannelNumber & H323ChannelNumber::operator++(int)
  611. {
  612.   number++;
  613.   return *this;
  614. }
  615.  
  616.  
  617. /////////////////////////////////////////////////////////////////////////////
  618.  
  619. H323Channel::H323Channel(H323Connection & conn, const H323Capability & cap)
  620.   : endpoint(conn.GetEndPoint()),
  621.     connection(conn)
  622. {
  623.   capability = (H323Capability *)cap.Clone();
  624.   codec = NULL;
  625.   bandwidthUsed = 0;
  626.   receiveThread = NULL;
  627.   transmitThread = NULL;
  628.   terminating = FALSE;
  629.   opened = FALSE;
  630.   paused = FALSE;
  631. }
  632.  
  633.  
  634. H323Channel::~H323Channel()
  635. {
  636.   connection.UseBandwidth(bandwidthUsed, TRUE);
  637.  
  638.   delete codec;
  639.   delete capability;
  640. }
  641.  
  642.  
  643. void H323Channel::PrintOn(ostream & strm) const
  644. {
  645.   strm << number;
  646. }
  647.  
  648.  
  649. unsigned H323Channel::GetSessionID() const
  650. {
  651.   return 0;
  652. }
  653.  
  654.  
  655. void H323Channel::CleanUpOnTermination()
  656. {
  657.   if (!opened || terminating)
  658.     return;
  659.  
  660.   PTRACE(3, "LogChan\tCleaning up " << number);
  661.  
  662.   terminating = TRUE;
  663.  
  664.   // If we have a codec, then close it, this allows the transmitThread to be
  665.   // broken out of any I/O block on reading the codec.
  666.   if (codec != NULL)
  667.     codec->Close();
  668.  
  669.   // If we have a receiver thread, wait for it to die.
  670.   if (receiveThread != NULL) {
  671.     PTRACE(4, "LogChan\tAwaiting termination of " << receiveThread << ' ' << receiveThread->GetThreadName());
  672.     PAssert(receiveThread->WaitForTermination(10000), "Receive media thread did not terminate");
  673.     delete receiveThread;
  674.     receiveThread = NULL;
  675.   }
  676.  
  677.   // If we have a transmitter thread, wait for it to die.
  678.   if (transmitThread != NULL) {
  679.     PTRACE(4, "LogChan\tAwaiting termination of " << transmitThread << ' ' << transmitThread->GetThreadName());
  680.     PAssert(transmitThread->WaitForTermination(10000), "Transmit media thread did not terminate");
  681.     delete transmitThread;
  682.     transmitThread = NULL;
  683.   }
  684.  
  685.   // Signal to the connection that this channel is on the way out
  686.   connection.OnClosedLogicalChannel(*this);
  687.  
  688.   PTRACE(3, "LogChan\tCleaned up " << number);
  689. }
  690.  
  691.  
  692. BOOL H323Channel::IsRunning() const
  693. {
  694.   if (receiveThread  != NULL && !receiveThread ->IsTerminated())
  695.     return TRUE;
  696.  
  697.   if (transmitThread != NULL && !transmitThread->IsTerminated())
  698.     return TRUE;
  699.  
  700.   return FALSE;
  701. }
  702.  
  703.  
  704. BOOL H323Channel::OnReceivedPDU(const H245_OpenLogicalChannel & /*pdu*/,
  705.                                 unsigned & /*errorCode*/)
  706. {
  707.   return TRUE;
  708. }
  709.  
  710.  
  711. BOOL H323Channel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & /*pdu*/)
  712. {
  713.   return TRUE;
  714. }
  715.  
  716.  
  717. void H323Channel::OnSendOpenAck(const H245_OpenLogicalChannel & /*pdu*/,
  718.                                 H245_OpenLogicalChannelAck & /* pdu*/) const
  719. {
  720. }
  721.  
  722.  
  723. void H323Channel::OnFlowControl(long bitRateRestriction)
  724. {
  725.   if (GetCodec() != NULL)
  726.     codec->OnFlowControl(bitRateRestriction);
  727.   else
  728.     PTRACE(3, "LogChan\tOnFlowControl: " << bitRateRestriction);
  729. }
  730.  
  731.  
  732. void H323Channel::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
  733. {
  734.   if (GetCodec() != NULL)
  735.     codec->OnMiscellaneousCommand(type);
  736.   else
  737.     PTRACE(3, "LogChan\tOnMiscellaneousCommand: chan=" << number
  738.            << ", type=" << type.GetTagName());
  739. }
  740.  
  741.  
  742. void H323Channel::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type)
  743. {
  744.   if (GetCodec() != NULL)
  745.     codec->OnMiscellaneousIndication(type);
  746.   else
  747.     PTRACE(3, "LogChan\tOnMiscellaneousIndication: chan=" << number
  748.            << ", type=" << type.GetTagName());
  749. }
  750.  
  751.  
  752. void H323Channel::OnJitterIndication(DWORD PTRACE_jitter,
  753.                                      int   PTRACE_skippedFrameCount,
  754.                                      int   PTRACE_additionalBuffer)
  755. {
  756.   PTRACE(3, "LogChan\tOnJitterIndication:"
  757.             " jitter=" << PTRACE_jitter <<
  758.             " skippedFrameCount=" << PTRACE_skippedFrameCount <<
  759.             " additionalBuffer=" << PTRACE_additionalBuffer);
  760. }
  761.  
  762.  
  763. BOOL H323Channel::SetInitialBandwidth()
  764. {
  765.   if (GetCodec() == NULL)
  766.     return TRUE;
  767.  
  768.   return SetBandwidthUsed(codec->GetMediaFormat().GetBandwidth()/100);
  769. }
  770.  
  771.  
  772. BOOL H323Channel::SetBandwidthUsed(unsigned bandwidth)
  773. {
  774.   PTRACE(3, "LogChan\tBandwidth requested/used = "
  775.          << bandwidth/10 << '.' << bandwidth%10 << '/'
  776.          << bandwidthUsed/10 << '.' << bandwidthUsed%10
  777.          << " kb/s");
  778.   connection.UseBandwidth(bandwidthUsed, TRUE);
  779.   bandwidthUsed = 0;
  780.  
  781.   if (!connection.UseBandwidth(bandwidth, FALSE))
  782.     return FALSE;
  783.  
  784.   bandwidthUsed = bandwidth;
  785.   return TRUE;
  786. }
  787.  
  788.  
  789. BOOL H323Channel::Open()
  790. {
  791.   if (opened)
  792.     return TRUE;
  793.  
  794.   // Give the connection (or endpoint) a chance to do something with
  795.   // the opening of the codec. Default calls codec->Open();
  796.   if (!connection.OnStartLogicalChannel(*this)) {
  797.     PTRACE(1, "LogChan\tOnStartLogicalChannel failed");
  798.     return FALSE;
  799.   }
  800.   
  801.   opened = TRUE;
  802.   return TRUE;
  803. }
  804.  
  805.  
  806. H323Codec * H323Channel::GetCodec() const
  807. {
  808.   if (codec == NULL) {
  809.     ((H323Channel*)this)->codec = capability->CreateCodec(
  810.                   GetDirection() == IsReceiver ? H323Codec::Decoder : H323Codec::Encoder);
  811.     if (codec && codec->IsDescendant(H323AudioCodec::Class()))
  812.       ((H323AudioCodec*)codec)->SetSilenceDetectionMode(endpoint.GetSilenceDetectionMode()); 
  813.   }
  814.  
  815.   return codec;
  816. }
  817.  
  818.  
  819. void H323Channel::SendMiscCommand(unsigned command)
  820.   connection.SendLogicalChannelMiscCommand(*this, command); 
  821. }
  822.  
  823.  
  824. /////////////////////////////////////////////////////////////////////////////
  825.  
  826. H323UnidirectionalChannel::H323UnidirectionalChannel(H323Connection & conn,
  827.                                                      const H323Capability & cap,
  828.                                                      Directions direction)
  829.   : H323Channel(conn, cap),
  830.     receiver(direction == IsReceiver)
  831. {
  832. }
  833.  
  834.  
  835. H323Channel::Directions H323UnidirectionalChannel::GetDirection() const
  836. {
  837.   return receiver ? IsReceiver : IsTransmitter;
  838. }
  839.  
  840.  
  841. BOOL H323UnidirectionalChannel::Start()
  842. {
  843.   if (!Open())
  844.     return FALSE;
  845.  
  846.   PThread * thread = new H323LogicalChannelThread(endpoint, *this, receiver);
  847.  
  848.   if (receiver)
  849.     receiveThread  = thread;
  850.   else
  851.     transmitThread = thread;
  852.   return TRUE;
  853. }
  854.  
  855.  
  856. /////////////////////////////////////////////////////////////////////////////
  857.  
  858. H323BidirectionalChannel::H323BidirectionalChannel(H323Connection & conn,
  859.                                                    const H323Capability & cap)
  860.   : H323Channel(conn, cap)
  861. {
  862. }
  863.  
  864.  
  865. H323Channel::Directions H323BidirectionalChannel::GetDirection() const
  866. {
  867.   return IsBidirectional;
  868. }
  869.  
  870.  
  871. BOOL H323BidirectionalChannel::Start()
  872. {
  873.   receiveThread  = new H323LogicalChannelThread(endpoint, *this, TRUE);
  874.   transmitThread = new H323LogicalChannelThread(endpoint, *this, FALSE);
  875.   return TRUE;
  876. }
  877.  
  878.  
  879. /////////////////////////////////////////////////////////////////////////////
  880.  
  881. H323_RealTimeChannel::H323_RealTimeChannel(H323Connection & connection,
  882.                                            const H323Capability & capability,
  883.                                            Directions direction)
  884.   : H323UnidirectionalChannel(connection, capability, direction)
  885. {
  886.   rtpPayloadType = RTP_DataFrame::IllegalPayloadType;
  887. }
  888.  
  889.  
  890. BOOL H323_RealTimeChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
  891. {
  892.   PTRACE(3, "H323RTP\tOnSendingPDU");
  893.  
  894.   open.m_forwardLogicalChannelNumber = (unsigned)number;
  895.  
  896.   if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
  897.     open.m_reverseLogicalChannelParameters.IncludeOptionalField(
  898.             H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
  899.     // Set the communications information for unicast IPv4
  900.     open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
  901.                 H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
  902.                     ::e_h2250LogicalChannelParameters);
  903.  
  904.     return OnSendingPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters);
  905.   }
  906.   else {
  907.     // Set the communications information for unicast IPv4
  908.     open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
  909.                 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
  910.                     ::e_h2250LogicalChannelParameters);
  911.  
  912.     return OnSendingPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters);
  913.   }
  914. }
  915.  
  916.  
  917. void H323_RealTimeChannel::OnSendOpenAck(const H245_OpenLogicalChannel & open,
  918.                                          H245_OpenLogicalChannelAck & ack) const
  919. {
  920.   PTRACE(3, "H323RTP\tOnSendOpenAck");
  921.  
  922.   // set forwardMultiplexAckParameters option
  923.   ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
  924.  
  925.   // select H225 choice
  926.   ack.m_forwardMultiplexAckParameters.SetTag(
  927.       H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
  928.  
  929.   // get H225 parms
  930.   H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
  931.  
  932.   // set session ID
  933.   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
  934.   const H245_H2250LogicalChannelParameters & openparam =
  935.                           open.m_forwardLogicalChannelParameters.m_multiplexParameters;
  936.   unsigned sessionID = openparam.m_sessionID;
  937.   param.m_sessionID = sessionID;
  938.  
  939.   OnSendOpenAck(param);
  940.  
  941.   PTRACE(2, "H323RTP\tSending open logical channel ACK: sessionID=" << sessionID);
  942. }
  943.  
  944.  
  945. BOOL H323_RealTimeChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
  946.                                          unsigned & errorCode)
  947. {
  948.   if (receiver)
  949.     number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
  950.  
  951.   PTRACE(3, "H323RTP\tOnReceivedPDU for channel: " << number);
  952.  
  953.   unsigned prevTxFrames = capability->GetTxFramesInPacket();
  954.   unsigned prevRxFrames = capability->GetRxFramesInPacket();
  955.   PString  prevFormat   = capability->GetFormatName();
  956.  
  957.   BOOL reverse = open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
  958.   const H245_DataType & dataType = reverse ? open.m_reverseLogicalChannelParameters.m_dataType
  959.                                            : open.m_forwardLogicalChannelParameters.m_dataType;
  960.  
  961.   if (!capability->OnReceivedPDU(dataType, receiver)) {
  962.     PTRACE(1, "H323RTP\tData type not supported");
  963.     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
  964.     return FALSE;
  965.   }
  966.  
  967.   // If we have already created a codec, and the new parameters indicate that
  968.   // the capability limits have changed, then kill off the old codec it will
  969.   // be wrongly constructed.
  970.   if (codec != NULL &&
  971.       (prevTxFrames != capability->GetTxFramesInPacket() ||
  972.        prevRxFrames != capability->GetRxFramesInPacket() ||
  973.        prevFormat   != capability->GetFormatName())) {
  974.     delete codec;
  975.     codec = NULL;
  976.   }
  977.  
  978.   if (reverse) {
  979.     if (open.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() ==
  980.              H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
  981.       return OnReceivedPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters, errorCode);
  982.   }
  983.   else {
  984.     if (open.m_forwardLogicalChannelParameters.m_multiplexParameters.GetTag() ==
  985.              H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_h2250LogicalChannelParameters)
  986.       return OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters, errorCode);
  987.   }
  988.  
  989.   PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
  990.   errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
  991.   return FALSE;
  992. }
  993.  
  994.  
  995. BOOL H323_RealTimeChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
  996. {
  997.   PTRACE(3, "H323RTP\tOnReceiveOpenAck");
  998.  
  999.   if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
  1000.     PTRACE(1, "H323RTP\tNo forwardMultiplexAckParameters");
  1001.     return FALSE;
  1002.   }
  1003.  
  1004.   if (ack.m_forwardMultiplexAckParameters.GetTag() !=
  1005.             H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
  1006.     PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported");
  1007.     return FALSE;
  1008.   }
  1009.  
  1010.   return OnReceivedAckPDU(ack.m_forwardMultiplexAckParameters);
  1011. }
  1012.  
  1013.  
  1014. BOOL H323_RealTimeChannel::SetDynamicRTPPayloadType(int newType)
  1015. {
  1016.   PTRACE(1, "H323RTP\tSetting dynamic RTP payload type: " << newType);
  1017.  
  1018.   // This is "no change"
  1019.   if (newType == -1)
  1020.     return TRUE;
  1021.  
  1022.   // Check for illegal type
  1023.   if (newType < RTP_DataFrame::DynamicBase || newType > RTP_DataFrame::MaxPayloadType)
  1024.     return FALSE;
  1025.  
  1026.   // Check for overwriting "known" type
  1027.   if (rtpPayloadType < RTP_DataFrame::DynamicBase)
  1028.     return FALSE;
  1029.  
  1030.   rtpPayloadType = (RTP_DataFrame::PayloadTypes)newType;
  1031.   PTRACE(3, "H323RTP\tSetting dynamic payload type to " << rtpPayloadType);
  1032.   return TRUE;
  1033. }
  1034.  
  1035.  
  1036. /////////////////////////////////////////////////////////////////////////////
  1037.  
  1038. H323_RTPChannel::H323_RTPChannel(H323Connection & conn,
  1039.                                  const H323Capability & cap,
  1040.                                  Directions direction,
  1041.                                  RTP_Session & r)
  1042.   : H323_RealTimeChannel(conn, cap, direction),
  1043.     rtpSession(r),
  1044.     rtpCallbacks(*(H323_RTP_Session *)r.GetUserData())
  1045. {
  1046.   PTRACE(3, "H323RTP\t" << (receiver ? "Receiver" : "Transmitter")
  1047.          << " created using session " << GetSessionID());
  1048. }
  1049.  
  1050.  
  1051. H323_RTPChannel::~H323_RTPChannel()
  1052. {
  1053.   // Finished with the RTP session, this will delete the session if it is no
  1054.   // longer referenced by any logical channels.
  1055.   connection.ReleaseSession(GetSessionID());
  1056. }
  1057.  
  1058.  
  1059. void H323_RTPChannel::CleanUpOnTermination()
  1060. {
  1061.   if (terminating)
  1062.     return;
  1063.  
  1064.   PTRACE(3, "H323RTP\tCleaning up RTP " << number);
  1065.  
  1066.   // Break any I/O blocks and wait for the thread that uses this object to
  1067.   // terminate before we allow it to be deleted.
  1068.   if ((receiver ? receiveThread : transmitThread) != NULL)
  1069.     rtpSession.Close(receiver);
  1070.  
  1071.   H323Channel::CleanUpOnTermination();
  1072. }
  1073.  
  1074.  
  1075. unsigned H323_RTPChannel::GetSessionID() const
  1076. {
  1077.   return rtpSession.GetSessionID();
  1078. }
  1079.  
  1080.  
  1081. BOOL H323_RTPChannel::Open()
  1082. {
  1083.   if (opened)
  1084.     return TRUE;
  1085.  
  1086.   if (!GetCodec()->GetMediaFormat().IsValid()) {
  1087.     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
  1088.            << " thread aborted (invalid media format)");
  1089.     return FALSE;
  1090.   }
  1091.  
  1092.   // Open the codec
  1093.   if (!GetCodec()->Open(connection)) {
  1094.     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
  1095.            << " thread aborted (open fail) for "<< *capability);
  1096.     return FALSE;
  1097.   }
  1098.  
  1099.   // Give the connection (or endpoint) a chance to do something with
  1100.   // the opening of the codec. Default calls codec->Open();
  1101.   if (!connection.OnStartLogicalChannel(*this)) {
  1102.     PTRACE(1, "LogChan\t" << (GetDirection() == IsReceiver ? "Receive" : "Transmit")
  1103.            << " thread aborted (OnStartLogicalChannel fail)");
  1104.     return FALSE;
  1105.   }
  1106.   
  1107.   PTRACE(3, "LogChan\tOpened using capability " << *capability);
  1108.  
  1109.   GetCodec()->AttachLogicalChannel((H323Channel*)this);
  1110.  
  1111.   opened = TRUE;
  1112.  
  1113.   return TRUE;
  1114. }
  1115.  
  1116.  
  1117. BOOL H323_RTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
  1118. {
  1119.   return rtpCallbacks.OnSendingPDU(*this, param);
  1120. }
  1121.  
  1122.  
  1123. void H323_RTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
  1124. {
  1125.   rtpCallbacks.OnSendingAckPDU(*this, param);
  1126. }
  1127.  
  1128.  
  1129. BOOL H323_RTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
  1130.                                     unsigned & errorCode)
  1131. {
  1132.   return rtpCallbacks.OnReceivedPDU(*this, param, errorCode);
  1133. }
  1134.  
  1135.  
  1136. BOOL H323_RTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
  1137. {
  1138.   return rtpCallbacks.OnReceivedAckPDU(*this, param);
  1139. }
  1140.  
  1141.  
  1142. #if PTRACING
  1143. class CodecReadAnalyser
  1144. {
  1145.   enum { MaxSamples = 1000 };
  1146.   public:
  1147.     CodecReadAnalyser() { count = 0; }
  1148.     void AddSample(DWORD timestamp)
  1149.       {
  1150.         if (count < MaxSamples) {
  1151.           tick[count] = PTimer::Tick();
  1152.           rtp[count] = timestamp;
  1153.           count++;
  1154.         }
  1155.       }
  1156.     friend ostream & operator<<(ostream & strm, const CodecReadAnalyser & analysis)
  1157.       {
  1158.         PTimeInterval minimum = PMaxTimeInterval;
  1159.         PTimeInterval maximum;
  1160.         for (PINDEX i = 1; i < analysis.count; i++) {
  1161.           PTimeInterval delta = analysis.tick[i] - analysis.tick[i-1];
  1162.           strm << setw(6) << analysis.rtp[i] << ' '
  1163.                << setw(6) << (analysis.tick[i] - analysis.tick[0]) << ' '
  1164.                << setw(6) << delta
  1165.                << '\n';
  1166.           if (delta > maximum)
  1167.             maximum = delta;
  1168.           if (delta < minimum)
  1169.             minimum = delta;
  1170.         }
  1171.         strm << "Maximum delta time: " << maximum << "\n"
  1172.                 "Minimum delta time: " << minimum << '\n';
  1173.         return strm;
  1174.       }
  1175.   private:
  1176.     PTimeInterval tick[MaxSamples];
  1177.     DWORD rtp[MaxSamples];
  1178.     PINDEX count;
  1179. };
  1180. #endif
  1181.  
  1182.  
  1183. void H323_RTPChannel::Transmit()
  1184. {
  1185.   if (terminating) {
  1186.     PTRACE(3, "H323RTP\tTransmit thread terminated on start up");
  1187.     return;
  1188.   }
  1189.  
  1190.   const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
  1191.  
  1192.   // Get parameters from the codec on time and data sizes
  1193.   BOOL isAudio = mediaFormat.NeedsJitterBuffer();
  1194.   unsigned framesInPacket = capability->GetTxFramesInPacket();
  1195.   unsigned maxFrameSize = mediaFormat.GetFrameSize();
  1196.   if (maxFrameSize == 0)
  1197.     maxFrameSize = isAudio ? 8 : 2000;
  1198.   RTP_DataFrame frame(framesInPacket*maxFrameSize);
  1199.  
  1200.   if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
  1201.     rtpPayloadType = capability->GetPayloadType();
  1202.     if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType)
  1203.       rtpPayloadType = mediaFormat.GetPayloadType();
  1204.   }
  1205.  
  1206.   if (mediaFormat.GetTimeUnits() != 0) {
  1207.   PTRACE(2, "H323RTP\tTransmit " << mediaFormat << " thread started:"
  1208.             " rate=" << codec->GetFrameRate() <<
  1209.             " time=" << (codec->GetFrameRate()/mediaFormat.GetTimeUnits()) << "ms" <<
  1210.             " size=" << framesInPacket << '*' << maxFrameSize << '='
  1211.                      << (framesInPacket*maxFrameSize) );
  1212.   } else {
  1213.   PTRACE(2, "H323RTP\tTransmit " << mediaFormat << " thread started:"
  1214.             " rate=" << codec->GetFrameRate() <<
  1215.             " time= GetTimeUnits() is zero" <<
  1216.             " size=" << framesInPacket << '*' << maxFrameSize << '='
  1217.                      << (framesInPacket*maxFrameSize) );
  1218.   }
  1219.  
  1220.   // This is real time so need to keep track of elapsed milliseconds
  1221.   BOOL silent = TRUE;
  1222.   unsigned length;
  1223.   unsigned frameOffset = 0;
  1224.   unsigned frameCount = 0;
  1225.   DWORD rtpTimestamp = 0;
  1226.   frame.SetPayloadSize(0);
  1227.  
  1228. #if PTRACING
  1229.   DWORD lastDisplayedTimestamp = 0;
  1230.   CodecReadAnalyser * codecReadAnalysis = NULL;
  1231.   if (PTrace::GetLevel() >= 5)
  1232.     codecReadAnalysis = new CodecReadAnalyser;
  1233. #endif
  1234.  
  1235.   /* Now keep getting encoded frames from the codec, it is expected that the
  1236.      Read() function will maintain the Real Time aspects of the transmission.
  1237.      That is for GSM codec say with a single frame, this function will take
  1238.      20 milliseconds to complete.
  1239.    */
  1240.   while (codec->Read(frame.GetPayloadPtr()+frameOffset, length, frame)) {
  1241.     // Calculate the timestamp and real time to take in processing
  1242.     rtpTimestamp += codec->GetFrameRate();
  1243.  
  1244. #if PTRACING
  1245.     if (rtpTimestamp - lastDisplayedTimestamp > RTP_TRACE_DISPLAY_RATE) {
  1246.       PTRACE(3, "H323RTP\tTransmitter sent timestamp " << rtpTimestamp);
  1247.       lastDisplayedTimestamp = rtpTimestamp;
  1248.     }
  1249.  
  1250.     if (codecReadAnalysis != NULL)
  1251.       codecReadAnalysis->AddSample(rtpTimestamp);
  1252. #endif
  1253.  
  1254.     if (paused)
  1255.       length = 0; // Act as though silent/no video
  1256.  
  1257.     // Handle marker bit for audio codec
  1258.     if (isAudio) {
  1259.       // If switching from silence to signal
  1260.       if (silent && length > 0) {
  1261.         silent = FALSE;
  1262.         frame.SetMarker(TRUE);  // Set flag for start of sound
  1263.         PTRACE(3, "H323RTP\tTransmit start of talk burst: " << rtpTimestamp);
  1264.       }
  1265.       // If switching from signal to silence
  1266.       else if (!silent && length == 0) {
  1267.         silent = TRUE;
  1268.         // If had some data waiting to go out
  1269.         if (frameOffset > 0)
  1270.           frameCount = framesInPacket;  // Force the RTP write
  1271.         PTRACE(3, "H323RTP\tTransmit  end  of talk burst: " << rtpTimestamp);
  1272.       }
  1273.     }
  1274.  
  1275.     // See if is silence or have some audio data to stuff in the RTP packet
  1276.     if (length == 0)
  1277.       frame.SetTimestamp(rtpTimestamp);
  1278.     else {
  1279.       silenceStartTick = PTimer::Tick();
  1280.  
  1281.       // If first read frame in packet, set timestamp for it
  1282.       if (frameOffset == 0)
  1283.         frame.SetTimestamp(rtpTimestamp);
  1284.       frameOffset += length;
  1285.  
  1286.       // Look for special cases
  1287.       if (rtpPayloadType == RTP_DataFrame::G729 && length == 2) {
  1288.         /* If we have a G729 sid frame (ie 2 bytes instead of 10) then we must
  1289.            not send any more frames in the RTP packet.
  1290.          */
  1291.         frameCount = framesInPacket;
  1292.       }
  1293.       else {
  1294.         /* Increment by number of frames that were read in one hit Note a
  1295.            codec that does variable length frames should never return more
  1296.            than one frame per Read() call or confusion will result.
  1297.          */
  1298.         frameCount += (length + maxFrameSize - 1)/maxFrameSize;
  1299.       }
  1300.     }
  1301.  
  1302.     BOOL sendPacket = FALSE;
  1303.  
  1304.     // Have read number of frames for packet (or just went silent)
  1305.     if (frameCount >= framesInPacket) {
  1306.       // Set payload size to frame offset, now length of frame.
  1307.       frame.SetPayloadSize(frameOffset);
  1308.       frame.SetPayloadType(rtpPayloadType);
  1309.  
  1310.       frameOffset = 0;
  1311.       frameCount = 0;
  1312.  
  1313.       sendPacket = TRUE;
  1314.     }
  1315.  
  1316.     filterMutex.Wait();
  1317.     for (PINDEX i = 0; i < filters.GetSize(); i++)
  1318.       filters[i](frame, (INT)&sendPacket);
  1319.     filterMutex.Signal();
  1320.  
  1321.     if (sendPacket || (silent && frame.GetPayloadSize() > 0)) {
  1322.       // Send the frame of coded data we have so far to RTP transport
  1323.       if (!rtpSession.WriteData(frame))
  1324.          break;
  1325.  
  1326.       // Reset flag for in talk burst
  1327.       if (isAudio)
  1328.         frame.SetMarker(FALSE); 
  1329.  
  1330.       frame.SetPayloadSize(0);
  1331.       frameOffset = 0;
  1332.       frameCount = 0;
  1333.     }
  1334.  
  1335.     if (terminating)
  1336.       break;
  1337.   }
  1338.  
  1339. #if PTRACING
  1340.   PTRACE(5, "Codec read timing:\n" << *codecReadAnalysis);
  1341.   delete codecReadAnalysis;
  1342. #endif
  1343.  
  1344.   if (!terminating)
  1345.     connection.CloseLogicalChannelNumber(number);
  1346.  
  1347.   PTRACE(2, "H323RTP\tTransmit " << mediaFormat << " thread ended");
  1348. }
  1349.  
  1350.  
  1351. void H323_RTPChannel::Receive()
  1352. {
  1353.   if (terminating) {
  1354.     PTRACE(3, "H323RTP\tReceive thread terminated on start up");
  1355.     return;
  1356.   }
  1357.  
  1358.   const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
  1359.  
  1360.   PTRACE(2, "H323RTP\tReceive " << mediaFormat << " thread started.");
  1361.  
  1362.   // if jitter buffer required, start the thread that is on the other end of it
  1363.   if (mediaFormat.NeedsJitterBuffer())
  1364.     rtpSession.SetJitterBufferSize(connection.GetMinAudioJitterDelay()*mediaFormat.GetTimeUnits(),
  1365.                                    connection.GetMaxAudioJitterDelay()*mediaFormat.GetTimeUnits(),
  1366.                                    endpoint.GetJitterThreadStackSize());
  1367.  
  1368.   // Keep time using th RTP timestamps.
  1369.   DWORD codecFrameRate = codec->GetFrameRate();
  1370.   DWORD rtpTimestamp = 0;
  1371. #if PTRACING
  1372.   DWORD lastDisplayedTimestamp = 0;
  1373. #endif
  1374.  
  1375.   // keep track of consecutive payload type mismatches
  1376.   int consecutiveMismatches = 0;
  1377.  
  1378.   if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
  1379.     rtpPayloadType = capability->GetPayloadType();
  1380.     if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType)
  1381.       rtpPayloadType = mediaFormat.GetPayloadType();
  1382.   }
  1383.  
  1384.   RTP_DataFrame frame;
  1385.   while (rtpSession.ReadBufferedData(rtpTimestamp, frame)) {
  1386.  
  1387.     filterMutex.Wait();
  1388.     for (PINDEX i = 0; i < filters.GetSize(); i++)
  1389.       filters[i](frame, 0);
  1390.     filterMutex.Signal();
  1391.  
  1392.     int size = frame.GetPayloadSize();
  1393.     rtpTimestamp = frame.GetTimestamp();
  1394.  
  1395. #if PTRACING
  1396.     if (rtpTimestamp - lastDisplayedTimestamp > RTP_TRACE_DISPLAY_RATE) {
  1397.       PTRACE(3, "H323RTP\tReceiver written timestamp " << rtpTimestamp);
  1398.       lastDisplayedTimestamp = rtpTimestamp;
  1399.     }
  1400. #endif
  1401.  
  1402.     unsigned written;
  1403.     BOOL ok = TRUE;
  1404.     if (size == 0) {
  1405.       ok = codec->Write(NULL, 0, frame, written);
  1406.       rtpTimestamp += codecFrameRate;
  1407.     } else {
  1408.       silenceStartTick = PTimer::Tick();
  1409.  
  1410.       BOOL isCodecPacket = TRUE;
  1411.  
  1412.       if (frame.GetPayloadType() == rtpPayloadType) {
  1413.         PTRACE_IF(2, consecutiveMismatches > 0,
  1414.                   "H323RTP\tPayload type matched again " << rtpPayloadType);
  1415.         consecutiveMismatches = 0;
  1416.       }
  1417.       else {
  1418.         consecutiveMismatches++;
  1419.         if (consecutiveMismatches >= MAX_PAYLOAD_TYPE_MISMATCHES) {
  1420.           rtpPayloadType = frame.GetPayloadType();
  1421.           consecutiveMismatches = 0;
  1422.           PTRACE(1, "H323RTP\tResetting expected payload type to " << rtpPayloadType);
  1423.         }
  1424.         else {
  1425.           PTRACE(2, "H323RTP\tPayload type mismatch: expected "
  1426.                  << rtpPayloadType << ", got " << frame.GetPayloadType()
  1427.                  << ". Ignoring packet.");
  1428.         }
  1429.       }
  1430.  
  1431.       if (isCodecPacket && consecutiveMismatches == 0) {
  1432.         const BYTE * ptr = frame.GetPayloadPtr();
  1433.         while (ok && size > 0) {
  1434.           /* Now write data to the codec, it is expected that the Write()
  1435.              function will maintain the Real Time aspects of the system. That
  1436.              is for GSM codec, say with a single frame, this function will take
  1437.              20 milliseconds to complete. It is very important that this occurs
  1438.              for audio codecs or the jitter buffer will not operate correctly.
  1439.            */
  1440.           ok = codec->Write(ptr, paused ? 0 : size, frame, written);
  1441.           rtpTimestamp += codecFrameRate;
  1442.           size -= written;
  1443.           ptr += written;
  1444.         }
  1445.         PTRACE_IF(1, size < 0, "H323RTP\tPayload size too small, short " << -size << " bytes.");
  1446.       }
  1447.     }
  1448.  
  1449.     if (terminating)
  1450.       break;
  1451.  
  1452.     if (!ok) {
  1453.       connection.CloseLogicalChannelNumber(number);
  1454.       break;
  1455.     }
  1456.   }
  1457.  
  1458.   PTRACE(2, "H323RTP\tReceive " << mediaFormat << " thread ended");
  1459. }
  1460.  
  1461.  
  1462. void H323_RTPChannel::AddFilter(const PNotifier & filterFunction)
  1463. {
  1464.   filterMutex.Wait();
  1465.   filters.Append(new PNotifier(filterFunction));
  1466.   filterMutex.Signal();
  1467. }
  1468.  
  1469.  
  1470. void H323_RTPChannel::RemoveFilter(const PNotifier & filterFunction)
  1471. {
  1472.   filterMutex.Wait();
  1473.   PINDEX idx = filters.GetValuesIndex(filterFunction);
  1474.   if (idx != P_MAX_INDEX)
  1475.     filters.RemoveAt(idx);
  1476.   filterMutex.Signal();
  1477. }
  1478.  
  1479.  
  1480. PTimeInterval H323_RTPChannel::GetSilenceDuration() const
  1481. {
  1482.   if (silenceStartTick == 0)
  1483.     return silenceStartTick;
  1484.  
  1485.   return PTimer::Tick() - silenceStartTick;
  1486. }
  1487.  
  1488.  
  1489. /////////////////////////////////////////////////////////////////////////////
  1490.  
  1491. H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
  1492.                                                  const H323Capability & capability,
  1493.                                                  Directions direction,
  1494.                                                  unsigned id)
  1495.   : H323_RealTimeChannel(connection, capability, direction)
  1496. {
  1497.   sessionID = id;
  1498.   isRunning = FALSE;
  1499. }
  1500.  
  1501.  
  1502. H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
  1503.                                                  const H323Capability & capability,
  1504.                                                  Directions direction,
  1505.                                                  unsigned id,
  1506.                                                  const H323TransportAddress & data,
  1507.                                                  const H323TransportAddress & control)
  1508.   : H323_RealTimeChannel(connection, capability, direction),
  1509.     externalMediaAddress(data),
  1510.     externalMediaControlAddress(control)
  1511. {
  1512.   sessionID = id;
  1513.   isRunning = FALSE;
  1514. }
  1515.  
  1516.  
  1517. H323_ExternalRTPChannel::H323_ExternalRTPChannel(H323Connection & connection,
  1518.                                                  const H323Capability & capability,
  1519.                                                  Directions direction,
  1520.                                                  unsigned id,
  1521.                                                  const PIPSocket::Address & ip,
  1522.                                                  WORD dataPort)
  1523.   : H323_RealTimeChannel(connection, capability, direction),
  1524.     externalMediaAddress(ip, dataPort),
  1525.     externalMediaControlAddress(ip, (WORD)(dataPort+1))
  1526. {
  1527.   sessionID = id;
  1528.   isRunning = FALSE;
  1529. }
  1530.  
  1531.  
  1532. unsigned H323_ExternalRTPChannel::GetSessionID() const
  1533. {
  1534.   return sessionID;
  1535. }
  1536.  
  1537.  
  1538. BOOL H323_ExternalRTPChannel::Start()
  1539. {
  1540.   isRunning = TRUE;
  1541.   return Open();
  1542. }
  1543.  
  1544.  
  1545. BOOL H323_ExternalRTPChannel::IsRunning() const
  1546. {
  1547.   return opened && isRunning;
  1548. }
  1549.  
  1550.  
  1551. void H323_ExternalRTPChannel::Receive()
  1552. {
  1553.   // Do nothing
  1554. }
  1555.  
  1556.  
  1557. void H323_ExternalRTPChannel::Transmit()
  1558. {
  1559.   // Do nothing
  1560. }
  1561.  
  1562.  
  1563. BOOL H323_ExternalRTPChannel::OnSendingPDU(H245_H2250LogicalChannelParameters & param) const
  1564. {
  1565.   param.m_sessionID = sessionID;
  1566.  
  1567.   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaGuaranteedDelivery);
  1568.   param.m_mediaGuaranteedDelivery = FALSE;
  1569.  
  1570.   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_silenceSuppression);
  1571.   param.m_silenceSuppression = FALSE;
  1572.  
  1573.   // unicast must have mediaControlChannel
  1574.   param.IncludeOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel);
  1575.   externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
  1576.  
  1577.   if (receiver) {
  1578.     // set mediaChannel
  1579.     param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
  1580.     externalMediaAddress.SetPDU(param.m_mediaChannel);
  1581.   }
  1582.  
  1583.   return TRUE;
  1584. }
  1585.  
  1586.  
  1587. void H323_ExternalRTPChannel::OnSendOpenAck(H245_H2250LogicalChannelAckParameters & param) const
  1588. {
  1589.   // set mediaControlChannel
  1590.   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel);
  1591.   externalMediaControlAddress.SetPDU(param.m_mediaControlChannel);
  1592.  
  1593.   // set mediaChannel
  1594.   param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
  1595.   externalMediaAddress.SetPDU(param.m_mediaChannel);
  1596. }
  1597.  
  1598.  
  1599. BOOL H323_ExternalRTPChannel::OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,
  1600.                                           unsigned & errorCode)
  1601. {
  1602.   // Only support a single audio session
  1603.   if (param.m_sessionID != sessionID) {
  1604.     PTRACE(1, "LogChan\tOpen for invalid session: " << param.m_sessionID);
  1605.     errorCode = H245_OpenLogicalChannelReject_cause::e_invalidSessionID;
  1606.     return FALSE;
  1607.   }
  1608.  
  1609.   if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
  1610.     PTRACE(1, "LogChan\tNo mediaControlChannel specified");
  1611.     errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
  1612.     return FALSE;
  1613.   }
  1614.  
  1615.   remoteMediaControlAddress = param.m_mediaControlChannel;
  1616.   if (remoteMediaControlAddress.IsEmpty())
  1617.     return FALSE;
  1618.  
  1619.   if (param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
  1620.     remoteMediaAddress = param.m_mediaChannel;
  1621.     if (remoteMediaAddress.IsEmpty())
  1622.       return FALSE;
  1623.   }
  1624.  
  1625.   return TRUE;
  1626. }
  1627.  
  1628.  
  1629. BOOL H323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
  1630. {
  1631.   if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID)) {
  1632.     PTRACE(1, "LogChan\tNo session specified");
  1633.     return FALSE;
  1634.   }
  1635.  
  1636.   if (param.m_sessionID != sessionID) {
  1637.     PTRACE(1, "LogChan\tAck for invalid session: " << param.m_sessionID);
  1638.   }
  1639.  
  1640.   if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaControlChannel)) {
  1641.     PTRACE(1, "LogChan\tNo mediaControlChannel specified");
  1642.     return FALSE;
  1643.   }
  1644.  
  1645.   remoteMediaControlAddress = param.m_mediaControlChannel;
  1646.   if (remoteMediaControlAddress.IsEmpty())
  1647.     return FALSE;
  1648.  
  1649.   if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
  1650.     PTRACE(1, "LogChan\tNo mediaChannel specified");
  1651.     return FALSE;
  1652.   }
  1653.  
  1654.   remoteMediaAddress = param.m_mediaChannel;
  1655.   if (remoteMediaAddress.IsEmpty())
  1656.     return FALSE;
  1657.  
  1658.   return TRUE;
  1659. }
  1660.  
  1661.  
  1662. void H323_ExternalRTPChannel::SetExternalAddress(const H323TransportAddress & data,
  1663.                                                  const H323TransportAddress & control)
  1664. {
  1665.   externalMediaAddress = data;
  1666.   externalMediaControlAddress = control;
  1667.  
  1668.   if (data.IsEmpty() || control.IsEmpty()) {
  1669.     PIPSocket::Address ip;
  1670.     WORD port;
  1671.     if (data.GetIpAndPort(ip, port))
  1672.       externalMediaControlAddress = H323TransportAddress(ip, (WORD)(port+1));
  1673.     else if (control.GetIpAndPort(ip, port))
  1674.       externalMediaAddress = H323TransportAddress(ip, (WORD)(port-1));
  1675.   }
  1676. }
  1677.  
  1678.  
  1679. BOOL H323_ExternalRTPChannel::GetRemoteAddress(PIPSocket::Address & ip,
  1680.                                                WORD & dataPort) const
  1681. {
  1682.   if (!remoteMediaControlAddress) {
  1683.     if (remoteMediaControlAddress.GetIpAndPort(ip, dataPort)) {
  1684.       dataPort--;
  1685.       return TRUE;
  1686.     }
  1687.   }
  1688.  
  1689.   if (!remoteMediaAddress)
  1690.     return remoteMediaAddress.GetIpAndPort(ip, dataPort);
  1691.  
  1692.   return FALSE;
  1693. }
  1694.  
  1695.  
  1696. /////////////////////////////////////////////////////////////////////////////
  1697.  
  1698. H323DataChannel::H323DataChannel(H323Connection & conn,
  1699.                                  const H323Capability & cap,
  1700.                                  Directions dir,
  1701.                                  unsigned id)
  1702.   : H323UnidirectionalChannel(conn, cap, dir)
  1703. {
  1704.   sessionID = id;
  1705.   listener = NULL;
  1706.   autoDeleteListener = TRUE;
  1707.   transport = NULL;
  1708.   autoDeleteTransport = TRUE;
  1709.   separateReverseChannel = FALSE;
  1710. }
  1711.  
  1712.  
  1713. H323DataChannel::~H323DataChannel()
  1714. {
  1715.   if (autoDeleteListener)
  1716.     delete listener;
  1717.   if (autoDeleteTransport)
  1718.     delete transport;
  1719. }
  1720.  
  1721.  
  1722. void H323DataChannel::CleanUpOnTermination()
  1723. {
  1724.   if (terminating)
  1725.     return;
  1726.  
  1727.   PTRACE(3, "LogChan\tCleaning up data channel " << number);
  1728.  
  1729.   // Break any I/O blocks and wait for the thread that uses this object to
  1730.   // terminate before we allow it to be deleted.
  1731.   if (listener != NULL)
  1732.     listener->Close();
  1733.   if (transport != NULL)
  1734.     transport->Close();
  1735.  
  1736.   H323UnidirectionalChannel::CleanUpOnTermination();
  1737. }
  1738.  
  1739.  
  1740. unsigned H323DataChannel::GetSessionID() const
  1741. {
  1742.   return sessionID;
  1743. }
  1744.  
  1745.  
  1746. BOOL H323DataChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const
  1747. {
  1748.   PTRACE(3, "LogChan\tOnSendingPDU for channel: " << number);
  1749.  
  1750.   open.m_forwardLogicalChannelNumber = (unsigned)number;
  1751.  
  1752.   open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
  1753.               H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
  1754.                   ::e_h2250LogicalChannelParameters);
  1755.   H245_H2250LogicalChannelParameters & fparam = open.m_forwardLogicalChannelParameters.m_multiplexParameters;
  1756.   fparam.m_sessionID = GetSessionID();
  1757.  
  1758.   if (separateReverseChannel)
  1759.     return TRUE;
  1760.  
  1761.   open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
  1762.   open.m_reverseLogicalChannelParameters.IncludeOptionalField(
  1763.               H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters);
  1764.   open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
  1765.               H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
  1766.                   ::e_h2250LogicalChannelParameters);
  1767.   H245_H2250LogicalChannelParameters & rparam = open.m_reverseLogicalChannelParameters.m_multiplexParameters;
  1768.   rparam.m_sessionID = GetSessionID();
  1769.  
  1770.   return capability->OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType);
  1771. }
  1772.  
  1773.  
  1774. void H323DataChannel::OnSendOpenAck(const H245_OpenLogicalChannel & /*open*/,
  1775.                                     H245_OpenLogicalChannelAck & ack) const
  1776. {
  1777.   if (listener == NULL && transport == NULL) {
  1778.     PTRACE(2, "LogChan\tOnSendOpenAck without a listener or transport");
  1779.     return;
  1780.   }
  1781.  
  1782.   PTRACE(3, "LogChan\tOnSendOpenAck for channel: " << number);
  1783.  
  1784.   H245_H2250LogicalChannelAckParameters * param;
  1785.  
  1786.   if (separateReverseChannel) {
  1787.     ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters);
  1788.     ack.m_forwardMultiplexAckParameters.SetTag(
  1789.               H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters);
  1790.     param = (H245_H2250LogicalChannelAckParameters*)&ack.m_forwardMultiplexAckParameters.GetObject();
  1791.   }
  1792.   else {
  1793.     ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters);
  1794.     ack.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag(
  1795.               H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
  1796.                   ::e_h2250LogicalChannelParameters);
  1797.     param = (H245_H2250LogicalChannelAckParameters*)
  1798.                 &ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetObject();
  1799.   }
  1800.  
  1801.   unsigned session = GetSessionID();
  1802.   if (session != 0) {
  1803.     param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID);
  1804.     param->m_sessionID = GetSessionID();
  1805.   }
  1806.  
  1807.   param->IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel);
  1808.   if (listener != NULL)
  1809.     listener->SetUpTransportPDU(param->m_mediaChannel, connection.GetControlChannel());
  1810.   else
  1811.     transport->SetUpTransportPDU(param->m_mediaChannel, H323Transport::UseLocalTSAP);
  1812. }
  1813.  
  1814.  
  1815. BOOL H323DataChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
  1816.                                     unsigned & errorCode)
  1817. {
  1818.   number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
  1819.  
  1820.   PTRACE(3, "LogChan\tOnReceivedPDU for data channel: " << number);
  1821.  
  1822.   if (!CreateListener()) {
  1823.     PTRACE(1, "LogChan\tCould not create listener");
  1824.     errorCode = H245_OpenLogicalChannelReject_cause::e_unspecified;
  1825.     return FALSE;
  1826.   }
  1827.  
  1828.   if (separateReverseChannel &&
  1829.       open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
  1830.     errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters;
  1831.     PTRACE(2, "LogChan\tOnReceivedPDU has unexpected reverse parameters");
  1832.     return FALSE;
  1833.   }
  1834.  
  1835.   if (!capability->OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_dataType, receiver)) {
  1836.     PTRACE(1, "H323RTP\tData type not supported");
  1837.     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotSupported;
  1838.     return FALSE;
  1839.   }
  1840.  
  1841.   return TRUE;
  1842. }
  1843.  
  1844.  
  1845. BOOL H323DataChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack)
  1846. {
  1847.   PTRACE(3, "LogChan\tOnReceivedAckPDU");
  1848.  
  1849.   const H245_TransportAddress * address;
  1850.  
  1851.   if (separateReverseChannel) {
  1852.       PTRACE(3, "LogChan\tseparateReverseChannels");
  1853.     if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) {
  1854.       PTRACE(1, "LogChan\tNo forwardMultiplexAckParameters");
  1855.       return FALSE;
  1856.     }
  1857.  
  1858.     if (ack.m_forwardMultiplexAckParameters.GetTag() !=
  1859.               H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) {
  1860.       PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
  1861.       return FALSE;
  1862.     }
  1863.  
  1864.     const H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters;
  1865.  
  1866.     if (!param.HasOptionalField(H245_H2250LogicalChannelAckParameters::e_mediaChannel)) {
  1867.       PTRACE(1, "LogChan\tNo media channel address provided");
  1868.       return FALSE;
  1869.     }
  1870.  
  1871.     address = ¶m.m_mediaChannel;
  1872.  
  1873.     if (ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
  1874.       PTRACE(3, "LogChan\treverseLogicalChannelParameters set");
  1875.       reverseChannel = H323ChannelNumber(ack.m_reverseLogicalChannelParameters.m_reverseLogicalChannelNumber, TRUE);
  1876.     }
  1877.   }
  1878.   else {
  1879.     if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_reverseLogicalChannelParameters)) {
  1880.       PTRACE(1, "LogChan\tNo reverseLogicalChannelParameters");
  1881.       return FALSE;
  1882.     }
  1883.  
  1884.     if (ack.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() !=
  1885.               H245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
  1886.                               ::e_h2250LogicalChannelParameters) {
  1887.       PTRACE(1, "LogChan\tOnly H.225.0 multiplex supported");
  1888.       return FALSE;
  1889.     }
  1890.  
  1891.     const H245_H2250LogicalChannelParameters & param = ack.m_reverseLogicalChannelParameters.m_multiplexParameters;
  1892.  
  1893.     if (!param.HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaChannel)) {
  1894.       PTRACE(1, "LogChan\tNo media channel address provided");
  1895.       return FALSE;
  1896.     }
  1897.  
  1898.     address = ¶m.m_mediaChannel;
  1899.   }
  1900.  
  1901.   if (!CreateTransport()) {
  1902.     PTRACE(1, "LogChan\tCould not create transport");
  1903.     return FALSE;
  1904.   }
  1905.  
  1906.   if (!transport->ConnectTo(*address)) {
  1907.     PTRACE(1, "LogChan\tCould not connect to remote transport address: " << *address);
  1908.     return FALSE;
  1909.   }
  1910.  
  1911.   return TRUE;
  1912. }
  1913.  
  1914.  
  1915. BOOL H323DataChannel::CreateListener()
  1916. {
  1917.   if (listener == NULL) {
  1918.     listener = connection.GetControlChannel().GetLocalAddress().CreateCompatibleListener(connection.GetEndPoint());
  1919.     if (listener == NULL)
  1920.       return FALSE;
  1921.  
  1922.     PTRACE(3, "LogChan\tCreated listener for data channel: " << *listener);
  1923.   }
  1924.  
  1925.   return listener->Open();
  1926. }
  1927.  
  1928.  
  1929. BOOL H323DataChannel::CreateTransport()
  1930. {
  1931.   if (transport == NULL) {
  1932.     transport = connection.GetControlChannel().GetLocalAddress().CreateTransport(connection.GetEndPoint());
  1933.     if (transport == NULL)
  1934.       return FALSE;
  1935.  
  1936.     PTRACE(3, "LogChan\tCreated transport for data channel: " << *transport);
  1937.   }
  1938.  
  1939.   return transport != NULL;
  1940. }
  1941.  
  1942.  
  1943. /////////////////////////////////////////////////////////////////////////////
  1944.