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 / h323neg.cxx < prev    next >
Text File  |  2003-01-29  |  49KB  |  1,666 lines

  1. /*
  2.  * h323neg.cxx
  3.  *
  4.  * H.323 PDU definitions
  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: h323neg.cxx,v $
  30.  * Revision 1.69  2003/01/30 01:38:19  robertj
  31.  * Fixed some trace log errors
  32.  *
  33.  * Revision 1.68  2002/11/05 05:33:56  robertj
  34.  * Fixed problem where if capability is rejected by OnReceivedCapabilitySet()
  35.  *   it still thinks it has received them.
  36.  *
  37.  * Revision 1.67  2002/08/05 10:03:47  robertj
  38.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  39.  *
  40.  * Revision 1.66  2002/06/27 07:11:55  robertj
  41.  * Fixed GNU warning
  42.  *
  43.  * Revision 1.65  2002/06/26 08:51:19  robertj
  44.  * Fixed deadlock if logical channel is closed via H.245 at exactly same
  45.  *   time as being closed locally due to a channel I/O error.
  46.  *
  47.  * Revision 1.64  2002/05/03 03:08:40  robertj
  48.  * Added replacementFor field in OLC when resolving conflicting channels.
  49.  *
  50.  * Revision 1.63  2002/01/10 04:38:29  robertj
  51.  * Fixed problem with having incorrect constraint if getting array from caller on
  52.  *   setting up a requestMode.
  53.  *
  54.  * Revision 1.62  2002/01/10 04:02:08  robertj
  55.  * Fixed correct filling of modeRequest structure.
  56.  *
  57.  * Revision 1.61  2002/01/09 00:21:40  robertj
  58.  * Changes to support outgoing H.245 RequstModeChange.
  59.  *
  60.  * Revision 1.60  2002/01/08 01:26:32  robertj
  61.  * Removed PTRACE in FindChannelsBySession as it can get called a LOT.
  62.  *
  63.  * Revision 1.59  2002/01/01 23:24:04  craigs
  64.  * Removed reference to myPTRACE
  65.  *
  66.  * Revision 1.58  2002/01/01 23:20:22  craigs
  67.  * Added HandleAck and StartRequest implementations for T.38
  68.  * thanks to Vyacheslav Frolov
  69.  *
  70.  * Revision 1.57  2001/12/22 03:10:17  robertj
  71.  * Changed OnRequstModeChange to return ack, then actually do the change.
  72.  *
  73.  * Revision 1.56  2001/12/22 01:46:33  robertj
  74.  * Fixed bug in RequestMode negotiation, failure to set sequence number.
  75.  *
  76.  * Revision 1.55  2001/12/14 08:36:36  robertj
  77.  * More implementation of T.38, thanks Adam Lazur
  78.  *
  79.  * Revision 1.54  2001/11/11 23:07:52  robertj
  80.  * Some clean ups after T.38 commit, thanks Adam Lazur
  81.  *
  82.  * Revision 1.53  2001/11/09 05:39:54  craigs
  83.  * Added initial T.38 support thanks to Adam Lazur
  84.  *
  85.  * Revision 1.52  2001/09/13 04:18:57  robertj
  86.  * Added support for "reopen" function when closing logical channel.
  87.  *
  88.  * Revision 1.51  2001/08/06 03:08:56  robertj
  89.  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
  90.  *
  91.  * Revision 1.50  2001/05/30 23:34:54  robertj
  92.  * Added functions to send TCS=0 for transmitter side pause.
  93.  *
  94.  * Revision 1.49  2001/05/09 02:34:37  robertj
  95.  * Fixed problem with being able to start two MSD's at the same time.
  96.  * Fixed possible race condition in code to prevent two TCS's happening
  97.  *   at the same time.
  98.  *
  99.  * Revision 1.48  2001/04/26 02:01:53  robertj
  100.  * Added workaround for more strange Cisco behaviour, stops sending RTP
  101.  *   data if you try and do a H.245 RoundTripDelay request!!
  102.  *
  103.  * Revision 1.47  2001/03/16 07:11:39  robertj
  104.  * Added logical channel open function version without locking.
  105.  *
  106.  * Revision 1.46  2001/03/14 03:20:27  robertj
  107.  * Fixed possible nested mutex deadlock in logical channel negotiator.
  108.  *
  109.  * Revision 1.45  2001/03/06 04:44:47  robertj
  110.  * Fixed problem where could send capability set twice. This should not be
  111.  *   a problem except when talking to another broken stack, eg Cisco routers.
  112.  *
  113.  * Revision 1.44  2001/02/09 05:13:56  craigs
  114.  * Added pragma implementation to (hopefully) reduce the executable image size
  115.  * under Linux
  116.  *
  117.  * Revision 1.43  2001/01/04 07:46:22  robertj
  118.  * Added special test for broken NetMeeting in restablishing logical channels
  119.  *   when have to close one due to device conflict (asymetric codecs).
  120.  *
  121.  * Revision 1.42  2001/01/02 08:03:28  robertj
  122.  * Changed MSD determination number comparision to be clearly as per spec.
  123.  *
  124.  * Revision 1.41  2000/10/16 09:46:37  robertj
  125.  * Fixed problem with opening codec before capability fields updated from
  126.  *    OLC PDU, caused problems in G.711 tweaked psuedo-packet size.
  127.  *
  128.  * Revision 1.40  2000/09/22 01:35:50  robertj
  129.  * Added support for handling LID's that only do symmetric codecs.
  130.  *
  131.  * Revision 1.39  2000/09/12 01:01:17  robertj
  132.  * Fixed protocol issue, should send CloseLogicalChannel PDU's on accepting RequestClose.
  133.  *
  134.  * Revision 1.38  2000/08/31 10:49:38  robertj
  135.  * Fixed unix deadlock when non-fastStart but with H245 tunneling.
  136.  *
  137.  * Revision 1.37  2000/08/21 12:37:14  robertj
  138.  * Fixed race condition if close call just as slow start media channels are opening, part 2.
  139.  *
  140.  * Revision 1.36  2000/08/21 02:50:28  robertj
  141.  * Fixed race condition if close call just as slow start media channels are opening.
  142.  *
  143.  * Revision 1.35  2000/07/14 09:00:48  robertj
  144.  * Fixed race condition in closing connection and explicit close logical channel.
  145.  *
  146.  * Revision 1.34  2000/07/11 19:31:28  robertj
  147.  * Fixed possible deadlock under unix when trying to restart running TCS.
  148.  *
  149.  * Revision 1.33  2000/07/10 16:04:01  robertj
  150.  * Added TCS=0 support.
  151.  * Fixed bug where negotiations hang if not fast start and tunnelled but remot does not tunnel.
  152.  *
  153.  * Revision 1.32  2000/07/09 14:57:54  robertj
  154.  * Fixed bug where don't accept TCS if supplied sequence number is zero.
  155.  *
  156.  * Revision 1.31  2000/07/04 13:00:36  craigs
  157.  * Fixed problem with selecting large and small video sizes
  158.  *
  159.  * Revision 1.30  2000/07/04 04:15:41  robertj
  160.  * Fixed capability check of "combinations" for fast start cases.
  161.  *
  162.  * Revision 1.29  2000/07/03 00:38:40  robertj
  163.  * Fixed deadlock caused by nested mutex waits in negotiated channel closing.
  164.  *
  165.  * Revision 1.28  2000/06/27 03:46:52  robertj
  166.  * Fixed another possible race condition on logical channel closure.
  167.  *
  168.  * Revision 1.27  2000/06/03 03:16:39  robertj
  169.  * Fixed using the wrong capability table (should be connections) for some operations.
  170.  *
  171.  * Revision 1.26  2000/05/23 11:32:37  robertj
  172.  * Rewrite of capability table to combine 2 structures into one and move functionality into that class
  173.  *    allowing some normalisation of usage across several applications.
  174.  * Changed H323Connection so gets a copy of capabilities instead of using endponts, allows adjustments
  175.  *    to be done depending on the remote client application.
  176.  *
  177.  * Revision 1.25  2000/05/22 07:32:51  craigs
  178.  * Fixed problem with ohphone silence detection hanging
  179.  *
  180.  * Revision 1.24  2000/05/16 08:13:42  robertj
  181.  * Added function to find channel by session ID, supporting H323Connection::FindChannel() with mutex.
  182.  *
  183.  * Revision 1.23  2000/05/11 04:19:45  robertj
  184.  * Fixed typo
  185.  *
  186.  * Revision 1.22  2000/05/11 04:16:35  robertj
  187.  * Fixed missing timeout (and typo!) in bidirectional open logical channel.
  188.  *
  189.  * Revision 1.21  2000/05/08 05:06:27  robertj
  190.  * Fixed bug in H.245 close logical channel timeout, thanks XuPeili.
  191.  *
  192.  * Revision 1.20  2000/05/05 04:35:10  robertj
  193.  * Changed where the system timer is sampled to minimise overhead in round trip delay calculation.
  194.  *
  195.  * Revision 1.19  2000/05/02 04:32:27  robertj
  196.  * Fixed copyright notice comment.
  197.  *
  198.  * Revision 1.18  2000/04/24 23:47:01  robertj
  199.  * Fixed bug in master/slave negotiator for if have "in sync" random number generators, thanks Shawn Sincoski.
  200.  *
  201.  * Revision 1.17  2000/04/10 17:50:28  robertj
  202.  * Fixed yet another race condition needing mutex in logical channels management class.
  203.  *
  204.  * Revision 1.16  2000/04/05 03:17:31  robertj
  205.  * Added more RTP statistics gathering and H.245 round trip delay calculation.
  206.  *
  207.  * Revision 1.15  2000/03/29 02:14:46  robertj
  208.  * Changed TerminationReason to CallEndReason to use correct telephony nomenclature.
  209.  * Added CallEndReason for capability exchange failure.
  210.  *
  211.  * Revision 1.14  2000/03/25 02:19:50  robertj
  212.  * Fixed missing mutex call in some logical channels structure access.
  213.  *
  214.  * Revision 1.13  2000/02/17 12:07:43  robertj
  215.  * Used ne wPWLib random number generator after finding major problem in MSVC rand().
  216.  *
  217.  * Revision 1.12  1999/11/26 01:25:01  craigs
  218.  * Removed deadlock when remote endpoint requests unsupported channel type
  219.  *
  220.  * Revision 1.11  1999/11/19 09:07:27  robertj
  221.  * Fixed bug allocating incorrect channel number to fast start transmit channel.
  222.  *
  223.  * Revision 1.10  1999/11/06 11:00:18  robertj
  224.  * Fixed race condition in explicit channel close and connection close.
  225.  *
  226.  * Revision 1.9  1999/11/06 05:37:45  robertj
  227.  * Complete rewrite of termination of connection to avoid numerous race conditions.
  228.  *
  229.  * Revision 1.8  1999/10/30 12:34:47  robertj
  230.  * Added information callback for closed logical channel on H323EndPoint.
  231.  *
  232.  * Revision 1.7  1999/10/24 04:45:14  robertj
  233.  * Removed requirement that must be sending capability set to receive capability set.
  234.  *
  235.  * Revision 1.6  1999/09/21 14:10:41  robertj
  236.  * Fixed incorrect PTRACING test and removed uneeded include of videoio.h
  237.  *
  238.  * Revision 1.5  1999/09/15 01:26:27  robertj
  239.  * Changed capability set call backs to have more specific class as parameter.
  240.  *
  241.  * Revision 1.4  1999/09/14 14:26:17  robertj
  242.  * Added more debug tracing.
  243.  *
  244.  * Revision 1.3  1999/09/08 04:05:49  robertj
  245.  * Added support for video capabilities & codec, still needs the actual codec itself!
  246.  *
  247.  * Revision 1.2  1999/08/31 12:34:19  robertj
  248.  * Added gatekeeper support.
  249.  *
  250.  * Revision 1.1  1999/08/25 05:08:14  robertj
  251.  * File fission (critical mass reached).
  252.  *
  253.  */
  254.  
  255. #include <ptlib.h>
  256.  
  257. #ifdef __GNUC__
  258. #pragma implementation "h323neg.h"
  259. #endif
  260.  
  261. #include "h323neg.h"
  262.  
  263. #include "h323ep.h"
  264.  
  265. #include <ptclib/random.h>
  266.  
  267.  
  268. #define new PNEW
  269.  
  270.  
  271. ///////////////////////////////////////////////////////////////////////////////
  272.  
  273. H245Negotiator::H245Negotiator(H323EndPoint & end, H323Connection & conn)
  274.   : endpoint(end),
  275.     connection(conn)
  276. {
  277.   replyTimer.SetNotifier(PCREATE_NOTIFIER(HandleTimeout));
  278. }
  279.  
  280.  
  281. void H245Negotiator::HandleTimeout(PTimer &, INT)
  282. {
  283. }
  284.  
  285.  
  286. /////////////////////////////////////////////////////////////////////////////
  287.  
  288. H245NegMasterSlaveDetermination::H245NegMasterSlaveDetermination(H323EndPoint & end,
  289.                                                                  H323Connection & conn)
  290.   : H245Negotiator(end, conn)
  291. {
  292.   retryCount = 1;
  293.   state = e_Idle;
  294.   status = e_Indeterminate;
  295. }
  296.  
  297.  
  298. BOOL H245NegMasterSlaveDetermination::Start(BOOL renegotiate)
  299. {
  300.   PWaitAndSignal wait(mutex);
  301.  
  302.   if (state != e_Idle) {
  303.     PTRACE(3, "H245\tMasterSlaveDetermination already in progress");
  304.     return TRUE;
  305.   }
  306.  
  307.   if (!renegotiate && IsDetermined())
  308.     return TRUE;
  309.  
  310.   retryCount = 1;
  311.   return Restart();
  312. }
  313.  
  314.  
  315. BOOL H245NegMasterSlaveDetermination::Restart()
  316. {
  317.   PTRACE(3, "H245\tSending MasterSlaveDetermination");
  318.  
  319.   // Begin the Master/Slave determination procedure
  320.   determinationNumber = PRandom::Number()%16777216;
  321.   replyTimer = endpoint.GetMasterSlaveDeterminationTimeout();
  322.   state = e_Outgoing;
  323.  
  324.   H323ControlPDU pdu;
  325.   pdu.BuildMasterSlaveDetermination(endpoint.GetTerminalType(), determinationNumber);
  326.   return connection.WriteControlPDU(pdu);
  327. }
  328.  
  329.  
  330. void H245NegMasterSlaveDetermination::Stop()
  331. {
  332.   PWaitAndSignal wait(mutex);
  333.  
  334.   PTRACE(3, "H245\tStopping MasterSlaveDetermination: state=" << state);
  335.  
  336.   if (state == e_Idle)
  337.     return;
  338.  
  339.   replyTimer.Stop();
  340.   state = e_Idle;
  341. }
  342.  
  343.  
  344. BOOL H245NegMasterSlaveDetermination::HandleIncoming(const H245_MasterSlaveDetermination & pdu)
  345. {
  346.   PWaitAndSignal wait(mutex);
  347.  
  348.   PTRACE(3, "H245\tReceived MasterSlaveDetermination: state=" << state);
  349.  
  350.   if (state == e_Incoming) {
  351.     replyTimer.Stop();
  352.     state = e_Idle;
  353.     return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  354.                                              "Duplicate MasterSlaveDetermination");
  355.   }
  356.  
  357.   replyTimer = endpoint.GetMasterSlaveDeterminationTimeout();
  358.  
  359.   // Determine the master and slave
  360.   MasterSlaveStatus newStatus;
  361.   if (pdu.m_terminalType < (unsigned)endpoint.GetTerminalType())
  362.     newStatus = e_DeterminedMaster;
  363.   else if (pdu.m_terminalType > (unsigned)endpoint.GetTerminalType())
  364.     newStatus = e_DeterminedSlave;
  365.   else {
  366.     DWORD moduloDiff = (pdu.m_statusDeterminationNumber - determinationNumber)&0xffffff;
  367.     if (moduloDiff == 0 || moduloDiff == 0x800000)
  368.       newStatus = e_Indeterminate;
  369.     else if (moduloDiff < 0x800000)
  370.       newStatus = e_DeterminedMaster;
  371.     else
  372.       newStatus = e_DeterminedSlave;
  373.   }
  374.  
  375.   H323ControlPDU reply;
  376.  
  377.   if (newStatus != e_Indeterminate) {
  378.     PTRACE(2, "H245\tMasterSlaveDetermination: local is "
  379.                   << (newStatus == e_DeterminedMaster ? "master" : "slave"));
  380.     reply.BuildMasterSlaveDeterminationAck(newStatus == e_DeterminedMaster);
  381.     state = e_Incoming;
  382.     status = newStatus;
  383.   }
  384.   else if (state == e_Outgoing) {
  385.     retryCount++;
  386.     if (retryCount < endpoint.GetMasterSlaveDeterminationRetries())
  387.       return Restart(); // Try again
  388.  
  389.     replyTimer.Stop();
  390.     state = e_Idle;
  391.     return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  392.                                              "Retries exceeded");
  393.   }
  394.   else {
  395.     reply.BuildMasterSlaveDeterminationReject(H245_MasterSlaveDeterminationReject_cause::e_identicalNumbers);
  396.   }
  397.  
  398.   return connection.WriteControlPDU(reply);
  399. }
  400.  
  401.  
  402. BOOL H245NegMasterSlaveDetermination::HandleAck(const H245_MasterSlaveDeterminationAck & pdu)
  403. {
  404.   PWaitAndSignal wait(mutex);
  405.  
  406.   PTRACE(3, "H245\tReceived MasterSlaveDeterminationAck: state=" << state);
  407.  
  408.   if (state == e_Idle)
  409.     return TRUE;
  410.  
  411.   replyTimer = endpoint.GetMasterSlaveDeterminationTimeout();
  412.  
  413.   MasterSlaveStatus newStatus;
  414.   if (pdu.m_decision.GetTag() == H245_MasterSlaveDeterminationAck_decision::e_master)
  415.     newStatus = e_DeterminedMaster;
  416.   else
  417.     newStatus = e_DeterminedSlave;
  418.  
  419.   H323ControlPDU reply;
  420.   if (state == e_Outgoing) {
  421.     status = newStatus;
  422.     PTRACE(2, "H245\tMasterSlaveDetermination: remote is "
  423.                   << (newStatus == e_DeterminedSlave ? "master" : "slave"));
  424.     reply.BuildMasterSlaveDeterminationAck(newStatus == e_DeterminedMaster);
  425.     if (!connection.WriteControlPDU(reply))
  426.       return FALSE;
  427.   }
  428.  
  429.   replyTimer.Stop();
  430.   state = e_Idle;
  431.  
  432.   if (status != newStatus)
  433.     return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  434.                                              "Master/Slave mismatch");
  435.  
  436.   return TRUE;
  437. }
  438.  
  439.  
  440. BOOL H245NegMasterSlaveDetermination::HandleReject(const H245_MasterSlaveDeterminationReject & pdu)
  441. {
  442.   PWaitAndSignal wait(mutex);
  443.  
  444.   PTRACE(3, "H245\tReceived MasterSlaveDeterminationReject: state=" << state);
  445.  
  446.   switch (state) {
  447.     case e_Idle :
  448.       return TRUE;
  449.  
  450.     case e_Outgoing :
  451.       if (pdu.m_cause.GetTag() == H245_MasterSlaveDeterminationReject_cause::e_identicalNumbers) {
  452.         retryCount++;
  453.         if (retryCount < endpoint.GetMasterSlaveDeterminationRetries())
  454.           return Restart();
  455.       }
  456.  
  457.     default :
  458.       break;
  459.   }
  460.  
  461.   replyTimer.Stop();
  462.   state = e_Idle;
  463.  
  464.   return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  465.                                            "Retries exceeded");
  466. }
  467.  
  468.  
  469. BOOL H245NegMasterSlaveDetermination::HandleRelease(const H245_MasterSlaveDeterminationRelease & /*pdu*/)
  470. {
  471.   PWaitAndSignal wait(mutex);
  472.  
  473.   PTRACE(3, "H245\tReceived MasterSlaveDeterminationRelease: state=" << state);
  474.  
  475.   if (state == e_Idle)
  476.     return TRUE;
  477.  
  478.   replyTimer.Stop();
  479.   state = e_Idle;
  480.  
  481.   return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  482.                                            "Aborted");
  483. }
  484.  
  485.  
  486. void H245NegMasterSlaveDetermination::HandleTimeout(PTimer &, INT)
  487. {
  488.   PWaitAndSignal wait(mutex);
  489.  
  490.   PTRACE(3, "H245\tTimeout on MasterSlaveDetermination: state=" << state);
  491.  
  492.   if (state == e_Outgoing) {
  493.     H323ControlPDU reply;
  494.     reply.Build(H245_IndicationMessage::e_masterSlaveDeterminationRelease);
  495.     connection.WriteControlPDU(reply);
  496.   }
  497.  
  498.   state = e_Idle;
  499.  
  500.   connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination,
  501.                                     "Timeout");
  502. }
  503.  
  504.  
  505. #if PTRACING
  506. const char * const H245NegMasterSlaveDetermination::StateNames[] = {
  507.   "Idle", "Outgoing", "Incoming"
  508. };
  509.  
  510.  
  511. const char * const H245NegMasterSlaveDetermination::StatusNames[] = {
  512.   "Indeterminate", "DeterminedMaster", "DeterminedSlave"
  513. };
  514. #endif
  515.  
  516.  
  517. /////////////////////////////////////////////////////////////////////////////
  518.  
  519. H245NegTerminalCapabilitySet::H245NegTerminalCapabilitySet(H323EndPoint & end,
  520.                                                            H323Connection & conn)
  521.   : H245Negotiator(end, conn)
  522. {
  523.   inSequenceNumber = UINT_MAX;
  524.   outSequenceNumber = 0;
  525.   state = e_Idle;
  526.   receivedCapabilites = FALSE;
  527. }
  528.  
  529.  
  530. BOOL H245NegTerminalCapabilitySet::Start(BOOL renegotiate, BOOL empty)
  531. {
  532.   PWaitAndSignal wait(mutex);
  533.  
  534.   if (state == e_InProgress) {
  535.     PTRACE(3, "H245\tTerminalCapabilitySet already in progress: outSeq=" << outSequenceNumber);
  536.     return TRUE;
  537.   }
  538.  
  539.   if (!renegotiate && state == e_Sent) {
  540.     PTRACE(3, "H245\tTerminalCapabilitySet already sent.");
  541.     return TRUE;
  542.   }
  543.  
  544.   // Begin the capability exchange procedure
  545.   outSequenceNumber = (outSequenceNumber+1)%256;
  546.   replyTimer = endpoint.GetCapabilityExchangeTimeout();
  547.   state = e_InProgress;
  548.  
  549.   PTRACE(3, "H245\tSending TerminalCapabilitySet: outSeq=" << outSequenceNumber);
  550.  
  551.   H323ControlPDU pdu;
  552.   connection.OnSendCapabilitySet(pdu.BuildTerminalCapabilitySet(connection, outSequenceNumber, empty));
  553.   return connection.WriteControlPDU(pdu);
  554. }
  555.  
  556.  
  557. void H245NegTerminalCapabilitySet::Stop()
  558. {
  559.   PWaitAndSignal wait(mutex);
  560.  
  561.   PTRACE(3, "H245\tStopping TerminalCapabilitySet: state=" << state);
  562.  
  563.   if (state == e_Idle)
  564.     return;
  565.  
  566.   replyTimer.Stop();
  567.   state = e_Idle;
  568.   receivedCapabilites = FALSE;
  569. }
  570.  
  571.  
  572. BOOL H245NegTerminalCapabilitySet::HandleIncoming(const H245_TerminalCapabilitySet & pdu)
  573. {
  574.   mutex.Wait();
  575.  
  576.   PTRACE(3, "H245\tReceived TerminalCapabilitySet:"
  577.                      " state=" << state <<
  578.                      " pduSeq=" << pdu.m_sequenceNumber <<
  579.                      " inSeq=" << inSequenceNumber);
  580.  
  581.   if (pdu.m_sequenceNumber == inSequenceNumber) {
  582.     mutex.Signal();
  583.     PTRACE(3, "H245\tIgnoring TerminalCapabilitySet, already received sequence number");
  584.     return TRUE;  // Already had this one
  585.   }
  586.  
  587.   inSequenceNumber = pdu.m_sequenceNumber;
  588.  
  589.   mutex.Signal();
  590.  
  591.   H323Capabilities remoteCapabilities(connection, pdu);
  592.  
  593.   const H245_MultiplexCapability * muxCap = NULL;
  594.   if (pdu.HasOptionalField(H245_TerminalCapabilitySet::e_multiplexCapability))
  595.     muxCap = &pdu.m_multiplexCapability;
  596.  
  597.   H323ControlPDU reject;
  598.   if (connection.OnReceivedCapabilitySet(remoteCapabilities, muxCap,
  599.                     reject.BuildTerminalCapabilitySetReject(inSequenceNumber,
  600.                             H245_TerminalCapabilitySetReject_cause::e_unspecified))) {
  601.     receivedCapabilites = TRUE;
  602.     H323ControlPDU ack;
  603.     ack.BuildTerminalCapabilitySetAck(inSequenceNumber);
  604.     return connection.WriteControlPDU(ack);
  605.   }
  606.  
  607.   connection.WriteControlPDU(reject);
  608.   connection.ClearCall(H323Connection::EndedByCapabilityExchange);
  609.   return TRUE;
  610. }
  611.  
  612.  
  613. BOOL H245NegTerminalCapabilitySet::HandleAck(const H245_TerminalCapabilitySetAck & pdu)
  614. {
  615.   PWaitAndSignal wait(mutex);
  616.  
  617.   PTRACE(3, "H245\tReceived TerminalCapabilitySetAck:"
  618.                      " state=" << state <<
  619.                      " pduSeq=" << pdu.m_sequenceNumber <<
  620.                      " outSeq=" << (unsigned)outSequenceNumber);
  621.  
  622.   if (state != e_InProgress)
  623.     return TRUE;
  624.  
  625.   if (pdu.m_sequenceNumber != outSequenceNumber)
  626.     return TRUE;
  627.  
  628.   replyTimer.Stop();
  629.   state = e_Sent;
  630.   PTRACE(2, "H245\tTerminalCapabilitySet Sent.");
  631.   return TRUE;
  632. }
  633.  
  634.  
  635. BOOL H245NegTerminalCapabilitySet::HandleReject(const H245_TerminalCapabilitySetReject & pdu)
  636. {
  637.   PWaitAndSignal wait(mutex);
  638.  
  639.   PTRACE(3, "H245\tReceived TerminalCapabilitySetReject:"
  640.                      " state=" << state <<
  641.                      " pduSeq=" << pdu.m_sequenceNumber <<
  642.                      " outSeq=" << (unsigned)outSequenceNumber);
  643.  
  644.   if (state != e_InProgress)
  645.     return TRUE;
  646.  
  647.   if (pdu.m_sequenceNumber != outSequenceNumber)
  648.     return TRUE;
  649.  
  650.   state = e_Idle;
  651.   replyTimer.Stop();
  652.   return connection.OnControlProtocolError(H323Connection::e_CapabilityExchange,
  653.                                            "Rejected");
  654. }
  655.  
  656.  
  657. BOOL H245NegTerminalCapabilitySet::HandleRelease(const H245_TerminalCapabilitySetRelease & /*pdu*/)
  658. {
  659.   PWaitAndSignal wait(mutex);
  660.  
  661.   PTRACE(3, "H245\tReceived TerminalCapabilityRelease: state=" << state);
  662.  
  663.   receivedCapabilites = FALSE;
  664.   return connection.OnControlProtocolError(H323Connection::e_CapabilityExchange,
  665.                                            "Aborted");
  666. }
  667.  
  668.  
  669. void H245NegTerminalCapabilitySet::HandleTimeout(PTimer &, INT)
  670. {
  671.   PWaitAndSignal wait(mutex);
  672.  
  673.   PTRACE(3, "H245\tTimeout on TerminalCapabilitySet: state=" << state);
  674.  
  675.   H323ControlPDU reply;
  676.   reply.Build(H245_IndicationMessage::e_terminalCapabilitySetRelease);
  677.   connection.WriteControlPDU(reply);
  678.  
  679.   connection.OnControlProtocolError(H323Connection::e_CapabilityExchange, "Timeout");
  680. }
  681.  
  682.  
  683. #if PTRACING
  684. const char * const H245NegTerminalCapabilitySet::StateNames[] = {
  685.   "Idle", "InProgress", "Sent"
  686. };
  687. #endif
  688.  
  689.  
  690. /////////////////////////////////////////////////////////////////////////////
  691.  
  692. H245NegLogicalChannel::H245NegLogicalChannel(H323EndPoint & end,
  693.                                              H323Connection & conn,
  694.                                              const H323ChannelNumber & chanNum)
  695.   : H245Negotiator(end, conn),
  696.     channelNumber(chanNum)
  697. {
  698.   channel = NULL;
  699.   state = e_Released;
  700. }
  701.  
  702.  
  703. H245NegLogicalChannel::H245NegLogicalChannel(H323EndPoint & end,
  704.                                              H323Connection & conn,
  705.                                              H323Channel & chan)
  706.   : H245Negotiator(end, conn),
  707.     channelNumber(chan.GetNumber())
  708. {
  709.   channel = &chan;
  710.   state = e_Established;
  711. }
  712.  
  713.  
  714. H245NegLogicalChannel::~H245NegLogicalChannel()
  715. {
  716.   replyTimer.Stop();
  717.   PThread::Yield(); // Do this to avoid possible race condition with timer
  718.  
  719.   mutex.Wait();
  720.   delete channel;
  721.   mutex.Signal();
  722. }
  723.  
  724.  
  725. BOOL H245NegLogicalChannel::Open(const H323Capability & capability,
  726.                                  unsigned sessionID,
  727.                                  unsigned replacementFor)
  728. {
  729.   PWaitAndSignal wait(mutex);
  730.   return OpenWhileLocked(capability, sessionID, replacementFor);
  731. }
  732.  
  733.  
  734. BOOL H245NegLogicalChannel::OpenWhileLocked(const H323Capability & capability,
  735.                                             unsigned sessionID,
  736.                                             unsigned replacementFor)
  737. {
  738.   if (state != e_Released && state != e_AwaitingRelease) {
  739.     PTRACE(3, "H245\tOpen of channel currently in negotiations: " << channelNumber);
  740.     return FALSE;
  741.   }
  742.  
  743.   PTRACE(3, "H245\tOpening channel: " << channelNumber);
  744.  
  745.   if (channel != NULL) {
  746.     channel->CleanUpOnTermination();
  747.     delete channel;
  748.     channel = NULL;
  749.   }
  750.  
  751.   state = e_AwaitingEstablishment;
  752.  
  753.   H323ControlPDU pdu;
  754.   H245_OpenLogicalChannel & open = pdu.BuildOpenLogicalChannel(channelNumber);
  755.  
  756.   if (!capability.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_dataType)) {
  757.     PTRACE(3, "H245\tOpening channel: " << channelNumber
  758.            << ", capability.OnSendingPDU() failed");
  759.     return FALSE;
  760.   }
  761.  
  762.   channel = capability.CreateChannel(connection, H323Channel::IsTransmitter, sessionID, NULL);
  763.   if (channel == NULL) {
  764.     PTRACE(3, "H245\tOpening channel: " << channelNumber
  765.            << ", capability.CreateChannel() failed");
  766.     return FALSE;
  767.   }
  768.  
  769.   channel->SetNumber(channelNumber);
  770.  
  771.   if (!channel->OnSendingPDU(open)) {
  772.     PTRACE(3, "H245\tOpening channel: " << channelNumber
  773.            << ", channel->OnSendingPDU() failed");
  774.     return FALSE;
  775.   }
  776.  
  777.   if (replacementFor > 0) {
  778.     if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) {
  779.       open.m_reverseLogicalChannelParameters.IncludeOptionalField(H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_replacementFor);
  780.       open.m_reverseLogicalChannelParameters.m_replacementFor = replacementFor;
  781.     }
  782.     else {
  783.       open.m_forwardLogicalChannelParameters.IncludeOptionalField(H245_OpenLogicalChannel_forwardLogicalChannelParameters::e_replacementFor);
  784.       open.m_forwardLogicalChannelParameters.m_replacementFor = replacementFor;
  785.     }
  786.   }
  787.  
  788.   if (!channel->Open())
  789.     return FALSE;
  790.  
  791.   if (!channel->SetInitialBandwidth()) {
  792.     PTRACE(3, "H245\tOpening channel: " << channelNumber << ", Insufficient bandwidth");
  793.     return FALSE;
  794.   }
  795.  
  796.   replyTimer = endpoint.GetLogicalChannelTimeout();
  797.  
  798.   return connection.WriteControlPDU(pdu);
  799. }
  800.  
  801.  
  802. BOOL H245NegLogicalChannel::Close()
  803. {
  804.   PWaitAndSignal wait(mutex);
  805.   return CloseWhileLocked();
  806. }
  807.  
  808.  
  809. BOOL H245NegLogicalChannel::CloseWhileLocked()
  810. {
  811.   PTRACE(3, "H245\tClosing channel: " << channelNumber << ", state=" << state);
  812.  
  813.   if (state != e_AwaitingEstablishment && state != e_Established)
  814.     return TRUE;
  815.  
  816.   replyTimer = endpoint.GetLogicalChannelTimeout();
  817.  
  818.   H323ControlPDU reply;
  819.  
  820.   if (channelNumber.IsFromRemote()) {
  821.     reply.BuildRequestChannelClose(channelNumber, H245_RequestChannelClose_reason::e_normal);
  822.     state = e_AwaitingResponse;
  823.   }
  824.   else {
  825.     reply.BuildCloseLogicalChannel(channelNumber);
  826.     state = e_AwaitingRelease;
  827.   }
  828.  
  829.   return connection.WriteControlPDU(reply);
  830. }
  831.  
  832.  
  833. BOOL H245NegLogicalChannel::HandleOpen(const H245_OpenLogicalChannel & pdu)
  834. {
  835.   PTRACE(3, "H245\tReceived open channel: " << channelNumber << ", state=" << state);
  836.  
  837.   if (channel != NULL) {
  838.     channel->CleanUpOnTermination();
  839.     delete channel;
  840.     channel = NULL;
  841.   }
  842.  
  843.   state = e_AwaitingEstablishment;
  844.  
  845.   H323ControlPDU reply;
  846.   H245_OpenLogicalChannelAck & ack = reply.BuildOpenLogicalChannelAck(channelNumber);
  847.  
  848.   BOOL ok = FALSE;
  849.  
  850.   unsigned cause = H245_OpenLogicalChannelReject_cause::e_unspecified;
  851.   if (connection.OnOpenLogicalChannel(pdu, ack, cause))
  852.     channel = connection.CreateLogicalChannel(pdu, FALSE, cause);
  853.  
  854.   if (channel != NULL) {
  855.     channel->SetNumber(channelNumber);
  856.     channel->OnSendOpenAck(pdu, ack);
  857.     if (channel->GetDirection() == H323Channel::IsBidirectional) {
  858.       state = e_AwaitingConfirmation;
  859.       replyTimer = endpoint.GetLogicalChannelTimeout(); // T103
  860.       ok = TRUE;
  861.     }
  862.     else {
  863.       ok = channel->Start();
  864.       if (!ok) {
  865.         // The correct protocol thing to do is reject the channel if we are
  866.         // the master. However NetMeeting will not then reopen a channel, so
  867.         // we act like we are a slave and close our end instead.
  868.         if (connection.IsH245Master() &&
  869.             connection.GetRemoteApplication().Find("NetMeeting") == P_MAX_INDEX)
  870.           cause = H245_OpenLogicalChannelReject_cause::e_masterSlaveConflict;
  871.         else {
  872.           connection.OnConflictingLogicalChannel(*channel);
  873.           ok = channel->Start();
  874.         }
  875.       }
  876.  
  877.       if (ok)
  878.         state = e_Established;
  879.     }
  880.   }
  881.  
  882.   if (ok)
  883.     mutex.Signal();
  884.   else {
  885.     reply.BuildOpenLogicalChannelReject(channelNumber, cause);
  886.     Release();
  887.   }
  888.  
  889.   return connection.WriteControlPDU(reply);
  890. }
  891.  
  892.  
  893. BOOL H245NegLogicalChannel::HandleOpenAck(const H245_OpenLogicalChannelAck & pdu)
  894. {
  895.   PWaitAndSignal wait(mutex);
  896.  
  897.   PTRACE(3, "H245\tReceived open channel ack: " << channelNumber << ", state=" << state);
  898.  
  899.   switch (state) {
  900.     case e_Released :
  901.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  902.                                                "Ack unknown channel");
  903.     case e_AwaitingEstablishment :
  904.       state = e_Established;
  905.       replyTimer.Stop();
  906.  
  907.       if (!channel->OnReceivedAckPDU(pdu))
  908.         return CloseWhileLocked();
  909.  
  910.       if (channel->GetDirection() == H323Channel::IsBidirectional) {
  911.         H323ControlPDU reply;
  912.         reply.BuildOpenLogicalChannelConfirm(channelNumber);
  913.         if (!connection.WriteControlPDU(reply))
  914.           return FALSE;
  915.       }
  916.  
  917.       // Channel was already opened when OLC sent, if have error here it is
  918.       // somthing other than an asymmetric codec conflict, so close it down.
  919.       if (!channel->Start())
  920.         return CloseWhileLocked();
  921.  
  922.     default :
  923.       break;
  924.   }
  925.  
  926.   return TRUE;
  927. }
  928.  
  929.  
  930. BOOL H245NegLogicalChannel::HandleOpenConfirm(const H245_OpenLogicalChannelConfirm & /*pdu*/)
  931. {
  932.   PWaitAndSignal wait(mutex);
  933.  
  934.   PTRACE(3, "H245\tReceived open channel confirm: " << channelNumber << ", state=" << state);
  935.  
  936.   switch (state) {
  937.     case e_Released :
  938.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  939.                                                "Confirm unknown channel");
  940.     case e_AwaitingEstablishment :
  941.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  942.                                                "Confirm established channel");
  943.     case e_AwaitingConfirmation :
  944.       replyTimer.Stop();
  945.       state = e_Established;
  946.       // Channel was already opened when OLC sent, if have error here it is
  947.       // somthing other than an asymmetric codec conflict, so close it down.
  948.       if (!channel->Start())
  949.         return CloseWhileLocked();
  950.  
  951.     default :
  952.       break;
  953.   }
  954.  
  955.   return TRUE;
  956. }
  957.  
  958.  
  959. BOOL H245NegLogicalChannel::HandleReject(const H245_OpenLogicalChannelReject & pdu)
  960. {
  961.   mutex.Wait();
  962.  
  963.   PTRACE(3, "H245\tReceived open channel reject: " << channelNumber << ", state=" << state);
  964.  
  965.   switch (state) {
  966.     case e_Released :
  967.       mutex.Signal();
  968.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  969.                                                "Reject unknown channel");
  970.     case e_Established :
  971.       Release();
  972.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  973.                                                "Reject established channel");
  974.     case e_AwaitingEstablishment :
  975.       // Master rejected our attempt to open, so try something else.
  976.       if (pdu.m_cause.GetTag() == H245_OpenLogicalChannelReject_cause::e_masterSlaveConflict)
  977.         connection.OnConflictingLogicalChannel(*channel);
  978.       // Do next case
  979.  
  980.     case e_AwaitingRelease :
  981.       Release();
  982.       break;
  983.  
  984.     default :
  985.       mutex.Signal();
  986.       break;
  987.   }
  988.  
  989.   return TRUE;
  990. }
  991.  
  992.  
  993. BOOL H245NegLogicalChannel::HandleClose(const H245_CloseLogicalChannel & /*pdu*/)
  994. {
  995.   mutex.Wait();
  996.  
  997.   PTRACE(3, "H245\tReceived close channel: " << channelNumber << ", state=" << state);
  998.  
  999.   //if (pdu.m_source.GetTag() == H245_CloseLogicalChannel_source::e_user)
  1000.  
  1001.   H323ControlPDU reply;
  1002.   reply.BuildCloseLogicalChannelAck(channelNumber);
  1003.  
  1004.   Release();
  1005.  
  1006.   return connection.WriteControlPDU(reply);
  1007. }
  1008.  
  1009.  
  1010. BOOL H245NegLogicalChannel::HandleCloseAck(const H245_CloseLogicalChannelAck & /*pdu*/)
  1011. {
  1012.   mutex.Wait();
  1013.  
  1014.   PTRACE(3, "H245\tReceived close channel ack: " << channelNumber << ", state=" << state);
  1015.  
  1016.   switch (state) {
  1017.     case e_Established :
  1018.       Release();
  1019.       return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1020.                                                "Close ack open channel");
  1021.     case e_AwaitingRelease :
  1022.       Release();
  1023.       break;
  1024.  
  1025.     default :
  1026.       mutex.Signal();
  1027.       break;
  1028.   }
  1029.  
  1030.   return TRUE;
  1031. }
  1032.  
  1033.  
  1034. BOOL H245NegLogicalChannel::HandleRequestClose(const H245_RequestChannelClose & pdu)
  1035. {
  1036.   PWaitAndSignal wait(mutex);
  1037.  
  1038.   PTRACE(3, "H245\tReceived request close channel: " << channelNumber << ", state=" << state);
  1039.  
  1040.   if (state != e_Established)
  1041.     return TRUE;    // Already closed
  1042.  
  1043.   H323ControlPDU reply;
  1044.   if (connection.OnClosingLogicalChannel(*channel)) {
  1045.     reply.BuildRequestChannelCloseAck(channelNumber);
  1046.     if (!connection.WriteControlPDU(reply))
  1047.       return FALSE;
  1048.  
  1049.     // Do normal Close procedure
  1050.     replyTimer = endpoint.GetLogicalChannelTimeout();
  1051.     reply.BuildCloseLogicalChannel(channelNumber);
  1052.     state = e_AwaitingRelease;
  1053.  
  1054.     if (pdu.m_reason.GetTag() == H245_RequestChannelClose_reason::e_reopen) {
  1055.       PTRACE(2, "H245\tReopening channel: " << channelNumber);
  1056.       connection.OpenLogicalChannel(channel->GetCapability(),
  1057.                                     channel->GetSessionID(),
  1058.                                     channel->GetDirection());
  1059.     }
  1060.   }
  1061.   else
  1062.     reply.BuildRequestChannelCloseReject(channelNumber);
  1063.  
  1064.   return connection.WriteControlPDU(reply);
  1065. }
  1066.  
  1067.  
  1068. BOOL H245NegLogicalChannel::HandleRequestCloseAck(const H245_RequestChannelCloseAck & /*pdu*/)
  1069. {
  1070.   mutex.Wait();
  1071.  
  1072.   PTRACE(3, "H245\tReceived request close ack channel: " << channelNumber << ", state=" << state);
  1073.  
  1074.   if (state == e_AwaitingResponse)
  1075.     Release();  // Other end says close OK, so do so.
  1076.   else
  1077.     mutex.Signal();
  1078.  
  1079.   return TRUE;
  1080. }
  1081.  
  1082.  
  1083. BOOL H245NegLogicalChannel::HandleRequestCloseReject(const H245_RequestChannelCloseReject & /*pdu*/)
  1084. {
  1085.   PWaitAndSignal wait(mutex);
  1086.  
  1087.   PTRACE(3, "H245\tReceived request close reject channel: " << channelNumber << ", state=" << state);
  1088.  
  1089.   // Other end refused close, so go back to still having channel open
  1090.   if (state == e_AwaitingResponse)
  1091.     state = e_Established;
  1092.  
  1093.   return TRUE;
  1094. }
  1095.  
  1096.  
  1097. BOOL H245NegLogicalChannel::HandleRequestCloseRelease(const H245_RequestChannelCloseRelease & /*pdu*/)
  1098. {
  1099.   PWaitAndSignal wait(mutex);
  1100.  
  1101.   PTRACE(3, "H245\tReceived request close release channel: " << channelNumber << ", state=" << state);
  1102.  
  1103.   // Other end refused close, so go back to still having channel open
  1104.   state = e_Established;
  1105.  
  1106.   return TRUE;
  1107. }
  1108.  
  1109.  
  1110. void H245NegLogicalChannel::HandleTimeout(PTimer &, INT)
  1111. {
  1112.   mutex.Wait();
  1113.  
  1114.   PTRACE(3, "H245\tTimeout on open channel: " << channelNumber << ", state=" << state);
  1115.  
  1116.   H323ControlPDU reply;
  1117.   switch (state) {
  1118.     case e_AwaitingEstablishment :
  1119.       reply.BuildCloseLogicalChannel(channelNumber);
  1120.       connection.WriteControlPDU(reply);
  1121.       break;
  1122.  
  1123.     case e_AwaitingResponse :
  1124.       reply.BuildRequestChannelCloseRelease(channelNumber);
  1125.       connection.WriteControlPDU(reply);
  1126.       break;
  1127.  
  1128.     case e_Released :
  1129.       mutex.Signal();
  1130.       return;
  1131.  
  1132.     default :
  1133.       break;
  1134.   }
  1135.  
  1136.   Release();
  1137.   connection.OnControlProtocolError(H323Connection::e_LogicalChannel, "Timeout");
  1138. }
  1139.  
  1140.  
  1141. void H245NegLogicalChannel::Release()
  1142. {
  1143.   state = e_Released;
  1144.   H323Channel * chan = channel;
  1145.   channel = NULL;
  1146.   mutex.Signal();
  1147.  
  1148.   replyTimer.Stop();
  1149.  
  1150.   if (chan != NULL) {
  1151.     chan->CleanUpOnTermination();
  1152.     delete chan;
  1153.   }
  1154. }
  1155.  
  1156.  
  1157. H323Channel * H245NegLogicalChannel::GetChannel()
  1158. {
  1159.   return channel;
  1160. }
  1161.  
  1162.  
  1163. #if PTRACING
  1164. const char * const H245NegLogicalChannel::StateNames[] = {
  1165.   "Released",
  1166.   "AwaitingEstablishment",
  1167.   "Established",
  1168.   "AwaitingRelease",
  1169.   "AwatingConfirmation",
  1170.   "AwaitingResponse"
  1171. };
  1172. #endif
  1173.  
  1174.  
  1175. /////////////////////////////////////////////////////////////////////////////
  1176.  
  1177. H245NegLogicalChannels::H245NegLogicalChannels(H323EndPoint & end,
  1178.                                                H323Connection & conn)
  1179.   : H245Negotiator(end, conn),
  1180.     lastChannelNumber(100, FALSE)
  1181. {
  1182. }
  1183.  
  1184.  
  1185. void H245NegLogicalChannels::Add(H323Channel & channel)
  1186. {
  1187.   mutex.Wait();
  1188.   channels.SetAt(channel.GetNumber(), new H245NegLogicalChannel(endpoint, connection, channel));
  1189.   mutex.Signal();
  1190. }
  1191.  
  1192.  
  1193. BOOL H245NegLogicalChannels::Open(const H323Capability & capability,
  1194.                                   unsigned sessionID,
  1195.                                   unsigned replacementFor)
  1196. {
  1197.   mutex.Wait();
  1198.  
  1199.   lastChannelNumber++;
  1200.  
  1201.   H245NegLogicalChannel * negChan = new H245NegLogicalChannel(endpoint, connection, lastChannelNumber);
  1202.   channels.SetAt(lastChannelNumber, negChan);
  1203.  
  1204.   mutex.Signal();
  1205.  
  1206.   return negChan->Open(capability, sessionID, replacementFor);
  1207. }
  1208.  
  1209.  
  1210. BOOL H245NegLogicalChannels::Close(unsigned channelNumber, BOOL fromRemote)
  1211. {
  1212.   H245NegLogicalChannel * chan = FindNegLogicalChannel(channelNumber, fromRemote);
  1213.   if (chan != NULL)
  1214.     return chan->Close();
  1215.  
  1216.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1217.                                            "Close unknown");
  1218. }
  1219.  
  1220.  
  1221. BOOL H245NegLogicalChannels::HandleOpen(const H245_OpenLogicalChannel & pdu)
  1222. {
  1223.   H323ChannelNumber chanNum(pdu.m_forwardLogicalChannelNumber, TRUE);
  1224.   H245NegLogicalChannel * chan;
  1225.  
  1226.   mutex.Wait();
  1227.  
  1228.   if (channels.Contains(chanNum))
  1229.     chan = &channels[chanNum];
  1230.   else {
  1231.     chan = new H245NegLogicalChannel(endpoint, connection, chanNum);
  1232.     channels.SetAt(chanNum, chan);
  1233.   }
  1234.  
  1235.   chan->mutex.Wait();
  1236.  
  1237.   mutex.Signal();
  1238.  
  1239.   return chan->HandleOpen(pdu);
  1240. }
  1241.  
  1242.  
  1243. BOOL H245NegLogicalChannels::HandleOpenAck(const H245_OpenLogicalChannelAck & pdu)
  1244. {
  1245.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, FALSE);
  1246.   if (chan != NULL)
  1247.     return chan->HandleOpenAck(pdu);
  1248.  
  1249.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1250.                                            "Ack unknown");
  1251. }
  1252.  
  1253.  
  1254. BOOL H245NegLogicalChannels::HandleOpenConfirm(const H245_OpenLogicalChannelConfirm & pdu)
  1255. {
  1256.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, TRUE);
  1257.   if (chan != NULL)
  1258.     return chan->HandleOpenConfirm(pdu);
  1259.  
  1260.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1261.                                            "Confirm unknown");
  1262. }
  1263.  
  1264.  
  1265. BOOL H245NegLogicalChannels::HandleReject(const H245_OpenLogicalChannelReject & pdu)
  1266. {
  1267.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, FALSE);
  1268.   if (chan != NULL)
  1269.     return chan->HandleReject(pdu);
  1270.  
  1271.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1272.                                            "Reject unknown");
  1273. }
  1274.  
  1275.  
  1276. BOOL H245NegLogicalChannels::HandleClose(const H245_CloseLogicalChannel & pdu)
  1277. {
  1278.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, TRUE);
  1279.   if (chan != NULL)
  1280.     return chan->HandleClose(pdu);
  1281.  
  1282.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1283.                                            "Close unknown");
  1284. }
  1285.  
  1286.  
  1287. BOOL H245NegLogicalChannels::HandleCloseAck(const H245_CloseLogicalChannelAck & pdu)
  1288. {
  1289.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, FALSE);
  1290.   if (chan != NULL)
  1291.     return chan->HandleCloseAck(pdu);
  1292.  
  1293.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1294.                                            "Close Ack unknown");
  1295. }
  1296.  
  1297.  
  1298. BOOL H245NegLogicalChannels::HandleRequestClose(const H245_RequestChannelClose & pdu)
  1299. {
  1300.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, FALSE);
  1301.   if (chan != NULL)
  1302.     return chan->HandleRequestClose(pdu);
  1303.  
  1304.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1305.                                            "Request Close unknown");
  1306. }
  1307.  
  1308.  
  1309. BOOL H245NegLogicalChannels::HandleRequestCloseAck(const H245_RequestChannelCloseAck & pdu)
  1310. {
  1311.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, TRUE);
  1312.   if (chan != NULL)
  1313.     return chan->HandleRequestCloseAck(pdu);
  1314.  
  1315.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1316.                                            "Request Close Ack unknown");
  1317. }
  1318.  
  1319.  
  1320. BOOL H245NegLogicalChannels::HandleRequestCloseReject(const H245_RequestChannelCloseReject & pdu)
  1321. {
  1322.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, TRUE);
  1323.   if (chan != NULL)
  1324.     return chan->HandleRequestCloseReject(pdu);
  1325.  
  1326.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1327.                                            "Request Close Reject unknown");
  1328. }
  1329.  
  1330.  
  1331. BOOL H245NegLogicalChannels::HandleRequestCloseRelease(const H245_RequestChannelCloseRelease & pdu)
  1332. {
  1333.   H245NegLogicalChannel * chan = FindNegLogicalChannel(pdu.m_forwardLogicalChannelNumber, FALSE);
  1334.   if (chan != NULL)
  1335.     return chan->HandleRequestCloseRelease(pdu);
  1336.  
  1337.   return connection.OnControlProtocolError(H323Connection::e_LogicalChannel,
  1338.                                            "Request Close Release unknown");
  1339. }
  1340.  
  1341.  
  1342. H323ChannelNumber H245NegLogicalChannels::GetNextChannelNumber()
  1343. {
  1344.   PWaitAndSignal wait(mutex);
  1345.   lastChannelNumber++;
  1346.   return lastChannelNumber;
  1347. }
  1348.  
  1349.  
  1350. H323Channel * H245NegLogicalChannels::GetChannelAt(PINDEX i)
  1351. {
  1352.   mutex.Wait();
  1353.   H323Channel * chan =  channels.GetDataAt(i).GetChannel();
  1354.   mutex.Signal();
  1355.   return chan;
  1356. }
  1357.  
  1358.  
  1359. H323Channel * H245NegLogicalChannels::FindChannel(unsigned channelNumber,
  1360.                                                   BOOL fromRemote)
  1361. {
  1362.   PWaitAndSignal wait(mutex);
  1363.  
  1364.   H323ChannelNumber chanNum(channelNumber, fromRemote);
  1365.  
  1366.   if (channels.Contains(chanNum))
  1367.     return channels[chanNum].GetChannel();
  1368.  
  1369.   return NULL;
  1370. }
  1371.  
  1372.  
  1373. H245NegLogicalChannel & H245NegLogicalChannels::GetNegLogicalChannelAt(PINDEX i)
  1374. {
  1375.   PWaitAndSignal wait(mutex);
  1376.   return channels.GetDataAt(i);
  1377. }
  1378.  
  1379.  
  1380. H245NegLogicalChannel * H245NegLogicalChannels::FindNegLogicalChannel(unsigned channelNumber,
  1381.                                                                       BOOL fromRemote)
  1382. {
  1383.   H323ChannelNumber chanNum(channelNumber, fromRemote);
  1384.  
  1385.   mutex.Wait();
  1386.   H245NegLogicalChannel * channel = channels.GetAt(chanNum);
  1387.   mutex.Signal();
  1388.  
  1389.   return channel;
  1390. }
  1391.  
  1392.  
  1393. H323Channel * H245NegLogicalChannels::FindChannelBySession(unsigned rtpSessionId,
  1394.                                                            BOOL fromRemote)
  1395. {
  1396.   PWaitAndSignal wait(mutex);
  1397.  
  1398.   PINDEX i;
  1399.   H323Channel::Directions desiredDirection = fromRemote ? H323Channel::IsReceiver : H323Channel::IsTransmitter;
  1400.   for (i = 0; i < GetSize(); i++) {
  1401.     H323Channel * channel = channels.GetDataAt(i).GetChannel();
  1402.     if (channel != NULL && channel->GetSessionID() == rtpSessionId &&
  1403.                            channel->GetDirection() == desiredDirection)
  1404.       return channel;
  1405.   }
  1406.  
  1407.   return NULL;
  1408. }
  1409.  
  1410.  
  1411. void H245NegLogicalChannels::RemoveAll()
  1412. {
  1413.   PWaitAndSignal wait(mutex);
  1414.  
  1415.   for (PINDEX i = 0; i < channels.GetSize(); i++) {
  1416.     H245NegLogicalChannel & neg = channels.GetDataAt(i);
  1417.     neg.mutex.Wait();
  1418.     H323Channel * channel = neg.GetChannel();
  1419.     if (channel != NULL)
  1420.       channel->CleanUpOnTermination();
  1421.     neg.mutex.Signal();
  1422.   }
  1423.  
  1424.   channels.RemoveAll();
  1425. }
  1426.  
  1427.  
  1428. /////////////////////////////////////////////////////////////////////////////
  1429.  
  1430. H245NegRequestMode::H245NegRequestMode(H323EndPoint & end, H323Connection & conn)
  1431.   : H245Negotiator(end, conn)
  1432. {
  1433.   awaitingResponse = FALSE;
  1434.   inSequenceNumber = UINT_MAX;
  1435.   outSequenceNumber = 0;
  1436. }
  1437.  
  1438.  
  1439. BOOL H245NegRequestMode::StartRequest(const PString & newModes)
  1440. {
  1441.   PStringArray modes = newModes.Lines();
  1442.   if (modes.IsEmpty())
  1443.     return FALSE;
  1444.  
  1445.   H245_ArrayOf_ModeDescription descriptions;
  1446.   PINDEX modeCount = 0;
  1447.  
  1448.   const H323Capabilities & localCapabilities = connection.GetLocalCapabilities();
  1449.  
  1450.   for (PINDEX i = 0; i < modes.GetSize(); i++) {
  1451.     H245_ModeDescription description;
  1452.     PINDEX count = 0;
  1453.  
  1454.     PStringArray caps = modes[i].Tokenise('\t');
  1455.     for (PINDEX j = 0; j < caps.GetSize(); j++) {
  1456.       H323Capability * capability = localCapabilities.FindCapability(caps[j]);
  1457.       if (capability != NULL) {
  1458.         description.SetSize(count+1);
  1459.         capability->OnSendingPDU(description[count]);
  1460.         count++;
  1461.       }
  1462.     }
  1463.  
  1464.     if (count > 0) {
  1465.       descriptions.SetSize(modeCount+1);
  1466.       descriptions[modeCount] = description;
  1467.       modeCount++;
  1468.     }
  1469.   }
  1470.  
  1471.   if (modeCount == 0)
  1472.     return FALSE;
  1473.  
  1474.   return StartRequest(descriptions);
  1475. }
  1476.  
  1477.  
  1478. BOOL H245NegRequestMode::StartRequest(const H245_ArrayOf_ModeDescription & newModes)
  1479. {
  1480.   PTRACE(1, "H245\tStarted request mode: outSeq=" << outSequenceNumber
  1481.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1482.  
  1483.   if (awaitingResponse)
  1484.     return FALSE;
  1485.  
  1486.   // Initiate a mode request
  1487.   outSequenceNumber = (outSequenceNumber+1)%256;
  1488.   replyTimer = endpoint.GetRequestModeTimeout();
  1489.   awaitingResponse = TRUE;
  1490.  
  1491.   H323ControlPDU pdu;
  1492.   H245_RequestMode & requestMode = pdu.BuildRequestMode(outSequenceNumber);
  1493.   requestMode.m_requestedModes = newModes;
  1494.   requestMode.m_requestedModes.SetConstraints(PASN_Object::FixedConstraint, 1, 256);
  1495.  
  1496.   return connection.WriteControlPDU(pdu);
  1497. }
  1498.  
  1499.  
  1500. BOOL H245NegRequestMode::HandleRequest(const H245_RequestMode & pdu)
  1501. {
  1502.   inSequenceNumber = pdu.m_sequenceNumber;
  1503.  
  1504.   PTRACE(3, "H245\tReceived request mode: inSeq=" << inSequenceNumber);
  1505.  
  1506.   H323ControlPDU reply_ack;
  1507.   H245_RequestModeAck & ack = reply_ack.BuildRequestModeAck(inSequenceNumber,
  1508.                   H245_RequestModeAck_response::e_willTransmitMostPreferredMode);
  1509.  
  1510.   H323ControlPDU reply_reject;
  1511.   H245_RequestModeReject & reject = reply_reject.BuildRequestModeReject(inSequenceNumber,
  1512.                                         H245_RequestModeReject_cause::e_modeUnavailable);
  1513.  
  1514.   PINDEX selectedMode = 0;
  1515.   if (!connection.OnRequestModeChange(pdu, ack, reject, selectedMode))
  1516.     return connection.WriteControlPDU(reply_reject);
  1517.  
  1518.   if (selectedMode != 0)
  1519.     ack.m_response.SetTag(H245_RequestModeAck_response::e_willTransmitLessPreferredMode);
  1520.  
  1521.   if (!connection.WriteControlPDU(reply_ack))
  1522.     return FALSE;
  1523.  
  1524.   connection.OnModeChanged(pdu.m_requestedModes[selectedMode]);
  1525.   return TRUE;
  1526. }
  1527.  
  1528.  
  1529. BOOL H245NegRequestMode::HandleAck(const H245_RequestModeAck & pdu)
  1530. {
  1531.   PTRACE(3, "H245\tReceived ack on request mode: outSeq=" << outSequenceNumber
  1532.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1533.  
  1534.   if (awaitingResponse && pdu.m_sequenceNumber == outSequenceNumber) {
  1535.     awaitingResponse = FALSE;
  1536.     replyTimer.Stop();
  1537.     connection.OnAcceptModeChange(pdu);
  1538.   }
  1539.  
  1540.   return TRUE;
  1541. }
  1542.  
  1543. BOOL H245NegRequestMode::HandleReject(const H245_RequestModeReject & pdu)
  1544. {
  1545.   PTRACE(3, "H245\tReceived reject on request mode: outSeq=" << outSequenceNumber
  1546.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1547.  
  1548.   if (awaitingResponse && pdu.m_sequenceNumber == outSequenceNumber) {
  1549.     awaitingResponse = FALSE;
  1550.     replyTimer.Stop();
  1551.     connection.OnRefusedModeChange(&pdu);
  1552.   }
  1553.  
  1554.   return TRUE;
  1555. }
  1556.  
  1557.  
  1558. BOOL H245NegRequestMode::HandleRelease(const H245_RequestModeRelease & /*pdu*/)
  1559. {
  1560.   PTRACE(3, "H245\tReceived release on request mode: inSeq=" << inSequenceNumber);
  1561.   return TRUE;
  1562. }
  1563.  
  1564.  
  1565. void H245NegRequestMode::HandleTimeout(PTimer &, INT)
  1566. {
  1567.   PTRACE(3, "H245\tTimeout on request mode: outSeq=" << outSequenceNumber
  1568.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1569.  
  1570.   if (awaitingResponse) {
  1571.     awaitingResponse = FALSE;
  1572.     H323ControlPDU pdu;
  1573.     pdu.Build(H245_IndicationMessage::e_requestModeRelease);
  1574.     connection.WriteControlPDU(pdu);
  1575.     connection.OnRefusedModeChange(NULL);
  1576.   }
  1577.  
  1578.   connection.OnControlProtocolError(H323Connection::e_ModeRequest, "Timeout");
  1579. }
  1580.  
  1581.  
  1582. /////////////////////////////////////////////////////////////////////////////
  1583.  
  1584. H245NegRoundTripDelay::H245NegRoundTripDelay(H323EndPoint & end, H323Connection & conn)
  1585.   : H245Negotiator(end, conn)
  1586. {
  1587.   awaitingResponse = FALSE;
  1588.   sequenceNumber = 0;
  1589.  
  1590.   // Temporary (ie quick) fix for strange Cisco behaviour. If keep trying to
  1591.   // do this it stops sending RTP audio data!!
  1592.   retryCount = 1;
  1593. }
  1594.  
  1595.  
  1596. BOOL H245NegRoundTripDelay::StartRequest()
  1597. {
  1598.   PWaitAndSignal wait(mutex);
  1599.  
  1600.   replyTimer = endpoint.GetRoundTripDelayTimeout();
  1601.   sequenceNumber = (sequenceNumber + 1)%256;
  1602.   awaitingResponse = TRUE;
  1603.  
  1604.   PTRACE(3, "H245\tStarted round trip delay: seq=" << sequenceNumber
  1605.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1606.  
  1607.   H323ControlPDU pdu;
  1608.   pdu.BuildRoundTripDelayRequest(sequenceNumber);
  1609.   if (!connection.WriteControlPDU(pdu))
  1610.     return FALSE;
  1611.  
  1612.   tripStartTime = PTimer::Tick();
  1613.   return TRUE;
  1614. }
  1615.  
  1616.  
  1617. BOOL H245NegRoundTripDelay::HandleRequest(const H245_RoundTripDelayRequest & pdu)
  1618. {
  1619.   PWaitAndSignal wait(mutex);
  1620.  
  1621.   PTRACE(3, "H245\tStarted round trip delay: seq=" << sequenceNumber
  1622.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1623.  
  1624.   H323ControlPDU reply;
  1625.   reply.BuildRoundTripDelayResponse(pdu.m_sequenceNumber);
  1626.   return connection.WriteControlPDU(reply);
  1627. }
  1628.  
  1629.  
  1630. BOOL H245NegRoundTripDelay::HandleResponse(const H245_RoundTripDelayResponse & pdu)
  1631. {
  1632.   PWaitAndSignal wait(mutex);
  1633.  
  1634.   PTimeInterval tripEndTime = PTimer::Tick();
  1635.  
  1636.   PTRACE(3, "H245\tHandling round trip delay: seq=" << sequenceNumber
  1637.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1638.  
  1639.   if (awaitingResponse && pdu.m_sequenceNumber == sequenceNumber) {
  1640.     replyTimer.Stop();
  1641.     awaitingResponse = FALSE;
  1642.     roundTripTime = tripEndTime - tripStartTime;
  1643.     retryCount = 3;
  1644.   }
  1645.  
  1646.   return TRUE;
  1647. }
  1648.  
  1649.  
  1650. void H245NegRoundTripDelay::HandleTimeout(PTimer &, INT)
  1651. {
  1652.   PWaitAndSignal wait(mutex);
  1653.  
  1654.   PTRACE(3, "H245\tTimeout on round trip delay: seq=" << sequenceNumber
  1655.          << (awaitingResponse ? " awaitingResponse" : " idle"));
  1656.  
  1657.   if (awaitingResponse && retryCount > 0)
  1658.     retryCount--;
  1659.   awaitingResponse = FALSE;
  1660.  
  1661.   connection.OnControlProtocolError(H323Connection::e_RoundTripDelay, "Timeout");
  1662. }
  1663.  
  1664.  
  1665. /////////////////////////////////////////////////////////////////////////////
  1666.