3749 lines
135 KiB
C
3749 lines
135 KiB
C
/******************************************************************************
|
|
*
|
|
* INTEL Corporation Proprietary Information
|
|
* Copyright (c) 1994, 1995, 1996 Intel Corporation.
|
|
*
|
|
* This listing is supplied under the terms of a license agreement
|
|
* with INTEL Corporation and may not be used, copied, nor disclosed
|
|
* except in accordance with the terms of that agreement.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* $Workfile: api_up.c $
|
|
* $Revision: 1.33 $
|
|
* $Modtime: 06 Feb 1997 14:37:24 $
|
|
* $Log: S:\sturgeon\src\h245\src\vcs\api_up.c_v $
|
|
*
|
|
* Rev 1.33 06 Feb 1997 18:14:22 SBELL1
|
|
* took out ossDecoding of returnFunction in FunctionNotSupported PDU.
|
|
*
|
|
* Rev 1.32 05 Feb 1997 16:46:42 EHOWARDX
|
|
* Was allocating nLength bytes, not WCHARS, for UserInputIndication
|
|
* ASCII to Unicode conversion. Changed to allocate nLength WCHARs.
|
|
*
|
|
* Rev 1.31 06 Jan 1997 20:38:18 EHOWARDX
|
|
*
|
|
* Changed H245_CONF_CLOSE and H245_CONF_REQ_CLOSE to fill in
|
|
* AccRej with H245_REJ for any errors.
|
|
*
|
|
* Rev 1.30 19 Dec 1996 21:00:56 EHOWARDX
|
|
* Oops! H245_IND_OPEN_CONF can occur from T103 timeout (it's unique among
|
|
* indications; it's the only one that can happen in response to a timeout!)
|
|
*
|
|
* Rev 1.29 19 Dec 1996 17:18:22 EHOWARDX
|
|
* Changed to use h245asn1.h definitions instead of _setof3 and _setof8.
|
|
*
|
|
* Rev 1.28 18 Dec 1996 16:33:18 EHOWARDX
|
|
*
|
|
* Fixed bug in Master Slave Determination Kludge.
|
|
*
|
|
* Rev 1.27 17 Dec 1996 17:13:20 EHOWARDX
|
|
* Added pSeparateStack to IND_OPEN_T.
|
|
*
|
|
* Rev 1.26 12 Dec 1996 15:57:12 EHOWARDX
|
|
* Master Slave Determination kludge.
|
|
*
|
|
* Rev 1.25 21 Oct 1996 16:07:38 EHOWARDX
|
|
* Modified to make sure H245_INDETERMINATE is returned and Master/Slave
|
|
* status if determination fails.
|
|
*
|
|
* Rev 1.24 17 Oct 1996 18:17:14 EHOWARDX
|
|
* Changed general string to always be Unicode.
|
|
*
|
|
* Rev 1.23 14 Oct 1996 14:01:12 EHOWARDX
|
|
* Unicode changes.
|
|
*
|
|
* Rev 1.22 27 Aug 1996 10:54:16 unknown
|
|
* Deleted redundant lines.
|
|
*
|
|
* Rev 1.22 27 Aug 1996 10:52:28 unknown
|
|
* Deleted redundant lines.
|
|
*
|
|
* Rev 1.22 27 Aug 1996 09:54:12 unknown
|
|
* Deleted redundant lines.
|
|
*
|
|
* Rev 1.21 26 Aug 1996 14:19:18 EHOWARDX
|
|
* Added code to send FunctionNotUnderstood indication to remote peer
|
|
* if receive callback returns H245_ERROR_NOSUP.
|
|
*
|
|
* Rev 1.20 20 Aug 1996 14:44:40 EHOWARDX
|
|
* Changed H245_IND_COMM_MODE_RESPONSE and H245_IND_COMM_MODE_COMMAND
|
|
* callbacks to fill in DataType field in Cap as per Mike Andrews' request.
|
|
*
|
|
* Rev 1.19 15 Aug 1996 15:20:24 EHOWARDX
|
|
* First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews.
|
|
* Use at your own risk!
|
|
*
|
|
* Rev 1.18 15 Aug 1996 09:34:20 EHOWARDX
|
|
* Made TOTCAP and MUX structure in process_open_ind static since we are
|
|
* accessing pointers to them after return from the function.
|
|
*
|
|
* Rev 1.17 29 Jul 1996 19:33:00 EHOWARDX
|
|
*
|
|
* Fixed bug in flow control - missing break in restriction switch statement.
|
|
*
|
|
* Rev 1.16 19 Jul 1996 14:11:26 EHOWARDX
|
|
*
|
|
* Added indication callback structure for CommunicationModeResponse
|
|
* and CommunicationModeCommand.
|
|
*
|
|
* Rev 1.15 19 Jul 1996 12:48:00 EHOWARDX
|
|
*
|
|
* Multipoint clean-up.
|
|
*
|
|
* Rev 1.14 09 Jul 1996 17:09:28 EHOWARDX
|
|
* Fixed pointer offset bug in processing DataType from received
|
|
* OpenLogicalChannel.
|
|
*
|
|
* Rev 1.13 01 Jul 1996 22:13:04 EHOWARDX
|
|
*
|
|
* Added Conference and CommunicationMode structures and functions.
|
|
*
|
|
* Rev 1.12 18 Jun 1996 14:50:28 EHOWARDX
|
|
*
|
|
* Changed MLSE confirm handling.
|
|
*
|
|
* Rev 1.11 14 Jun 1996 18:57:52 EHOWARDX
|
|
* Geneva update.
|
|
*
|
|
* Rev 1.10 10 Jun 1996 16:55:34 EHOWARDX
|
|
* Removed #include "h245init.x"
|
|
*
|
|
* Rev 1.9 06 Jun 1996 18:45:52 EHOWARDX
|
|
* Added check for null dwTransId to Tracker routines; changed to use
|
|
* tracker routines instead of PLOCK macros.
|
|
*
|
|
* Rev 1.8 04 Jun 1996 13:56:46 EHOWARDX
|
|
* Fixed Release build warnings.
|
|
*
|
|
* Rev 1.7 30 May 1996 23:39:00 EHOWARDX
|
|
* Cleanup.
|
|
*
|
|
* Rev 1.6 29 May 1996 15:20:06 EHOWARDX
|
|
* Change to use HRESULT.
|
|
*
|
|
* Rev 1.5 28 May 1996 14:22:58 EHOWARDX
|
|
* Tel Aviv update.
|
|
*
|
|
* Rev 1.4 20 May 1996 22:17:58 EHOWARDX
|
|
* Completed NonStandard Message and H.225.0 Maximum Skew indication
|
|
* implementation. Added ASN.1 validation to H245SetLocalCap and
|
|
* H245SetCapDescriptor. Check-in from Microsoft drop on 17-May-96.
|
|
*
|
|
* Rev 1.3 16 May 1996 19:40:46 EHOWARDX
|
|
* Fixed multiplex capability bug.
|
|
*
|
|
* Rev 1.2 16 May 1996 15:59:24 EHOWARDX
|
|
* Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/
|
|
* H245DelCapDescriptor behaviour.
|
|
*
|
|
* Rev 1.1 13 May 1996 23:16:26 EHOWARDX
|
|
* Fixed remote terminal capability handling.
|
|
*
|
|
* Rev 1.0 09 May 1996 21:06:08 EHOWARDX
|
|
* Initial revision.
|
|
*
|
|
* Rev 1.23.1.11 09 May 1996 19:31:30 EHOWARDX
|
|
* Redesigned thread locking logic.
|
|
* Added new API functions.
|
|
*
|
|
* Rev 1.23.1.10 01 May 1996 19:30:32 EHOWARDX
|
|
* Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux().
|
|
* Changed H2250_xxx definitions for H.225.0 address types to H245_xxx.
|
|
*
|
|
* Rev 1.23.1.9 29 Apr 1996 16:02:58 EHOWARDX
|
|
* Changed callback to give second parameters as pointer to specific message
|
|
* instead of pointer to general PDU structure.
|
|
*
|
|
* Rev 1.23.1.8 27 Apr 1996 21:09:40 EHOWARDX
|
|
* Changed Channel Numbers to words, added H.225.0 support.
|
|
*
|
|
* Rev 1.23.1.7 26 Apr 1996 15:54:34 EHOWARDX
|
|
* Added H.225.0 Capability support; Changed Capability indication
|
|
* to only callback once with PDU.
|
|
*
|
|
* Rev 1.23.1.6 24 Apr 1996 20:53:56 EHOWARDX
|
|
* Added new OpenLogicalChannelAck/OpenLogicalChannelReject support.
|
|
*
|
|
* Rev 1.23.1.5 23 Apr 1996 14:45:28 EHOWARDX
|
|
* Disabled Curt's "Conflict Resolution".
|
|
*
|
|
* Rev 1.23.1.4 19 Apr 1996 12:55:10 EHOWARDX
|
|
* Updated to 1.29
|
|
*
|
|
* Rev 1.23.1.3 17 Apr 1996 14:37:38 unknown
|
|
* Added load_H222_param(), load_VGMUX_param(), and load_H2250_param() and
|
|
* modified process_open_ind() to use them.
|
|
*
|
|
* Rev 1.23.1.2 15 Apr 1996 15:10:32 EHOWARDX
|
|
* Updated to match Curt's current version.
|
|
*
|
|
* Rev 1.23.1.1 03 Apr 1996 17:15:00 EHOWARDX
|
|
* No change.
|
|
*
|
|
* Rev 1.23.1.0 03 Apr 1996 15:54:04 cjutzi
|
|
* Branched for H.323.
|
|
*
|
|
* Rev 1.23 01 Apr 1996 16:46:20 cjutzi
|
|
*
|
|
* - changed tracker structure
|
|
* - Completed ENdConnection, and made asynch.. rather
|
|
* than sync.. as before
|
|
* Changed H245ShutDown to be sync rather than async..
|
|
*
|
|
* Rev 1.22 29 Mar 1996 14:54:28 cjutzi
|
|
* - added UserInput,
|
|
*
|
|
* Rev 1.21 28 Mar 1996 15:57:46 cjutzi
|
|
* - removed ASSERT line 1290.. close can occur on any channel at any time
|
|
*
|
|
* Rev 1.20 27 Mar 1996 08:36:40 cjutzi
|
|
* - removed PDU from stack.. made them dynamically allocated
|
|
*
|
|
* Rev 1.19 26 Mar 1996 13:48:30 cjutzi
|
|
*
|
|
* - dwPreserved in the callback routine was uninitialized..
|
|
*
|
|
* Rev 1.18 18 Mar 1996 15:23:30 cjutzi
|
|
*
|
|
*
|
|
*
|
|
* Rev 1.17 13 Mar 1996 14:14:02 cjutzi
|
|
*
|
|
* - clean up and added ASSERTs ..
|
|
*
|
|
* Rev 1.16 13 Mar 1996 12:06:12 cjutzi
|
|
*
|
|
* - fixed .. CONFIRM open.. for hani.. It released the tracker..
|
|
* was supposed to simply update the state to IDLE..
|
|
*
|
|
* Rev 1.15 13 Mar 1996 09:22:12 cjutzi
|
|
*
|
|
* - removed CRITICAL SECTIONS
|
|
*
|
|
* Rev 1.14 12 Mar 1996 15:52:32 cjutzi
|
|
*
|
|
* - fixed master slave (forgot a break)
|
|
* - fixed callback bug w/ cleanup on termcaps.
|
|
* - implemented End Session
|
|
* - fixed shutdown
|
|
* - Implemented Locking (big changes here.. )
|
|
*
|
|
* Rev 1.13 08 Mar 1996 14:04:18 cjutzi
|
|
*
|
|
* - implemented the upcall for mux table entries..
|
|
* - implemented capabillity descriptor callback
|
|
*
|
|
* Rev 1.12 05 Mar 1996 17:36:28 cjutzi
|
|
*
|
|
* - added MasterSlave indication message
|
|
* - remove bzero/bcopy and changed free call
|
|
* - implemented Mux Table down.. (not up)
|
|
*
|
|
* Rev 1.11 01 Mar 1996 14:16:08 cjutzi
|
|
*
|
|
* - added hani's error messages.. MasterSlave_FAILED.. oppss.. Forgot..
|
|
*
|
|
* Rev 1.10 01 Mar 1996 13:47:58 cjutzi
|
|
*
|
|
* - added hani's new fsm id's
|
|
*
|
|
* Rev 1.9 29 Feb 1996 17:26:16 cjutzi
|
|
* - bi-directional channel open working
|
|
*
|
|
* Rev 1.8 27 Feb 1996 14:56:30 cjutzi
|
|
*
|
|
* - fixed termcap_ack.. pdu was not being zero'd out..
|
|
* - cleaned up the code alittle..
|
|
*
|
|
* Rev 1.7 26 Feb 1996 17:22:40 cjutzi
|
|
*
|
|
* - Misc Command Indication added
|
|
*
|
|
* Rev 1.6 26 Feb 1996 11:05:48 cjutzi
|
|
*
|
|
* - lot's o-changes.. (sorry)
|
|
*
|
|
* Rev 1.5 16 Feb 1996 13:01:54 cjutzi
|
|
*
|
|
* - got open / close / request close working in both directions.
|
|
*
|
|
* Rev 1.4 15 Feb 1996 14:11:46 cjutzi
|
|
*
|
|
* - added muxt table to incoming open..
|
|
*
|
|
* Rev 1.3 15 Feb 1996 10:51:56 cjutzi
|
|
*
|
|
* - termcaps working
|
|
* - changed API interface for MUX_T
|
|
* - changed callback for IND_OPEN
|
|
* - changed constants IND_OPEN/IND_OPEN_NEEDSRSP
|
|
* - cleaned up the open.
|
|
* - modified H223 stuff
|
|
*
|
|
* Rev 1.2 09 Feb 1996 16:58:28 cjutzi
|
|
*
|
|
* - cleanup.. and some fixes..
|
|
* - added and or changed headers to reflect the log of changes
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/**** *****/
|
|
/**** NOTES TO THE READER *****/
|
|
/**** *****/
|
|
/**** This program has been put together using a a screen which is *****/
|
|
/**** wider than 80 characters.. It is best if a similar screen size is *****/
|
|
/**** used.. Of course emacs is my preference but 80 col screens will *****/
|
|
/**** cause you much frustration.. *****/
|
|
/**** *****/
|
|
/**** Tabs are set to 8 *****/
|
|
/**** *****/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
|
|
#ifndef STRICT
|
|
#define STRICT
|
|
#endif
|
|
|
|
#include "precomp.h"
|
|
|
|
/***********************/
|
|
/* H245 INCLUDES */
|
|
/***********************/
|
|
#include "h245api.h"
|
|
#include "h245com.h"
|
|
#include "h245sys.x"
|
|
#include "h245asn1.h"
|
|
#include "fsmexpor.h"
|
|
#include "api_util.x"
|
|
#include "pdu.x"
|
|
|
|
|
|
|
|
HRESULT
|
|
LoadUnicastAddress (H245_TRANSPORT_ADDRESS_T *pOut,
|
|
UnicastAddress *pIn)
|
|
{
|
|
switch (pIn->choice)
|
|
{
|
|
case UnicastAddress_iPAddress_chosen:
|
|
pOut->type = H245_IP_UNICAST;
|
|
memcpy(pOut->u.ip.network,
|
|
pIn->u.UnicastAddress_iPAddress.network.value,
|
|
4);
|
|
pOut->u.ip.tsapIdentifier = pIn->u.UnicastAddress_iPAddress.tsapIdentifier;
|
|
break;
|
|
|
|
case iPXAddress_chosen:
|
|
pOut->type = H245_IPX_UNICAST;
|
|
memcpy(pOut->u.ipx.node,
|
|
pIn->u.iPXAddress.node.value,
|
|
6);
|
|
memcpy(pOut->u.ipx.netnum,
|
|
pIn->u.iPXAddress.netnum.value,
|
|
4);
|
|
memcpy(pOut->u.ipx.tsapIdentifier,
|
|
pIn->u.iPXAddress.tsapIdentifier.value,
|
|
2);
|
|
break;
|
|
|
|
case UncstAddrss_iP6Address_chosen:
|
|
pOut->type = H245_IP6_UNICAST;
|
|
memcpy(pOut->u.ip6.network,
|
|
pIn->u.UncstAddrss_iP6Address.network.value,
|
|
16);
|
|
pOut->u.ip6.tsapIdentifier = pIn->u.UncstAddrss_iP6Address.tsapIdentifier;
|
|
break;
|
|
|
|
case netBios_chosen:
|
|
pOut->type = H245_NETBIOS_UNICAST;
|
|
memcpy(pOut->u.netBios, pIn->u.netBios.value, 16);
|
|
break;
|
|
|
|
case iPSourceRouteAddress_chosen:
|
|
switch (pIn->u.iPSourceRouteAddress.routing.choice)
|
|
{
|
|
case strict_chosen:
|
|
pOut->type = H245_IPSSR_UNICAST;
|
|
break;
|
|
|
|
case loose_chosen:
|
|
pOut->type = H245_IPLSR_UNICAST;
|
|
break;
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
memcpy(pOut->u.ipSourceRoute.network,
|
|
pIn->u.iPSourceRouteAddress.network.value,
|
|
4);
|
|
pOut->u.ipSourceRoute.tsapIdentifier = pIn->u.iPSourceRouteAddress.tsapIdentifier;
|
|
// TBD - handle route
|
|
break;
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
return H245_ERROR_OK;
|
|
} // LoadUnicastAddress()
|
|
|
|
|
|
|
|
HRESULT
|
|
LoadMulticastAddress(H245_TRANSPORT_ADDRESS_T *pOut,
|
|
MulticastAddress *pIn)
|
|
{
|
|
switch (pIn->choice)
|
|
{
|
|
case MltcstAddrss_iPAddress_chosen:
|
|
pOut->type = H245_IP_MULTICAST;
|
|
memcpy(pOut->u.ip.network,
|
|
pIn->u.MltcstAddrss_iPAddress.network.value,
|
|
4);
|
|
pOut->u.ip.tsapIdentifier = pIn->u.MltcstAddrss_iPAddress.tsapIdentifier;
|
|
break;
|
|
|
|
case MltcstAddrss_iP6Address_chosen:
|
|
pOut->type = H245_IP6_MULTICAST;
|
|
memcpy(pOut->u.ip6.network,
|
|
pIn->u.MltcstAddrss_iP6Address.network.value,
|
|
16);
|
|
pOut->u.ip6.tsapIdentifier = pIn->u.MltcstAddrss_iP6Address.tsapIdentifier;
|
|
break;
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
return H245_ERROR_OK;
|
|
} // LoadMulticastAddress()
|
|
|
|
|
|
|
|
HRESULT
|
|
LoadTransportAddress(H245_TRANSPORT_ADDRESS_T *pOut,
|
|
H245TransportAddress *pIn)
|
|
{
|
|
switch (pIn->choice)
|
|
{
|
|
case unicastAddress_chosen:
|
|
return LoadUnicastAddress (pOut, &pIn->u.unicastAddress);
|
|
|
|
case multicastAddress_chosen:
|
|
return LoadMulticastAddress(pOut, &pIn->u.multicastAddress);
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
} // LoadTransportAddress()
|
|
|
|
|
|
|
|
HRESULT
|
|
LoadCommModeEntry(H245_COMM_MODE_ENTRY_T *pOut,
|
|
CommunicationModeTableEntry *pIn)
|
|
{
|
|
HRESULT lResult;
|
|
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
if (pIn->bit_mask & CMTEy_nnStndrd_present)
|
|
{
|
|
pOut->pNonStandard = pIn->CMTEy_nnStndrd;
|
|
}
|
|
|
|
pOut->sessionID = (unsigned char)pIn->sessionID;
|
|
|
|
if (pIn->bit_mask & CMTEy_assctdSssnID_present)
|
|
{
|
|
pOut->associatedSessionID = (unsigned char)pIn->CMTEy_assctdSssnID;
|
|
pOut->associatedSessionIDPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & CommunicationModeTableEntry_terminalLabel_present)
|
|
{
|
|
pOut->terminalLabel = pIn->terminalLabel;
|
|
pOut->terminalLabelPresent = TRUE;
|
|
}
|
|
|
|
pOut->pSessionDescription = pIn->sessionDescription.value;
|
|
pOut->wSessionDescriptionLength = (WORD) pIn->sessionDescription.length;
|
|
|
|
switch (pIn->dataType.choice)
|
|
{
|
|
case dataType_videoData_chosen:
|
|
pOut->dataType.DataType = H245_DATA_VIDEO;
|
|
break;
|
|
|
|
case dataType_audioData_chosen:
|
|
pOut->dataType.DataType = H245_DATA_AUDIO;
|
|
break;
|
|
|
|
case dataType_data_chosen:
|
|
pOut->dataType.DataType = H245_DATA_DATA;
|
|
break;
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
|
|
lResult = build_totcap_cap_n_client_from_capability ((struct Capability *)&pIn->dataType,
|
|
pOut->dataType.DataType,
|
|
pIn->dataType.u.dataType_videoData.choice,
|
|
&pOut->dataType);
|
|
if (lResult != H245_ERROR_OK)
|
|
return lResult;
|
|
|
|
if (pIn->bit_mask & CMTEy_mdChnnl_present)
|
|
{
|
|
lResult = LoadTransportAddress(&pOut->mediaChannel, &pIn->CMTEy_mdChnnl);
|
|
if (lResult != H245_ERROR_OK)
|
|
return lResult;
|
|
pOut->mediaChannelPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & CMTEy_mdGrntdDlvry_present)
|
|
{
|
|
pOut->mediaGuaranteed = pIn->CMTEy_mdGrntdDlvry;
|
|
pOut->mediaGuaranteedPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & CMTEy_mdCntrlChnnl_present)
|
|
{
|
|
lResult = LoadTransportAddress(&pOut->mediaControlChannel, &pIn->CMTEy_mdCntrlChnnl);
|
|
if (lResult != H245_ERROR_OK)
|
|
return lResult;
|
|
pOut->mediaControlChannelPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & CMTEy_mdCntrlGrntdDlvry_present)
|
|
{
|
|
pOut->mediaControlGuaranteed = pIn->CMTEy_mdCntrlGrntdDlvry;
|
|
pOut->mediaControlGuaranteedPresent = TRUE;
|
|
}
|
|
|
|
return H245_ERROR_OK;
|
|
} // LoadCommModeEntry()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: load_H222_param
|
|
* load_H223_param
|
|
* load_VGMUX_param
|
|
* load_H2250_param
|
|
* load_H2250ACK_param
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* This routine builds local API-style Logical Parameters out of ASN.1
|
|
* structure passed to it
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static HRESULT
|
|
load_H222_param (H245_H222_LOGICAL_PARAM_T * pOut, /* output */
|
|
H222LogicalChannelParameters * pIn) /* input */
|
|
{
|
|
/* See setup_H220_mux() for inverse function */
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
pOut->resourceID = pIn->resourceID;
|
|
pOut->subChannelID = pIn->subChannelID;
|
|
if (pIn->bit_mask & pcr_pid_present)
|
|
{
|
|
pOut->pcr_pidPresent = TRUE;
|
|
pOut->pcr_pid = pIn->pcr_pid;
|
|
}
|
|
if (pIn->bit_mask & programDescriptors_present)
|
|
{
|
|
pOut->programDescriptors.length = pIn->programDescriptors.length;
|
|
pOut->programDescriptors.value = pIn->programDescriptors.value;
|
|
}
|
|
if (pIn->bit_mask & streamDescriptors_present)
|
|
{
|
|
pOut->streamDescriptors.length = pIn->streamDescriptors.length;
|
|
pOut->streamDescriptors.value = pIn->streamDescriptors.value;
|
|
}
|
|
return H245_ERROR_OK;
|
|
} // load_H222_param()
|
|
|
|
static HRESULT
|
|
load_H223_param (H245_H223_LOGICAL_PARAM_T * pOut, /* output */
|
|
H223LogicalChannelParameters * pIn) /* input */
|
|
{
|
|
HRESULT lError = H245_ERROR_OK;
|
|
|
|
/* See setup_H223_mux() for inverse function */
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
pOut->SegmentFlag = pIn->segmentableFlag;
|
|
|
|
switch (pIn->adaptationLayerType.choice)
|
|
{
|
|
case H223LCPs_aLTp_nnStndrd_chosen:
|
|
lError = CopyNonStandardParameter(&pOut->H223_NONSTD,
|
|
&pIn->adaptationLayerType.u.H223LCPs_aLTp_nnStndrd);
|
|
pOut->AlType = H245_H223_AL_NONSTD;
|
|
break;
|
|
case H223LCPs_aLTp_al1Frmd_chosen:
|
|
pOut->AlType = H245_H223_AL_AL1FRAMED;
|
|
break;
|
|
case H223LCPs_aLTp_al1NtFrmd_chosen:
|
|
pOut->AlType = H245_H223_AL_AL1NOTFRAMED;
|
|
break;
|
|
case H223LCPs_aLTp_a2WSNs_1_chosen:
|
|
pOut->AlType = H245_H223_AL_AL2NOSEQ;
|
|
break;
|
|
case H223LCPs_aLTp_a2WSNs_2_chosen:
|
|
pOut->AlType = H245_H223_AL_AL2SEQ;
|
|
break;
|
|
case H223LCPs_aLTp_al3_chosen:
|
|
pOut->AlType = H245_H223_AL_AL3;
|
|
pOut->CtlFldOctet = (unsigned char)pIn->adaptationLayerType.u.H223LCPs_aLTp_al3.controlFieldOctets;
|
|
pOut->SndBufSize = pIn->adaptationLayerType.u.H223LCPs_aLTp_al3.sendBufferSize;
|
|
break;
|
|
} /* switch */
|
|
|
|
return lError;
|
|
} // load_H223_param()
|
|
|
|
static HRESULT
|
|
load_VGMUX_param(H245_VGMUX_LOGICAL_PARAM_T *pOut, /* output */
|
|
V76LogicalChannelParameters *pIn) /* input */
|
|
{
|
|
/* See setup_VGMUX_mux() for inverse function */
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
pOut->crcLength = pIn->hdlcParameters.crcLength.choice;
|
|
pOut->n401 = pIn->hdlcParameters.n401;
|
|
pOut->loopbackTestProcedure = pIn->hdlcParameters.loopbackTestProcedure;
|
|
pOut->suspendResume = pIn->suspendResume.choice;
|
|
pOut->uIH = pIn->uIH;
|
|
pOut->mode = pIn->mode.choice;
|
|
switch (pIn->mode.choice)
|
|
{
|
|
case eRM_chosen:
|
|
pOut->windowSize = pIn->mode.u.eRM.windowSize;
|
|
pOut->recovery = pIn->mode.u.eRM.recovery.choice;
|
|
break;
|
|
} // switch
|
|
pOut->audioHeaderPresent = pIn->v75Parameters.audioHeaderPresent;
|
|
return H245_ERROR_OK;
|
|
} // load_VGMUX_param()
|
|
|
|
static HRESULT
|
|
load_H2250_param(H245_H2250_LOGICAL_PARAM_T * pOut, /* output */
|
|
H2250LogicalChannelParameters *pIn) /* input */
|
|
{
|
|
HRESULT lError = H245_ERROR_OK;
|
|
|
|
/* See setup_H2250_mux() for inverse function */
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
if (pIn->bit_mask & H2250LCPs_nnStndrd_present)
|
|
{
|
|
pOut->nonStandardList = pIn->H2250LCPs_nnStndrd;
|
|
}
|
|
|
|
pOut->sessionID = (unsigned char) pIn->sessionID;
|
|
|
|
if (pIn->bit_mask & H2250LCPs_assctdSssnID_present)
|
|
{
|
|
pOut->associatedSessionID = (unsigned char)pIn->H2250LCPs_assctdSssnID;
|
|
pOut->associatedSessionIDPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCPs_mdChnnl_present)
|
|
{
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = LoadTransportAddress(&pOut->mediaChannel,
|
|
&pIn->H2250LCPs_mdChnnl);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
pOut->mediaChannelPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCPs_mdGrntdDlvry_present)
|
|
{
|
|
pOut->mediaGuaranteed = pIn->H2250LCPs_mdGrntdDlvry;
|
|
pOut->mediaGuaranteedPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCPs_mdCntrlChnnl_present)
|
|
{
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = LoadTransportAddress(&pOut->mediaControlChannel,
|
|
&pIn->H2250LCPs_mdCntrlChnnl);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
pOut->mediaControlChannelPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCPs_mCGDy_present)
|
|
{
|
|
pOut->mediaControlGuaranteed = pIn->H2250LCPs_mCGDy;
|
|
pOut->mediaControlGuaranteedPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & silenceSuppression_present)
|
|
{
|
|
pOut->silenceSuppression = pIn->silenceSuppression;
|
|
pOut->silenceSuppressionPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LogicalChannelParameters_destination_present)
|
|
{
|
|
pOut->destination = pIn->destination;
|
|
pOut->destinationPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCPs_dRTPPTp_present)
|
|
{
|
|
pOut->dynamicRTPPayloadType = (unsigned char)pIn->H2250LCPs_dRTPPTp;
|
|
pOut->dynamicRTPPayloadTypePresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & mediaPacketization_present)
|
|
{
|
|
switch (pIn->mediaPacketization.choice)
|
|
{
|
|
case h261aVideoPacketization_chosen:
|
|
pOut->h261aVideoPacketization = TRUE;
|
|
break;
|
|
|
|
default:
|
|
return H245_ERROR_INVALID_DATA_FORMAT;
|
|
} // switch
|
|
}
|
|
|
|
return lError;
|
|
} // load_H2250_param()
|
|
|
|
static HRESULT
|
|
load_H2250ACK_param(H245_H2250ACK_LOGICAL_PARAM_T * pOut,
|
|
H2250LgclChnnlAckPrmtrs * pIn)
|
|
{
|
|
HRESULT lError = H245_ERROR_OK;
|
|
|
|
/* See setup_H2250ACK_mux() for inverse function */
|
|
memset(pOut, 0, sizeof(*pOut));
|
|
|
|
if (pIn->bit_mask & H2250LCAPs_nnStndrd_present)
|
|
{
|
|
pOut->nonStandardList = pIn->H2250LCAPs_nnStndrd;
|
|
}
|
|
|
|
if (pIn->bit_mask & sessionID_present)
|
|
{
|
|
pOut->sessionID = (unsigned char) pIn->sessionID;
|
|
pOut->sessionIDPresent = TRUE;
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCAPs_mdChnnl_present)
|
|
{
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = LoadTransportAddress(&pOut->mediaChannel,
|
|
&pIn->H2250LCAPs_mdChnnl);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
pOut->mediaChannelPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCAPs_mdCntrlChnnl_present)
|
|
{
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = LoadTransportAddress(&pOut->mediaControlChannel,
|
|
&pIn->H2250LCAPs_mdCntrlChnnl);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
pOut->mediaControlChannelPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pIn->bit_mask & H2250LCAPs_dRTPPTp_present)
|
|
{
|
|
pOut->dynamicRTPPayloadType = (unsigned char)pIn->H2250LCAPs_dRTPPTp;
|
|
pOut->dynamicRTPPayloadTypePresent = TRUE;
|
|
}
|
|
|
|
return lError;
|
|
} // load_H2250ACK_param()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: build_element_list_from_mux -
|
|
*
|
|
* DESCRIPTION
|
|
* recursively build H245_MUX_ENTRY_ELEMENT_T list from
|
|
* ASN1 mux table descriptor entrys.
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
static H245_MUX_ENTRY_ELEMENT_T *
|
|
build_element_list_from_mux (MultiplexElement *p_ASN_mux_el,
|
|
H245_ACC_REJ_T *p_acc_rej)
|
|
{
|
|
DWORD ii;
|
|
H245_MUX_ENTRY_ELEMENT_T *p_mux_el;
|
|
H245_MUX_ENTRY_ELEMENT_T *p_mux_el_tmp = NULL;
|
|
H245_MUX_ENTRY_ELEMENT_T *p_mux_el_lst = NULL;
|
|
|
|
if (!(p_mux_el = (H245_MUX_ENTRY_ELEMENT_T *)MemAlloc(sizeof(H245_MUX_ENTRY_ELEMENT_T))))
|
|
{
|
|
/* too complicated.. ran out of memory */
|
|
H245TRACE(0,1,"build_element_list_from_mux : H245_ERROR_NOMEM");
|
|
*p_acc_rej = H245_REJ_MUX_COMPLICATED;
|
|
return NULL;
|
|
}
|
|
|
|
/* zero it out */
|
|
memset (p_mux_el, 0, sizeof(H245_MUX_ENTRY_ELEMENT_T));
|
|
|
|
switch (p_ASN_mux_el->type.choice)
|
|
{
|
|
case typ_logicalChannelNumber_chosen:
|
|
/* assign as a logical channel */
|
|
p_mux_el->Kind = H245_MUX_LOGICAL_CHANNEL;
|
|
p_mux_el->u.Channel = p_ASN_mux_el->type.u.typ_logicalChannelNumber;
|
|
break;
|
|
case subElementList_chosen:
|
|
{
|
|
/* if the sub element list doesn't exist .. no go */
|
|
/* if the sub element list has less than 2 entries.. no go. */
|
|
if ((!p_ASN_mux_el->type.u.subElementList) ||
|
|
(p_ASN_mux_el->type.u.subElementList->count < 2))
|
|
{
|
|
/* invalid Element list.. */
|
|
H245TRACE(0,1,"build_element_list_from_mux : << ERROR >> Element Count < 2");
|
|
*p_acc_rej = H245_REJ;
|
|
free_mux_el_list (p_mux_el);
|
|
return NULL;
|
|
}
|
|
|
|
/* assign as entry element */
|
|
p_mux_el->Kind = H245_MUX_ENTRY_ELEMENT;
|
|
|
|
/* ok.. for every sub element in the list */
|
|
for (ii=0;ii<p_ASN_mux_el->type.u.subElementList->count;ii++)
|
|
{
|
|
if (!(p_mux_el_tmp = build_element_list_from_mux (&p_ASN_mux_el->type.u.subElementList->value[ii], p_acc_rej)))
|
|
{
|
|
/* *p_acc_rej is set from below */
|
|
free_mux_el_list (p_mux_el);
|
|
return NULL;
|
|
}
|
|
|
|
/* if first on the down sub element list.. assign to sub */
|
|
/* element portion of mux_el */
|
|
|
|
if (!p_mux_el_lst)
|
|
p_mux_el->u.pMuxTblEntryElem = p_mux_el_tmp;
|
|
/* otherwise.. just a list.. add it on.. */
|
|
else
|
|
p_mux_el_lst->pNext = p_mux_el_tmp;
|
|
|
|
p_mux_el_lst = p_mux_el_tmp;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
/* Un supported structure */
|
|
H245TRACE(0,1,"build_element_list_from_mux : INVALID MUX TABLE ENTRY PDU 'type.choice' unknown");
|
|
*p_acc_rej = H245_REJ;
|
|
free_mux_el_list (p_mux_el);
|
|
return NULL;
|
|
}
|
|
|
|
switch (p_ASN_mux_el->repeatCount.choice)
|
|
{
|
|
case repeatCount_finite_chosen:
|
|
p_mux_el->RepeatCount = p_ASN_mux_el->repeatCount.u.repeatCount_finite;
|
|
break;
|
|
case untilClosingFlag_chosen:
|
|
p_mux_el->RepeatCount = 0;
|
|
break;
|
|
default:
|
|
/* Un supported structure */
|
|
H245TRACE(0,1,"build_element_list_from_mux : INVALID MUX TABLE ENTRY PDU 'repeatCount.choice' unknown");
|
|
*p_acc_rej = H245_REJ;
|
|
free_mux_el_list (p_mux_el);
|
|
return NULL;
|
|
break;
|
|
}
|
|
|
|
return p_mux_el;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_mux_table_ind
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
static H245_MUX_TABLE_T *
|
|
process_mux_table_ind (MltmdSystmCntrlMssg *p_pdu_ind,
|
|
unsigned short *p_seq,
|
|
H245_ACC_REJ_MUX_T rej_mux,
|
|
DWORD *p_rej_cnt,
|
|
DWORD *p_acc_cnt)
|
|
{
|
|
UINT ii; /* generic counter */
|
|
MultiplexEntrySend *p_ASN_mux; /* ans1 mux entry */
|
|
MultiplexEntryDescriptorLink p_ASN_med_desc_lnk; /* asn1 mux entry descriptor */
|
|
int mux_entry; /* current mux entry descc */
|
|
H245_MUX_TABLE_T *p_mux_table_list = NULL;
|
|
|
|
ASSERT(p_pdu_ind->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(p_pdu_ind->u.MltmdSystmCntrlMssg_rqst.choice == multiplexEntrySend_chosen);
|
|
|
|
/* initialize rej_mux */
|
|
for (ii=0;ii<15;ii++)
|
|
{
|
|
rej_mux[ii].AccRej = H245_ACC;
|
|
rej_mux[ii].MuxEntryId = 0;
|
|
}
|
|
*p_rej_cnt = 0;
|
|
*p_acc_cnt = 0;
|
|
|
|
p_ASN_mux = &(p_pdu_ind->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend);
|
|
|
|
/* get sequence number */
|
|
*p_seq = p_ASN_mux->sequenceNumber;
|
|
|
|
/* this should never happen.. */
|
|
if (!(p_ASN_mux->multiplexEntryDescriptors))
|
|
return NULL;
|
|
|
|
/* for each descriptor.. ie mux table entry */
|
|
for (p_ASN_med_desc_lnk = p_ASN_mux->multiplexEntryDescriptors, mux_entry=0;
|
|
p_ASN_med_desc_lnk;
|
|
p_ASN_med_desc_lnk = p_ASN_med_desc_lnk->next, mux_entry++)
|
|
{
|
|
/* remove descriptor from table */
|
|
H245_MUX_TABLE_T *p_mux_table;
|
|
H245_MUX_TABLE_T *p_mux_table_lst = NULL;
|
|
|
|
if (!(p_mux_table = (H245_MUX_TABLE_T *)MemAlloc(sizeof(H245_MUX_TABLE_T))))
|
|
{
|
|
/* houston.. we have a problem !!!!!!!! */
|
|
/* rejet this one.. */
|
|
/* and move on.. */
|
|
|
|
rej_mux[mux_entry].MuxEntryId = p_ASN_med_desc_lnk->value.multiplexTableEntryNumber;
|
|
rej_mux[mux_entry].AccRej = H245_REJ;
|
|
(*p_rej_cnt)++;
|
|
continue;
|
|
}
|
|
|
|
/* zero it out */
|
|
memset (p_mux_table, 0, sizeof(H245_MUX_TABLE_T));
|
|
|
|
/* assign mux table entry */
|
|
rej_mux[mux_entry].MuxEntryId = (DWORD)
|
|
p_mux_table->MuxEntryId =
|
|
p_ASN_med_desc_lnk->value.multiplexTableEntryNumber;
|
|
|
|
/* if element is not present */
|
|
if (p_ASN_med_desc_lnk->value.bit_mask != elementList_present)
|
|
{
|
|
p_mux_table->pMuxTblEntryElem = NULL;
|
|
rej_mux[mux_entry].AccRej = H245_ACC;
|
|
(*p_acc_cnt)++;
|
|
}
|
|
/* if element list present */
|
|
else
|
|
{
|
|
H245_MUX_ENTRY_ELEMENT_T *p_mux_el_lst = NULL;
|
|
H245_MUX_ENTRY_ELEMENT_T *p_mux_el_tmp = NULL;
|
|
|
|
/* start if off.. w/ ok */
|
|
rej_mux[mux_entry].AccRej = H245_ACC;
|
|
|
|
/* for each element in the element list.. */
|
|
/* build the subelements.. if error .. free */
|
|
/* what youve done so far.. and break out */
|
|
for (ii=0;
|
|
ii < p_ASN_med_desc_lnk->value.elementList.count;
|
|
ii++)
|
|
{
|
|
/* if any of the elements fail.. flag the entry w/ reject reason */
|
|
/* (this is done inside the build_element_list..) */
|
|
/* and break out.. continue on with the next descriptor */
|
|
if (!(p_mux_el_tmp = build_element_list_from_mux (&(p_ASN_med_desc_lnk->value.elementList.value[ii]),&(rej_mux[mux_entry].AccRej))))
|
|
{
|
|
/* free the list.. */
|
|
free_mux_el_list (p_mux_table->pMuxTblEntryElem);
|
|
break;
|
|
}
|
|
|
|
/* ***************************** */
|
|
/* LINK IN THE MUX ENTRY ELEMENT */
|
|
/* ***************************** */
|
|
|
|
/* if first time through */
|
|
if (!p_mux_el_lst)
|
|
p_mux_table->pMuxTblEntryElem = p_mux_el_tmp;
|
|
/* otherwize .. just tag on the end */
|
|
else
|
|
p_mux_el_lst->pNext = p_mux_el_tmp;
|
|
|
|
p_mux_el_lst = p_mux_el_tmp;
|
|
|
|
} /* for each element in descriptor list */
|
|
|
|
} /* if element list present */
|
|
|
|
/* if you've accepted the mux table entry descriptor */
|
|
if (rej_mux[mux_entry].AccRej == H245_ACC)
|
|
{
|
|
/* indicate an accept */
|
|
(*p_acc_cnt)++;
|
|
|
|
/* ******************************** */
|
|
/* LINK IN THE MUX TABLE DESCRIPTOR */
|
|
/* ******************************** */
|
|
|
|
/* first table entry on the list.. (first time through) */
|
|
if (!p_mux_table_list)
|
|
p_mux_table_list = p_mux_table;
|
|
else
|
|
p_mux_table_lst->pNext = p_mux_table;
|
|
|
|
p_mux_table_lst = p_mux_table;
|
|
}
|
|
else
|
|
{
|
|
/* indicate a reject */
|
|
(*p_rej_cnt)++;
|
|
|
|
/* otherwise.. free it and move on to something better */
|
|
MemFree(p_mux_table);
|
|
}
|
|
|
|
} /* for each desriptor in the list */
|
|
|
|
return p_mux_table_list;
|
|
|
|
} /* procedure */
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_term_cap_set_ind__cap_table
|
|
*
|
|
* DESCRIPTION allocates a new cap link and copies the capabiliites.
|
|
* links into the tiven capabilityTableLink, and if
|
|
* Parameters are NONSTANDARD does some gymnastics to copy
|
|
* data so it can be used..
|
|
*
|
|
* NOTE: Copied data must be freed when capability is deleted.
|
|
* see where the capability is deleted for exceptions
|
|
* for "NONSTD" parameter sets .. (this is not pretty)
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static HRESULT
|
|
process_term_cap_set_ind__cap_table ( struct InstanceStruct *pInstance,
|
|
struct TerminalCapabilitySet *pTermCapSet,
|
|
CapabilityTableLink pCapLink,
|
|
MltmdSystmCntrlMssg *p_pdu_rsp)
|
|
{
|
|
H245_TOTCAP_T totcap;
|
|
CapabilityTableLink pNewLink;
|
|
HRESULT lError;
|
|
|
|
while (pCapLink)
|
|
{
|
|
if (build_totcap_from_captbl (&totcap,
|
|
pCapLink,
|
|
H245_REMOTE) == H245_ERROR_OK)
|
|
{
|
|
/* ok.. assume the CapId is set.. find it in the remote table */
|
|
/* if it exists, delete it so we can add new one in it's place */
|
|
pNewLink = find_capid_by_entrynumber( pTermCapSet, totcap.CapId);
|
|
if (pNewLink)
|
|
{
|
|
del_cap_link ( pTermCapSet, pNewLink );
|
|
}
|
|
|
|
/* ok.. if you've deleted the cap.. now see if there is a new one to take it's place */
|
|
if (pCapLink->value.bit_mask & capability_present)
|
|
{
|
|
/* load and link into remote table entry */
|
|
pNewLink = alloc_link_cap_entry (pTermCapSet);
|
|
if (!pNewLink)
|
|
{
|
|
return H245_ERROR_NORESOURCE;
|
|
}
|
|
|
|
/* copy the cap over to the remote entry */
|
|
pNewLink->value = pCapLink->value;
|
|
|
|
// If it's nonstandard, the above didn't work, so fix it up...
|
|
lError = H245_ERROR_OK;
|
|
switch (pCapLink->value.capability.choice)
|
|
{
|
|
case Capability_nonStandard_chosen:
|
|
lError = CopyNonStandardParameter(&pNewLink->value.capability.u.Capability_nonStandard,
|
|
&pCapLink->value.capability.u.Capability_nonStandard);
|
|
break;
|
|
|
|
case receiveVideoCapability_chosen:
|
|
case transmitVideoCapability_chosen:
|
|
case rcvAndTrnsmtVdCpblty_chosen:
|
|
if (pCapLink->value.capability.u.receiveVideoCapability.choice == VdCpblty_nonStandard_chosen)
|
|
{
|
|
lError = CopyNonStandardParameter(&pNewLink->value.capability.u.receiveVideoCapability.u.VdCpblty_nonStandard,
|
|
&pCapLink->value.capability.u.receiveVideoCapability.u.VdCpblty_nonStandard);
|
|
}
|
|
break;
|
|
|
|
case receiveAudioCapability_chosen:
|
|
case transmitAudioCapability_chosen:
|
|
case rcvAndTrnsmtAdCpblty_chosen:
|
|
if (pCapLink->value.capability.u.receiveAudioCapability.choice == AdCpblty_nonStandard_chosen)
|
|
{
|
|
lError = CopyNonStandardParameter(&pNewLink->value.capability.u.receiveAudioCapability.u.AdCpblty_nonStandard,
|
|
&pCapLink->value.capability.u.receiveAudioCapability.u.AdCpblty_nonStandard);
|
|
}
|
|
break;
|
|
|
|
case rcvDtApplctnCpblty_chosen:
|
|
case trnsmtDtApplctnCpblty_chosen:
|
|
case rATDACy_chosen :
|
|
if (pCapLink->value.capability.u.rcvDtApplctnCpblty.application.choice == DACy_applctn_nnStndrd_chosen)
|
|
{
|
|
lError = CopyNonStandardParameter(&pNewLink->value.capability.u.rcvDtApplctnCpblty.application.u.DACy_applctn_nnStndrd,
|
|
&pCapLink->value.capability.u.rcvDtApplctnCpblty.application.u.DACy_applctn_nnStndrd);
|
|
}
|
|
break;
|
|
|
|
} // switch
|
|
if (lError != H245_ERROR_OK)
|
|
return lError;
|
|
} /* if capability_present */
|
|
} /* if build_totcap_from_captbl succeeded */
|
|
|
|
pCapLink = pCapLink->next;
|
|
} /* for all entries in link */
|
|
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_term_cap_set_ind__cap_desc
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static HRESULT
|
|
process_term_cap_set_ind__cap_desc (struct InstanceStruct *pInstance,
|
|
struct TerminalCapabilitySet *pTermCapSet,
|
|
CapabilityDescriptor *pReqCapDesc,
|
|
MltmdSystmCntrlMssg *p_pdu_rsp)
|
|
{
|
|
unsigned int uCapDescNumber;
|
|
CapabilityDescriptor *pCapDesc;
|
|
unsigned int uCapDesc;
|
|
SmltnsCpbltsLink pSimCap;
|
|
SmltnsCpbltsLink pReqSimCap;
|
|
CapabilityDescriptor TempCapDesc;
|
|
unsigned int uSimCount;
|
|
unsigned int uReqAltCount;
|
|
unsigned int uReqAltCap;
|
|
unsigned int uAltCap;
|
|
HRESULT lError = H245_ERROR_OK;
|
|
|
|
uCapDescNumber = pReqCapDesc->capabilityDescriptorNumber & 255;
|
|
H245TRACE(pInstance->dwInst,20,"API:process_term_cap_set_ind - Remote Capability Descriptor #%d", uCapDescNumber);
|
|
|
|
// Find corresponding capability descriptor
|
|
pCapDesc = NULL;
|
|
for (uCapDesc = 0; uCapDesc < pTermCapSet->capabilityDescriptors.count; ++uCapDesc)
|
|
{
|
|
if (pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber == uCapDescNumber)
|
|
{
|
|
// Deallocate old simultaneous capabilities
|
|
pCapDesc = &pTermCapSet->capabilityDescriptors.value[uCapDesc];
|
|
if (pCapDesc->smltnsCpblts)
|
|
dealloc_simultaneous_cap(pCapDesc);
|
|
break;
|
|
} // if
|
|
} // for
|
|
|
|
if (pCapDesc == NULL)
|
|
{
|
|
// Allocate a new terminal capability descriptor
|
|
ASSERT(pTermCapSet->capabilityDescriptors.count < 256);
|
|
pCapDesc = &pTermCapSet->capabilityDescriptors.value[pTermCapSet->capabilityDescriptors.count++];
|
|
}
|
|
|
|
ASSERT(pCapDesc->smltnsCpblts == NULL);
|
|
if (!(pReqCapDesc->bit_mask & smltnsCpblts_present))
|
|
{
|
|
// Delete the terminal capability descriptor
|
|
pTermCapSet->capabilityDescriptors.count--;
|
|
*pCapDesc = pTermCapSet->capabilityDescriptors.value[pTermCapSet->capabilityDescriptors.count];
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
// Make a copy of the (volatile) new capability descriptor
|
|
pCapDesc->bit_mask = 0;
|
|
pCapDesc->capabilityDescriptorNumber = (CapabilityDescriptorNumber)uCapDescNumber;
|
|
pCapDesc->smltnsCpblts = NULL;
|
|
|
|
// We copy the linked list to a temporary so that it
|
|
// gets reversed twice and ends up in same order
|
|
TempCapDesc.smltnsCpblts = NULL;
|
|
uSimCount = 0;
|
|
pReqSimCap = pReqCapDesc->smltnsCpblts;
|
|
while (pReqSimCap)
|
|
{
|
|
// Allocate a new simultaneous capability list element
|
|
pSimCap = MemAlloc(sizeof(*pSimCap));
|
|
if (pSimCap == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"API:process_term_cap_set_ind: malloc failed");
|
|
lError = H245_ERROR_NOMEM;
|
|
break;
|
|
}
|
|
|
|
// Verify that each alternative capability in the request
|
|
// simultaneous capability is valid
|
|
// if so, copy it
|
|
uAltCap = 0;
|
|
uReqAltCount = pReqSimCap->value.count;
|
|
for (uReqAltCap = 0; uReqAltCap < uReqAltCount; ++uReqAltCap)
|
|
{
|
|
// Is the Capability in the remote Capability Table?
|
|
if (find_capid_by_entrynumber (pTermCapSet, pReqSimCap->value.value[uReqAltCap]) == NULL)
|
|
{
|
|
// can't find the Capability
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - Remote Capability Table Entry #%d not found",
|
|
pReqSimCap->value.value[uReqAltCap]);
|
|
lError = H245_ERROR_UNKNOWN;
|
|
}
|
|
else if (uAltCap >= H245_MAX_ALTCAPS)
|
|
{
|
|
// Exceeded arbitrary limit
|
|
H245TRACE(pInstance->dwInst,1,
|
|
"API:process_term_cap_set_ind - Too many alternative capabilities (%d)",
|
|
uAltCap);
|
|
lError = H245_ERROR_NORESOURCE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Copy the capability number
|
|
pSimCap->value.value[uAltCap++] = pReqSimCap->value.value[uReqAltCap];
|
|
}
|
|
} /* for alternative capbilities */
|
|
|
|
if (uAltCap)
|
|
{
|
|
// Verify that we have not exceeded arbitrary limit
|
|
if (++uSimCount > H245_MAX_SIMCAPS)
|
|
{
|
|
// Exceeded arbitrary limit
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"API:process_term_cap_set_ind - Too many simultaneous capabilities (%d)",
|
|
uSimCount);
|
|
MemFree(pSimCap);
|
|
lError = H245_ERROR_NORESOURCE;
|
|
}
|
|
else
|
|
{
|
|
// Add new simultaneous capability to the temporary list
|
|
pSimCap->value.count = (unsigned short)uAltCap;
|
|
pSimCap->next = TempCapDesc.smltnsCpblts;
|
|
TempCapDesc.smltnsCpblts = pSimCap;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"API:process_term_cap_set_ind - No valid alternative capabilities found");
|
|
MemFree(pSimCap);
|
|
lError = H245_ERROR_UNKNOWN;
|
|
}
|
|
|
|
pReqSimCap = pReqSimCap->next;
|
|
} // while
|
|
|
|
while (TempCapDesc.smltnsCpblts)
|
|
{
|
|
// Move elements from temporary to final linked list
|
|
pSimCap = TempCapDesc.smltnsCpblts;
|
|
TempCapDesc.smltnsCpblts = pSimCap->next;
|
|
pSimCap->next = pCapDesc->smltnsCpblts;
|
|
pCapDesc->smltnsCpblts = pSimCap;
|
|
}
|
|
|
|
// Error if no simultaneous capabilities found
|
|
if (pCapDesc->smltnsCpblts)
|
|
{
|
|
pCapDesc->bit_mask |= smltnsCpblts_present;
|
|
}
|
|
else
|
|
{
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"API:process_term_cap_set_ind - No simultaneous capabilities found");
|
|
lError = H245_ERROR_UNKNOWN;
|
|
}
|
|
|
|
return lError;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_term_cap_set_ind__mux_cap
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
* NOTES:
|
|
* We do a copy to set up a capability structure, then do another copy via
|
|
* H245CopyCap() to create a copy of the capability because the structure
|
|
* given to us by the ASN.1 decoded may contain pointers to data which will
|
|
* be deallocated upon return.
|
|
*
|
|
*****************************************************************************/
|
|
static HRESULT
|
|
process_term_cap_set_ind__mux_cap (struct InstanceStruct *pInstance,
|
|
struct TerminalCapabilitySet *pTermCapSet,
|
|
MultiplexCapability * pReqMuxCap,
|
|
MltmdSystmCntrlMssg *p_pdu_rsp)
|
|
{
|
|
H245_TOTCAP_T TotCap;
|
|
|
|
// Initialize temporary capability structure
|
|
memset(&TotCap, 0, sizeof(TotCap));
|
|
TotCap.Dir = H245_CAPDIR_RMTRXTX;
|
|
TotCap.DataType = H245_DATA_MUX;
|
|
|
|
// Get rid of old remote multiplex capability, if any
|
|
if (pTermCapSet->bit_mask & multiplexCapability_present)
|
|
{
|
|
del_mux_cap(pTermCapSet);
|
|
}
|
|
|
|
switch (pReqMuxCap->choice)
|
|
{
|
|
case MltplxCpblty_nonStandard_chosen:
|
|
// Save a copy of the multiplex capability
|
|
TotCap.Cap.H245Mux_NONSTD = pReqMuxCap->u.MltplxCpblty_nonStandard;
|
|
TotCap.ClientType = H245_CLIENT_MUX_NONSTD;
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind__mux_cap - Nonstandard Mux not yet supported");
|
|
break;
|
|
|
|
case h222Capability_chosen:
|
|
// Save a copy of the multiplex capability
|
|
TotCap.Cap.H245Mux_H222 = pReqMuxCap->u.h222Capability;
|
|
TotCap.ClientType = H245_CLIENT_MUX_H222;
|
|
break;
|
|
|
|
case h223Capability_chosen:
|
|
// Save a copy of the multiplex capability
|
|
TotCap.Cap.H245Mux_H223 = pReqMuxCap->u.h223Capability;
|
|
TotCap.ClientType = H245_CLIENT_MUX_H223;
|
|
break;
|
|
|
|
case v76Capability_chosen:
|
|
// Save a copy of the multiplex capability
|
|
TotCap.Cap.H245Mux_VGMUX = pReqMuxCap->u.v76Capability;
|
|
TotCap.ClientType = H245_CLIENT_MUX_VGMUX;
|
|
break;
|
|
|
|
case h2250Capability_chosen:
|
|
// Save a copy of the multiplex capability
|
|
TotCap.Cap.H245Mux_H2250 = pReqMuxCap->u.h2250Capability;
|
|
TotCap.ClientType = H245_CLIENT_MUX_H2250;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind__mux_cap - invalid mux cap type %d",
|
|
&pReqMuxCap->choice);
|
|
return H245_ERROR_NOSUP;
|
|
}
|
|
|
|
return set_mux_cap(pInstance, pTermCapSet, &TotCap);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_term_cap_set_ind
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
**************************************************************
|
|
*
|
|
* (TBD) .. this module will ack all terminal capbilities
|
|
* need to build reject.. (maybe later??)
|
|
*
|
|
* THIS IS A BIG TBD
|
|
*
|
|
**************************************************************
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
static HRESULT
|
|
process_term_cap_set_ind (struct InstanceStruct *pInstance,
|
|
MltmdSystmCntrlMssg *p_pdu_req,
|
|
MltmdSystmCntrlMssg *p_pdu_rsp)
|
|
{
|
|
HRESULT lError = H245_ERROR_OK;
|
|
TerminalCapabilitySet *pTermCapSet;
|
|
|
|
ASSERT (p_pdu_req->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.choice == terminalCapabilitySet_chosen);
|
|
H245TRACE(pInstance->dwInst,10,"API:process_term_cap_set_ind <-");
|
|
|
|
/* build ack response */
|
|
p_pdu_rsp->choice = MSCMg_rspns_chosen;
|
|
p_pdu_rsp->u.MSCMg_rspns.choice = terminalCapabilitySetAck_chosen;
|
|
p_pdu_rsp->u.MSCMg_rspns.u.terminalCapabilitySetAck.sequenceNumber =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.sequenceNumber;
|
|
|
|
pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
|
|
//***************************
|
|
// Deal with Capability Table
|
|
//***************************
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & capabilityTable_present)
|
|
{
|
|
CapabilityTableLink pCapTable = p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable;
|
|
if (pCapTable->value.capability.choice == Capability_nonStandard_chosen &&
|
|
pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice == h221NonStandard_chosen &&
|
|
pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == 0xB5 &&
|
|
pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension == 0x42 &&
|
|
pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == 0x8080)
|
|
{
|
|
pInstance->bMasterSlaveKludge = TRUE;
|
|
pCapTable = pCapTable->next;
|
|
}
|
|
lError = process_term_cap_set_ind__cap_table(pInstance,
|
|
pTermCapSet,
|
|
pCapTable,
|
|
p_pdu_rsp);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - cap table error %s",map_api_error(lError));
|
|
/* (TBC) need to reject somehow */
|
|
}
|
|
} /* if Capability Table Present */
|
|
|
|
//**************************************
|
|
// Deal with Capability Descriptor Table
|
|
// i.e. simultaneous capabilities
|
|
// NOTE: these are not held in the remote terminal capbility set
|
|
//**************************************
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & capabilityDescriptors_present)
|
|
{
|
|
int des_cnt;
|
|
int ii;
|
|
|
|
des_cnt = p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityDescriptors.count;
|
|
H245TRACE(pInstance->dwInst,20,"API:process_term_cap_set_ind - %d Simultaneous Capabilities",des_cnt);
|
|
for (ii = 0; ii < des_cnt; ++ii)
|
|
{
|
|
lError = process_term_cap_set_ind__cap_desc (pInstance,
|
|
pTermCapSet,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.
|
|
terminalCapabilitySet.capabilityDescriptors.value[ii],
|
|
p_pdu_rsp);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - cap desc error %s",map_api_error(lError));
|
|
/* (TBC) need to reject somehow */
|
|
}
|
|
} /* for each descriptor */
|
|
} /* if capability descriptor present */
|
|
|
|
/**************************************/
|
|
/* Deal with Multiplex Capability set */
|
|
/**************************************/
|
|
/* NOTE: these are not held in the remote terminal capability set */
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & multiplexCapability_present)
|
|
{
|
|
/* send up the indication to the client for each new entry */
|
|
lError = process_term_cap_set_ind__mux_cap(pInstance,
|
|
pTermCapSet,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.
|
|
terminalCapabilitySet.multiplexCapability,
|
|
p_pdu_rsp);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - mux cap error %s",map_api_error(lError));
|
|
/* (TBC) need to reject somehow */
|
|
}
|
|
}
|
|
|
|
H245TRACE(pInstance->dwInst,10,"API:process_term_cap_set_ind -> OK");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_open_ind
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
* ASSUME:
|
|
* Callback must happen inside this routine since the
|
|
* datastructures passed back to the application are allocated
|
|
* in this moudle.
|
|
*
|
|
* Application will <<<COPY>>> the needed data structures when
|
|
* callback occurs..
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static HRESULT
|
|
process_open_ind (struct InstanceStruct *pInstance,
|
|
MltmdSystmCntrlMssg *p_pdu_req,
|
|
unsigned short *p_FwdChan, /* for return on error */
|
|
H245_ACC_REJ_T *p_AccRej, /* for return error */
|
|
H245_CONF_IND_T *p_conf_ind) /* out */
|
|
{
|
|
static H245_TOTCAP_T rx_totcap; /* for receive caps */
|
|
static H245_TOTCAP_T tx_totcap; /* for transmit caps */
|
|
static H245_MUX_T RxMux;
|
|
static H245_MUX_T TxMux;
|
|
unsigned short choice; /* tmp for type of cap to routine */
|
|
HRESULT lError;
|
|
Tracker_T *p_tracker;
|
|
|
|
H245TRACE(pInstance->dwInst,10,"API:process_open_ind <-");
|
|
|
|
*p_AccRej = H245_ACC;
|
|
|
|
/********************************/
|
|
/* check for forward parameters */
|
|
/********************************/
|
|
|
|
/* get forward Rx channel id */
|
|
p_conf_ind->u.Indication.u.IndOpen.RxChannel =
|
|
*p_FwdChan =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelNumber;
|
|
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - channel = %d",p_conf_ind->u.Indication.u.IndOpen.RxChannel);
|
|
|
|
/* get port number */
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.bit_mask & fLCPs_prtNmbr_present)
|
|
{
|
|
p_conf_ind->u.Indication.u.IndOpen.RxPort =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.fLCPs_prtNmbr;
|
|
}
|
|
else
|
|
p_conf_ind->u.Indication.u.IndOpen.RxPort = H245_INVALID_PORT_NUMBER;
|
|
|
|
/* ok.. forward data type selection */
|
|
switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.dataType.choice)
|
|
{
|
|
case DataType_nonStandard_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx nonStandard");
|
|
/* (TBD) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
case nullData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx nullData");
|
|
/* (TBD) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
break;
|
|
case DataType_videoData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx videoData");
|
|
p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_VIDEO;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
|
|
u.DataType_videoData.choice;
|
|
break;
|
|
case DataType_audioData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx audioData");
|
|
p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_AUDIO;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
|
|
u.DataType_audioData.choice;
|
|
break;
|
|
case DataType_data_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx dataData");
|
|
p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_DATA;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
|
|
u.DataType_data.application.choice;
|
|
break;
|
|
case encryptionData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx encryptionData");
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
break;
|
|
default:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx encryptionData");
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_UNKNOWN;
|
|
return H245_ERROR_NOSUP;
|
|
break;
|
|
}
|
|
|
|
/* load the tot cap's capability and client from capability */
|
|
/* this will give us the client type and the Capability for the indication */
|
|
if ((lError = build_totcap_cap_n_client_from_capability ((struct Capability *)
|
|
&(p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.dataType),
|
|
p_conf_ind->u.Indication.u.IndOpen.RxDataType,
|
|
choice,
|
|
&rx_totcap)) != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return lError;
|
|
}
|
|
|
|
/* load it from the totcap you just built.. then toss it aside.. like an empty can of soda.. */
|
|
p_conf_ind->u.Indication.u.IndOpen.RxClientType = rx_totcap.ClientType;
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxCap = &(rx_totcap.Cap);
|
|
|
|
/* H.223/H.222 Mux table parameters for forward channel */
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxMux = &RxMux;
|
|
switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.choice)
|
|
{
|
|
case fLCPs_mPs_h223LCPs_chosen:
|
|
/* H.223 Logical Parameters */
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H223;
|
|
lError = load_H223_param(&RxMux.u.H223,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h223LCPs);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ_AL_COMB;
|
|
return lError;
|
|
}
|
|
break;
|
|
|
|
case fLCPs_mPs_h222LCPs_chosen:
|
|
/* H.222 Logical Parameters */
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H222;
|
|
lError = load_H222_param(&RxMux.u.H222,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h222LCPs);
|
|
break;
|
|
|
|
case fLCPs_mPs_v76LCPs_chosen:
|
|
/* VGMUX Logical Parameters */
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_VGMUX;
|
|
lError =load_VGMUX_param(&RxMux.u.VGMUX,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_v76LCPs);
|
|
break;
|
|
|
|
case fLCPs_mPs_h2250LCPs_chosen:
|
|
/* H.225.0 Logical Parameters */
|
|
p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H2250;
|
|
lError = load_H2250_param(&RxMux.u.H2250,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h2250LCPs);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_NOSUP;
|
|
} // switch
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ;
|
|
return lError;
|
|
}
|
|
|
|
/********************************/
|
|
/* check for reverse parameters */
|
|
/********************************/
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.bit_mask & OLCl_rLCPs_present)
|
|
{
|
|
switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.choice)
|
|
{
|
|
case DataType_nonStandard_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx nonStandard");
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
|
|
case nullData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx nullData");
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
break;
|
|
|
|
case DataType_videoData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx videoData");
|
|
p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_VIDEO;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_videoData.choice;
|
|
break;
|
|
|
|
case DataType_audioData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx audioData");
|
|
p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_AUDIO;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_audioData.choice;
|
|
break;
|
|
|
|
case DataType_data_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx dataData");
|
|
p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_DATA;
|
|
choice =
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_data.application.choice;
|
|
break;
|
|
|
|
case encryptionData_chosen:
|
|
H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx encryptionData");
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return H245_ERROR_NOSUP;
|
|
break;
|
|
|
|
default:
|
|
/* (TBC) what do I do here ?? */
|
|
*p_AccRej = H245_REJ_TYPE_UNKNOWN;
|
|
H245TRACE(pInstance->dwInst,1,"API:process_open_ind - unknown choice %d",
|
|
p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.choice);
|
|
return H245_ERROR_NOSUP;
|
|
}
|
|
|
|
/* load the tot cap's capability and client from capability */
|
|
if ((lError = build_totcap_cap_n_client_from_capability ((struct Capability *)
|
|
&(p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.OLCl_rLCPs.dataType),
|
|
p_conf_ind->u.Indication.u.IndOpen.TxDataType,
|
|
choice,
|
|
&tx_totcap)) != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
|
|
return lError;
|
|
}
|
|
|
|
p_conf_ind->u.Indication.u.IndOpen.TxClientType = tx_totcap.ClientType;
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxCap = &(tx_totcap.Cap);
|
|
|
|
/* if H223/H222 Mux table parameters for reverse channel availalbe */
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.OLCl_rLCPs.bit_mask & OLCl_rLCPs_mltplxPrmtrs_present)
|
|
{
|
|
switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.choice)
|
|
{
|
|
case rLCPs_mPs_h223LCPs_chosen:
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_H223;
|
|
lError = load_H223_param(&TxMux.u.H223,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
|
|
OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_h223LCPs);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ_AL_COMB;
|
|
return H245_ERROR_NOSUP;
|
|
}
|
|
break;
|
|
|
|
case rLCPs_mPs_v76LCPs_chosen:
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_VGMUX;
|
|
lError = load_VGMUX_param(&TxMux.u.VGMUX,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
|
|
OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_v76LCPs);
|
|
break;
|
|
|
|
case rLCPs_mPs_h2250LCPs_chosen:
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
|
|
p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_H2250;
|
|
lError = load_H2250_param(&TxMux.u.H2250,
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
|
|
OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_h2250LCPs);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_NOSUP;
|
|
}
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
*p_AccRej = H245_REJ;
|
|
return lError;
|
|
}
|
|
} /* if H223/H222 mux table reverse parameters */
|
|
|
|
} /* if reverse parameters present */
|
|
|
|
if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.bit_mask & OpnLgclChnnl_sprtStck_present)
|
|
{
|
|
p_conf_ind->u.Indication.u.IndOpen.pSeparateStack =
|
|
&p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OpnLgclChnnl_sprtStck;
|
|
}
|
|
|
|
|
|
/* conflict resolution .. just do it now.. */
|
|
/* only on opens.. of same data type .. */
|
|
|
|
#if 0
|
|
#ifndef LOOPBACK
|
|
/* if master */
|
|
if (pInstance->API.MasterSlave == APIMS_Master)
|
|
{
|
|
p_tracker = NULL;
|
|
while (p_tracker = find_tracker_by_type (dwInst, API_OPEN_CHANNEL_T, p_tracker))
|
|
{
|
|
/* if allocated locally .. and incoming */
|
|
/* data type == outstanding incoming */
|
|
/* there is a conflict */
|
|
|
|
if ((p_tracker->u.Channel.ChannelAlloc == API_CH_ALLOC_LCL) &&
|
|
(p_tracker->u.Channel.DataType == p_conf_ind->u.Indication.u.IndOpen.RxDataType))
|
|
{
|
|
*p_AccRej = H245_REJ;
|
|
return H245_ERROR_INVALID_OP;
|
|
|
|
} /* if conflict */
|
|
|
|
} /* while */
|
|
|
|
} /* if master */
|
|
|
|
#endif /* LOOPBACK */
|
|
#endif
|
|
/* setup a tracker for this guy. */
|
|
p_tracker = alloc_link_tracker (pInstance,
|
|
API_OPEN_CHANNEL_T,
|
|
0,
|
|
API_ST_WAIT_LCLACK,
|
|
API_CH_ALLOC_RMT,
|
|
(p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
|
|
u.openLogicalChannel.bit_mask & OLCl_rLCPs_present)?API_CH_TYPE_BI:API_CH_TYPE_UNI,
|
|
p_conf_ind->u.Indication.u.IndOpen.RxDataType,
|
|
H245_INVALID_CHANNEL,
|
|
p_conf_ind->u.Indication.u.IndOpen.RxChannel,
|
|
0);
|
|
|
|
if (!(p_tracker))
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:process_open_ind -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
*p_AccRej = H245_REJ;
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
H245TRACE(pInstance->dwInst,10,"API:process_open_ind -> OK");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Local
|
|
*
|
|
* PROCEDURE: process_bi_open_rsp
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
* ASSUME:
|
|
* Callback must happen inside this routine since the
|
|
* datastructures passed back to the application are allocated
|
|
* in this moudle.
|
|
*
|
|
* Application will <<<COPY>>> the needed data structures when
|
|
* callback occurs..
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static HRESULT
|
|
process_bi_open_rsp (struct InstanceStruct * pInstance, /* in */
|
|
MltmdSystmCntrlMssg *p_pdu_rsp, /* in */
|
|
H245_MUX_T *p_RxMux, /* in */
|
|
DWORD *p_RxChannel, /* out */
|
|
H245_CONF_IND_T *p_conf_ind /* out */
|
|
)
|
|
{
|
|
H245TRACE(pInstance->dwInst,10,"API:process_bi_open_rsp <-");
|
|
|
|
p_conf_ind->u.Confirm.Error = H245_ERROR_OK;
|
|
|
|
// Get Reverse Logical Channel Number
|
|
*p_RxChannel =
|
|
p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.RxChannel =
|
|
p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.reverseLogicalChannelNumber;
|
|
|
|
// Get Reverse Port Number
|
|
if (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.bit_mask & rLCPs_prtNmbr_present)
|
|
{
|
|
p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.RxPort =
|
|
p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.rLCPs_prtNmbr;
|
|
}
|
|
|
|
if (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.bit_mask & OLCAk_rLCPs_mPs_present)
|
|
{
|
|
// Get Reverse Logical Channel ACK Parameters
|
|
switch (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.choice)
|
|
{
|
|
case rLCPs_mPs_h222LCPs_chosen:
|
|
p_RxMux->Kind = H245_H222;
|
|
p_conf_ind->u.Confirm.Error = load_H222_param(&p_RxMux->u.H222,
|
|
&p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.u.rLCPs_mPs_h222LCPs);
|
|
p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.pRxMux = p_RxMux;
|
|
break;
|
|
|
|
case mPs_h2250LgclChnnlPrmtrs_chosen:
|
|
p_RxMux->Kind = H245_H2250ACK;
|
|
p_conf_ind->u.Confirm.Error = load_H2250_param(&p_RxMux->u.H2250,
|
|
&p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.u. mPs_h2250LgclChnnlPrmtrs);
|
|
p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.pRxMux = p_RxMux;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"API:process_bi_open_rsp - unknown choice %d",
|
|
p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.choice);
|
|
p_conf_ind->u.Confirm.Error = H245_ERROR_NOSUP;
|
|
} // switch
|
|
}
|
|
|
|
H245TRACE(pInstance->dwInst,10,"API:process_bi_open_rsp -> OK");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
WORD awObject[64];
|
|
|
|
unsigned int ArrayFromObject(WORD *pwObject, unsigned uSize, POBJECTID pObject)
|
|
{
|
|
register unsigned int uLength = 0;
|
|
while (pObject)
|
|
{
|
|
if (uLength >= uSize)
|
|
{
|
|
H245TRACE(0,1,"API:ArrayFromObject Object ID too long");
|
|
return uLength;
|
|
}
|
|
pwObject[uLength++] = (WORD) pObject->value;
|
|
pObject = pObject->next;
|
|
}
|
|
return uLength;
|
|
} // ArrayFromObject()
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: Callback
|
|
*
|
|
* PROCEDURE:
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static Tracker_T *
|
|
TrackerValidate(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:ValidateTracker -> Tracker Not Found");
|
|
return NULL;
|
|
}
|
|
|
|
return pTracker;
|
|
}
|
|
|
|
static DWORD_PTR
|
|
TranslateTransId(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TranslateTransId -> NULL Tracker");
|
|
return 0;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TranslateTransId -> Tracker Not Found");
|
|
return 0;
|
|
}
|
|
|
|
return pTracker->TransId;
|
|
}
|
|
|
|
static void
|
|
TrackerFree(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TrackerFree -> NULL Tracker");
|
|
return;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TrackerFree -> Tracker Not Found");
|
|
return;
|
|
}
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
}
|
|
|
|
static DWORD_PTR
|
|
TranslateAndFree(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TranslateAndFree -> NULL Tracker");
|
|
return 0;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TranslateAndFree -> Tracker Not Found");
|
|
return 0;
|
|
}
|
|
dwTransId = pTracker->TransId;
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
return dwTransId;
|
|
}
|
|
|
|
static void
|
|
TrackerNewState(struct InstanceStruct *pInstance, DWORD_PTR dwTransId, int nNewState)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TrackerNewState -> NULL Tracker");
|
|
return;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:TrackerNewState -> Tracker Not Found");
|
|
return;
|
|
}
|
|
pTracker->State = nNewState;
|
|
}
|
|
|
|
static WORD
|
|
GetRxChannel(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:GetRxChannel -> NULL Tracker");
|
|
return 0;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:GetRxChannel -> Tracker Not Found");
|
|
return 0;
|
|
}
|
|
|
|
return (WORD)pTracker->u.Channel.RxChannel;
|
|
}
|
|
|
|
static WORD
|
|
GetTxChannel(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
|
|
{
|
|
register Tracker_T *pTracker = (Tracker_T *)dwTransId;
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:GetTxChannel -> NULL Tracker");
|
|
return 0;
|
|
}
|
|
if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"API:GetTxChannel -> Tracker Not Found");
|
|
return 0;
|
|
}
|
|
|
|
return (WORD)pTracker->u.Channel.TxChannel;
|
|
}
|
|
|
|
HRESULT
|
|
H245FunctionNotUnderstood(struct InstanceStruct *pInstance, PDU_T *pPdu)
|
|
{
|
|
HRESULT hr = H245_ERROR_OK;
|
|
MltmdSystmCntrlMssg *pMmPdu = NULL;
|
|
|
|
pMmPdu = (MltmdSystmCntrlMssg *) MemAlloc(sizeof(MltmdSystmCntrlMssg));
|
|
if(NULL == pMmPdu)
|
|
{
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pMmPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
pMmPdu->choice = indication_chosen;
|
|
pMmPdu->u.indication.choice = functionNotUnderstood_chosen;
|
|
pMmPdu->u.indication.u.functionNotUnderstood.choice = pPdu->choice;
|
|
switch (pPdu->choice)
|
|
{
|
|
case FnctnNtUndrstd_request_chosen:
|
|
pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_request =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst;
|
|
break;
|
|
|
|
case FnctnNtUndrstd_response_chosen:
|
|
pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_response =
|
|
pPdu->u.MSCMg_rspns;
|
|
break;
|
|
|
|
case FnctnNtUndrstd_command_chosen:
|
|
pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_command =
|
|
pPdu->u.MSCMg_cmmnd;
|
|
default:
|
|
MemFree(pMmPdu);
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
hr = sendPDU(pInstance, pMmPdu);
|
|
MemFree(pMmPdu);
|
|
return hr;
|
|
} // H245FunctionNotUnderstood()
|
|
|
|
HRESULT
|
|
H245FsmConfirm (PDU_t * pPdu,
|
|
DWORD dwEvent,
|
|
struct InstanceStruct * pInstance,
|
|
DWORD_PTR dwTransId,
|
|
HRESULT lError)
|
|
{
|
|
H245_CONF_IND_T ConfInd;
|
|
DWORD dwIndex;
|
|
H245_MUX_T TxMux;
|
|
H245_MUX_T RxMux;
|
|
HRESULT lResult = H245_ERROR_OK;
|
|
|
|
ASSERT(pInstance != NULL);
|
|
ASSERT(pInstance->API.ConfIndCallBack != NULL);
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmConfirm <- Event=%s (%d)",
|
|
map_fsm_event(dwEvent),dwEvent);
|
|
|
|
memset (&ConfInd, 0, sizeof(ConfInd));
|
|
ConfInd.Kind = H245_CONF;
|
|
ConfInd.u.Confirm.Confirm = dwEvent;
|
|
ConfInd.u.Confirm.dwPreserved = pInstance->API.dwPreserved;
|
|
ConfInd.u.Confirm.dwTransId = dwTransId;
|
|
ConfInd.u.Confirm.Error = lError;
|
|
|
|
switch (dwEvent)
|
|
{
|
|
/******************************/
|
|
/* */
|
|
/* master slave determination */
|
|
/* */
|
|
/******************************/
|
|
case H245_CONF_INIT_MSTSLV:
|
|
ConfInd.u.Confirm.dwTransId = TranslateAndFree(pInstance, dwTransId);
|
|
|
|
/* handle errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == mstrSlvDtrmntnAck_chosen);
|
|
pInstance->API.SystemState = APIST_Connected;
|
|
if (pPdu->u.MSCMg_rspns.u.mstrSlvDtrmntnAck.decision.choice == master_chosen)
|
|
{
|
|
pInstance->API.MasterSlave = APIMS_Master;
|
|
ConfInd.u.Confirm.u.ConfMstSlv = H245_MASTER;
|
|
}
|
|
else
|
|
{
|
|
pInstance->API.MasterSlave = APIMS_Slave;
|
|
ConfInd.u.Confirm.u.ConfMstSlv = H245_SLAVE;
|
|
}
|
|
break;
|
|
|
|
case REJECT:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Master Slave Reject");
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
// case MS_FAILED:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Master Slave Error %d", lError);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* Terminal Capability exchange confirm */
|
|
/* */
|
|
/****************************************/
|
|
case H245_CONF_SEND_TERMCAP:
|
|
ConfInd.u.Confirm.dwTransId = TranslateAndFree(pInstance, dwTransId);
|
|
|
|
/* determine errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == terminalCapabilitySetAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfSndTcap.AccRej = H245_ACC;
|
|
clean_cap_table(&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
|
|
break;
|
|
|
|
case REJECT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_OK;
|
|
ConfInd.u.Confirm.u.ConfSndTcap.AccRej = H245_REJ;
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Term Cap Error %d", lError);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
/***************************************/
|
|
/* */
|
|
/* unidirectional logical channel open */
|
|
/* */
|
|
/***************************************/
|
|
case H245_CONF_OPEN:
|
|
ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
|
|
ConfInd.u.Confirm.u.ConfOpen.TxChannel = GetTxChannel(pInstance, dwTransId);
|
|
ConfInd.u.Confirm.u.ConfOpen.RxPort = H245_INVALID_PORT_NUMBER;
|
|
|
|
/* determine errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelAck_chosen);
|
|
ASSERT((pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_rLCPs_present) == 0);
|
|
|
|
if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_sprtStck_present)
|
|
{
|
|
ConfInd.u.Confirm.u.ConfOpen.pSeparateStack =
|
|
&pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_sprtStck;
|
|
}
|
|
|
|
if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & frwrdMltplxAckPrmtrs_present)
|
|
{
|
|
switch (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.choice)
|
|
{
|
|
case h2250LgclChnnlAckPrmtrs_chosen:
|
|
TxMux.Kind = H245_H2250ACK;
|
|
load_H2250ACK_param(&TxMux.u.H2250ACK,
|
|
&pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.u.h2250LgclChnnlAckPrmtrs);
|
|
ConfInd.u.Confirm.u.ConfOpen.pTxMux = &TxMux;
|
|
break;
|
|
|
|
} // switch
|
|
}
|
|
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_ACC;
|
|
TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
|
|
break;
|
|
|
|
case REJECT:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelReject_chosen);
|
|
|
|
ConfInd.u.Confirm.Error = H245_ERROR_OK;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej =
|
|
pPdu->u.MSCMg_rspns.u.openLogicalChannelReject.cause.choice;
|
|
TrackerFree(pInstance,dwTransId);
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
|
|
TrackerFree(pInstance,dwTransId);
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Open Channel Error %d", lError);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
|
|
TrackerFree(pInstance,dwTransId);
|
|
}
|
|
break;
|
|
|
|
/***********************************************/
|
|
/* */
|
|
/* bidirectional logical channel open (TBD)??? */
|
|
/* */
|
|
/***********************************************/
|
|
case H245_CONF_NEEDRSP_OPEN:
|
|
{
|
|
Tracker_T *pTracker;
|
|
|
|
pTracker = TrackerValidate(pInstance, dwTransId);
|
|
if (pTracker == NULL)
|
|
return H245_ERROR_OK;
|
|
|
|
ConfInd.u.Confirm.dwTransId = pTracker->TransId;
|
|
ConfInd.u.Confirm.u.ConfOpenNeedRsp.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
|
|
ConfInd.u.Confirm.u.ConfOpenNeedRsp.RxPort = H245_INVALID_PORT_NUMBER;
|
|
|
|
/* determine errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelAck_chosen);
|
|
ASSERT((pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_rLCPs_present) != 0);
|
|
|
|
ConfInd.u.Confirm.u.ConfOpenNeedRsp.AccRej = H245_ACC;
|
|
|
|
if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_sprtStck_present)
|
|
{
|
|
ConfInd.u.Confirm.u.ConfOpenNeedRsp.pSeparateStack =
|
|
&pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_sprtStck;
|
|
}
|
|
|
|
if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & frwrdMltplxAckPrmtrs_present)
|
|
{
|
|
switch (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.choice)
|
|
{
|
|
case h2250LgclChnnlAckPrmtrs_chosen:
|
|
TxMux.Kind = H245_H2250ACK;
|
|
load_H2250ACK_param(&TxMux.u.H2250ACK,
|
|
&pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.u.h2250LgclChnnlAckPrmtrs);
|
|
ConfInd.u.Confirm.u.ConfOpenNeedRsp.pTxMux = &TxMux;
|
|
break;
|
|
|
|
} // switch
|
|
}
|
|
|
|
/* NOTE Receive Channel is assigned in this call */
|
|
process_bi_open_rsp (pInstance,
|
|
pPdu,
|
|
&RxMux,
|
|
&(pTracker->u.Channel.RxChannel),
|
|
&ConfInd);
|
|
|
|
/* NOTE: this is a special case since we have to assign */
|
|
/* the receive channel to the tracker.. otherwise we */
|
|
/* will not be able to find it later.. */
|
|
/* Here we have to update both the state, and the channel */
|
|
pTracker->State = API_ST_WAIT_CONF;
|
|
break;
|
|
|
|
case REJECT:
|
|
ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
|
|
ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
|
|
ConfInd.u.Confirm.Error = H245_ERROR_OK;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej =
|
|
pPdu->u.MSCMg_rspns.u.openLogicalChannelReject.cause.choice;
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
|
|
ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Open Channel Error %d", lError);
|
|
ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
|
|
ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
}
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* unidirectional logical channel close */
|
|
/* */
|
|
/* bidirection logical channel close */
|
|
/* */
|
|
/************************************************/
|
|
case H245_CONF_CLOSE:
|
|
ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
|
|
ConfInd.u.Confirm.u.ConfClose.Channel = GetTxChannel(pInstance, dwTransId);
|
|
ConfInd.u.Confirm.u.ConfClose.AccRej = H245_ACC;
|
|
|
|
/* determine errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == closeLogicalChannelAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfClose.AccRej = H245_ACC;
|
|
TrackerFree(pInstance,dwTransId);
|
|
break;
|
|
|
|
case REJECT:
|
|
/* should never be rejected */
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Close Channel Rejected");
|
|
TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Close Channel Error %d", lError);
|
|
TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
|
|
}
|
|
break;
|
|
|
|
/***************************/
|
|
/* */
|
|
/* request channel close */
|
|
/* */
|
|
/***************************/
|
|
case H245_CONF_REQ_CLOSE:
|
|
ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
|
|
ConfInd.u.Confirm.u.ConfReqClose.Channel = GetRxChannel(pInstance, dwTransId);
|
|
TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
|
|
|
|
/* determine errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == requestChannelCloseAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_ACC;
|
|
break;
|
|
|
|
case REJECT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_OK;
|
|
ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Request Channel Close Error %d", lError);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
|
|
}
|
|
break;
|
|
|
|
/*******************/
|
|
/* */
|
|
/* mux table entry */
|
|
/* */
|
|
/*******************/
|
|
case H245_CONF_MUXTBL_SND:
|
|
{
|
|
UINT ii;
|
|
Tracker_T *pTracker;
|
|
|
|
pTracker = TrackerValidate(pInstance, dwTransId);
|
|
if (pTracker == NULL)
|
|
return H245_ERROR_OK;
|
|
|
|
ConfInd.u.Confirm.dwTransId = pTracker->TransId;
|
|
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == multiplexEntrySendAck_chosen);
|
|
for (ii = 0;
|
|
ii < pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck.multiplexTableEntryNumber.count;
|
|
ii ++)
|
|
{
|
|
pTracker->u.MuxEntryCount--;
|
|
ConfInd.u.Confirm.u.ConfMuxSnd.MuxEntryId =
|
|
pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck.multiplexTableEntryNumber.value[ii];
|
|
ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_ACC;
|
|
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
pTracker = TrackerValidate(pInstance, dwTransId);
|
|
if (pTracker == NULL)
|
|
return H245_ERROR_OK;
|
|
}
|
|
if (pTracker->u.MuxEntryCount == 0)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
}
|
|
pPdu = NULL; // Don't do callback again!
|
|
break;
|
|
|
|
case REJECT:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == multiplexEntrySendReject_chosen);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_OK;
|
|
for (ii = 0;
|
|
ii < pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.count;
|
|
++ii)
|
|
{
|
|
pTracker->u.MuxEntryCount--;
|
|
ConfInd.u.Confirm.u.ConfMuxSnd.MuxEntryId =
|
|
pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.value[ii].multiplexTableEntryNumber;
|
|
|
|
switch (pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.value[ii].cause.choice)
|
|
{
|
|
default:
|
|
H245PANIC();
|
|
case MERDs_cs_unspcfdCs_chosen:
|
|
ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_REJ; /* unspecified */
|
|
break;
|
|
case descriptorTooComplex_chosen:
|
|
ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_REJ_MUX_COMPLICATED;
|
|
break;
|
|
}
|
|
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
pTracker = TrackerValidate(pInstance, dwTransId);
|
|
if (pTracker == NULL)
|
|
return H245_ERROR_OK;
|
|
}
|
|
if (pTracker->u.MuxEntryCount == 0)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
}
|
|
pPdu = NULL; // Don't do callback again!
|
|
break;
|
|
|
|
case TIMER_EXPIRY:
|
|
case ERROR_D_TIMEOUT:
|
|
case ERROR_F_TIMEOUT:
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
|
|
break;
|
|
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Mux Table Send Error %d", lError);
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
|
|
} // switch
|
|
}
|
|
break;
|
|
|
|
case H245_CONF_RMESE:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == requestMultiplexEntryAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfRmese.dwCount =
|
|
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count;
|
|
for (dwIndex = 0; dwIndex < ConfInd.u.Confirm.u.ConfRmese.dwCount; ++dwIndex)
|
|
{
|
|
ConfInd.u.Confirm.u.ConfRmese.awMultiplexTableEntryNumbers[dwIndex] =
|
|
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex];
|
|
}
|
|
break;
|
|
|
|
case H245_CONF_RMESE_REJECT:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == rqstMltplxEntryRjct_chosen);
|
|
ConfInd.u.Confirm.u.ConfRmeseReject.dwCount =
|
|
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count;
|
|
for (dwIndex = 0; dwIndex < ConfInd.u.Confirm.u.ConfRmeseReject.dwCount; ++dwIndex)
|
|
{
|
|
ConfInd.u.Confirm.u.ConfRmeseReject.awMultiplexTableEntryNumbers[dwIndex] =
|
|
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber;
|
|
}
|
|
break;
|
|
|
|
case H245_CONF_RMESE_EXPIRED:
|
|
ASSERT(pPdu == NULL);
|
|
break;
|
|
|
|
case H245_CONF_MRSE:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == requestModeAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfMrse =
|
|
pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice;
|
|
break;
|
|
|
|
case H245_CONF_MRSE_REJECT:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == requestModeReject_chosen);
|
|
ConfInd.u.Confirm.u.ConfMrseReject =
|
|
pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice;
|
|
break;
|
|
|
|
case H245_CONF_MRSE_EXPIRED:
|
|
ASSERT(pPdu == NULL);
|
|
break;
|
|
|
|
case H245_CONF_MLSE:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == maintenanceLoopAck_chosen);
|
|
ConfInd.u.Confirm.u.ConfMlse.LoopType =
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice;
|
|
switch (pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice)
|
|
{
|
|
case systemLoop_chosen:
|
|
ConfInd.u.Confirm.u.ConfMlse.Channel = 0;
|
|
break;
|
|
|
|
case mediaLoop_chosen:
|
|
case logicalChannelLoop_chosen:
|
|
ConfInd.u.Confirm.u.ConfMlse.Channel =
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,
|
|
"H245FsmConfirm: Invalid Maintenance Loop Ack type %d",
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_CONF_MLSE_REJECT:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == maintenanceLoopReject_chosen);
|
|
ConfInd.u.Confirm.u.ConfMlseReject.LoopType =
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice;
|
|
switch (pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice)
|
|
{
|
|
case systemLoop_chosen:
|
|
ConfInd.u.Confirm.u.ConfMlseReject.Channel = 0;
|
|
break;
|
|
|
|
case mediaLoop_chosen:
|
|
case logicalChannelLoop_chosen:
|
|
ConfInd.u.Confirm.u.ConfMlseReject.Channel =
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,
|
|
"H245FsmConfirm: Invalid Maintenance Loop Reject type %d",
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_CONF_MLSE_EXPIRED:
|
|
ASSERT(pPdu == NULL);
|
|
break;
|
|
|
|
case H245_CONF_RTDSE:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == roundTripDelayResponse_chosen);
|
|
break;
|
|
|
|
case H245_CONF_RTDSE_EXPIRED:
|
|
ASSERT(pPdu == NULL);
|
|
break;
|
|
|
|
default:
|
|
/* Possible Error */
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmConfirm -> Invalid Confirm Event %d",
|
|
dwEvent);
|
|
return H245_ERROR_SUBSYS;
|
|
} // switch
|
|
|
|
if (lResult == H245_ERROR_OK)
|
|
{
|
|
if (pPdu)
|
|
{
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(*pInstance->API.ConfIndCallBack)(&ConfInd, NULL);
|
|
}
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmConfirm -> OK");
|
|
}
|
|
else
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmConfirm -> %s", map_api_error(lResult));
|
|
}
|
|
return lResult;
|
|
} // H245FsmConfirm()
|
|
|
|
|
|
|
|
HRESULT
|
|
H245FsmIndication (PDU_t * pPdu,
|
|
DWORD dwEvent,
|
|
struct InstanceStruct * pInstance,
|
|
DWORD_PTR dwTransId,
|
|
HRESULT lError)
|
|
{
|
|
H245_CONF_IND_T ConfInd;
|
|
DWORD dwIndex;
|
|
MltmdSystmCntrlMssg *pRsp;
|
|
HRESULT lResult = H245_ERROR_OK;
|
|
#if 1
|
|
int nLength;
|
|
WCHAR * pwchar = NULL;
|
|
#endif
|
|
|
|
ASSERT(dwEvent == H245_IND_OPEN_CONF || pPdu != NULL);
|
|
ASSERT(pInstance != NULL);
|
|
ASSERT(pInstance->API.ConfIndCallBack != NULL);
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication <- Event=%s (%d)",
|
|
map_fsm_event(dwEvent),dwEvent);
|
|
|
|
memset (&ConfInd, 0, sizeof(ConfInd));
|
|
ConfInd.Kind = H245_IND;
|
|
ConfInd.u.Indication.Indicator = dwEvent;
|
|
ConfInd.u.Indication.dwPreserved = pInstance->API.dwPreserved;
|
|
|
|
switch (dwEvent)
|
|
{
|
|
/******************************/
|
|
/* */
|
|
/* master slave determination */
|
|
/* */
|
|
/******************************/
|
|
case H245_IND_MSTSLV:
|
|
|
|
/* handle errors */
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == mstrSlvDtrmntnAck_chosen);
|
|
|
|
pInstance->API.SystemState = APIST_Connected;
|
|
if (pPdu->u.MSCMg_rspns.u.mstrSlvDtrmntnAck.decision.choice == master_chosen)
|
|
{
|
|
pInstance->API.MasterSlave = APIMS_Master;
|
|
ConfInd.u.Indication.u.IndMstSlv = H245_MASTER;
|
|
}
|
|
else
|
|
{
|
|
pInstance->API.MasterSlave = APIMS_Slave;
|
|
ConfInd.u.Indication.u.IndMstSlv = H245_SLAVE;
|
|
}
|
|
break;
|
|
|
|
case MS_FAILED:
|
|
case REJECT:
|
|
case TIMER_EXPIRY:
|
|
ConfInd.u.Indication.u.IndMstSlv = H245_INDETERMINATE;
|
|
break;
|
|
|
|
// case ERROR_D_TIMEOUT:
|
|
// case ERROR_F_TIMEOUT:
|
|
// case FUNCT_NOT_SUP:
|
|
// case ERROR_A_INAPPROPRIATE:
|
|
// case ERROR_B_INAPPROPRIATE:
|
|
// case ERROR_C_INAPPROPRIATE:
|
|
default:
|
|
H245PANIC();
|
|
/* (TBC) */
|
|
return H245_ERROR_OK;
|
|
}
|
|
break;
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* Terminal Capability exchange */
|
|
/* */
|
|
/****************************************/
|
|
/* decode_termcapset breaks the termcap set up and sends up */
|
|
/* a single indication to the client */
|
|
case H245_IND_CAP:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == terminalCapabilitySet_chosen);
|
|
pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
|
|
if (pRsp == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmIndication TermCap: no memory for response");
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pRsp, 0, sizeof(*pRsp));
|
|
process_term_cap_set_ind (pInstance, pPdu, pRsp);
|
|
FsmOutgoing(pInstance, pRsp, 0);
|
|
MemFree (pRsp);
|
|
break;
|
|
|
|
case H245_IND_CESE_RELEASE:
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* unidirectional logical channel open */
|
|
/* */
|
|
/* bidirectional logical channel open */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_OPEN:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == openLogicalChannel_chosen);
|
|
{
|
|
unsigned short forward_channel;
|
|
H245_ACC_REJ_T acc_rej;
|
|
|
|
/* if error, process_open_ind will tell us what to send for reject */
|
|
if (process_open_ind(pInstance,pPdu,&forward_channel,&acc_rej,&ConfInd) != H245_ERROR_OK)
|
|
{
|
|
// Reject the open
|
|
pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
|
|
if (pRsp == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmIndication TermCap: no memory for response");
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pRsp, 0, sizeof(*pRsp));
|
|
pdu_rsp_open_logical_channel_rej(pRsp, forward_channel, (WORD)acc_rej);
|
|
FsmOutgoing(pInstance, pRsp, 0);
|
|
MemFree (pRsp);
|
|
}
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* Confirm bi-directional open */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_OPEN_CONF:
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
ASSERT(pPdu != NULL);
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == opnLgclChnnlCnfrm_chosen);
|
|
}
|
|
#endif
|
|
{
|
|
Tracker_T *pTracker;
|
|
|
|
pTracker = TrackerValidate(pInstance, dwTransId);
|
|
if (pTracker == NULL)
|
|
return H245_ERROR_OK;
|
|
|
|
/* confirm processing */
|
|
ASSERT(pTracker->State == API_ST_WAIT_CONF);
|
|
ASSERT(pTracker->TrackerType == API_OPEN_CHANNEL_T);
|
|
ASSERT(pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
|
|
ASSERT(pTracker->u.Channel.ChannelType == API_CH_TYPE_BI);
|
|
|
|
ConfInd.u.Indication.u.IndOpenConf.RxChannel = (WORD)pTracker->u.Channel.RxChannel;
|
|
ConfInd.u.Indication.u.IndOpenConf.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
|
|
|
|
pTracker->State = API_ST_IDLE;
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* unidirectional logical channel close */
|
|
/* */
|
|
/* bidirectional logical channel close */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_CLOSE:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == closeLogicalChannel_chosen);
|
|
{
|
|
Tracker_T *pTracker;
|
|
|
|
ConfInd.u.Indication.u.IndClose.Channel =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.closeLogicalChannel.forwardLogicalChannelNumber;
|
|
ConfInd.u.Indication.u.IndClose.Reason =
|
|
(pPdu->u.MltmdSystmCntrlMssg_rqst.u.closeLogicalChannel.source.choice==user_chosen)?H245_USER:H245_LCSE;
|
|
|
|
/* find the tracker */
|
|
pTracker = find_tracker_by_rxchannel (pInstance,
|
|
ConfInd.u.Indication.u.IndClose.Channel,
|
|
API_CH_ALLOC_RMT);
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> close indication - Tracker not found");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* request channel close */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_REQ_CLOSE:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestChannelClose_chosen);
|
|
{
|
|
Tracker_T *pTracker;
|
|
|
|
ConfInd.u.Indication.u.IndReqClose =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestChannelClose.forwardLogicalChannelNumber;
|
|
|
|
/* find the tracker */
|
|
pTracker = find_tracker_by_txchannel (pInstance,
|
|
ConfInd.u.Indication.u.IndReqClose,
|
|
API_CH_ALLOC_LCL);
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication Request Channel Close: Tracker not found");
|
|
|
|
pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
|
|
if (pRsp == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmIndication Request Channel Close: no memory for response");
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pRsp, 0, sizeof(*pRsp));
|
|
|
|
/* can't find it.. must be closed.. respond anyway */
|
|
pdu_rsp_request_channel_close_rej(pRsp, (WORD)ConfInd.u.Indication.u.IndReqClose,H245_REJ);
|
|
FsmOutgoing(pInstance, pRsp, 0);
|
|
MemFree(pRsp);
|
|
/* Possible Error.. could have been removed from list or */
|
|
/* could have been allocated remotely... and this is a protocol */
|
|
/* error */
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
ASSERT(pTracker->State == API_ST_IDLE);
|
|
pTracker->State = API_ST_WAIT_LCLACK;
|
|
pTracker->TrackerType = API_CLOSE_CHANNEL_T;
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* Release Close Request */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_CLCSE_RELEASE:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == rqstChnnlClsRls_chosen);
|
|
{
|
|
Tracker_T *pTracker;
|
|
|
|
/* find tracker.. and set to LCLACK_CANCEL */
|
|
/* this will tell api to notify user */
|
|
|
|
pTracker = find_tracker_by_txchannel (pInstance,
|
|
pPdu->u.indication.u.rqstChnnlClsRls.forwardLogicalChannelNumber,
|
|
API_CH_ALLOC_LCL);
|
|
if (pTracker)
|
|
{
|
|
if (pTracker->State != API_ST_WAIT_LCLACK)
|
|
{
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pTracker->State = API_ST_WAIT_LCLACK_CANCEL;
|
|
}
|
|
else
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmIndication -> IND_REL_CLSE: Cancel.. NO TRACKER FOUND");
|
|
}
|
|
}
|
|
break;
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* mux table entry */
|
|
/* */
|
|
/************************************************/
|
|
case H245_IND_MUX_TBL:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == multiplexEntrySend_chosen);
|
|
{
|
|
unsigned short seq_num;
|
|
H245_ACC_REJ_MUX_T rej_mux;
|
|
H245_MUX_TABLE_T *p_mux_tbl;
|
|
DWORD rej_cnt;
|
|
DWORD acc_cnt;
|
|
Tracker_T *pTracker;
|
|
|
|
/* process the mux table entry */
|
|
p_mux_tbl = process_mux_table_ind(pPdu,&seq_num,rej_mux,&rej_cnt,&acc_cnt);
|
|
|
|
if (rej_cnt)
|
|
{
|
|
/* build the reject pdu from the rej_mux table */
|
|
if (!(pRsp = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
return H245_ERROR_NOMEM;
|
|
memset(pRsp, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
pdu_rsp_mux_table_rej (pRsp,seq_num,rej_mux,(rej_cnt+acc_cnt));
|
|
FsmOutgoing(pInstance, pRsp, 0);
|
|
MemFree(pRsp);
|
|
}
|
|
|
|
/* if there are any left to send up. */
|
|
if (p_mux_tbl)
|
|
{
|
|
if (!(pTracker = alloc_link_tracker (pInstance,
|
|
API_RECV_MUX_T,
|
|
/* use the TransId.. for the sequence number */
|
|
seq_num,
|
|
API_ST_WAIT_LCLACK,
|
|
API_CH_ALLOC_UNDEF,
|
|
API_CH_TYPE_UNDEF,
|
|
0,
|
|
H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
|
|
0)))
|
|
{
|
|
free_mux_table_list (p_mux_tbl);
|
|
H245TRACE(pInstance->dwInst,1,"API:process_open_ind -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
/* (TBC) this should be a fatal error */
|
|
H245PANIC();
|
|
break;
|
|
}
|
|
|
|
pTracker->u.MuxEntryCount = acc_cnt;
|
|
ConfInd.u.Indication.u.IndMuxTbl.Count = acc_cnt;
|
|
ConfInd.u.Indication.u.IndMuxTbl.pMuxTbl = p_mux_tbl;
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
free_mux_table_list (p_mux_tbl);
|
|
return H245_ERROR_OK;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H245_IND_MTSE_RELEASE:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == mltplxEntrySndRls_chosen);
|
|
break;
|
|
|
|
case H245_IND_RMESE:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestMultiplexEntry_chosen);
|
|
ConfInd.u.Indication.u.IndRmese.dwCount =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count;
|
|
for (dwIndex = 0; dwIndex < ConfInd.u.Indication.u.IndRmese.dwCount; ++dwIndex)
|
|
{
|
|
ConfInd.u.Indication.u.IndRmese.awMultiplexTableEntryNumbers[dwIndex] =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex];
|
|
}
|
|
break;
|
|
|
|
case H245_IND_RMESE_RELEASE:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == rqstMltplxEntryRls_chosen);
|
|
break;
|
|
|
|
case H245_IND_MRSE:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestMode_chosen);
|
|
ConfInd.u.Indication.u.IndMrse.pRequestedModes =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes;
|
|
break;
|
|
|
|
case H245_IND_MRSE_RELEASE:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == requestModeRelease_chosen);
|
|
break;
|
|
|
|
case H245_IND_MLSE:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == maintenanceLoopRequest_chosen);
|
|
ConfInd.u.Indication.u.IndMlse.LoopType =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice;
|
|
if (ConfInd.u.Indication.u.IndMlse.LoopType == systemLoop_chosen)
|
|
ConfInd.u.Indication.u.IndMlse.Channel = 0;
|
|
else
|
|
ConfInd.u.Indication.u.IndMlse.Channel =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop;
|
|
break;
|
|
|
|
case H245_IND_MLSE_RELEASE:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == mntnncLpOffCmmnd_chosen);
|
|
break;
|
|
|
|
case H245_IND_NONSTANDARD_REQUEST:
|
|
case H245_IND_NONSTANDARD_RESPONSE:
|
|
case H245_IND_NONSTANDARD_COMMAND:
|
|
case H245_IND_NONSTANDARD:
|
|
ConfInd.u.Indication.u.IndNonstandard.pData = pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value;
|
|
ConfInd.u.Indication.u.IndNonstandard.dwDataLength = pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length;
|
|
switch (pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice)
|
|
{
|
|
case object_chosen:
|
|
ConfInd.u.Indication.u.IndNonstandard.pwObjectId = awObject;
|
|
ConfInd.u.Indication.u.IndNonstandard.dwObjectIdLength =
|
|
ArrayFromObject(&awObject[0], sizeof(awObject)/sizeof(awObject[0]),
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object);
|
|
ConfInd.u.Indication.u.IndNonstandard.byCountryCode = 0;
|
|
ConfInd.u.Indication.u.IndNonstandard.byExtension = 0;
|
|
ConfInd.u.Indication.u.IndNonstandard.wManufacturerCode = 0;
|
|
break;
|
|
|
|
case h221NonStandard_chosen:
|
|
ConfInd.u.Indication.u.IndNonstandard.pwObjectId = NULL;
|
|
ConfInd.u.Indication.u.IndNonstandard.dwObjectIdLength = 0;
|
|
ConfInd.u.Indication.u.IndNonstandard.byCountryCode = (BYTE)
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode;
|
|
ConfInd.u.Indication.u.IndNonstandard.byExtension = (BYTE)
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension;
|
|
ConfInd.u.Indication.u.IndNonstandard.wManufacturerCode =
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst,1,
|
|
"H245FsmIndication: unrecognized nonstandard identifier type %d",
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_IND_MISC_COMMAND:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == miscellaneousCommand_chosen);
|
|
break;
|
|
|
|
case H245_IND_MISC:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == miscellaneousIndication_chosen);
|
|
break;
|
|
|
|
case H245_IND_COMM_MODE_REQUEST:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == communicationModeRequest_chosen);
|
|
break;
|
|
|
|
case H245_IND_COMM_MODE_RESPONSE:
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == cmmnctnMdRspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice == communicationModeTable_chosen);
|
|
{
|
|
unsigned int uCount;
|
|
CommunicationModeTableLink pLink;
|
|
H245_COMM_MODE_ENTRY_T * pTable;
|
|
|
|
uCount = 0;
|
|
pLink = pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable;
|
|
while (pLink)
|
|
{
|
|
++uCount;
|
|
pLink = pLink->next;
|
|
}
|
|
|
|
pTable = MemAlloc(uCount * sizeof(*pTable));
|
|
if (pTable)
|
|
{
|
|
ConfInd.u.Indication.u.IndCommRsp.pTable = pTable;
|
|
ConfInd.u.Indication.u.IndCommRsp.byTableCount = (BYTE)uCount;
|
|
pLink = pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable;
|
|
while (pLink)
|
|
{
|
|
lResult = LoadCommModeEntry(pTable, &pLink->value);
|
|
if (lResult != H245_ERROR_OK)
|
|
{
|
|
MemFree(pTable);
|
|
return lResult;
|
|
}
|
|
++pTable;
|
|
pLink = pLink->next;
|
|
}
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
MemFree(pTable);
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
lResult = H245_ERROR_NOMEM;
|
|
}
|
|
break;
|
|
|
|
case H245_IND_COMM_MODE_COMMAND:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == communicationModeCommand_chosen);
|
|
{
|
|
unsigned int uCount;
|
|
CommunicationModeCommandLink pLink;
|
|
H245_COMM_MODE_ENTRY_T * pTable;
|
|
|
|
uCount = 0;
|
|
pLink = pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable;
|
|
while (pLink)
|
|
{
|
|
++uCount;
|
|
pLink = pLink->next;
|
|
}
|
|
|
|
pTable = MemAlloc(uCount * sizeof(*pTable));
|
|
if (pTable)
|
|
{
|
|
ConfInd.u.Indication.u.IndCommCmd.pTable = pTable;
|
|
ConfInd.u.Indication.u.IndCommCmd.byTableCount = (BYTE)uCount;
|
|
pLink = pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable;
|
|
while (pLink)
|
|
{
|
|
lResult = LoadCommModeEntry(pTable, &pLink->value);
|
|
if (lResult != H245_ERROR_OK)
|
|
{
|
|
MemFree(pTable);
|
|
return lResult;
|
|
}
|
|
++pTable;
|
|
pLink = pLink->next;
|
|
}
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
MemFree(pTable);
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
lResult = H245_ERROR_NOMEM;
|
|
}
|
|
break;
|
|
|
|
case H245_IND_CONFERENCE_REQUEST:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == conferenceRequest_chosen);
|
|
ConfInd.u.Indication.u.IndConferReq.RequestType =
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice;
|
|
ConfInd.u.Indication.u.IndConferReq.byMcuNumber = (BYTE)
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber;
|
|
ConfInd.u.Indication.u.IndConferReq.byTerminalNumber = (BYTE)
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber;
|
|
break;
|
|
|
|
case H245_IND_CONFERENCE_RESPONSE:
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == conferenceResponse_chosen);
|
|
ConfInd.u.Indication.u.IndConferRsp.ResponseType =
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice;
|
|
switch (pPdu->u.MSCMg_rspns.u.conferenceResponse.choice)
|
|
{
|
|
case mCTerminalIDResponse_chosen:
|
|
case terminalIDResponse_chosen:
|
|
case conferenceIDResponse_chosen:
|
|
case passwordResponse_chosen:
|
|
ConfInd.u.Indication.u.IndConferRsp.byMcuNumber = (BYTE)
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber;
|
|
ConfInd.u.Indication.u.IndConferRsp.byTerminalNumber = (BYTE)
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber;
|
|
ConfInd.u.Indication.u.IndConferRsp.pOctetString =
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value;
|
|
ConfInd.u.Indication.u.IndConferRsp.byOctetStringLength = (BYTE)
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length;
|
|
break;
|
|
|
|
case terminalListResponse_chosen:
|
|
ConfInd.u.Indication.u.IndConferRsp.pTerminalList =
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value;
|
|
ConfInd.u.Indication.u.IndConferRsp.wTerminalListCount = (WORD)
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count;
|
|
break;
|
|
|
|
case videoCommandReject_chosen:
|
|
case terminalDropReject_chosen:
|
|
break;
|
|
|
|
case makeMeChairResponse_chosen:
|
|
switch (pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice)
|
|
{
|
|
case grantedChairToken_chosen:
|
|
ConfInd.u.Indication.u.IndConferRsp.ResponseType = H245_RSP_GRANTED_CHAIR_TOKEN;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid make me chair response %d",
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice);
|
|
|
|
// Fall-through to next case
|
|
|
|
case deniedChairToken_chosen:
|
|
ConfInd.u.Indication.u.IndConferRsp.ResponseType = H245_RSP_DENIED_CHAIR_TOKEN;
|
|
} // switch
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid Conference Response type %d",
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_IND_CONFERENCE_COMMAND:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == conferenceCommand_chosen);
|
|
ConfInd.u.Indication.u.IndConferCmd.CommandType =
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice;
|
|
ConfInd.u.Indication.u.IndConferCmd.Channel =
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl;
|
|
ConfInd.u.Indication.u.IndConferCmd.byMcuNumber = (BYTE)
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.sendThisSource.mcuNumber;
|
|
ConfInd.u.Indication.u.IndConferCmd.byTerminalNumber = (BYTE)
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.sendThisSource.terminalNumber;
|
|
break;
|
|
|
|
case H245_IND_CONFERENCE:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == conferenceIndication_chosen);
|
|
ConfInd.u.Indication.u.IndConfer.IndicationType =
|
|
pPdu->u.indication.u.conferenceIndication.choice;
|
|
ConfInd.u.Indication.u.IndConfer.bySbeNumber = (BYTE)
|
|
pPdu->u.indication.u.conferenceIndication.u.sbeNumber;
|
|
ConfInd.u.Indication.u.IndConfer.byMcuNumber = (BYTE)
|
|
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber;
|
|
ConfInd.u.Indication.u.IndConfer.byTerminalNumber = (BYTE)
|
|
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber;
|
|
break;
|
|
|
|
case H245_IND_SEND_TERMCAP:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == sndTrmnlCpbltySt_chosen);
|
|
break;
|
|
|
|
case H245_IND_ENCRYPTION:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == encryptionCommand_chosen);
|
|
break;
|
|
|
|
case H245_IND_FLOW_CONTROL:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == flowControlCommand_chosen);
|
|
ConfInd.u.Indication.u.IndFlowControl.Scope =
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice;
|
|
switch (pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice)
|
|
{
|
|
case FCCd_scp_lgclChnnlNmbr_chosen:
|
|
ConfInd.u.Indication.u.IndFlowControl.Channel =
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr;
|
|
break;
|
|
|
|
case FlwCntrlCmmnd_scp_rsrcID_chosen:
|
|
ConfInd.u.Indication.u.IndFlowControl.wResourceID =
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID;
|
|
break;
|
|
|
|
case FCCd_scp_whlMltplx_chosen:
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid Flow Control restriction %d",
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
switch (pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice)
|
|
{
|
|
case maximumBitRate_chosen:
|
|
ConfInd.u.Indication.u.IndFlowControl.dwRestriction =
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate;
|
|
break;
|
|
|
|
case noRestriction_chosen:
|
|
ConfInd.u.Indication.u.IndFlowControl.dwRestriction = H245_NO_RESTRICTION;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid Flow Control restriction %d",
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_IND_ENDSESSION:
|
|
ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
|
|
ASSERT(pPdu->u.MSCMg_cmmnd.choice == endSessionCommand_chosen);
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_DISCONNECT;
|
|
switch (pPdu->u.MSCMg_cmmnd.u.endSessionCommand.choice)
|
|
{
|
|
case EndSssnCmmnd_nonStandard_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_NONSTD,
|
|
ConfInd.u.Indication.u.IndEndSession.SessionNonStd =
|
|
pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.EndSssnCmmnd_nonStandard;
|
|
break;
|
|
case disconnect_chosen:
|
|
break;
|
|
case gstnOptions_chosen:
|
|
switch (pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.gstnOptions.choice)
|
|
{
|
|
case EndSessionCommand_gstnOptions_telephonyMode_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_TELEPHONY;
|
|
break;
|
|
case v8bis_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V8BIS;
|
|
break;
|
|
case v34DSVD_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34DSVD;
|
|
break;
|
|
case v34DuplexFAX_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34DUPFAX;
|
|
break;
|
|
case v34H324_chosen:
|
|
ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34H324;
|
|
break;
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid End Session GSTN options %d",
|
|
pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.gstnOptions.choice);
|
|
} // switch
|
|
break;
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: Invalid End Session type %d",
|
|
pPdu->u.MSCMg_cmmnd.u.endSessionCommand.choice);
|
|
} // switch
|
|
break;
|
|
|
|
case H245_IND_FUNCTION_NOT_UNDERSTOOD:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == functionNotUnderstood_chosen);
|
|
break;
|
|
|
|
case H245_IND_JITTER:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == jitterIndication_chosen);
|
|
break;
|
|
|
|
case H245_IND_H223_SKEW:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == h223SkewIndication_chosen);
|
|
ConfInd.u.Indication.u.IndH223Skew.LogicalChannelNumber1 =
|
|
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1;
|
|
ConfInd.u.Indication.u.IndH223Skew.LogicalChannelNumber2 =
|
|
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2;
|
|
ConfInd.u.Indication.u.IndH223Skew.wSkew =
|
|
pPdu->u.indication.u.h223SkewIndication.skew;
|
|
break;
|
|
|
|
case H245_IND_NEW_ATM_VC:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == newATMVCIndication_chosen);
|
|
break;
|
|
|
|
case H245_IND_USERINPUT:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == userInput_chosen);
|
|
ConfInd.u.Indication.u.IndUserInput.Kind =
|
|
pPdu->u.indication.u.userInput.choice;
|
|
switch (pPdu->u.indication.u.userInput.choice)
|
|
{
|
|
case UsrInptIndctn_nnStndrd_chosen:
|
|
ConfInd.u.Indication.u.IndUserInput.u.NonStd =
|
|
pPdu->u.indication.u.userInput.u.UsrInptIndctn_nnStndrd;
|
|
break;
|
|
case alphanumeric_chosen:
|
|
#if 1
|
|
nLength = MultiByteToWideChar(CP_ACP, // code page
|
|
0, // dwFlags
|
|
pPdu->u.indication.u.userInput.u.alphanumeric,
|
|
-1, // ASCII string length (in bytes)
|
|
NULL, // Unicode string
|
|
0); // max Unicode string length
|
|
pwchar = MemAlloc(nLength * sizeof(WCHAR));
|
|
if (pwchar == NULL)
|
|
{
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: no memory for user input", 0);
|
|
lResult = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
nLength = MultiByteToWideChar(CP_ACP, // code page
|
|
0, // dwFlags
|
|
pPdu->u.indication.u.userInput.u.alphanumeric,
|
|
-1, // ASCII string length (in bytes)
|
|
pwchar, // Unicode string
|
|
nLength); // max Unicode string length
|
|
ConfInd.u.Indication.u.IndUserInput.u.pGenString = pwchar;
|
|
}
|
|
#else
|
|
ConfInd.u.Indication.u.IndUserInput.u.pGenString =
|
|
pPdu->u.indication.u.userInput.u.alphanumeric;
|
|
#endif
|
|
break;
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: unrecognized user input type %d",
|
|
pPdu->u.indication.u.userInput.choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
break;
|
|
|
|
case H245_IND_H2250_MAX_SKEW:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == h2250MxmmSkwIndctn_chosen);
|
|
ConfInd.u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber1 =
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1;
|
|
ConfInd.u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber2 =
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2;
|
|
ConfInd.u.Indication.u.IndH2250MaxSkew.wSkew =
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew;
|
|
break;
|
|
|
|
case H245_IND_MC_LOCATION:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == mcLocationIndication_chosen);
|
|
lResult = LoadTransportAddress(&ConfInd.u.Indication.u.IndMcLocation,
|
|
&pPdu->u.indication.u.mcLocationIndication.signalAddress);
|
|
break;
|
|
|
|
case H245_IND_VENDOR_ID:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == vendorIdentification_chosen);
|
|
ConfInd.u.Indication.u.IndVendorId.Identifier =
|
|
pPdu->u.indication.u.vendorIdentification.vendor;
|
|
if (pPdu->u.indication.u.vendorIdentification.bit_mask & productNumber_present)
|
|
{
|
|
ConfInd.u.Indication.u.IndVendorId.pProductNumber =
|
|
pPdu->u.indication.u.vendorIdentification.productNumber.value;
|
|
ConfInd.u.Indication.u.IndVendorId.byProductNumberLength = (BYTE)
|
|
pPdu->u.indication.u.vendorIdentification.productNumber.length;
|
|
}
|
|
if (pPdu->u.indication.u.vendorIdentification.bit_mask & versionNumber_present)
|
|
{
|
|
ConfInd.u.Indication.u.IndVendorId.pVersionNumber =
|
|
pPdu->u.indication.u.vendorIdentification.versionNumber.value;
|
|
ConfInd.u.Indication.u.IndVendorId.byVersionNumberLength = (BYTE)
|
|
pPdu->u.indication.u.vendorIdentification.versionNumber.length;
|
|
}
|
|
break;
|
|
|
|
case H245_IND_FUNCTION_NOT_SUPPORTED:
|
|
ASSERT(pPdu->choice == indication_chosen);
|
|
ASSERT(pPdu->u.indication.choice == IndicationMessage_functionNotSupported_chosen);
|
|
ConfInd.u.Indication.u.IndFns.Cause =
|
|
pPdu->u.indication.u.functionNotSupported.cause.choice;
|
|
ConfInd.u.Indication.u.IndFns.Type = UNKNOWN;
|
|
|
|
/*if (pPdu->u.indication.u.functionNotSupported.bit_mask & returnedFunction_present)
|
|
{
|
|
int pduNum = MltmdSystmCntrlMssg_PDU;
|
|
OssBuf ossBuf;
|
|
MltmdSystmCntrlMssg *pPduReturned;
|
|
ossBuf.value = pPdu->u.indication.u.functionNotSupported.returnedFunction.value;
|
|
ossBuf.length = pPdu->u.indication.u.functionNotSupported.returnedFunction.length;
|
|
if (ossDecode(pInstance->p_ossWorld,
|
|
&pduNum,
|
|
&ossBuf,
|
|
(void * *)&pPduReturned) == PDU_DECODED)
|
|
{
|
|
switch (pPduReturned->choice)
|
|
{
|
|
case MltmdSystmCntrlMssg_rqst_chosen:
|
|
ConfInd.u.Indication.u.IndFns.Type =
|
|
pPduReturned->u.MltmdSystmCntrlMssg_rqst.choice -
|
|
RqstMssg_nonStandard_chosen + REQ_NONSTANDARD;
|
|
break;
|
|
case MSCMg_rspns_chosen:
|
|
ConfInd.u.Indication.u.IndFns.Type =
|
|
pPduReturned->u.MSCMg_rspns.choice -
|
|
RspnsMssg_nonStandard_chosen + RSP_NONSTANDARD;
|
|
break;
|
|
case MSCMg_cmmnd_chosen:
|
|
ConfInd.u.Indication.u.IndFns.Type =
|
|
pPduReturned->u.MSCMg_cmmnd.choice -
|
|
CmmndMssg_nonStandard_chosen + CMD_NONSTANDARD;
|
|
break;
|
|
case indication_chosen:
|
|
ConfInd.u.Indication.u.IndFns.Type =
|
|
pPduReturned->u.indication.choice -
|
|
IndctnMssg_nonStandard_chosen + IND_NONSTANDARD;
|
|
break;
|
|
default:
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication: unrecognized FunctionNotSupported message type %d",
|
|
pPduReturned->choice);
|
|
lResult = H245_ERROR_NOSUP;
|
|
} // switch
|
|
// Free the PDU
|
|
if (ossFreePDU(pInstance->p_ossWorld, pduNum, pPduReturned))
|
|
{
|
|
H245TRACE(pInstance->dwInst, 1, "H245FsmIndication: FREE FAILURE");
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
break;
|
|
#if(0) // this isn't in H245 Version 3. and this code did nothing with it anyway
|
|
case H245_IND_H223_RECONFIG:
|
|
ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
|
|
ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == h223AnnxARcnfgrtn_chosen);
|
|
break;
|
|
|
|
case H245_IND_H223_RECONFIG_ACK:
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == h223AnnxARcnfgrtnAck_chosen);
|
|
break;
|
|
|
|
case H245_IND_H223_RECONFIG_REJECT:
|
|
ASSERT(pPdu->choice == MSCMg_rspns_chosen);
|
|
ASSERT(pPdu->u.MSCMg_rspns.choice == h223AnnxARcnfgrtnRjct_chosen);
|
|
break;
|
|
#endif // if(0)
|
|
default:
|
|
/* Possible Error */
|
|
H245TRACE(pInstance->dwInst, 1,
|
|
"H245FsmIndication -> Invalid Indication Event %d", dwEvent);
|
|
lResult = H245_ERROR_SUBSYS;
|
|
} // switch
|
|
|
|
#if 1
|
|
if (pwchar)
|
|
MemFree(pwchar);
|
|
#endif
|
|
|
|
if (lResult == H245_ERROR_OK)
|
|
{
|
|
if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
|
|
{
|
|
H245FunctionNotUnderstood(pInstance, pPdu);
|
|
}
|
|
H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
|
|
}
|
|
else
|
|
{
|
|
H245TRACE(pInstance->dwInst,1,"H245FsmIndication -> %s", map_api_error(lResult));
|
|
}
|
|
return lResult;
|
|
} // H245FsmIndication()
|
|
|