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