windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/callcont/api_up.c
2020-09-26 16:20:57 +08:00

3735 lines
131 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
*
* 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;
}
H245FunctionNotUnderstood(struct InstanceStruct *pInstance, PDU_T *pPdu)
{
MltmdSystmCntrlMssg Pdu = {0};
Pdu.choice = indication_chosen;
Pdu.u.indication.choice = functionNotUnderstood_chosen;
Pdu.u.indication.u.functionNotUnderstood.choice = pPdu->choice;
switch (pPdu->choice)
{
case FnctnNtUndrstd_request_chosen:
Pdu.u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_request =
pPdu->u.MltmdSystmCntrlMssg_rqst;
break;
case FnctnNtUndrstd_response_chosen:
Pdu.u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_response =
pPdu->u.MSCMg_rspns;
break;
case FnctnNtUndrstd_command_chosen:
Pdu.u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_command =
pPdu->u.MSCMg_cmmnd;
default:
return H245_ERROR_OK;
}
return sendPDU(pInstance, &Pdu);
} // 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()