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 / h323t120.cxx < prev    next >
C/C++ Source or Header  |  2002-11-10  |  11KB  |  346 lines

  1. /*
  2.  * h323t120.cxx
  3.  *
  4.  * H.323 T.120 logical channel establishment
  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.  * Contributor(s): ______________________________________.
  25.  *
  26.  * $Log: h323t120.cxx,v $
  27.  * Revision 1.12  2002/11/10 08:10:43  robertj
  28.  * Moved constants for "well known" ports to better place (OPAL change).
  29.  *
  30.  * Revision 1.11  2002/08/05 10:03:47  robertj
  31.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  32.  *
  33.  * Revision 1.10  2002/07/02 10:02:32  robertj
  34.  * Added H323TransportAddress::GetIpAddress() so don't have to provide port
  35.  *   when you don't need it as in GetIpAndPort(),.
  36.  *
  37.  * Revision 1.9  2002/06/28 03:34:28  robertj
  38.  * Fixed issues with address translation on gatekeeper RAS channel.
  39.  *
  40.  * Revision 1.8  2002/05/10 05:48:13  robertj
  41.  * Added the max bit rate field to the data channel capability class.
  42.  * Added session ID to the data logical channel class.
  43.  *
  44.  * Revision 1.7  2002/02/01 01:47:18  robertj
  45.  * Some more fixes for T.120 channel establishment, more to do!
  46.  *
  47.  * Revision 1.6  2002/01/09 00:21:40  robertj
  48.  * Changes to support outgoing H.245 RequstModeChange.
  49.  *
  50.  * Revision 1.5  2001/12/22 03:22:29  robertj
  51.  * Added create protocol function to H323Connection.
  52.  *
  53.  * Revision 1.4  2001/09/12 07:48:05  robertj
  54.  * Fixed various problems with tracing.
  55.  *
  56.  * Revision 1.3  2001/08/06 03:08:57  robertj
  57.  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
  58.  *
  59.  * Revision 1.2  2001/07/18 02:27:24  robertj
  60.  * Fixed GNU warning.
  61.  *
  62.  * Revision 1.1  2001/07/17 04:44:32  robertj
  63.  * Partial implementation of T.120 and T.38 logical channels.
  64.  *
  65.  */
  66.  
  67. #include <ptlib.h>
  68.  
  69. #ifdef __GNUC__
  70. #pragma implementation "h323t120.h"
  71. #endif
  72.  
  73. #include "h323t120.h"
  74.  
  75. #include "h323ep.h"
  76. #include "h245.h"
  77. #include "t120proto.h"
  78. #include "x224.h"
  79.  
  80.  
  81. #define new PNEW
  82.  
  83. #define T120_MAX_BIT_RATE 825000
  84.  
  85.  
  86. /////////////////////////////////////////////////////////////////////////////
  87.  
  88. H323_T120Capability::H323_T120Capability()
  89.   : H323DataCapability(T120_MAX_BIT_RATE)
  90. {
  91.   dynamicPortCapability = TRUE;
  92. }
  93.  
  94.  
  95. PObject * H323_T120Capability::Clone() const
  96. {
  97.   return new H323_T120Capability(*this);
  98. }
  99.  
  100.  
  101. unsigned H323_T120Capability::GetSubType() const
  102. {
  103.   return H245_DataApplicationCapability_application::e_t120;
  104. }
  105.  
  106.  
  107. PString H323_T120Capability::GetFormatName() const
  108. {
  109.   return "T.120";
  110. }
  111.  
  112.  
  113. H323Channel * H323_T120Capability::CreateChannel(H323Connection & connection,
  114.                                                  H323Channel::Directions direction,
  115.                                                  unsigned sessionID,
  116.                                 const H245_H2250LogicalChannelParameters *) const
  117. {
  118.   return new H323_T120Channel(connection, *this, direction, sessionID);
  119. }
  120.  
  121.  
  122. BOOL H323_T120Capability::OnSendingPDU(H245_DataApplicationCapability & pdu) const
  123. {
  124.   pdu.m_application.SetTag(H245_DataApplicationCapability_application::e_t120);
  125.   return OnSendingPDU((H245_DataProtocolCapability &)pdu.m_application);
  126. }
  127.  
  128.  
  129. BOOL H323_T120Capability::OnSendingPDU(H245_DataMode & pdu) const
  130. {
  131.   pdu.m_application.SetTag(H245_DataMode_application::e_t120);
  132.   return OnSendingPDU((H245_DataProtocolCapability &)pdu.m_application);
  133. }
  134.  
  135.  
  136. BOOL H323_T120Capability::OnSendingPDU(H245_DataProtocolCapability & pdu) const
  137. {
  138.   pdu.SetTag(H245_DataProtocolCapability::e_separateLANStack);
  139.   return TRUE;
  140. }
  141.  
  142.  
  143. BOOL H323_T120Capability::OnReceivedPDU(const H245_DataApplicationCapability & cap)
  144. {
  145.   if (cap.m_application.GetTag() != H245_DataApplicationCapability_application::e_t120)
  146.     return FALSE;
  147.  
  148.   const H245_DataProtocolCapability & dataCap = cap.m_application;
  149.  
  150.   return dataCap.GetTag() == H245_DataProtocolCapability::e_separateLANStack;
  151. }
  152.  
  153.  
  154. /////////////////////////////////////////////////////////////////////////////
  155.  
  156. H323_T120Channel::H323_T120Channel(H323Connection & connection,
  157.                                    const H323Capability & capability,
  158.                                    Directions direction,
  159.                                    unsigned id)
  160.   : H323DataChannel(connection, capability, direction, id)
  161. {
  162.   t120handler = NULL;
  163.   PTRACE(3, "H323T120\tCreated logical channel for T.120");
  164. }
  165.  
  166.  
  167. void H323_T120Channel::Receive()
  168. {
  169.   HandleChannel();
  170. }
  171.  
  172.  
  173. void H323_T120Channel::Transmit()
  174. {
  175.   HandleChannel();
  176. }
  177.  
  178.  
  179. void H323_T120Channel::HandleChannel()
  180. {
  181.   PTRACE(2, "H323T120\tThread started.");
  182.  
  183.   if (t120handler == NULL) {
  184.     PTRACE(1, "H323T120\tNo protocol handler, aborting thread.");
  185.   }
  186.   else if (transport == NULL && listener == NULL) {
  187.     PTRACE(1, "H323T120\tNo listener or transport, aborting thread.");
  188.   }
  189.   else if (listener != NULL) {
  190.     if ((transport = listener->Accept(30000)) != NULL)  // 30 second wait for connect back
  191.       t120handler->Answer(*transport);
  192.     else {
  193.       PTRACE(1, "H323T120\tAccept failed, aborting thread.");
  194.     }
  195.   }
  196.   else if (transport->IsOpen())
  197.     t120handler->Originate(*transport);
  198.   else {
  199.     PTRACE(1, "H323T120\tConnect failed, aborting thread.");
  200.   }
  201.  
  202.   connection.CloseLogicalChannelNumber(number);
  203.  
  204.   PTRACE(2, "H323T120\tThread ended");
  205. }
  206.  
  207.  
  208. BOOL H323_T120Channel::OnSendingPDU(H245_OpenLogicalChannel & open) const
  209. {
  210.   if (!H323DataChannel::OnSendingPDU(open))
  211.     return FALSE;
  212.  
  213.   if (!((H323_T120Channel*)this)->CreateListener()) {
  214.     PTRACE(1, "H323T120\tCould not create listener");
  215.     return FALSE;
  216.   }
  217.  
  218.   PTRACE(3, "H323T120\tOnSendingPDU");
  219.  
  220.   open.IncludeOptionalField(H245_OpenLogicalChannel::e_separateStack);
  221.   open.m_separateStack.IncludeOptionalField(H245_NetworkAccessParameters::e_distribution);
  222.   open.m_separateStack.m_distribution.SetTag(H245_NetworkAccessParameters_distribution::e_unicast);
  223.   open.m_separateStack.m_networkAddress.SetTag(H245_NetworkAccessParameters_networkAddress::e_localAreaAddress);
  224.   H245_TransportAddress & address = open.m_separateStack.m_networkAddress;
  225.   return listener->SetUpTransportPDU(address, connection.GetControlChannel());
  226. }
  227.  
  228.  
  229. void H323_T120Channel::OnSendOpenAck(const H245_OpenLogicalChannel & /*open*/,
  230.                                      H245_OpenLogicalChannelAck & ack) const
  231. {
  232.   PTRACE(3, "H323T120\tOnSendOpenAck");
  233.  
  234.   if (listener != NULL || transport != NULL) {
  235.     ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_separateStack);
  236.     ack.m_separateStack.IncludeOptionalField(H245_NetworkAccessParameters::e_distribution);
  237.     ack.m_separateStack.m_distribution.SetTag(H245_NetworkAccessParameters_distribution::e_unicast);
  238.     ack.m_separateStack.m_networkAddress.SetTag(H245_NetworkAccessParameters_networkAddress::e_localAreaAddress);
  239.     H245_TransportAddress & address = ack.m_separateStack.m_networkAddress;
  240.     if (listener != NULL)
  241.       listener->SetUpTransportPDU(address, connection.GetControlChannel());
  242.     else
  243.       transport->SetUpTransportPDU(address, H323Transport::UseLocalTSAP);
  244.   }
  245. }
  246.  
  247.  
  248. BOOL H323_T120Channel::OnReceivedPDU(const H245_OpenLogicalChannel & open,
  249.                                      unsigned & errorCode)
  250. {
  251.   number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE);
  252.  
  253.   PTRACE(3, "H323T120\tOnReceivedPDU for channel: " << number);
  254.  
  255.   H323EndPoint & endpoint = connection.GetEndPoint();
  256.  
  257.   t120handler = connection.CreateT120ProtocolHandler();
  258.   if (t120handler == NULL) {
  259.     PTRACE(1, "H323T120\tCould not create protocol handler");
  260.     errorCode = H245_OpenLogicalChannelReject_cause::e_dataTypeNotAvailable;
  261.     return FALSE;
  262.   }
  263.  
  264.   BOOL listen = connection.HadAnsweredCall();
  265.  
  266.   H323TransportAddress address;
  267.   if (open.HasOptionalField(H245_OpenLogicalChannel::e_separateStack) &&
  268.     open.m_separateStack.m_networkAddress.GetTag() == H245_NetworkAccessParameters_networkAddress::e_localAreaAddress) {
  269.     address = (const H245_TransportAddress &)open.m_separateStack.m_networkAddress;
  270.     if (open.m_separateStack.HasOptionalField(H245_NetworkAccessParameters::e_t120SetupProcedure))
  271.       listen = open.m_separateStack.m_t120SetupProcedure.GetTag() ==
  272.                             H245_NetworkAccessParameters_t120SetupProcedure::e_waitForCall;
  273.   }
  274.  
  275.   if (listen) {
  276.     if (!address)
  277.       listener = address.CreateCompatibleListener(endpoint);
  278.     else {
  279.       // No address specified, assume same IP as the transport and use default port
  280.       PIPSocket::Address ip;
  281.       if (!connection.GetControlChannel().GetLocalAddress().GetIpAddress(ip)) {
  282.         PTRACE(1, "H323T120\tOnly IPv4 supported");
  283.         errorCode = H245_OpenLogicalChannelReject_cause::e_separateStackEstablishmentFailed;
  284.         return FALSE;
  285.       }
  286.       listener = new H323ListenerTCP(endpoint, ip, OpalT120Protocol::DefaultTcpPort, FALSE);
  287.     }
  288.  
  289.     if (!listener->Open()) {
  290.       PTRACE(1, "H323T120\tCould not open listener");
  291.       errorCode = H245_OpenLogicalChannelReject_cause::e_separateStackEstablishmentFailed;
  292.       return FALSE;
  293.     }
  294.  
  295.     PTRACE(2, "H323T120\tCreated listener on " << listener->GetTransportAddress());
  296.   }
  297.   else {
  298.     if (address.IsEmpty()) {
  299.       // No address specified, assume same IP as the transport and use default port
  300.       PIPSocket::Address ip;
  301.       if (!connection.GetControlChannel().GetRemoteAddress().GetIpAddress(ip)) {
  302.         PTRACE(1, "H323T120\tOnly IPv4 supported");
  303.         errorCode = H245_OpenLogicalChannelReject_cause::e_separateStackEstablishmentFailed;
  304.         return FALSE;
  305.       }
  306.       address = H323TransportAddress(ip, OpalT120Protocol::DefaultTcpPort);
  307.     }
  308.  
  309.     transport = address.CreateTransport(endpoint);
  310.     if (transport == NULL) {
  311.       PTRACE(1, "H323T120\tCould not create transport");
  312.       errorCode = H245_OpenLogicalChannelReject_cause::e_separateStackEstablishmentFailed;
  313.       return FALSE;
  314.     }
  315.  
  316.     transport->SetReadTimeout(10000); // 10 second wait for connect
  317.     if (!transport->ConnectTo(address)) {
  318.       PTRACE(1, "H323T120\tCould not connect to remote address: " << address);
  319.       errorCode = H245_OpenLogicalChannelReject_cause::e_separateStackEstablishmentFailed;
  320.       return FALSE;
  321.     }
  322.  
  323.     PTRACE(2, "H323T120\tCreated transport from "
  324.            << transport->GetLocalAddress() << " to " << transport->GetRemoteAddress());
  325.   }
  326.  
  327.   return TRUE;
  328. }
  329.  
  330.  
  331. BOOL H323_T120Channel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & /*ack*/)
  332. {
  333.   PTRACE(3, "H323T120\tOnReceivedAckPDU");
  334.  
  335.   t120handler = connection.CreateT120ProtocolHandler();
  336.   if (t120handler == NULL) {
  337.     PTRACE(1, "H323T120\tCould not create protocol handler");
  338.     return FALSE;
  339.   }
  340.  
  341.   return TRUE;
  342. }
  343.  
  344.     
  345. /////////////////////////////////////////////////////////////////////////////
  346.