You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6323 lines
205 KiB
6323 lines
205 KiB
/******************************************************************************
|
|
*
|
|
* 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.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* AUTHOR: cjutzi (Curt Jutzi) Intel Corporation
|
|
*
|
|
* $Workfile: api_dwn.c $
|
|
* $Revision: 1.45 $
|
|
* $Modtime: 05 Mar 1997 09:53:36 $
|
|
* $Log: S:/STURGEON/SRC/H245/SRC/VCS/api_dwn.c_v $
|
|
*
|
|
* Rev 1.45 05 Mar 1997 09:56:04 MANDREWS
|
|
* Fixed compiler warning in release mode.
|
|
*
|
|
* Rev 1.44 04 Mar 1997 17:33:26 MANDREWS
|
|
* H245CopyCap() and H245CopyCapDescriptor() now return HRESULTs.
|
|
*
|
|
* Rev 1.43 26 Feb 1997 11:12:06 MANDREWS
|
|
* Fixed problem in assigning dynamic term cap IDs; the dynamic IDs were
|
|
* overlapping with static IDs.
|
|
*
|
|
* Rev 1.42 Feb 24 1997 18:30:18 tomitowx
|
|
* multiple modedescriptor support
|
|
*
|
|
* Rev 1.41 07 Feb 1997 15:33:58 EHOWARDX
|
|
* Changed H245DelCapDescriptor to match changes to set_cap_descriptor.
|
|
*
|
|
* Rev 1.40 27 Jan 1997 12:40:16 MANDREWS
|
|
*
|
|
* Fixed warnings.
|
|
*
|
|
* Rev 1.39 09 Jan 1997 19:17:04 EHOWARDX
|
|
*
|
|
* Initialize lError to H245_ERROR_OK to prevent "may be uninitialized"
|
|
* warning.
|
|
*
|
|
* Rev 1.38 19 Dec 1996 17:18:50 EHOWARDX
|
|
* Changed to use h245asn1.h definitions instead of _setof3 and _setof8.
|
|
*
|
|
* Rev 1.37 12 Dec 1996 15:57:22 EHOWARDX
|
|
* Master Slave Determination kludge.
|
|
*
|
|
* Rev 1.36 11 Dec 1996 13:55:44 SBELL1
|
|
* Changed H245Init parameters.
|
|
*
|
|
* Rev 1.35 17 Oct 1996 18:17:36 EHOWARDX
|
|
* Changed general string to always be Unicode.
|
|
*
|
|
* Rev 1.34 14 Oct 1996 14:01:26 EHOWARDX
|
|
* Unicode changes.
|
|
*
|
|
* Rev 1.33 11 Oct 1996 15:19:56 EHOWARDX
|
|
* Fixed H245CopyCap() bug.
|
|
*
|
|
* Rev 1.32 28 Aug 1996 11:37:10 EHOWARDX
|
|
* const changes.
|
|
*
|
|
* Rev 1.31 19 Aug 1996 16:28:36 EHOWARDX
|
|
* H245CommunicationModeResponse/H245CommunicationModeCommand bug fixes.
|
|
*
|
|
* Rev 1.30 15 Aug 1996 15:19:46 EHOWARDX
|
|
* First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews.
|
|
* Use at your own risk!
|
|
*
|
|
* Rev 1.29 08 Aug 1996 16:02:58 EHOWARDX
|
|
*
|
|
* Eliminated api_vers.h.
|
|
* Changed H245Init Debug trace to eliminate API_VERSION.
|
|
*
|
|
* Rev 1.28 19 Jul 1996 12:48:22 EHOWARDX
|
|
*
|
|
* Multipoint clean-up.
|
|
*
|
|
* Rev 1.27 01 Jul 1996 22:13:42 EHOWARDX
|
|
*
|
|
* Added Conference and CommunicationMode structures and functions.
|
|
*
|
|
* Rev 1.26 18 Jun 1996 14:53:16 EHOWARDX
|
|
* Eliminated Channel parameter to MaintenanceLoopRelease.
|
|
* Made Multiplex Capability mandatory -- H245SendTermCaps now returns
|
|
* H245_ERROR_NO_MUX_CAPS if no Multiplex Capability has been defined.
|
|
*
|
|
* Rev 1.25 14 Jun 1996 18:57:38 EHOWARDX
|
|
* Geneva update.
|
|
*
|
|
* Rev 1.24 10 Jun 1996 16:59:02 EHOWARDX
|
|
* Moved init/shutdown of submodules to CreateInstance/InstanceUnlock.
|
|
*
|
|
* Rev 1.23 06 Jun 1996 18:50:10 EHOWARDX
|
|
* Equivalent of H.324 bugs #808 and 875 fixed.
|
|
*
|
|
* Rev 1.22 05 Jun 1996 17:16:48 EHOWARDX
|
|
* MaintenanceLoop bug fix.
|
|
*
|
|
* Rev 1.21 04 Jun 1996 13:56:42 EHOWARDX
|
|
* Fixed Release build warnings.
|
|
*
|
|
* Rev 1.20 30 May 1996 23:38:52 EHOWARDX
|
|
* Cleanup.
|
|
*
|
|
* Rev 1.19 29 May 1996 16:08:04 unknown
|
|
* Fixed bug in copying nonstandard identifiers.
|
|
*
|
|
* Rev 1.18 29 May 1996 15:19:48 EHOWARDX
|
|
* Change to use HRESULT.
|
|
*
|
|
* Rev 1.17 28 May 1996 14:25:12 EHOWARDX
|
|
* Tel Aviv update.
|
|
*
|
|
* Rev 1.16 21 May 1996 15:46:54 EHOWARDX
|
|
* Fixed bugs in NonStandard messages using object identifier.
|
|
*
|
|
* Rev 1.15 20 May 1996 22:17:54 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.14 20 May 1996 14:35:12 EHOWARDX
|
|
* Got rid of asynchronous H245EndConnection/H245ShutDown stuff...
|
|
*
|
|
* Rev 1.13 17 May 1996 14:53:38 EHOWARDX
|
|
* Added calls to StartSystemClose() and EndSystemClose().
|
|
*
|
|
* Rev 1.12 16 May 1996 19:40:30 EHOWARDX
|
|
* Fixed multiplex capability bug.
|
|
*
|
|
* Rev 1.11 16 May 1996 16:36:10 EHOWARDX
|
|
* Fixed typo in H245SetCapDescriptor.
|
|
*
|
|
* Rev 1.10 16 May 1996 16:14:06 EHOWARDX
|
|
* Fixed backwards-compatibility problem in H245SetLocalCap
|
|
* (CapId of zero should result in dynamically-allocated cap id being used)
|
|
*
|
|
* Rev 1.9 16 May 1996 16:03:44 EHOWARDX
|
|
* Fixed typo in H245SetCapDescriptor.
|
|
*
|
|
* Rev 1.8 16 May 1996 15:58:32 EHOWARDX
|
|
* Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/
|
|
* H245DelCapDescriptor behaviour.
|
|
*
|
|
* Rev 1.7 15 May 1996 21:49:46 unknown
|
|
* Added call to InstanceLock() to increment lock count before call
|
|
* to InstanceDelete() in H245EndConnectionPhase2().
|
|
*
|
|
* Rev 1.6 15 May 1996 19:54:02 unknown
|
|
* Fixed H245SetCapDescriptor.
|
|
*
|
|
* Rev 1.5 14 May 1996 16:56:22 EHOWARDX
|
|
* Last minute change from H245_IND_CAPDESC_T to H245_TOTCAPDESC_T.
|
|
* H245EnumCaps() callback now uses H245_TOTCAPDESC_T instead
|
|
* of separate H245_CAPDESCID_T and H245_CAPDESC_T for consistency.
|
|
*
|
|
* Rev 1.4 14 May 1996 15:55:44 EHOWARDX
|
|
* Added mux cap handling to H245DelLocalCap.
|
|
*
|
|
* Rev 1.3 14 May 1996 14:06:06 EHOWARDX
|
|
* Fixed abort from H245EnumCaps - if Cap Callback returns non-zero,
|
|
* Cap Desc Callback is never called.
|
|
*
|
|
* Rev 1.2 13 May 1996 23:16:42 EHOWARDX
|
|
* Fixed remote terminal capability handling.
|
|
*
|
|
* Rev 1.1 11 May 1996 20:32:52 EHOWARDX
|
|
* Checking in for the night...
|
|
*
|
|
* Rev 1.0 09 May 1996 21:06:06 EHOWARDX
|
|
* Initial revision.
|
|
*
|
|
* Rev 1.25.1.10 09 May 1996 19:31:02 EHOWARDX
|
|
* Redesigned thread locking logic.
|
|
* Added new API functions.
|
|
*
|
|
* Rev 1.25.1.9 01 May 1996 19:31:16 EHOWARDX
|
|
* Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux().
|
|
* Changed H2250_xxx definitions for H.225.0 address types to H245_xxx.
|
|
*
|
|
* Rev 1.25.1.8 27 Apr 1996 21:09:20 EHOWARDX
|
|
* Changed Channel Numbers to words, added H.225.0 support.
|
|
*
|
|
* Rev 1.25.1.7 25 Apr 1996 20:06:26 EHOWARDX
|
|
* Moved setting of EndSessionPdu in EndSessionPhase1 to before call to api_fs
|
|
*
|
|
* Rev 1.25.1.6 25 Apr 1996 17:57:00 EHOWARDX
|
|
* Added dwTxPort argument to H245OpenChannel().
|
|
*
|
|
* Rev 1.25.1.5 25 Apr 1996 16:51:00 EHOWARDX
|
|
* Function changes as per H.245 API Changes spec.
|
|
*
|
|
* Rev 1.25.1.4 24 Apr 1996 20:54:32 EHOWARDX
|
|
* Added new OpenLogicalChannelAck/OpenLogicalChannelReject support.
|
|
*
|
|
* Rev 1.25.1.3 19 Apr 1996 12:54:40 EHOWARDX
|
|
* Updated to 1.30
|
|
*
|
|
* Rev 1.25.1.2 15 Apr 1996 15:10:48 EHOWARDX
|
|
* Updated to match Curt's current version.
|
|
*
|
|
* Rev 1.25.1.1 03 Apr 1996 17:12:50 EHOWARDX
|
|
* Integrated latest H.323 changes.
|
|
*
|
|
* Rev 1.25.1.0 03 Apr 1996 15:53:42 cjutzi
|
|
* Branched for H.323.
|
|
*
|
|
* Rev 1.20 27 Mar 1996 15:25:34 cjutzi
|
|
* - fixed a bug from this morning checkin dynamically allocating
|
|
* pdu's.. free_mux_tbl was getting called after pdu was free'd..
|
|
* this was a problem since the mux table pointer was in the pdu
|
|
*
|
|
* Rev 1.19 27 Mar 1996 08:37:08 cjutzi
|
|
*
|
|
* - removed PDU from stack.. made them dynamically allocated
|
|
*
|
|
* Rev 1.18 20 Mar 1996 14:47:32 cjutzi
|
|
* - added ERROR H245_ERROR_NO_CAPDESC to SendTermCaps.
|
|
*
|
|
* Rev 1.17 18 Mar 1996 15:23:16 cjutzi
|
|
*
|
|
*
|
|
*
|
|
* Rev 1.16 13 Mar 1996 09:15:44 cjutzi
|
|
*
|
|
* - changed LLPCRITICAL_SECTION to CRITICAL_SECTION *
|
|
*
|
|
* Rev 1.15 12 Mar 1996 15:51:48 cjutzi
|
|
*
|
|
* - implemented locking
|
|
* - fixed callback bug w/ clenaup on term caps..
|
|
* - implemented End Session
|
|
* - fixed shutdown
|
|
*
|
|
* Rev 1.14 08 Mar 1996 14:02:48 cjutzi
|
|
*
|
|
* - removed H245SetSimultaneous stuff..
|
|
* - added H245SetCapDescriptor Stuff..
|
|
* - completeed MuxTable Entry Stuff.
|
|
* - required H223 -or- some portion of MuxCapbilities to be
|
|
* there before you issue SendCaps..
|
|
* - NOTE: need to inforce the Simultaneous capabilities in
|
|
* the same mannor..
|
|
*
|
|
* Rev 1.13 05 Mar 1996 17:35:38 cjutzi
|
|
*
|
|
* - implemented SendMultiplexTable..
|
|
* - removed bcopy/bzero and changed free call
|
|
* - added master slave indication
|
|
*
|
|
* Rev 1.12 01 Mar 1996 13:48:24 cjutzi
|
|
*
|
|
* - added hani's new fsm id's
|
|
* - added some support for release on close request.
|
|
*
|
|
* Rev 1.11 29 Feb 1996 17:27:10 cjutzi
|
|
*
|
|
* - bi-directional channel working..
|
|
*
|
|
* Rev 1.10 29 Feb 1996 08:35:52 cjutzi
|
|
*
|
|
* - added p_ossWorld to initialization
|
|
*
|
|
* Rev 1.9 27 Feb 1996 13:30:18 cjutzi
|
|
*
|
|
* - fixed master slave problem with conf_ind and tracker type
|
|
* - removed RSP_LCSE in close channel resp
|
|
*
|
|
* Rev 1.8 26 Feb 1996 17:23:18 cjutzi
|
|
*
|
|
* - MiscCommand API added
|
|
* - Fixed Assert for H245Init.. was not NULL'n out the pointers for the
|
|
* context blocks..
|
|
*
|
|
* Rev 1.7 26 Feb 1996 11:05:16 cjutzi
|
|
*
|
|
* - added simultaneous caps.. and fixed bugs..
|
|
* lot's of changes..
|
|
*
|
|
* Rev 1.6 16 Feb 1996 13:01:08 cjutzi
|
|
*
|
|
* - got open / close / request close working in both directions.
|
|
*
|
|
* Rev 1.5 15 Feb 1996 14:42:54 cjutzi
|
|
*
|
|
* - fixed trace level bind w/ Instance.. no other change but had to
|
|
* add when h245deb.c when in..
|
|
*
|
|
*
|
|
* Rev 1.4 15 Feb 1996 10:50:54 cjutzi
|
|
*
|
|
* - termcaps working
|
|
* - changed API interface for MUX_T
|
|
* - changed callback or IND_OPEN
|
|
* - changed constants IND_OPEN/IND_OPEN_NEEDRSP etc..
|
|
* - cleaned up the open.. (not complete yet.. )
|
|
*
|
|
* Rev 1.3 09 Feb 1996 16:58:36 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 *****/
|
|
/**** *****/
|
|
/**** NOTE: *****/
|
|
/**** Headers are documented, however they may or may not *****/
|
|
/**** coorispond to reality. See the H245Spec.doc from Intel for the *****/
|
|
/**** current :-> H245 specification *****/
|
|
/**** *****/
|
|
/**** DISCLAMER: *****/
|
|
/**** *****/
|
|
/**** Since this code wasn't developed in Word 7.0, I am fully *****/
|
|
/**** responsable for all spelling mistakes in the comments. Please *****/
|
|
/**** disregard the spelling mistakes.. or fix them, if you are *****/
|
|
/**** currently modifying the code. *****/
|
|
/**** *****/
|
|
/**** - Thankyou *****/
|
|
/**** *****/
|
|
/**** Curt Jutzi *****/
|
|
/**** Oregon, USA *****/
|
|
/**** *****/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
|
|
#ifndef STRICT
|
|
#define STRICT
|
|
#endif
|
|
|
|
#include "precomp.h"
|
|
|
|
/***********************/
|
|
/* H245 INCLUDES */
|
|
/***********************/
|
|
#define H245DLL_EXPORT
|
|
#include "h245api.h"
|
|
#include "h245com.h"
|
|
#include "h245sys.x"
|
|
|
|
#include "api_util.x"
|
|
#include "pdu.x"
|
|
#include "fsmexpor.h"
|
|
#include "api_debu.x"
|
|
#include "sr_api.h"
|
|
#include "h245deb.x"
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245Init
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* H245_INST_T H245Init (
|
|
* H245_CONF_T Configuration,
|
|
* DWORD dwH245PhysId,
|
|
* DWORD dwLinkLayerPhysId,
|
|
* DWORD dwPreserved,
|
|
* H245_CONF_IND_CALLBACK_T Callback
|
|
* )
|
|
* Description:
|
|
*
|
|
* Called to create an H.245 instance and its related sublayers
|
|
* (e.g., SRP). This function must be called before any other
|
|
* API calls may be called The current H.245 implementation can
|
|
* only have, at most, one client. Therefore H245Init can only be
|
|
* called once per physical ID.
|
|
* Input
|
|
*
|
|
* Configuration Indicates the type of configuration the client
|
|
* wishes to establish, e.g. H.324, H.323, H.310,
|
|
* or DSVD.
|
|
* dwH245PhysId Parameter identifying the H245 entry
|
|
* pdwLinkLayerPhysId
|
|
* Output parameter identifying the linkLayer
|
|
* entry.
|
|
* dwPreserved Parameter that may be used by H.245 client to
|
|
* provide context, passed back to client in all
|
|
* confirms and indications.
|
|
* Callback Callback routine supplied by the client which
|
|
* will be used by the H.245 subsystem to convey
|
|
* confirm and indication messages back to the
|
|
* client.
|
|
* Call Type:
|
|
*
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
*
|
|
* Return value of 0 indicates Failure
|
|
* Return value of non 0 is a valid H245_INST_T
|
|
*
|
|
* Errors:
|
|
* N/A
|
|
*
|
|
* See Also:
|
|
* H245EndSession
|
|
* H245Shutdown
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL H245_INST_T
|
|
H245Init (
|
|
H245_CONFIG_T Configuration,
|
|
unsigned long dwH245PhysId,
|
|
unsigned long *pdwLinkLayerPhysId,
|
|
DWORD_PTR dwPreserved,
|
|
H245_CONF_IND_CALLBACK_T CallBack,
|
|
unsigned char byTerminalType
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
|
|
H245TRACE(dwH245PhysId,4,"H245Init(%d, 0x%x, 0x%x, 0x%x, %d) <-",
|
|
Configuration, dwH245PhysId, dwPreserved, CallBack, byTerminalType);
|
|
|
|
switch (Configuration)
|
|
{
|
|
case H245_CONF_H324:
|
|
case H245_CONF_H323:
|
|
break;
|
|
|
|
default:
|
|
H245TRACE(dwH245PhysId,1,"H245Init -> Invalid Configuration %d", Configuration);
|
|
return H245_INVALID_ID;
|
|
} // switch
|
|
|
|
if (CallBack == NULL)
|
|
{
|
|
H245TRACE(dwH245PhysId,1,"H245Init -> Null CallBack");
|
|
return H245_INVALID_ID;
|
|
}
|
|
|
|
/* see if this physical identifier has been initialized already */
|
|
// Send down H245PhysId that was input.
|
|
pInstance = InstanceCreate(dwH245PhysId, Configuration);
|
|
if (pInstance == NULL)
|
|
{
|
|
return H245_INVALID_ID;
|
|
}
|
|
|
|
// Get the linkLayer PhysId.
|
|
*pdwLinkLayerPhysId = pInstance->SendReceive.hLinkLayerInstance;
|
|
|
|
// Initialize instance API structure
|
|
pInstance->API.dwPreserved = dwPreserved;
|
|
pInstance->API.ConfIndCallBack = CallBack;
|
|
|
|
// Initialize instance FSM structure
|
|
pInstance->StateMachine.sv_TT = byTerminalType;
|
|
pInstance->StateMachine.sv_STATUS = INDETERMINATE;
|
|
|
|
H245TRACE(pInstance->dwInst,4,"H245Init -> %d", pInstance->dwInst);
|
|
lError = pInstance->dwInst;
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245Init()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245EndSession
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* Yes.. this should be explained.. Since Send Receive needs
|
|
* to flush some buffers and send out an End Session.. what we've
|
|
* hopefully done is a 2 phase shut down...
|
|
*
|
|
* call StartSessionClose which initiates the flush..
|
|
* when flush is complete EndSessionPhase1 is called..
|
|
* The end session pdu is then placed in the send queue..
|
|
* When the End Session Pdu is sent.. the EndSession Phase
|
|
* 2 is called, and the result is sent up to the client..
|
|
*
|
|
* Hope that helps..
|
|
*
|
|
*
|
|
* HRESULT H245EndSession ( H245_INST_T dwInst,
|
|
* H245_ENDSESSION_T Mode,
|
|
* H245_NONSTANDARD_T *pNonStd (*optional*)
|
|
* )
|
|
*
|
|
* Description:
|
|
* Called to shutdown the peer to peer session between this H.245
|
|
* session and the remote peers H.245 layer.
|
|
*
|
|
* It will terminate by issuing an EndSession command to the
|
|
* remote side and call end session for all the H.245 subsystems.
|
|
* All resources are returned; therefore no further action is
|
|
* permitted, except H245ShutDown until another H245Init API call
|
|
* is made.
|
|
*
|
|
* input
|
|
* dwInst Instance handle returned by H245Init
|
|
* Mode Mode which the client wishes to terminat
|
|
* the session
|
|
* pNonStd If the mode is non standard this is the non
|
|
* standard parameter passes to the remote client.
|
|
* This parameter is optional, and should be set
|
|
* to NULL if not used
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM
|
|
* H245_ERROR_INVALID_INST
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* See Also:
|
|
* H245Shutdown
|
|
* H245Init
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245EndSession (
|
|
H245_INST_T dwInst,
|
|
H245_ENDSESSION_T Mode,
|
|
const H245_NONSTANDARD_PARAMETER_T * pNonStd
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register MltmdSystmCntrlMssg *pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245EndSession <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in either connecting or connected */
|
|
|
|
switch (pInstance->API.SystemState)
|
|
{
|
|
case APIST_Connecting:
|
|
case APIST_Connected:
|
|
break;
|
|
|
|
default:
|
|
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
// Allocate the PDU buffer
|
|
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
// Build the PDU
|
|
lError = pdu_cmd_end_session (pPdu, Mode, pNonStd);
|
|
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Send the PDU
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
}
|
|
|
|
// Free the PDU buffer
|
|
MemFree(pPdu);
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(lError));
|
|
}
|
|
else
|
|
{
|
|
H245TRACE (dwInst,4,"H245EndSession -> OK");
|
|
pInstance->API.SystemState = APIST_Disconnected;
|
|
}
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245EndSession()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245ShutDown
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245Shutdown ( H245_INST_T dwInst);
|
|
*
|
|
* Description:
|
|
*
|
|
* Called to terminate the specified instance of H.245. If there
|
|
* is currently an active session (see H245Init) then the H.245
|
|
* subsystem will issue an EndSession to the other side and wait
|
|
* for H.245 sublayer termination notifications before it queues
|
|
* Callback confirm.
|
|
*
|
|
* This call will force the client to issue another H245Init
|
|
* before it can use any of the H.245 API functions.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
*
|
|
* Call Type:
|
|
* asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
*
|
|
* See Also:
|
|
* H245Init
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245ShutDown (H245_INST_T dwInst)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245ShutDown <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ShutDown -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
switch (pInstance->API.SystemState)
|
|
{
|
|
case APIST_Connecting:
|
|
case APIST_Connected:
|
|
lError = H245EndSession(dwInst,H245_ENDSESSION_DISCONNECT,NULL);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_OK;
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245ShutDown -> %s", map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245ShutDown -> OK");
|
|
InstanceDelete (pInstance);
|
|
return H245_ERROR_OK;
|
|
} // H245ShutDown()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245InitMasterSlave
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245InitMasterSlave ( H245_INST_T dwInst,
|
|
* DWORD dwTransId )
|
|
*
|
|
* Description:
|
|
* Called to initiate the H.245 master slave negotiation.
|
|
* Upon completion of the negotiation the local client will
|
|
* receive an H245_CONF_INIT_MSTSLV message indicating the
|
|
* result of the negotiation.
|
|
* Input
|
|
* dwInst Instance handle returned by
|
|
* H245GetInstanceId
|
|
* dwTransId User supplied object used to identify this
|
|
* request in the asynchronous response to
|
|
* this call.
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callbacks:
|
|
* H245_CONF_INIT_MSTSLV
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK Master Slave Determination started
|
|
* H245_ERROR_INPROCESS Master Slave Determination currently
|
|
* in process
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_INPROCESS In process
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
*
|
|
* See Also:
|
|
* H245Init
|
|
*
|
|
* callbacks
|
|
* H245_IND_MSTSLV
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245InitMasterSlave (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId
|
|
)
|
|
{
|
|
struct InstanceStruct *pInstance;
|
|
Tracker_T *pTracker;
|
|
HRESULT lError;
|
|
MltmdSystmCntrlMssg *pPdu = NULL;
|
|
|
|
/* check for valid instance handle */
|
|
|
|
H245TRACE (dwInst,4,"H245InitMasterSlave <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* if the transaction is in process.. tell client */
|
|
if (pInstance->API.MasterSlave == APIMS_InProcess)
|
|
{
|
|
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INPROCESS));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INPROCESS;
|
|
}
|
|
|
|
/* if the transaction is already complete */
|
|
if (pInstance->API.MasterSlave != APIMS_Undef)
|
|
{
|
|
if (pInstance->API.ConfIndCallBack)
|
|
{
|
|
H245_CONF_IND_T confirm_ind_event;
|
|
confirm_ind_event.Kind = H245_CONF;
|
|
confirm_ind_event.u.Confirm.Confirm = H245_CONF_INIT_MSTSLV;
|
|
confirm_ind_event.u.Confirm.dwPreserved = pInstance->API.dwPreserved;
|
|
confirm_ind_event.u.Confirm.dwTransId = dwTransId;
|
|
confirm_ind_event.u.Confirm.Error = H245_ERROR_OK;
|
|
confirm_ind_event.u.Confirm.u.ConfMstSlv =
|
|
(pInstance->API.MasterSlave == APIMS_Master) ? H245_MASTER : H245_SLAVE;
|
|
(*pInstance->API.ConfIndCallBack)(&confirm_ind_event, NULL);
|
|
}
|
|
H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
}
|
|
|
|
/* get somthing to keep track of what the heck you're doing.. */
|
|
if (!(pTracker = alloc_link_tracker (pInstance,
|
|
API_MSTSLV_T,
|
|
dwTransId,
|
|
API_ST_WAIT_RMTACK,
|
|
API_CH_ALLOC_UNDEF,
|
|
API_CH_TYPE_UNDEF,
|
|
0,
|
|
H245_INVALID_CHANNEL,
|
|
H245_INVALID_CHANNEL,
|
|
0)))
|
|
{
|
|
H245TRACE(dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
/* set master slave in process */
|
|
pInstance->API.SystemState = APIST_Connecting;
|
|
pInstance->API.MasterSlave = APIMS_InProcess;
|
|
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = masterSlaveDetermination_chosen;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
MemFree(pPdu);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(lError));
|
|
}
|
|
else
|
|
H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245InitMasterSlave()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245SetLocalCap
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245SetLocalCap (
|
|
* H245_INST_T dwInst,
|
|
* H245_TOTCAP_T *pTotCap,
|
|
* H245_CAPID_T *pCapId
|
|
* )
|
|
*
|
|
* Description:
|
|
* This function allows the client to define a specific
|
|
* capability to the H.245 subsystem. When this function is
|
|
* called a new capability entry is made in the local capability
|
|
* table. The returned value in *pCapId can be used by the client
|
|
* to refer to that registered capability. NULL in the *pCapId
|
|
* is valid.
|
|
*
|
|
* This call is used for both client (Audio / Video / Data / Mux)
|
|
* capabilities. It is not used for setting capability descriptors.
|
|
*
|
|
* Note:
|
|
* 7 This function does not communicate this update to the
|
|
* remote peer until the client calls H245SendTermCaps.
|
|
* 7 pTotCap->CapId is of no significance in this call.
|
|
*
|
|
* pTotCap->CapId is of no significance in this call and should
|
|
* be set to 0
|
|
*
|
|
* if DataType of H245_DATA_MUX is used (i.e. in setting the
|
|
* mux table capabilities) No capid is returned, and it can not
|
|
* be used in H245SetCapDescritptor api call.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by GetInstanceId
|
|
* pTotCap Capability set defining the capability
|
|
*
|
|
* Note: pTotCap->CapId is of no significance in this call.
|
|
*
|
|
* output
|
|
* pCapId Capability id which client can use to reference
|
|
* this capability in the H.245 subsystem. This can
|
|
* be NULL, in this case nothing is returned.
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* If pCap is not null, the local cap table id is returned
|
|
* to the client in this parameter.
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM There was an invalid parameter passed
|
|
* H245_ERROR_MAXTBL Entry not made because local cap table
|
|
* is full
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
*
|
|
* See Also:
|
|
* H245DelLocalCap
|
|
* H245EnumCaps
|
|
* H245SetCapDescriptor
|
|
*
|
|
*
|
|
* ASSUMPTION:
|
|
* pTotCap->CapId will be set to H245_INVALID_CAPID
|
|
* pTotCap->Dir will be set
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SetLocalCap (
|
|
H245_INST_T dwInst,
|
|
H245_TOTCAP_T * pTotCap,
|
|
H245_CAPID_T * pCapId
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
struct TerminalCapabilitySet *pTermCapSet;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245SetLocalCap <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* check for valid parameters */
|
|
if (pTotCap == NULL ||
|
|
pCapId == NULL ||
|
|
((*pCapId > H245_MAX_CAPID) && (*pCapId != H245_INVALID_CAPID)) ||
|
|
pTotCap->Dir < H245_CAPDIR_LCLRX ||
|
|
pTotCap->Dir > H245_CAPDIR_LCLRXTX ||
|
|
pTotCap->ClientType < H245_CLIENT_NONSTD ||
|
|
pTotCap->ClientType > H245_CLIENT_MUX_H2250)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
|
|
// Don't trust the user filled-in data type!
|
|
pTotCap->DataType = DataTypeMap[pTotCap->ClientType];
|
|
|
|
/* if it's a MUX type handle here */
|
|
if (pTotCap->DataType == H245_DATA_MUX)
|
|
{
|
|
// Add multiplex capability
|
|
if (pTermCapSet->bit_mask & multiplexCapability_present)
|
|
{
|
|
del_mux_cap(pTermCapSet);
|
|
}
|
|
|
|
*pCapId = pTotCap->CapId = 0;
|
|
lError = set_mux_cap(pInstance, pTermCapSet, pTotCap);
|
|
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Validate mux capability
|
|
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
|
|
{
|
|
// Bad mux capability - delete it
|
|
del_mux_cap(pTermCapSet);
|
|
lError = H245_ERROR_ASN1;
|
|
}
|
|
}
|
|
#endif // (DEBUG)
|
|
}
|
|
else if (*pCapId == 0 || *pCapId == H245_INVALID_CAPID)
|
|
{
|
|
// Assign the next never-used cap id
|
|
if (pInstance->API.LocalCapIdNum == H245_INVALID_CAPID)
|
|
{
|
|
// All possible capability identifiers have been assigned
|
|
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_MAXTBL));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_MAXTBL;
|
|
}
|
|
*pCapId = pInstance->API.LocalCapIdNum;
|
|
|
|
/* insert in the new capability in the local capability set table */
|
|
pTotCap->CapId = *pCapId;
|
|
lError = set_capability(pInstance, pTermCapSet, pTotCap);
|
|
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Validate capability
|
|
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
|
|
{
|
|
// Bad capability - delete it
|
|
H245DelLocalCap(dwInst, *pCapId);
|
|
lError = H245_ERROR_ASN1;
|
|
}
|
|
}
|
|
#endif // (DEBUG)
|
|
|
|
if (lError == H245_ERROR_OK)
|
|
pInstance->API.LocalCapIdNum++;
|
|
}
|
|
else
|
|
{
|
|
/* insert in the new capability in the local capability set table */
|
|
pTotCap->CapId = *pCapId;
|
|
lError = set_capability(pInstance, pTermCapSet, pTotCap);
|
|
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Validate capability
|
|
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
|
|
{
|
|
// Bad capability - delete it
|
|
H245DelLocalCap(dwInst, *pCapId);
|
|
lError = H245_ERROR_ASN1;
|
|
}
|
|
}
|
|
#endif // (DEBUG)
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(lError));
|
|
pTotCap->CapId = *pCapId = H245_INVALID_CAPID;
|
|
}
|
|
else
|
|
{
|
|
H245TRACE (dwInst,4,"H245SetLocalCap -> OK");
|
|
}
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245SetLocalCap()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245DelLocalCap
|
|
*
|
|
* DESCRIPTION Delete Local Cap simply disables the cap.. it
|
|
* will not be updated until the client issues
|
|
* H245SendTermCaps
|
|
*
|
|
*
|
|
* HRESULT H245DelLocalCap(
|
|
* H245_INST_T dwInst,
|
|
* H245_CAPID_T CapId
|
|
* )
|
|
*
|
|
* Description:
|
|
* This function allows the client to delete a specific
|
|
* capability id in the H.245 subsystem.
|
|
*
|
|
* Note: This function does not communicate this update
|
|
* to the remote peer until the client calls H245SendTermCaps.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245GetInstanceId
|
|
* CapId Cap Id the client wishes to remove from the
|
|
* capability table.
|
|
*
|
|
* If an error occurs no action is taken and the CapId the
|
|
* client wished to delete is not changed.
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK Capability deleted
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
*
|
|
* See Also:
|
|
* H245SetLocalCap
|
|
* H245SendTermCaps
|
|
* H245EnumCaps
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245DelLocalCap (
|
|
H245_INST_T dwInst,
|
|
H245_CAPID_T CapId
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
struct TerminalCapabilitySet *pTermCapSet;
|
|
CapabilityTableLink pCapLink;
|
|
HRESULT lError = H245_ERROR_OK;
|
|
|
|
H245TRACE (dwInst,4,"H245DelLocalCap <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
|
|
if (CapId == 0)
|
|
{
|
|
// Delete multiplex capability
|
|
del_mux_cap(pTermCapSet);
|
|
}
|
|
else
|
|
{
|
|
/* (TBC) if I delete my capability id.. what about simultaneous caps ?? */
|
|
/* should I go through the list and deactivate them ?? */
|
|
pCapLink = find_capid_by_entrynumber (pTermCapSet, CapId);
|
|
if (pCapLink)
|
|
{
|
|
// Delete terminal capability
|
|
disable_cap_link (pCapLink);
|
|
}
|
|
else
|
|
{
|
|
lError = H245_ERROR_PARAM;
|
|
}
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245DelLocalCap -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245DelLocalCap()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245SetCapDescriptor
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245SetCapDescriptor (
|
|
* H245_INST_T dwInst,
|
|
* H245_CAPDESC_T *pCapDesc,
|
|
* H245_CAPDESCID_T *pCapDescId (* Optional *)
|
|
* )
|
|
* Description:
|
|
* This procedure is called to set local capability descriptors.
|
|
* It will return a capability descriptor id in the parameter
|
|
* *pCapDescId if it is non null.
|
|
*
|
|
* Note:
|
|
* These capabilities are communicated via the H245SendTermCaps
|
|
* API call. Any updates to the CapDescriptor table (either
|
|
* additions or deletions ) will not be communicated to the
|
|
* remote side until the H245SendTermCaps call is made.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* CapDesc This is the capability Descriptor you wish
|
|
* to set
|
|
* Output
|
|
* pCapDescId optional: Capability id that will be returned.
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_INVALID_CAPID Capid used in CapDesc was not
|
|
* registred
|
|
* H245_ERROR_MAXTB Out of table space to store Descriptor
|
|
* H245_ERROR_PARAM Descriptor is too long or not valid
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_INVALID_INST
|
|
*
|
|
* See Also:
|
|
* H245DelCapDescriptor
|
|
* H245SendTermCaps
|
|
*
|
|
* ASSUMES:
|
|
* SimCapId is the array entry point in the apabilityDescriptors
|
|
* array.. this has a limitation, in that you can never wrap the
|
|
* array at 256.. this will be cleaned up when array is turned into
|
|
* linked list.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SetCapDescriptor (
|
|
H245_INST_T dwInst,
|
|
H245_CAPDESC_T *pCapDesc,
|
|
H245_CAPDESCID_T *pCapDescId
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245SetCapDescriptor <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* must have capdescriptor && */
|
|
/* length must be less than 256 */
|
|
if (pCapDesc == NULL ||
|
|
pCapDesc->Length >= 256 ||
|
|
pCapDescId == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
if (*pCapDescId >= 256)
|
|
{
|
|
// Assign the next never-used cap id
|
|
if (pInstance->API.LocalCapDescIdNum >= 256)
|
|
{
|
|
// All possible capability identifiers have been assigned
|
|
H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(H245_ERROR_MAXTBL));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_MAXTBL;
|
|
}
|
|
*pCapDescId = pInstance->API.LocalCapDescIdNum;
|
|
|
|
/* insert in the new capability descriptor in the local capability descriptor table */
|
|
lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
|
|
&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Validate Capability Descriptor
|
|
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
|
|
{
|
|
// Capability Descriptor Invalid - delete it
|
|
H245DelCapDescriptor(dwInst, *pCapDescId);
|
|
lError = H245_ERROR_ASN1;
|
|
}
|
|
}
|
|
#endif // (DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
pInstance->API.LocalCapDescIdNum++;
|
|
}
|
|
else
|
|
{
|
|
/* insert in the new capability in the local capability set table */
|
|
lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
|
|
&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
|
|
#if defined(_DEBUG)
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
// Validate Capability Descriptor
|
|
if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
|
|
{
|
|
// Capability Descriptor Invalid - delete it
|
|
H245DelCapDescriptor(dwInst, *pCapDescId);
|
|
lError = H245_ERROR_ASN1;
|
|
}
|
|
}
|
|
#endif // (DEBUG)
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(lError));
|
|
*pCapDescId = H245_INVALID_CAPDESCID;
|
|
}
|
|
else
|
|
{
|
|
H245TRACE (dwInst,4,"H245CapDescriptor -> OK");
|
|
}
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245SetCapDescriptor()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245DelCapDescriptor
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245DelCapDescriptor (
|
|
* H245_INST_T dwInst,
|
|
* H245_CAPDESCID_T CapDescId
|
|
* )
|
|
* Description:
|
|
* This procedure is called to delete local capability descriptors.
|
|
*
|
|
* Note:
|
|
* These capabilities are communicated via the
|
|
* H245SendTermCaps API call. Any updates to the
|
|
* CapDescriptor table (either additions or deletions )
|
|
* will not be communicated to the remote side until the
|
|
* H245SendTermCaps call is made.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* CapDescId This is the capability Descriptor you wish
|
|
* to delete
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_INVALID_INST
|
|
*
|
|
* See Also:
|
|
* H245SetCapDescriptor
|
|
* H245SendTermCaps
|
|
*
|
|
* ASSUMES:
|
|
*
|
|
* SimCapId is the array entry point in the apabilityDescriptors
|
|
* array.. this has a limitation, in that you can never wrap the
|
|
* array at 256.. this will be cleaned up when array is turned into
|
|
* linked list.
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245DelCapDescriptor (
|
|
H245_INST_T dwInst,
|
|
H245_CAPDESCID_T CapDescId
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
CapabilityDescriptor *p_cap_desc;
|
|
struct TerminalCapabilitySet *pTermCapSet;
|
|
unsigned int uId;
|
|
H245TRACE (dwInst,4,"H245DelCapDescriptor <-");
|
|
|
|
if (CapDescId >= 256)
|
|
{
|
|
H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
|
|
return H245_ERROR_INVALID_CAPDESCID;
|
|
}
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"API:H24DelCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* get pointer to Capability Descriptor */
|
|
p_cap_desc = NULL;
|
|
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
for (uId = 0; uId < pTermCapSet->capabilityDescriptors.count; ++uId)
|
|
{
|
|
if (pTermCapSet->capabilityDescriptors.value[uId].capabilityDescriptorNumber == CapDescId)
|
|
{
|
|
p_cap_desc = &pTermCapSet->capabilityDescriptors.value[uId];
|
|
break;
|
|
}
|
|
}
|
|
if (p_cap_desc == NULL ||
|
|
p_cap_desc->smltnsCpblts == NULL ||
|
|
(p_cap_desc->bit_mask & smltnsCpblts_present) == 0)
|
|
{
|
|
H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_CAPDESCID;
|
|
}
|
|
|
|
/* free up the list */
|
|
dealloc_simultaneous_cap (p_cap_desc);
|
|
|
|
/* (TBC) what if you've removed the last simultaneous cap ? */
|
|
|
|
/* in this case.. the count does not go down.. it simply */
|
|
/* removes the cap descriptor bit from the table.. */
|
|
|
|
H245TRACE (dwInst,4,"H245DelCapDescriptor -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
} // H245DelCapDescriptor()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245SendTermCaps
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT
|
|
* H245SendTermCaps (
|
|
* H245_INST_T dwInst,
|
|
* DWORD dwTransId
|
|
* )
|
|
*
|
|
* Description:
|
|
*
|
|
* Called to send terminal capabilities to the remote H.245 peer.
|
|
* When remote capabilities are receive the client will be
|
|
* notified by the H245_IND_CAP indication. When remote side has
|
|
* acknowledged the local terminal capabilities and has responded
|
|
* with their terminal capabilities the client will receive an
|
|
* H245_CONF_ TERMCAP. Between H245Init and H245SendTermCap the
|
|
* client may call H245SetLocalCap to register capabilities.
|
|
* These capabilities will not be registered to the remote side
|
|
* until H245SendTermCap has been called.
|
|
*
|
|
* Note: As required by the H245 specification, Mutliplex
|
|
* capabilities, and Capability descriptors must be
|
|
* loaded before the first capability PDU is sent.
|
|
*
|
|
* Once H245SendTermCap is called, any subsequent calls to
|
|
* H245SetLocalTermCap will result in that capability being
|
|
* communicated to the remote H.245 peer.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by
|
|
* H245GetInstanceId
|
|
* dwTransId User supplied object used to identify
|
|
* this request in the asynchronous
|
|
* response to this call.
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callbacks:
|
|
* H245_CONF_TERMCAP
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK Function succeeded
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
* H245_ERROR_NO_MUX_CAPS no Mux capabilities have been set yet
|
|
* H245_ERROR_NO_CAPDESC no Capability Descriptors have been set
|
|
*
|
|
* See Also:
|
|
* H245SetLocalCap
|
|
* H245Init
|
|
*
|
|
* callbacks
|
|
*
|
|
* H245_IND_CAP
|
|
* H245_IND_CAPDESC
|
|
* H245_IND_CAP_DEL
|
|
* H245_IND_CAPDESC_DEL
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SendTermCaps (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId
|
|
)
|
|
{
|
|
struct InstanceStruct *pInstance;
|
|
Tracker_T *pTracker;
|
|
HRESULT lError;
|
|
unsigned char TermCapData = TRUE;
|
|
struct TerminalCapabilitySet_capabilityTable TermCap = {0};
|
|
|
|
H245TRACE(dwInst,4,"H245SendTermCaps <-");
|
|
|
|
/* check for valid instance handle */
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* must have mux parameters set */
|
|
if ((pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & multiplexCapability_present) == 0)
|
|
{
|
|
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_MUX_CAPS));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NO_MUX_CAPS;
|
|
}
|
|
|
|
/* must have capability descriptors set */
|
|
if (!(pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & capabilityDescriptors_present))
|
|
{
|
|
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_CAPDESC));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NO_CAPDESC;
|
|
}
|
|
|
|
if (!(pTracker = alloc_link_tracker (pInstance,
|
|
API_TERMCAP_T,
|
|
dwTransId,
|
|
API_ST_WAIT_RMTACK,
|
|
API_CH_ALLOC_UNDEF,
|
|
API_CH_TYPE_UNDEF,
|
|
0,
|
|
H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
|
|
0)))
|
|
{
|
|
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
pdu_req_termcap_set (&pInstance->API.PDU_LocalTermCap, 0);
|
|
TermCap.next = pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable;
|
|
pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = &TermCap;
|
|
TermCap.value.bit_mask = capability_present;
|
|
TermCap.value.capabilityTableEntryNumber = pInstance->API.LocalCapIdNum;
|
|
TermCap.value.capability.choice = Capability_nonStandard_chosen;
|
|
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice = h221NonStandard_chosen;
|
|
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = 0xB5;
|
|
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension = 0x42;
|
|
TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = 0x8080;
|
|
TermCap.value.capability.u.Capability_nonStandard.data.value = &TermCapData;
|
|
TermCap.value.capability.u.Capability_nonStandard.data.length = sizeof(TermCapData);
|
|
lError = FsmOutgoing(pInstance, &pInstance->API.PDU_LocalTermCap, (DWORD_PTR)pTracker);
|
|
pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = TermCap.next;
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE(dwInst,4,"H245SendTermCaps -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245SendTermCaps()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245EnumCaps
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245EnumCaps (
|
|
* DWORD dwInst,
|
|
* DWORD dwTransId,
|
|
* H245_CAPDIR_T Direction,
|
|
* H245_DATA_T DataType,
|
|
* H245_CLIENT_T ClientType,
|
|
* H245_CAP_CALLBACK_T CallBack
|
|
* )
|
|
*
|
|
*
|
|
* Callback:
|
|
* CallBack (
|
|
* DWORD dwTransId,
|
|
* H245_TOTCAP_T *pTotCap,
|
|
* )
|
|
*
|
|
* Description:
|
|
*
|
|
* This function calls the H.245 client back for every
|
|
* capability as defined in the API call that complies with the
|
|
* request. If the DataType parameter is set to 0 all of the
|
|
* caps types are returned (either local or remote based on the
|
|
* Direction parameter) no mater what is in the ClientType
|
|
* parameter. If the ClientType parameter is 0, it will return
|
|
* all of the capabilities of the given DataType.
|
|
*
|
|
* The user supplied call back is called within the context of
|
|
* the call, therefor the call will be considered synchronous.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* Direction Local/Remote Receive, Transmit, or Receive and
|
|
* Transmit
|
|
* DataType Type of data (Audio, Video, Data, etc.)
|
|
* ClientType Client type (H.262, G.711. etc. ).
|
|
* dwTransId User supplied object used to identify this
|
|
* request in the callback.
|
|
*
|
|
* CallBack Output
|
|
* dwTransId Identical to dwTransId passed in H245EnumCaps
|
|
* pTotCap Pointer one of the capabilities.
|
|
*
|
|
* Note: TotCap parameter must be copied in the callback. This
|
|
* data structure is reused for each callback.
|
|
*
|
|
* Call Type:
|
|
* Synchronous Callback - i.e. called back in the context of
|
|
* the API call
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM One or more parameters were invalid
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle.
|
|
*
|
|
* See Also:
|
|
* H245SetLocalCap
|
|
* H245ReplLocalCap
|
|
*
|
|
* callback
|
|
*
|
|
* H245_IND_CAP
|
|
* H245_IND_CAPDESC
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245EnumCaps (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_CAPDIR_T Direction,
|
|
H245_DATA_T DataType,
|
|
H245_CLIENT_T ClientType,
|
|
H245_CAP_CALLBACK_T pfCapCallback,
|
|
H245_CAPDESC_CALLBACK_T pfCapDescCallback
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
struct TerminalCapabilitySet *pTermCapSet;
|
|
CapabilityTableLink pCapLink;
|
|
int lcl_rmt;
|
|
H245_TOTCAP_T totcap;
|
|
int nResult = 0;
|
|
|
|
H245TRACE (dwInst,4,"H245EnumCaps <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* check for callback routine */
|
|
if (pfCapCallback == NULL && pfCapDescCallback == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
/* ok... check the direction.. either remote or local caps.. */
|
|
switch (Direction)
|
|
{
|
|
case H245_CAPDIR_RMTRX:
|
|
case H245_CAPDIR_RMTTX:
|
|
case H245_CAPDIR_RMTRXTX:
|
|
pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
lcl_rmt = H245_REMOTE;
|
|
break;
|
|
|
|
case H245_CAPDIR_LCLRX:
|
|
case H245_CAPDIR_LCLTX:
|
|
case H245_CAPDIR_LCLRXTX:
|
|
pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
|
|
lcl_rmt = H245_LOCAL;
|
|
break;
|
|
|
|
/* must be either local or remote */
|
|
// case H245_CAPDIR_DONTCARE:
|
|
default:
|
|
H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
if (pfCapCallback)
|
|
{
|
|
if (pTermCapSet->bit_mask & multiplexCapability_present &&
|
|
build_totcap_from_mux(&totcap, &pTermCapSet->multiplexCapability, Direction) == H245_ERROR_OK)
|
|
{
|
|
(*pfCapCallback)(dwTransId, &totcap);
|
|
}
|
|
|
|
if (ClientType == H245_CLIENT_DONTCARE)
|
|
{
|
|
if (DataType == H245_DATA_DONTCARE)
|
|
{
|
|
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
|
|
{
|
|
/* if capability is present */
|
|
if (pCapLink->value.bit_mask & capability_present &&
|
|
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK)
|
|
{
|
|
nResult = (*pfCapCallback)(dwTransId, &totcap);
|
|
}
|
|
} // for
|
|
} // if
|
|
else
|
|
{
|
|
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
|
|
{
|
|
/* if capability is present */
|
|
if (pCapLink->value.bit_mask & capability_present &&
|
|
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
|
|
totcap.DataType == DataType)
|
|
{
|
|
nResult = (*pfCapCallback)(dwTransId, &totcap);
|
|
}
|
|
} // for
|
|
} // else
|
|
} // if
|
|
else
|
|
{
|
|
if (DataType == H245_DATA_DONTCARE)
|
|
{
|
|
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
|
|
{
|
|
/* if capability is present */
|
|
if (pCapLink->value.bit_mask & capability_present &&
|
|
build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
|
|
totcap.ClientType == ClientType)
|
|
{
|
|
nResult = (*pfCapCallback)(dwTransId, &totcap);
|
|
} /* if cap match */
|
|
} // for
|
|
} // if
|
|
else
|
|
{
|
|
for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
|
|
{
|
|
/* if capability is present */
|
|
if (pCapLink->value.bit_mask & capability_present &&
|
|
build_totcap_from_captbl(&totcap,pCapLink,lcl_rmt) == H245_ERROR_OK &&
|
|
totcap.ClientType == ClientType &&
|
|
totcap.DataType == DataType)
|
|
{
|
|
nResult = (*pfCapCallback)(dwTransId, &totcap);
|
|
}
|
|
} // for
|
|
} // else
|
|
} // else
|
|
} // if (pfCapCallback)
|
|
|
|
if (pfCapDescCallback)
|
|
{
|
|
// Convert CapabilityDescriptor format to H245_CAPDESC_T format
|
|
unsigned int uCapDesc;
|
|
register SmltnsCpbltsLink pSimCap;
|
|
register unsigned int uAltCap;
|
|
H245_TOTCAPDESC_T TotCapDesc;
|
|
|
|
for (uCapDesc = 0;
|
|
uCapDesc < pTermCapSet->capabilityDescriptors.count && nResult == 0;
|
|
++uCapDesc)
|
|
{
|
|
if (pTermCapSet->capabilityDescriptors.value[uCapDesc].bit_mask & smltnsCpblts_present)
|
|
{
|
|
ASSERT(pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber <= 256);
|
|
TotCapDesc.CapDesc.Length = 0;
|
|
pSimCap = pTermCapSet->capabilityDescriptors.value[uCapDesc].smltnsCpblts;
|
|
ASSERT(pSimCap != NULL);
|
|
while (pSimCap)
|
|
{
|
|
if (TotCapDesc.CapDesc.Length >= H245_MAX_SIMCAPS)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EnumCaps -> Number of simutaneous capabilities exceeds H245_MAX_SIMCAPS");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_MAXTBL;
|
|
}
|
|
if (pSimCap->value.count > H245_MAX_ALTCAPS)
|
|
{
|
|
H245TRACE (dwInst,1,"H245EnumCaps -> Number of alternative capabilities exceeds H245_MAX_ALTCAPS");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_MAXTBL;
|
|
}
|
|
TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].Length = (WORD) pSimCap->value.count;
|
|
for (uAltCap = 0; uAltCap < pSimCap->value.count; ++uAltCap)
|
|
{
|
|
TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].AltCaps[uAltCap] = pSimCap->value.value[uAltCap];
|
|
}
|
|
TotCapDesc.CapDesc.Length++;
|
|
pSimCap = pSimCap->next;
|
|
} // while
|
|
TotCapDesc.CapDescId = pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber;
|
|
nResult = pfCapDescCallback(dwTransId, &TotCapDesc);
|
|
} // if
|
|
} // for
|
|
} // if (pfCapDescCallback)
|
|
|
|
H245TRACE (dwInst,4,"H245EnumCaps -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
} // H245EnumCaps()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245GetCaps
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
static H245_TOTCAP_T * * ppTotCapGlobal;
|
|
static unsigned long dwTotCapLen;
|
|
static unsigned long dwTotCapMax;
|
|
static H245_TOTCAPDESC_T * * ppCapDescGlobal;
|
|
static unsigned long dwCapDescLen;
|
|
static unsigned long dwCapDescMax;
|
|
static HRESULT dwGetCapsError;
|
|
|
|
static int
|
|
GetCapsCapCallback(DWORD_PTR dwTransId, H245_TOTCAP_T *pTotCap)
|
|
{
|
|
H245_TOTCAP_T *pNewCap;
|
|
|
|
if (dwGetCapsError == H245_ERROR_OK)
|
|
{
|
|
if (dwTotCapLen >= dwTotCapMax)
|
|
{
|
|
dwGetCapsError = H245_ERROR_MAXTBL;
|
|
}
|
|
else
|
|
{
|
|
dwGetCapsError = H245CopyCap(&pNewCap, pTotCap);
|
|
if (dwGetCapsError == H245_ERROR_OK)
|
|
{
|
|
*ppTotCapGlobal++ = pNewCap;
|
|
++dwTotCapLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
} // GetCapsCapCallback()
|
|
|
|
static int
|
|
GetCapsCapDescCallback(DWORD_PTR dwTransId, H245_TOTCAPDESC_T *pCapDesc)
|
|
{
|
|
H245_TOTCAPDESC_T *pNewCapDesc;
|
|
|
|
if (dwGetCapsError == H245_ERROR_OK)
|
|
{
|
|
if (dwCapDescLen >= dwCapDescMax)
|
|
{
|
|
dwGetCapsError = H245_ERROR_MAXTBL;
|
|
}
|
|
else
|
|
{
|
|
dwGetCapsError = H245CopyCapDescriptor(&pNewCapDesc,pCapDesc);
|
|
{
|
|
*ppCapDescGlobal++ = pNewCapDesc;
|
|
++dwCapDescLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
} // GetCapsCapDescCallback()
|
|
|
|
H245DLL HRESULT
|
|
H245GetCaps (
|
|
H245_INST_T dwInst,
|
|
H245_CAPDIR_T Direction,
|
|
H245_DATA_T DataType,
|
|
H245_CLIENT_T ClientType,
|
|
H245_TOTCAP_T * * ppTotCap,
|
|
unsigned long * pdwTotCapLen,
|
|
H245_TOTCAPDESC_T * * ppCapDesc,
|
|
unsigned long * pdwCapDescLen
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
H245_CAP_CALLBACK_T CapCallback;
|
|
H245_CAPDESC_CALLBACK_T CapDescCallback;
|
|
|
|
H245TRACE (dwInst,4,"H245GetCaps <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
dwTotCapLen = 0;
|
|
if (ppTotCap == NULL || pdwTotCapLen == NULL || *pdwTotCapLen == 0)
|
|
{
|
|
CapCallback = NULL;
|
|
}
|
|
else
|
|
{
|
|
CapCallback = GetCapsCapCallback;
|
|
ppTotCapGlobal = ppTotCap;
|
|
dwTotCapMax = *pdwTotCapLen;
|
|
}
|
|
|
|
dwCapDescLen = 0;
|
|
if (ppCapDesc == NULL || pdwCapDescLen == NULL || *pdwCapDescLen == 0)
|
|
{
|
|
CapDescCallback = NULL;
|
|
}
|
|
else
|
|
{
|
|
CapDescCallback = GetCapsCapDescCallback;
|
|
ppCapDescGlobal = ppCapDesc;
|
|
dwCapDescMax = *pdwCapDescLen;
|
|
}
|
|
|
|
/* check parameters */
|
|
if (CapCallback == NULL && CapDescCallback == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
dwGetCapsError = H245_ERROR_OK;
|
|
H245EnumCaps(dwInst,
|
|
0,
|
|
Direction,
|
|
DataType,
|
|
ClientType,
|
|
CapCallback,
|
|
CapDescCallback);
|
|
|
|
if (pdwTotCapLen)
|
|
*pdwTotCapLen = dwTotCapLen;
|
|
if (pdwCapDescLen)
|
|
*pdwCapDescLen = dwCapDescLen;
|
|
if (dwGetCapsError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245GetCaps -> %s", map_api_error(dwGetCapsError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245GetCaps -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
} // H245GetCaps()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CopyCap
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CopyCap (H245_TOTCAP_T **ppDestTotCap,
|
|
const H245_TOTCAP_T *pTotCap)
|
|
{
|
|
POBJECTID pObjectTo;
|
|
POBJECTID pObjectFrom;
|
|
HRESULT Status;
|
|
|
|
if (ppDestTotCap == NULL)
|
|
return H245_ERROR_PARAM;
|
|
|
|
*ppDestTotCap = NULL;
|
|
|
|
if (pTotCap == NULL)
|
|
return H245_ERROR_PARAM;
|
|
|
|
switch (pTotCap->ClientType)
|
|
{
|
|
case H245_CLIENT_NONSTD:
|
|
case H245_CLIENT_VID_NONSTD:
|
|
case H245_CLIENT_AUD_NONSTD:
|
|
case H245_CLIENT_MUX_NONSTD:
|
|
if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen)
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245_NonStd.data.length +
|
|
ObjectIdLength(&pTotCap->Cap.H245_NonStd.nonStandardIdentifier) * sizeof(OBJECTID));
|
|
}
|
|
else
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245_NonStd.data.length);
|
|
}
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
if (pTotCap->Cap.H245_NonStd.data.length != 0)
|
|
{
|
|
(*ppDestTotCap)->Cap.H245_NonStd.data.value = (unsigned char *)(*ppDestTotCap + 1);
|
|
memcpy((*ppDestTotCap)->Cap.H245_NonStd.data.value,
|
|
pTotCap->Cap.H245_NonStd.data.value,
|
|
pTotCap->Cap.H245_NonStd.data.length);
|
|
}
|
|
else
|
|
{
|
|
(*ppDestTotCap)->Cap.H245_NonStd.data.value = NULL;
|
|
}
|
|
if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen &&
|
|
pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object != NULL)
|
|
{
|
|
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
|
|
pTotCap->Cap.H245_NonStd.data.length);
|
|
(*ppDestTotCap)->Cap.H245_NonStd.nonStandardIdentifier.u.object = pObjectTo;
|
|
pObjectFrom = pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object;
|
|
do
|
|
{
|
|
pObjectTo->value = pObjectFrom->value;
|
|
pObjectTo->next = pObjectTo + 1;
|
|
++pObjectTo;
|
|
} while ((pObjectFrom = pObjectFrom->next) != NULL);
|
|
--pObjectTo;
|
|
pObjectTo->next = NULL;
|
|
}
|
|
break;
|
|
|
|
case H245_CLIENT_DAT_NONSTD:
|
|
if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen)
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length +
|
|
ObjectIdLength(&pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
|
|
}
|
|
else
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
|
|
}
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
if (pTotCap->Cap.H245_NonStd.data.length != 0)
|
|
{
|
|
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value =
|
|
(unsigned char *)(*ppDestTotCap + 1);
|
|
memcpy((*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
|
|
}
|
|
else
|
|
{
|
|
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value = NULL;
|
|
}
|
|
if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object != NULL)
|
|
{
|
|
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
|
|
pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
|
|
(*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
|
|
pObjectFrom = pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object;
|
|
do
|
|
{
|
|
pObjectTo->value = pObjectFrom->value;
|
|
pObjectTo->next = pObjectTo + 1;
|
|
++pObjectTo;
|
|
} while ((pObjectFrom = pObjectFrom->next) != NULL);
|
|
--pObjectTo;
|
|
pObjectTo->next = NULL;
|
|
}
|
|
break;
|
|
|
|
case H245_CLIENT_DAT_T120:
|
|
case H245_CLIENT_DAT_DSMCC:
|
|
case H245_CLIENT_DAT_USERDATA:
|
|
case H245_CLIENT_DAT_T434:
|
|
case H245_CLIENT_DAT_H224:
|
|
case H245_CLIENT_DAT_H222:
|
|
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.choice == DtPrtclCpblty_nnStndrd_chosen)
|
|
{
|
|
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen)
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length +
|
|
ObjectIdLength(&pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
|
|
}
|
|
else
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
|
|
}
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
if (pTotCap->Cap.H245_NonStd.data.length != 0)
|
|
{
|
|
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value =
|
|
(unsigned char *)(*ppDestTotCap + 1);
|
|
memcpy((*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
|
|
}
|
|
else
|
|
{
|
|
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value = NULL;
|
|
}
|
|
if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object != NULL)
|
|
{
|
|
pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
|
|
pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
|
|
(*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
|
|
pObjectFrom = pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object;
|
|
do
|
|
{
|
|
pObjectTo->value = pObjectFrom->value;
|
|
pObjectTo->next = pObjectTo + 1;
|
|
++pObjectTo;
|
|
} while ((pObjectFrom = pObjectFrom->next) != NULL);
|
|
--pObjectTo;
|
|
pObjectTo->next = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
**ppDestTotCap = *pTotCap;
|
|
}
|
|
break;
|
|
|
|
case H245_CLIENT_CONFERENCE:
|
|
{
|
|
NonStandardDataLink pList;
|
|
NonStandardDataLink pFrom;
|
|
NonStandardDataLink pTo;
|
|
|
|
// Initialize Status here to prevent compiler warning "returning a possibly
|
|
// uninitialized value"
|
|
Status = H245_ERROR_NOMEM;
|
|
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
|
|
pList = NULL;
|
|
(*ppDestTotCap)->Cap.H245Conference.nonStandardData = NULL;
|
|
pFrom = pTotCap->Cap.H245Conference.nonStandardData;
|
|
while (pFrom)
|
|
{
|
|
pTo = MemAlloc(sizeof(*pTo));
|
|
if (pTo == NULL)
|
|
Status = H245_ERROR_NOMEM;
|
|
|
|
if (pTo != NULL)
|
|
{
|
|
Status = CopyNonStandardParameter(&pTo->value, &pFrom->value);
|
|
if (Status != H245_ERROR_OK)
|
|
{
|
|
MemFree(pTo);
|
|
pTo = NULL;
|
|
}
|
|
}
|
|
if (pTo == NULL)
|
|
{
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
FreeNonStandardParameter(&pTo->value);
|
|
MemFree(pTo);
|
|
}
|
|
MemFree(*ppDestTotCap);
|
|
*ppDestTotCap = NULL;
|
|
return Status;
|
|
}
|
|
pTo->next = pList;
|
|
pList = pTo;
|
|
pFrom = pFrom->next;
|
|
} // while
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
pTo->next = (*ppDestTotCap)->Cap.H245Conference.nonStandardData;
|
|
(*ppDestTotCap)->Cap.H245Conference.nonStandardData = pTo;
|
|
} // while
|
|
break;
|
|
}
|
|
|
|
case H245_CLIENT_MUX_H222:
|
|
{
|
|
VCCapabilityLink pList = NULL;
|
|
VCCapabilityLink pFrom;
|
|
VCCapabilityLink pTo;
|
|
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
(*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = NULL;
|
|
pFrom = pTotCap->Cap.H245Mux_H222.vcCapability;
|
|
while (pFrom)
|
|
{
|
|
pTo = MemAlloc(sizeof(*pTo));
|
|
if (pTo == NULL)
|
|
{
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
MemFree(pTo);
|
|
}
|
|
MemFree(*ppDestTotCap);
|
|
*ppDestTotCap = NULL;
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
pTo->value = pFrom->value;
|
|
pTo->next = pList;
|
|
pList = pTo;
|
|
pFrom = pFrom->next;
|
|
} // while
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
pTo->next = (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability;
|
|
(*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = pList;
|
|
} // while
|
|
break;
|
|
}
|
|
|
|
case H245_CLIENT_MUX_H2250:
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestTotCap = *pTotCap;
|
|
Status = CopyH2250Cap(&(*ppDestTotCap)->Cap.H245Mux_H2250, &pTotCap->Cap.H245Mux_H2250);
|
|
if (Status != H245_ERROR_OK)
|
|
{
|
|
MemFree(*ppDestTotCap);
|
|
*ppDestTotCap = NULL;
|
|
return Status;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
*ppDestTotCap = MemAlloc(sizeof(*pTotCap));
|
|
if (*ppDestTotCap == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
**ppDestTotCap = *pTotCap;
|
|
} // switch
|
|
|
|
return H245_ERROR_OK;
|
|
} // H245CopyCap()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245FreeCap
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245FreeCap (H245_TOTCAP_T * pTotCap)
|
|
{
|
|
if (pTotCap == NULL)
|
|
{
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
switch (pTotCap->ClientType)
|
|
{
|
|
case H245_CLIENT_CONFERENCE:
|
|
{
|
|
NonStandardDataLink pList;
|
|
NonStandardDataLink pTo;
|
|
|
|
pList = pTotCap->Cap.H245Conference.nonStandardData;
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
FreeNonStandardParameter(&pTo->value);
|
|
MemFree(pTo);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H245_CLIENT_MUX_H222:
|
|
{
|
|
VCCapabilityLink pList;
|
|
VCCapabilityLink pTo;
|
|
|
|
pList = pTotCap->Cap.H245Mux_H222.vcCapability;
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
MemFree(pTo);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H245_CLIENT_MUX_H2250:
|
|
FreeH2250Cap(&pTotCap->Cap.H245Mux_H2250);
|
|
break;
|
|
|
|
} // switch
|
|
MemFree(pTotCap);
|
|
return 0;
|
|
} // H245FreeCap()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CopyCapDescriptor
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CopyCapDescriptor (H245_TOTCAPDESC_T **ppDestCapDesc,
|
|
const H245_TOTCAPDESC_T *pCapDesc)
|
|
{
|
|
if (ppDestCapDesc == NULL)
|
|
return H245_ERROR_PARAM;
|
|
|
|
*ppDestCapDesc = NULL;
|
|
|
|
if (pCapDesc == NULL)
|
|
return H245_ERROR_PARAM;
|
|
|
|
*ppDestCapDesc = MemAlloc(sizeof(**ppDestCapDesc));
|
|
if (*ppDestCapDesc == NULL)
|
|
return H245_ERROR_NOMEM;
|
|
|
|
**ppDestCapDesc = *pCapDesc;
|
|
return H245_ERROR_OK;
|
|
} // H245CopyCapDescriptor()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245FreeCapDescriptor
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245FreeCapDescriptor (H245_TOTCAPDESC_T * pCapDesc)
|
|
{
|
|
if (pCapDesc == NULL)
|
|
{
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
MemFree(pCapDesc);
|
|
return 0;
|
|
} // H245FreeCapDescriptor()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CopyMux
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL H245_MUX_T *
|
|
H245CopyMux (const H245_MUX_T * pMux)
|
|
{
|
|
register unsigned int uLength;
|
|
register H245_MUX_T *pNew;
|
|
H2250LCPs_nnStndrdLink pList;
|
|
H2250LCPs_nnStndrdLink pFrom;
|
|
H2250LCPs_nnStndrdLink pTo;
|
|
|
|
switch (pMux->Kind)
|
|
{
|
|
case H245_H222:
|
|
uLength = sizeof(*pMux) +
|
|
pMux->u.H222.programDescriptors.length +
|
|
pMux->u.H222.streamDescriptors.length;
|
|
pNew = MemAlloc(uLength);
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
if (pMux->u.H222.programDescriptors.length != 0)
|
|
{
|
|
pNew->u.H222.programDescriptors.value = (unsigned char *)(pNew + 1);
|
|
memcpy(pNew->u.H222.programDescriptors.value,
|
|
pMux->u.H222.programDescriptors.value,
|
|
pMux->u.H222.programDescriptors.length);
|
|
}
|
|
else
|
|
{
|
|
pNew->u.H222.programDescriptors.value = NULL;
|
|
}
|
|
|
|
if (pMux->u.H222.streamDescriptors.length != 0)
|
|
{
|
|
pNew->u.H222.streamDescriptors.value = ((unsigned char *)pNew) +
|
|
(uLength - pMux->u.H222.streamDescriptors.length);
|
|
memcpy(pNew->u.H222.streamDescriptors.value,
|
|
pMux->u.H222.streamDescriptors.value,
|
|
pMux->u.H222.streamDescriptors.length);
|
|
}
|
|
else
|
|
{
|
|
pNew->u.H222.streamDescriptors.value = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H245_H223:
|
|
pNew = MemAlloc(sizeof(*pMux) + pMux->u.H223.H223_NONSTD.data.length);
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
if (pMux->u.H223.H223_NONSTD.data.length != 0)
|
|
{
|
|
pNew->u.H223.H223_NONSTD.data.value = (unsigned char *)(pNew + 1);
|
|
memcpy(pNew->u.H223.H223_NONSTD.data.value,
|
|
pMux->u.H223.H223_NONSTD.data.value,
|
|
pMux->u.H223.H223_NONSTD.data.length);
|
|
}
|
|
else
|
|
{
|
|
pNew->u.H223.H223_NONSTD.data.value = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case H245_H2250:
|
|
case H245_H2250ACK:
|
|
// Caveat: assumes nonstandard list, mediaChannel and mediaControlChannel
|
|
// in same place in both structures
|
|
if (pMux->u.H2250.mediaChannelPresent &&
|
|
(pMux->u.H2250.mediaChannel.type == H245_IPSSR_UNICAST ||
|
|
pMux->u.H2250.mediaChannel.type == H245_IPLSR_UNICAST) &&
|
|
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route != NULL &&
|
|
pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount != 0)
|
|
{
|
|
if (pMux->u.H2250.mediaControlChannelPresent &&
|
|
(pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
|
|
pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
|
|
{
|
|
unsigned int uLength2;
|
|
uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
|
|
uLength2 = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
|
|
pNew = MemAlloc(sizeof(*pMux) + uLength + uLength2);
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
|
|
pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route =
|
|
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route + uLength;
|
|
memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
|
|
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
|
|
uLength);
|
|
memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
|
|
uLength2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
|
|
pNew = MemAlloc(sizeof(*pMux) + uLength);
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
|
|
memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
|
|
pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
|
|
uLength);
|
|
}
|
|
}
|
|
}
|
|
else if (pMux->u.H2250.mediaControlChannelPresent &&
|
|
(pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
|
|
pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
|
|
{
|
|
uLength = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
|
|
pNew = MemAlloc(sizeof(*pMux) + uLength);
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
|
|
memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
|
|
pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
|
|
uLength);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNew = MemAlloc(sizeof(*pMux));
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
}
|
|
}
|
|
pList = NULL;
|
|
pNew->u.H2250.nonStandardList = NULL;
|
|
pFrom = pMux->u.H2250.nonStandardList;
|
|
while (pFrom)
|
|
{
|
|
pTo = MemAlloc(sizeof(*pTo));
|
|
if (pTo != NULL)
|
|
{
|
|
if (CopyNonStandardParameter(&pTo->value, &pFrom->value) != H245_ERROR_OK)
|
|
{
|
|
MemFree(pTo);
|
|
pTo = NULL;
|
|
}
|
|
}
|
|
if (pTo == NULL)
|
|
{
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
FreeNonStandardParameter(&pTo->value);
|
|
MemFree(pTo);
|
|
}
|
|
MemFree(pNew);
|
|
return NULL;
|
|
}
|
|
pTo->next = pList;
|
|
pList = pTo;
|
|
pFrom = pFrom->next;
|
|
} // while
|
|
while (pList)
|
|
{
|
|
pTo = pList;
|
|
pList = pList->next;
|
|
pTo->next = pNew->u.H2250.nonStandardList;
|
|
pNew->u.H2250.nonStandardList = pTo;
|
|
} // while
|
|
break;
|
|
|
|
// case H245_VGMUX:
|
|
default:
|
|
pNew = MemAlloc(sizeof(*pMux));
|
|
if (pNew != NULL)
|
|
{
|
|
*pNew = *pMux;
|
|
}
|
|
} // switch
|
|
|
|
return pNew;
|
|
} // H245CopyMux()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245FreeMux
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245FreeMux (H245_MUX_T * pMux)
|
|
{
|
|
H2250LCPs_nnStndrdLink pLink;
|
|
|
|
if (pMux == NULL)
|
|
{
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
switch (pMux->Kind)
|
|
{
|
|
case H245_H2250:
|
|
case H245_H2250ACK:
|
|
// Caveat: assumes nonstandard list is in same place in both structures
|
|
while (pMux->u.H2250.nonStandardList)
|
|
{
|
|
pLink = pMux->u.H2250.nonStandardList;
|
|
pMux->u.H2250.nonStandardList = pLink->next;
|
|
FreeNonStandardParameter(&pLink->value);
|
|
MemFree(pLink);
|
|
}
|
|
break;
|
|
} // switch
|
|
|
|
MemFree(pMux);
|
|
return 0;
|
|
} // H245FreeMux()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245OpenChannel
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245OpenChannel (
|
|
* H245_INST_T dwInst,
|
|
* DWORD dwTransId,
|
|
* DWORD dwTxChannel,
|
|
* H245_TOTCAP_T *pTxMode,
|
|
* H245_MUX_T *pTxMux,
|
|
* H245_TOTCAP_T *pRxMode, (* bi-dir only *)
|
|
* H245_MUX_T *pRxMux (* bi-dir only *)
|
|
* )
|
|
*
|
|
* Description:
|
|
* This function is called to open either a uni-directional,
|
|
* or a bi-directional channel. The mode to the remote peer
|
|
* will be designated by the *pTxMode.. To open a bi-directional
|
|
* channel the client selects a non-null receive mode ( *pRxMode).
|
|
* This mode indicates to the remote peer its transmit mode.
|
|
* For uni-directional channels the *pRxMode must be NULL.
|
|
*
|
|
* The dwTxChannel parameter indicates which forward logical
|
|
* channel the H.245 will open. If this is a bi-directional
|
|
* channel open, the confirm will indicate the logical channel
|
|
* specified in the open request by the remote terminal
|
|
*
|
|
* The pMux parameter will contain a pointer to H.223, H.222,
|
|
* VGMUX, or other logical channel parameters depending on the
|
|
* system configuration. (see H245_H223_LOGICAL_PARAM). This
|
|
* may be NULL for some clients.
|
|
*
|
|
* Note:
|
|
* 7 pTxMode->CapId is of no significance in this call.
|
|
* It is not used
|
|
* 7 pRxMode->CapId is of no significance in this call.
|
|
* It is not used
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* dwTransId User supplied object used to identify this
|
|
* request in the asynchronous confirm to this
|
|
* call.
|
|
* dwTxChannel Logical Channel number for forward (Transmit)
|
|
* Channel
|
|
* pTxMode The capability (mode) used for transmission
|
|
* to the remote peer.
|
|
* Note: pTxMode->CapId is ignored
|
|
* pTxMux The formward logical channel parameters
|
|
* for H.223, H.222, VGMUX, etc.
|
|
* pRxMode Optional: Transmit mode specified for the
|
|
* remote terminal. This is used only for
|
|
* Bi-directional Channel opens and must be set
|
|
* to NULL if opening a Uni-directional channel.
|
|
* Note: pRxMode->CapId is ignored
|
|
* pRxMux Optional : The reverse logical channel
|
|
* parameters for H.223, H.222, VGMUX, etc. or
|
|
* NULL.
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callback:
|
|
* H245_CONF_OPEN
|
|
* H245_CONF_NEEDRSP_OPEN Bi-Directional Channels only
|
|
* waiting for confirm.
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM One or more parameters were
|
|
* invalid
|
|
* H245_ERROR_BANDWIDTH_OVERFLOW Open would exceed bandwidth
|
|
* limitations
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_NORESOURCE Out of resources, too many
|
|
* open channels or outside scope
|
|
* of simultaneous capabilities.
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance
|
|
* handle
|
|
* H245_ERROR_INVALID_STATE Not in the proper state to
|
|
* issue open
|
|
* H245_ERROR_CHANNEL_INUSE Channel is currently open
|
|
*
|
|
* See Also:
|
|
* H245CloseChannel
|
|
* H245OpenChannelIndResp
|
|
* H245OpenChannelConfResp
|
|
*
|
|
* callback
|
|
*
|
|
* H245_CONF_OPEN
|
|
* H245_CONF_NEEDRSP_OPEN
|
|
* H245_IND_OPEN_CONF
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245OpenChannel (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_CHANNEL_T wTxChannel,
|
|
const H245_TOTCAP_T * pTxMode,
|
|
const H245_MUX_T * pTxMux,
|
|
H245_PORT_T dwTxPort, // optional
|
|
const H245_TOTCAP_T * pRxMode, // bi-dir only
|
|
const H245_MUX_T * pRxMux, // bi-dir only
|
|
const H245_ACCESS_T * pSeparateStack // optional
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
Tracker_T *pTracker;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245OpenChannel <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
/* must have performed Master Slave Negotiation at this point */
|
|
if (pInstance->Configuration == H245_CONF_H324 &&
|
|
pInstance->API.MasterSlave != APIMS_Master &&
|
|
pInstance->API.MasterSlave != APIMS_Slave)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_STATE));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_STATE;
|
|
}
|
|
|
|
pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
|
|
|
|
/* channel is currently in use */
|
|
if (pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_CHANNEL_INUSE));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_CHANNEL_INUSE;
|
|
}
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
|
|
/* lock in the transmit side.. */
|
|
/* wait until OpenChannelConfResp to setup RxChannel */
|
|
|
|
lError = pdu_req_open_channel(pPdu,
|
|
wTxChannel,
|
|
dwTxPort, /* forward port */
|
|
pTxMode,
|
|
pTxMux,
|
|
pRxMode,
|
|
pRxMux,
|
|
pSeparateStack);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
|
|
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
}
|
|
|
|
/* if allocation error */
|
|
|
|
if (!(pTracker = alloc_link_tracker (pInstance,
|
|
API_OPEN_CHANNEL_T,
|
|
dwTransId,
|
|
API_ST_WAIT_RMTACK,
|
|
API_CH_ALLOC_LCL,
|
|
(pRxMode?API_CH_TYPE_BI:API_CH_TYPE_UNI),
|
|
pTxMode->DataType,
|
|
wTxChannel, H245_INVALID_CHANNEL,
|
|
0)))
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
|
|
}
|
|
else
|
|
H245TRACE (dwInst,4,"H245OpenChannel -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245OpenChannel()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245OpenChannelAccept
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245OpenChannelAccept (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
|
|
const H245_MUX_T * pRxMux, // optional H2250LogicalChannelAckParameters
|
|
H245_CHANNEL_T wTxChannel, // bi-dir only
|
|
const H245_MUX_T * pTxMux, // bi-dir only optional H2250LogicalChannelParameters
|
|
H245_PORT_T dwTxPort, // bi-dir only optional
|
|
const H245_ACCESS_T * pSeparateStack // optional
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
Tracker_T * pTracker;
|
|
MltmdSystmCntrlMssg * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245OpenChannelAccept <- wRxChannel=%d wTxChannel=%d",
|
|
wRxChannel, wTxChannel);
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if channel not found in tracker list */
|
|
/* note that it looks for given channel given who alloced it */
|
|
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
|
|
|
|
/* not locking tracker.. since no indication will come in until I issue the request */
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* if not open.. invalid op */
|
|
if (pTracker->TrackerType != API_OPEN_CHANNEL_T)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* if was uni open w/ TxChannel set.. error */
|
|
/* -or - */
|
|
/* if was bi open w/ !TxChannel set.. error */
|
|
|
|
/* AND it wasn't a reject */
|
|
|
|
if (pTracker->u.Channel.ChannelType == API_CH_TYPE_BI && wTxChannel == 0)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
/* for debug */
|
|
ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
|
|
ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
|
|
|
|
/* check state.. must be returning.. */
|
|
if (pTracker->State != API_ST_WAIT_LCLACK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_STATE));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_STATE;
|
|
}
|
|
|
|
/* setup tracker object for new transaction */
|
|
pTracker->TransId = dwTransId;
|
|
|
|
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
|
|
|
|
switch (pTracker->u.Channel.ChannelType)
|
|
{
|
|
case API_CH_TYPE_UNI:
|
|
pTracker->State = API_ST_IDLE;
|
|
pTracker->u.Channel.TxChannel = 0;
|
|
lError = pdu_rsp_open_logical_channel_ack(pPdu,
|
|
wRxChannel,
|
|
pRxMux,
|
|
0,
|
|
NULL,
|
|
dwTxPort,
|
|
pSeparateStack);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
// If parameter error, we don't want to deallocate tracker
|
|
MemFree (pPdu);
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
}
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
break;
|
|
|
|
case API_CH_TYPE_BI:
|
|
pTracker->State = API_ST_WAIT_CONF; /* waiting for confirmation */
|
|
pTracker->u.Channel.TxChannel = wTxChannel;
|
|
lError = pdu_rsp_open_logical_channel_ack(pPdu,
|
|
wRxChannel,
|
|
pRxMux,
|
|
wTxChannel,
|
|
pTxMux,
|
|
dwTxPort,
|
|
pSeparateStack);
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
// If parameter error, we don't want to deallocate tracker
|
|
MemFree (pPdu);
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
}
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
break;
|
|
|
|
default:
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept: Invalid Tracker Channel Type %d",
|
|
pTracker->u.Channel.ChannelType);
|
|
lError = H245_ERROR_FATAL;
|
|
} // switch
|
|
|
|
MemFree (pPdu);
|
|
|
|
switch (lError)
|
|
{
|
|
case H245_ERROR_OK:
|
|
H245TRACE (dwInst,4,"H245OpenChannelAccept -> OK");
|
|
break;
|
|
|
|
default:
|
|
// Deallocate tracker object for all errors except parameter error
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
|
|
// Fall-through to next case is intentional
|
|
|
|
case H245_ERROR_PARAM:
|
|
// If parameter error, we don't want to deallocate tracker
|
|
H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(lError));
|
|
} // switch
|
|
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245OpenChannelAccept()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245OpenChannelReject
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245OpenChannelReject (
|
|
H245_INST_T dwInst,
|
|
H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
|
|
unsigned short wCause
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
Tracker_T * pTracker;
|
|
MltmdSystmCntrlMssg * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245OpenChannelReject <- wRxChannel=%d", wRxChannel);
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if channel not found in tracker list */
|
|
/* note that it looks for given channel given who alloced it */
|
|
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
|
|
|
|
/* not locking tracker.. since no indication will come in until I issue the request */
|
|
/* if not open.. invalid op */
|
|
if (pTracker == NULL || pTracker->TrackerType != API_OPEN_CHANNEL_T)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* for debug */
|
|
ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
|
|
ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
|
|
|
|
/* check state.. must be returning.. */
|
|
if (pTracker->State != API_ST_WAIT_LCLACK)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_STATE));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_STATE;
|
|
}
|
|
|
|
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
|
|
pdu_rsp_open_logical_channel_rej(pPdu, wRxChannel, wCause);
|
|
|
|
switch (pTracker->u.Channel.ChannelType)
|
|
{
|
|
case API_CH_TYPE_UNI:
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
break;
|
|
|
|
case API_CH_TYPE_BI:
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
break;
|
|
|
|
default:
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject: Invalid Tracker Channel Type %d",
|
|
pTracker->u.Channel.ChannelType);
|
|
lError = H245_ERROR_FATAL;
|
|
} // switch
|
|
|
|
MemFree (pPdu);
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245OpenChannelReject -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245OpenChannelReject()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245CloseChannel
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245CloseChannel (
|
|
* H245_INST_T dwInst,
|
|
* DWORD dwTransId,
|
|
* DWORD wTxChannel,
|
|
* )
|
|
* Description:
|
|
* Called to close a channel upon which the client previously
|
|
* issued an OpenChannel request.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* dwTransId User supplied object used to identify this
|
|
* request in the asynchronous confirm to this
|
|
* call.
|
|
* wChannel Logical Channel Number to close
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callbacks:
|
|
* H245_CONF_CLOSE
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM wChannel is not a locally opened
|
|
* channel
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid intance handle
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_INVALID_CHANNEL
|
|
* H245_ERROR_INVALID_OP Can not perform this operation on
|
|
* this channel.(See H245CloseChannelReq)
|
|
* See Also:
|
|
* H245OpenChannel
|
|
* H245OpenChannelIndResp
|
|
* H245OpenChannelConfResp
|
|
* H245CloseChannelReq
|
|
*
|
|
* callback
|
|
* H245_CONF_CLOSE
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CloseChannel (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_CHANNEL_T wTxChannel
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
Tracker_T *pTracker;
|
|
DWORD error;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245CloseChannel <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if channel not found in tracker list */
|
|
/* note that it looks for given channel given who alloced it */
|
|
pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
|
|
/* not locking tracker.. since no indication will come in until I issue the request */
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_CHANNEL;
|
|
}
|
|
|
|
/* setup new tracker state */
|
|
pTracker->State = API_ST_WAIT_RMTACK;
|
|
pTracker->TrackerType = API_CLOSE_CHANNEL_T;
|
|
pTracker->TransId = dwTransId;
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* ok.. get pdu */
|
|
pdu_req_close_logical_channel(pPdu, wTxChannel, 0/* user */);
|
|
|
|
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
MemFree (pPdu);
|
|
|
|
/* error.. so deallocate tracker structure */
|
|
if (error != H245_ERROR_OK)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(error));
|
|
}
|
|
else
|
|
{
|
|
H245TRACE (dwInst,4,"H245CloseChannel -> OK");
|
|
}
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
} // H245CloseChannel()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245CloseChannelReq
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245CloseChannelReq (
|
|
* H245_INST_T dwInst,
|
|
* DWORD dwTransId,
|
|
* DWORD wChannel,
|
|
* )
|
|
* Description:
|
|
* Called to request the remote peer to close a logical channel
|
|
* it previously opened
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* dwTransId User supplied object used to identify this
|
|
* request in the asynchronous confirm to this
|
|
* call
|
|
* wChannel Logical Channel Number to close
|
|
*
|
|
* Note: This is only asking permission. Even if the Close
|
|
* Request is accepted the channel still has to be closed from
|
|
* the remote side. (i.e. this does not close the channel it
|
|
* only asked the remote side it issue a close)
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callbacks:
|
|
* H245_CONF_CLOSE
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM wChannel is not a channel
|
|
* opened by remote peer
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance
|
|
* handle
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_INVALID_CHANNEL
|
|
* H245_ERROR_INVALID_OP Can not perform this operation
|
|
* on this channel
|
|
* (see H245CloseChannel)
|
|
* See Also:
|
|
* H245OpenChannel
|
|
* H245OpenChannelIndResp
|
|
* H245OpenChannelConfResp
|
|
* H245CloseChannel
|
|
*
|
|
* callback
|
|
*
|
|
* H245_CONF_CLOSE
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CloseChannelReq (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_CHANNEL_T wRxChannel
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
Tracker_T *pTracker;
|
|
DWORD error;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245CloseChannelReq <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if channel not found in tracker list */
|
|
/* note that it looks for given channel given who alloced it */
|
|
pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
|
|
/* not locking tracker.. since no indication will come in until I issue the request */
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* verify state of tracker */
|
|
pTracker->State = API_ST_WAIT_RMTACK;
|
|
pTracker->TrackerType = API_CLOSE_CHANNEL_T;
|
|
pTracker->TransId = dwTransId;
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* ok.. get pdu */
|
|
pdu_req_request_close_channel(pPdu, wRxChannel);
|
|
|
|
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
MemFree (pPdu);
|
|
if (error != H245_ERROR_OK)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(error));
|
|
}
|
|
else
|
|
H245TRACE (dwInst,4,"H245CloseChannelReq -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return error;
|
|
} // H245CloseChannelReq()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245CloseChannelReqResp
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245CloseChannelReqResp (
|
|
* H245_INST_T dwInst,
|
|
* H245_ACC_REJ_T AccRej,
|
|
* DWORD wChannel
|
|
* )
|
|
*
|
|
* Description:
|
|
* This routine is called to accept or reject a
|
|
* RequestChannelClose (H245_IND_REQ_CLOSE indication) from the
|
|
* remote peer. The channel must have been locally opened. The
|
|
* parameter AccRej is H245_ACC to accept or H245_REJ to reject
|
|
* the close. The local client should follow this response with
|
|
* a H245CloseChannel call.
|
|
*
|
|
* If there was a Release CloseChannelRequest event that
|
|
* occurred during this transaction there error code returned
|
|
* will be H245_ERROR_CANCELED. This indicates to the H.245
|
|
* client that no action should be taken.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245GetInstanceId
|
|
* AccRej this parameter contains either H245_ACC or
|
|
* H245_REJ. This indicates to H.245 which
|
|
* action to take.
|
|
* wChannel Logical Channel Number to close
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_PARAM
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_INVALID_CHANNEL
|
|
* H245_ERROR_INVALID_OP Can not perform this operation on this
|
|
* channel (see H245CloseChannel)
|
|
* H245_ERROR_INVALID_INST dwInst is not a valid instance handle
|
|
* H245_ERROR_CANCELED if release was received during the
|
|
* processing of this request..
|
|
* See Also:
|
|
* H245CloseChannel
|
|
*
|
|
* callback
|
|
*
|
|
* H245_IND_REQ_CLOSE
|
|
* H245_IND_CLOSE
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CloseChannelReqResp (
|
|
H245_INST_T dwInst,
|
|
H245_ACC_REJ_T AccRej,
|
|
H245_CHANNEL_T wChannel
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
Tracker_T *pTracker;
|
|
DWORD error;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245CloseChannelReqResp <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if channel not found in tracker list */
|
|
/* note that it looks for given channel given who alloced it */
|
|
pTracker = find_tracker_by_txchannel (pInstance, wChannel, API_CH_ALLOC_LCL);
|
|
|
|
/* not locking tracker.. since no indication will come in until I issue the request */
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* if the request was canceled.. tell useer */
|
|
if (pTracker->State == API_ST_WAIT_LCLACK_CANCEL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_CANCELED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_CANCELED;
|
|
}
|
|
|
|
/* verify state of tracker */
|
|
if ((pTracker->State != API_ST_WAIT_LCLACK) ||
|
|
(pTracker->TrackerType != API_CLOSE_CHANNEL_T))
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
/* set the state to idle.. expect this side to close the channel next */
|
|
pTracker->State = API_ST_IDLE;
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* ok.. get pdu */
|
|
if (AccRej == H245_ACC)
|
|
{
|
|
pTracker = NULL;
|
|
pdu_rsp_request_channel_close_ack(pPdu, wChannel);
|
|
}
|
|
else
|
|
{
|
|
pdu_rsp_request_channel_close_rej(pPdu, wChannel, AccRej);
|
|
}
|
|
|
|
error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
MemFree (pPdu);
|
|
if (error != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(error));
|
|
else
|
|
H245TRACE (dwInst,4,"H245CloseChannelReqResp ->");
|
|
InstanceUnlock(pInstance);
|
|
return error;
|
|
} // H245CloseChannelReqResp()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245SendLocalMuxTable
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245SendLocalMuxTable (
|
|
* H245_INST_T dwInst,
|
|
* DWORD dwTransId,
|
|
* H245_MUX_TABLE_T *pMuxTbl
|
|
* )
|
|
* Description:
|
|
* This routine is called to send a mux table to the remote
|
|
* side. The remote side can either reject or accept each mux
|
|
* table entry in a message. The confirm is sent back to the
|
|
* calling H.245 client based on the acceptance or non
|
|
* acceptance of each Mux table entry with H245_CONF_MUXTBL_SND.
|
|
*
|
|
* This is a fairly dangerous call, since the mux table
|
|
* structure is a linked lise of mux table entries. Invalid
|
|
* data structures could cause an access error. Example code is
|
|
* supplied in the appendix.
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* dwTransId User supplied object used to identify
|
|
* this request in the asynchronous
|
|
* confirm to this call.
|
|
* pMuxTbl Mux table entry structure
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Callbacks:
|
|
* H245_CONF_MUXTBLSND
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_INVALID_MUXTBLENTRY
|
|
* H245_ERROR_PARAM
|
|
* H245_ERROR_INVALID_INST
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_NOMEM
|
|
*
|
|
* See Also:
|
|
* APPENDIX Examples
|
|
*
|
|
* callback
|
|
*
|
|
* H245_CONF_MUXTBL_SND
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SendLocalMuxTable (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_MUX_TABLE_T *pMuxTable
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
Tracker_T *pTracker;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245SendLocalMuxTable <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* make sure parameters ar ok.. */
|
|
if (!pMuxTable)
|
|
{
|
|
H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
/* allocate tracker for event */
|
|
pTracker = alloc_link_tracker (pInstance,
|
|
API_SEND_MUX_T,
|
|
dwTransId,
|
|
API_ST_WAIT_RMTACK,
|
|
API_CH_ALLOC_UNDEF,
|
|
API_CH_TYPE_UNDEF,
|
|
0,
|
|
H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
|
|
0);
|
|
if (pTracker == NULL)
|
|
{
|
|
H245TRACE(dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
|
|
// Allocate PDU buffer
|
|
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
|
|
if (pPdu == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",H245_ERROR_NOMEM);
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
lError = pdu_req_send_mux_table(pInstance,
|
|
pPdu,
|
|
pMuxTable,
|
|
0,
|
|
&pTracker->u.MuxEntryCount);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
|
|
|
|
/* free the list just built */
|
|
free_mux_desc_list(pPdu->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend.multiplexEntryDescriptors);
|
|
}
|
|
|
|
/* free the pdu */
|
|
MemFree (pPdu);
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
{
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(lError));
|
|
}
|
|
else
|
|
H245TRACE (dwInst,4,"H245SendLocalMuxTable -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245SendLocalMuxTable()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245MuxTableIndResp
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245MuxTableIndResp (
|
|
* H45_INST_T dwInst,
|
|
* H245_ACC_REJ_MUX_T AccRejMux,
|
|
* DWORD Count
|
|
* )
|
|
* Description:
|
|
* This procedure is called to either accept or reject mux
|
|
* table entries sent up in the H245_IND_MUX_TBL indication.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* AccRejMux Accept Reject Mux structure
|
|
* Count number of entries in the structure
|
|
*
|
|
* Call Type:
|
|
* Asynchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_INVALID_MUXTBLENTRY
|
|
* H245_ERROR_PARAM
|
|
* H245_ERROR_INVALID_INST
|
|
* H245_ERROR_INVALID_OP
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_NOMEM
|
|
* See Also:
|
|
* H245SendLocalMuxTable
|
|
*
|
|
* callback
|
|
*
|
|
* H245_IND_MUX_TBL
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MuxTableIndResp (
|
|
H245_INST_T dwInst,
|
|
H245_ACC_REJ_MUX_T AccRejMux,
|
|
unsigned long dwCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
DWORD ii;
|
|
Tracker_T *pTracker;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245MuxTableIndResp <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* look for tracker.. */
|
|
pTracker = NULL;
|
|
pTracker = find_tracker_by_type (pInstance, API_RECV_MUX_T, pTracker);
|
|
|
|
/* if tracker not found.. issue invalid op */
|
|
if (!pTracker)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_OP;
|
|
}
|
|
|
|
ASSERT (pTracker->State == API_ST_WAIT_LCLACK);
|
|
|
|
/* can't ack or reject more than you got */
|
|
if ((dwCount > pTracker->u.MuxEntryCount) ||
|
|
(dwCount > 15))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
/* verify the mux table entry id's */
|
|
for (ii=0;ii<dwCount;ii++)
|
|
{
|
|
if ((AccRejMux[ii].MuxEntryId > 15) ||
|
|
(AccRejMux[ii].MuxEntryId <= 0))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
}
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* if there are any rejects in the list.. send reject */
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
if (pdu_rsp_mux_table_rej (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
|
|
FsmOutgoing(pInstance, pPdu, 0);
|
|
|
|
/* if there are any accepts in the list.. send accept */
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
if (pdu_rsp_mux_table_ack (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
|
|
FsmOutgoing(pInstance, pPdu, 0);
|
|
|
|
/* if we've acked all the entries */
|
|
if (!(pTracker->u.MuxEntryCount -= dwCount))
|
|
unlink_dealloc_tracker (pInstance, pTracker);
|
|
|
|
MemFree (pPdu);
|
|
H245TRACE (dwInst,4,"H245MuxTableIndResp -> %s",H245_ERROR_OK);
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_OK;
|
|
|
|
} // H245MuxTableIndResp()
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245MiscCommand
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245MiscCommand (
|
|
* H245_INST_T dwInst,
|
|
* DWORD wChannel,
|
|
* H245_MISC_T *pMisc
|
|
* )
|
|
* Description:
|
|
* Send a Misc. command to the remote side (see H245_MISC_T
|
|
* data Structure)
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* wChannel Logical Channel Number
|
|
* pMisc pointer to a misc. command structure
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_INVALID_CHANNEL
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_PARAM
|
|
* H245_ERROR_INVALID_INST
|
|
*
|
|
* callback
|
|
*
|
|
* H245_IND_MISC
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT H245MiscCommand (
|
|
H245_INST_T dwInst,
|
|
WORD wChannel,
|
|
H245_MISC_T *pMisc
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
|
|
H245TRACE (dwInst,4,"H245MiscCommand <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
/* system should be in connected state */
|
|
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
/* if the channel can not be found */
|
|
if (!find_tracker_by_txchannel(pInstance, wChannel, API_CH_ALLOC_LCL) &&
|
|
!find_tracker_by_rxchannel(pInstance, wChannel, API_CH_ALLOC_RMT))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_INVALID_CHANNEL;
|
|
}
|
|
|
|
if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* budld pdu for misc command */
|
|
pdu_cmd_misc (pPdu, pMisc, wChannel);
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree (pPdu);
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MiscCommand -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MiscCommand()
|
|
|
|
#endif
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestMultiplexEntry
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestMultiplexEntry (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
const unsigned short * pwMultiplexTableEntryNumbers,
|
|
unsigned long dwCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
DWORD dwIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntry <-");
|
|
|
|
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
{
|
|
if (pwMultiplexTableEntryNumbers[dwIndex] < 1 ||
|
|
pwMultiplexTableEntryNumbers[dwIndex] > 15)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMultiplexEntry_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count = (WORD)dwCount;
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
{
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex] =
|
|
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
|
|
}
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntry -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestMultiplexEntry()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestMultiplexEntryAck
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestMultiplexEntryAck (
|
|
H245_INST_T dwInst,
|
|
const unsigned short * pwMultiplexTableEntryNumbers,
|
|
unsigned long dwCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
DWORD dwIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck <-");
|
|
|
|
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = requestMultiplexEntryAck_chosen;
|
|
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count = (WORD)dwCount;
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
{
|
|
pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex] =
|
|
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
|
|
}
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestMultiplexEntryAck()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestMultiplexEntryReject
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestMultiplexEntryReject (
|
|
H245_INST_T dwInst,
|
|
const unsigned short * pwMultiplexTableEntryNumbers,
|
|
unsigned long dwCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
DWORD dwIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject <-");
|
|
|
|
if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = rqstMltplxEntryRjct_chosen;
|
|
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count = (WORD)dwCount;
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
{
|
|
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber =
|
|
(MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
|
|
pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].cause.choice = RMERDs_cs_unspcfdCs_chosen;
|
|
}
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestMultiplexEntryReject()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestMode
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestMode (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
// const ModeElement * pModeElements,
|
|
//[email protected]
|
|
ModeDescription ModeDescriptions[],
|
|
//[email protected]
|
|
unsigned long dwCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
RequestedModesLink pLink;
|
|
RequestedModesLink pLink_First;
|
|
DWORD dwIndex;
|
|
// [email protected]
|
|
ULONG ulPDUsize;
|
|
// [email protected]
|
|
|
|
H245TRACE (dwInst,4,"H245RequestMode <-");
|
|
|
|
//[email protected]
|
|
// if (pModeElements == NULL || dwCount == 0 || dwCount > 256)
|
|
if (ModeDescriptions == NULL || dwCount == 0 || dwCount > 256)
|
|
//[email protected]
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
//[email protected]
|
|
// pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + sizeof(*pLink));
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
|
|
//[email protected]
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
USHORT usModeDescIndex =0;
|
|
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMode_chosen;
|
|
//[email protected]
|
|
// pLink = (RequestedModesLink)(pPdu + 1);
|
|
pLink = (RequestedModesLink)(pPdu + usModeDescIndex+1);
|
|
//[email protected]
|
|
|
|
//[email protected]
|
|
// pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink;
|
|
//[email protected]
|
|
|
|
//[email protected]
|
|
pLink_First = pLink;
|
|
//[email protected]
|
|
// --> linked list of mode descriptions ... up to 1..256
|
|
//[email protected]
|
|
while(usModeDescIndex<=(dwCount-1))
|
|
{
|
|
//[email protected]
|
|
|
|
//[email protected]
|
|
// pLink->next = NULL;
|
|
//[email protected]
|
|
|
|
|
|
|
|
// --> number of actual mode-elements associated with this mode description
|
|
//[email protected]
|
|
// pLink->value.count = (WORD)dwCount;
|
|
pLink->value.count = (WORD)ModeDescriptions[usModeDescIndex].count;
|
|
//[email protected]
|
|
|
|
// for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
for (dwIndex = 0; dwIndex < ModeDescriptions[usModeDescIndex].count; ++dwIndex)
|
|
{
|
|
//[email protected]
|
|
// pLink->value.value[dwIndex] = pModeElements[dwIndex];
|
|
pLink->value.value[dwIndex] = ModeDescriptions[usModeDescIndex].value[dwIndex];
|
|
//[email protected]
|
|
}
|
|
//[email protected]
|
|
usModeDescIndex++;
|
|
if(usModeDescIndex<=(dwCount-1))
|
|
{
|
|
pLink->next = (RequestedModesLink)(pPdu + usModeDescIndex+1);
|
|
pLink = pLink->next;
|
|
pLink->next = NULL;
|
|
}
|
|
//[email protected]
|
|
|
|
|
|
//[email protected]
|
|
}
|
|
//[email protected]
|
|
|
|
//[email protected]
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink_First;
|
|
//[email protected]
|
|
//--
|
|
ulPDUsize = (sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
|
|
//--
|
|
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestMode -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestMode()
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestModeAck
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestModeAck (
|
|
H245_INST_T dwInst,
|
|
unsigned short wResponse
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245RequestModeAck <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = requestModeAck_chosen;
|
|
pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice = wResponse;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestModeAck -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestModeAck()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RequestModeReject
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RequestModeReject (
|
|
H245_INST_T dwInst,
|
|
unsigned short wCause
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245RequestModeReject <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = requestModeReject_chosen;
|
|
pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice = wCause;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RequestModeReject -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RequestModeReject()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245RoundTripDelayRequest
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245RoundTripDelayRequest (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245RoundTripDelayRequest <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = roundTripDelayRequest_chosen;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245RoundTripDelayRequest -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245RoundTripDelayRequest()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245MaintenanceLoop
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MaintenanceLoop (
|
|
H245_INST_T dwInst,
|
|
DWORD_PTR dwTransId,
|
|
H245_LOOP_TYPE_T dwLoopType,
|
|
H245_CHANNEL_T wChannel
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoop <-");
|
|
|
|
if (dwLoopType < systemLoop_chosen ||
|
|
dwLoopType > logicalChannelLoop_chosen ||
|
|
(dwLoopType != systemLoop_chosen && wChannel == 0))
|
|
{
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = maintenanceLoopRequest_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice = (WORD)dwLoopType;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop = wChannel;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, dwTransId);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoop -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MaintenanceLoop()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245MaintenanceLoopRelease
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MaintenanceLoopRelease (H245_INST_T dwInst)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopRelease <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = mntnncLpOffCmmnd_chosen;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopRelease -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MaintenanceLoopRelease()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245MaintenanceLoopAccept
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MaintenanceLoopAccept (
|
|
H245_INST_T dwInst,
|
|
H245_CHANNEL_T wChannel
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopAccept <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = maintenanceLoopAck_chosen;
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop = wChannel;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopAccept -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MaintenanceLoopAccept()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245MaintenanceLoopReject
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MaintenanceLoopReject (
|
|
H245_INST_T dwInst,
|
|
H245_CHANNEL_T wChannel,
|
|
unsigned short wCause
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopReject <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = maintenanceLoopReject_chosen;
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop = wChannel;
|
|
pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.cause.choice = wCause;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MaintenanceLoopReject -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MaintenanceLoopReject()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245NonStandardObject
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245NonStandardObject (
|
|
H245_INST_T dwInst,
|
|
H245_MESSAGE_TYPE_T MessageType,
|
|
const unsigned char * pData,
|
|
unsigned long dwDataLength,
|
|
const unsigned short * pwObjectId,
|
|
unsigned long dwObjectIdLength
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
POBJECTID pObject;
|
|
|
|
H245TRACE (dwInst,4,"H245NonStandardObject <-");
|
|
|
|
if (pData == NULL || dwDataLength == 0 || pwObjectId == NULL || dwObjectIdLength == 0)
|
|
{
|
|
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + dwObjectIdLength * sizeof(*pObject));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
switch (MessageType)
|
|
{
|
|
case H245_MESSAGE_REQUEST:
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_RESPONSE:
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_COMMAND:
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_INDICATION:
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
} // switch
|
|
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = object_chosen;
|
|
|
|
// Copy the object identifier
|
|
pObject = (POBJECTID) (pPdu + 1);
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object = pObject;
|
|
do
|
|
{
|
|
pObject->next = pObject + 1;
|
|
pObject->value = *pwObjectId++;
|
|
++pObject;
|
|
} while (--dwObjectIdLength);
|
|
|
|
// Null terminate the linked list
|
|
--pObject;
|
|
pObject->next = NULL;
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245NonStandardObject -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245NonStandardObject()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245NonStandardH221
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245NonStandardH221 (
|
|
H245_INST_T dwInst,
|
|
H245_MESSAGE_TYPE_T MessageType,
|
|
const unsigned char * pData,
|
|
unsigned long dwDataLength,
|
|
unsigned char byCountryCode,
|
|
unsigned char byExtension,
|
|
unsigned short wManufacturerCode
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245NonStandard221 <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
switch (MessageType)
|
|
{
|
|
case H245_MESSAGE_REQUEST:
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_RESPONSE:
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_COMMAND:
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
case H245_MESSAGE_INDICATION:
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
|
|
break;
|
|
|
|
default:
|
|
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_PARAM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_PARAM;
|
|
} // switch
|
|
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = h221NonStandard_chosen;
|
|
|
|
// Fill in the H.221 identifier
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = byCountryCode;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension = byExtension;
|
|
pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = wManufacturerCode;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245NonStandardH221 -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245NonStandardH221
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CommunicationModeRequest
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CommunicationModeRequest(H245_INST_T dwInst)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245CommunicationModeRequest <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = communicationModeRequest_chosen;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245CommunicationModeRequest -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245CommunicationModeRequest
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CommunicationModeResponse
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CommunicationModeResponse(
|
|
H245_INST_T dwInst,
|
|
const H245_COMM_MODE_ENTRY_T *pTable,
|
|
unsigned char byTableCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError = H245_ERROR_OK;
|
|
CommunicationModeTableLink pLink;
|
|
unsigned int uIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245CommunicationModeResponse <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = cmmnctnMdRspns_chosen;
|
|
pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice = communicationModeTable_chosen;
|
|
pLink = (CommunicationModeTableLink)(pPdu + 1);
|
|
pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable = pLink;
|
|
for (uIndex = 0; uIndex < byTableCount; ++uIndex)
|
|
{
|
|
pLink[uIndex].next = &pLink[uIndex + 1];
|
|
lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
|
|
if (lError != H245_ERROR_OK)
|
|
break;
|
|
}
|
|
pLink[byTableCount - 1].next = NULL;
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
}
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245CommunicationModeResponse -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245CommunicationModeResponse()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245CommunicationModeCommand
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245CommunicationModeCommand(
|
|
H245_INST_T dwInst,
|
|
const H245_COMM_MODE_ENTRY_T *pTable,
|
|
unsigned char byTableCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError = H245_ERROR_OK;
|
|
CommunicationModeCommandLink pLink;
|
|
unsigned int uIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245CommunicationModeCommand <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = communicationModeCommand_chosen;
|
|
pLink = (CommunicationModeCommandLink)(pPdu + 1);
|
|
pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable = pLink;
|
|
for (uIndex = 0; uIndex < byTableCount; ++uIndex)
|
|
{
|
|
pLink[uIndex].next = &pLink[uIndex + 1];
|
|
lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
|
|
if (lError != H245_ERROR_OK)
|
|
break;
|
|
}
|
|
pLink[byTableCount - 1].next = NULL;
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
}
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245CommunicationModeCommand -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245CommunicationModeCommand()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245ConferenceRequest
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245ConferenceRequest (
|
|
H245_INST_T dwInst,
|
|
H245_CONFER_REQ_ENUM_T RequestType,
|
|
unsigned char byMcuNumber,
|
|
unsigned char byTerminalNumber
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245ConferenceRequest <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.choice = conferenceRequest_chosen;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice = (WORD)RequestType;
|
|
switch (RequestType)
|
|
{
|
|
case dropTerminal_chosen:
|
|
case requestTerminalID_chosen:
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber = byMcuNumber;
|
|
pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber = byTerminalNumber;
|
|
|
|
// Fall-through to next case is intentional
|
|
|
|
case terminalListRequest_chosen:
|
|
case makeMeChair_chosen:
|
|
case cancelMakeMeChair_chosen:
|
|
case enterH243Password_chosen:
|
|
case enterH243TerminalID_chosen:
|
|
case enterH243ConferenceID_chosen:
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_PARAM;
|
|
} // switch
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245ConferenceRequest -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245ConferenceRequest()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245ConferenceResponse
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245ConferenceResponse (
|
|
H245_INST_T dwInst,
|
|
H245_CONFER_RSP_ENUM_T ResponseType,
|
|
unsigned char byMcuNumber,
|
|
unsigned char byTerminalNumber,
|
|
const unsigned char *pOctetString,
|
|
unsigned char byOctetStringLength,
|
|
const TerminalLabel *pTerminalList,
|
|
unsigned short wTerminalListCount
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
unsigned uIndex;
|
|
|
|
H245TRACE (dwInst,4,"H245ConferenceResponse <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_rspns_chosen;
|
|
pPdu->u.MSCMg_rspns.choice = conferenceResponse_chosen;
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = (WORD)ResponseType;
|
|
switch (ResponseType)
|
|
{
|
|
case mCTerminalIDResponse_chosen:
|
|
case terminalIDResponse_chosen:
|
|
case conferenceIDResponse_chosen:
|
|
case passwordResponse_chosen:
|
|
if (pOctetString == NULL ||
|
|
byOctetStringLength == 0 ||
|
|
byOctetStringLength > 128)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber = byMcuNumber;
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber = byTerminalNumber;
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length = byOctetStringLength;
|
|
memcpy(pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value,
|
|
pOctetString,
|
|
byOctetStringLength);
|
|
|
|
// Fall-through to next case is intentional
|
|
|
|
case videoCommandReject_chosen:
|
|
case terminalDropReject_chosen:
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case terminalListResponse_chosen:
|
|
if (pTerminalList == NULL ||
|
|
wTerminalListCount == 0 ||
|
|
wTerminalListCount > 256)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
|
|
return H245_ERROR_PARAM;
|
|
}
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count = wTerminalListCount;
|
|
for (uIndex = 0; uIndex < wTerminalListCount; ++uIndex)
|
|
{
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value[uIndex] =
|
|
pTerminalList[uIndex];
|
|
}
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case H245_RSP_DENIED_CHAIR_TOKEN:
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = deniedChairToken_chosen;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case H245_RSP_GRANTED_CHAIR_TOKEN:
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
|
|
pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = grantedChairToken_chosen;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_PARAM;
|
|
} // switch
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245ConferenceResponse -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245ConferenceResponse()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245ConferenceCommand
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245ConferenceCommand (
|
|
H245_INST_T dwInst,
|
|
H245_CONFER_CMD_ENUM_T CommandType,
|
|
H245_CHANNEL_T Channel,
|
|
unsigned char byMcuNumber,
|
|
unsigned char byTerminalNumber
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245ConferenceCommand <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = conferenceCommand_chosen;
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice = (WORD)CommandType;
|
|
switch (CommandType)
|
|
{
|
|
case brdcstMyLgclChnnl_chosen:
|
|
case cnclBrdcstMyLgclChnnl_chosen:
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl = Channel;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case ConferenceCommand_makeTerminalBroadcaster_chosen:
|
|
case ConferenceCommand_sendThisSource_chosen:
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.mcuNumber = byMcuNumber;
|
|
pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.terminalNumber = byTerminalNumber;
|
|
|
|
// Fall-through to next case is intentional
|
|
|
|
case cnclMkTrmnlBrdcstr_chosen:
|
|
case cancelSendThisSource_chosen:
|
|
case dropConference_chosen:
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_PARAM;
|
|
} // switch
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245ConferenceCommand -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245ConferenceCommand()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245ConferenceIndication
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245ConferenceIndication(
|
|
H245_INST_T dwInst,
|
|
H245_CONFER_IND_ENUM_T IndicationType,
|
|
unsigned char bySbeNumber,
|
|
unsigned char byMcuNumber,
|
|
unsigned char byTerminalNumber
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245ConferenceIndication <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = conferenceIndication_chosen;
|
|
pPdu->u.indication.u.conferenceIndication.choice = (WORD)IndicationType;
|
|
switch (IndicationType)
|
|
{
|
|
case sbeNumber_chosen:
|
|
pPdu->u.indication.u.conferenceIndication.u.sbeNumber = bySbeNumber;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case terminalNumberAssign_chosen:
|
|
case terminalJoinedConference_chosen:
|
|
case terminalLeftConference_chosen:
|
|
case terminalYouAreSeeing_chosen:
|
|
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber = byMcuNumber;
|
|
pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber = byTerminalNumber;
|
|
|
|
// Fall-through to next case is intentional
|
|
|
|
case seenByAtLeastOneOther_chosen:
|
|
case cnclSnByAtLstOnOthr_chosen:
|
|
case seenByAll_chosen:
|
|
case cancelSeenByAll_chosen:
|
|
case requestForFloor_chosen:
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_PARAM;
|
|
} // switch
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245ConferenceIndication -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245ConferenceIndication()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245UserInput
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245UserInput (
|
|
* H245_INST_T dwInst,
|
|
* char *pGenString,
|
|
* H245_NONSTANDARD_PARAMETER_T *pNonStd
|
|
* )
|
|
* Description:
|
|
*
|
|
* Send a User Input indiation to the remote side. One of the
|
|
* two parameters must be set (pGenString, pNonStd). The client
|
|
* can either send a string or a NonStandard parameter set to the
|
|
* remote client. Only one of the two parameters can contain a
|
|
* value. The other is required to be NULL.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* pGenString choice: String to be sent to remote
|
|
* side in accordance with T.51 specification.
|
|
* pNonStd choice: NonStandard Parameter
|
|
*
|
|
* Call Type:
|
|
* Synchronous
|
|
*
|
|
* Return Values:
|
|
* See Errors
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
* H245_ERROR_NOT_CONNECTED
|
|
* H245_ERROR_NOMEM
|
|
* H245_ERROR_PARAM
|
|
*
|
|
* callback
|
|
* H245_IND_USERINPUT
|
|
*
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245UserInput (
|
|
H245_INST_T dwInst,
|
|
const WCHAR * pGenString,
|
|
const H245_NONSTANDARD_PARAMETER_T * pNonStd
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
MltmdSystmCntrlMssg *pPdu;
|
|
#if 1
|
|
int nLength;
|
|
char * pszGeneral = NULL;
|
|
#endif
|
|
|
|
H245TRACE (dwInst,4,"H245UserInput <-");
|
|
|
|
/* check for valid instance handle */
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
/* system should be in connected state */
|
|
if (pInstance->API.SystemState != APIST_Connected)
|
|
{
|
|
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOT_CONNECTED;
|
|
}
|
|
|
|
pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
|
|
if (pPdu == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
|
|
|
|
/* build PDU */
|
|
#if 1
|
|
if (pGenString)
|
|
{
|
|
nLength = WideCharToMultiByte(CP_ACP, // code page
|
|
0, // dwFlags
|
|
pGenString, // Unicode string
|
|
-1, // Unicode string length (bytes)
|
|
NULL, // ASCII string
|
|
0, // max ASCII string length
|
|
NULL, // default character
|
|
NULL); // default character used
|
|
pszGeneral = MemAlloc(nLength);
|
|
if (pszGeneral == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
|
|
InstanceUnlock(pInstance);
|
|
return H245_ERROR_NOMEM;
|
|
}
|
|
nLength = WideCharToMultiByte(CP_ACP, // code page
|
|
0, // dwFlags
|
|
pGenString, // Unicode string
|
|
-1, // Unicode string length (bytes)
|
|
pszGeneral, // ASCII string
|
|
nLength, // max ASCII string length
|
|
NULL, // default character
|
|
NULL); // default character used
|
|
lError = pdu_ind_usrinpt (pPdu, NULL, pszGeneral);
|
|
}
|
|
else
|
|
{
|
|
lError = pdu_ind_usrinpt (pPdu, pNonStd, NULL);
|
|
}
|
|
#else
|
|
lError = pdu_ind_usrinpt (pPdu, pNonStd, pGenString);
|
|
#endif
|
|
if (lError == H245_ERROR_OK)
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
#if 1
|
|
if (pszGeneral)
|
|
MemFree(pszGeneral);
|
|
#endif
|
|
MemFree (pPdu);
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245UserInput -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245UserInput()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245FlowControl
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245FlowControl (
|
|
H245_INST_T dwInst,
|
|
H245_SCOPE_T Scope,
|
|
H245_CHANNEL_T Channel, // only used if Scope is H245_SCOPE_CHANNEL_NUMBER
|
|
unsigned short wResourceID, // only used if Scope is H245_SCOPE_RESOURCE_ID
|
|
unsigned long dwRestriction // H245_NO_RESTRICTION if no restriction
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245FlowControl <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = MSCMg_cmmnd_chosen;
|
|
pPdu->u.MSCMg_cmmnd.choice = flowControlCommand_chosen;
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice = (WORD)Scope;
|
|
if (dwRestriction == H245_NO_RESTRICTION)
|
|
{
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = noRestriction_chosen;
|
|
}
|
|
else
|
|
{
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = maximumBitRate_chosen;
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate = dwRestriction;
|
|
}
|
|
switch (Scope)
|
|
{
|
|
case FCCd_scp_lgclChnnlNmbr_chosen:
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr = Channel;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
case FlwCntrlCmmnd_scp_rsrcID_chosen:
|
|
pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID = wResourceID;
|
|
|
|
// Fall-through to next case
|
|
|
|
case FCCd_scp_whlMltplx_chosen:
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_PARAM;
|
|
} // switch
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245FlowControl -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245FlowControl()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245H223SkewIndication
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245H223SkewIndication (
|
|
H245_INST_T dwInst,
|
|
H245_CHANNEL_T wLogicalChannelNumber1,
|
|
H245_CHANNEL_T wLogicalChannelNumber2,
|
|
unsigned short wSkew
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245H223SkewIndication <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = h223SkewIndication_chosen;
|
|
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1 = wLogicalChannelNumber1;
|
|
pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2 = wLogicalChannelNumber2;
|
|
pPdu->u.indication.u.h223SkewIndication.skew = wSkew;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245H223SkewIndication -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245H223SkewIndication()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245H2250MaximumSkewIndication
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245H2250MaximumSkewIndication(
|
|
H245_INST_T dwInst,
|
|
H245_CHANNEL_T wLogicalChannelNumber1,
|
|
H245_CHANNEL_T wLogicalChannelNumber2,
|
|
unsigned short wMaximumSkew
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = h2250MxmmSkwIndctn_chosen;
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1 = wLogicalChannelNumber1;
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2 = wLogicalChannelNumber2;
|
|
pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew = wMaximumSkew;
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245H2250MaximumSkewIndication()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245MCLocationIndication
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245MCLocationIndication(
|
|
H245_INST_T dwInst,
|
|
const H245_TRANSPORT_ADDRESS_T * pSignalAddress
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245MCLocationIndication <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = mcLocationIndication_chosen;
|
|
lError = SetupTransportAddress(&pPdu->u.indication.u.mcLocationIndication.signalAddress,
|
|
pSignalAddress);
|
|
if (lError == H245_ERROR_OK)
|
|
{
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
}
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245MCLocationIndication -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245MCLocationIndication()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245VendorIdentification
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245VendorIdentification(
|
|
H245_INST_T dwInst,
|
|
const H245_NONSTANDID_T *pIdentifier,
|
|
const unsigned char *pProductNumber,
|
|
unsigned char byProductNumberLength,
|
|
const unsigned char *pVersionNumber,
|
|
unsigned char byVersionNumberLength
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
register PDU_T * pPdu;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245VendorIdentification <-");
|
|
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
|
|
if (pPdu == NULL)
|
|
{
|
|
lError = H245_ERROR_NOMEM;
|
|
}
|
|
else
|
|
{
|
|
memset(pPdu, 0, sizeof(*pPdu));
|
|
pPdu->choice = indication_chosen;
|
|
pPdu->u.indication.choice = vendorIdentification_chosen;
|
|
pPdu->u.indication.u.vendorIdentification.bit_mask = 0;
|
|
pPdu->u.indication.u.vendorIdentification.vendor = *pIdentifier;
|
|
if (pProductNumber != NULL && byProductNumberLength != 0)
|
|
{
|
|
pPdu->u.indication.u.vendorIdentification.bit_mask |= productNumber_present;
|
|
pPdu->u.indication.u.vendorIdentification.productNumber.length = byProductNumberLength;
|
|
memcpy(pPdu->u.indication.u.vendorIdentification.productNumber.value,
|
|
pProductNumber,
|
|
byProductNumberLength);
|
|
}
|
|
if (pVersionNumber != NULL && byVersionNumberLength != 0)
|
|
{
|
|
pPdu->u.indication.u.vendorIdentification.bit_mask |= versionNumber_present;
|
|
pPdu->u.indication.u.vendorIdentification.versionNumber.length = byVersionNumberLength;
|
|
memcpy(pPdu->u.indication.u.vendorIdentification.versionNumber.value,
|
|
pVersionNumber,
|
|
byVersionNumberLength);
|
|
}
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
MemFree(pPdu);
|
|
}
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245VendorIdentification -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245VendorIdentification()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
* PROCEDURE: H245SendPDU
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SendPDU (
|
|
H245_INST_T dwInst,
|
|
PDU_T * pPdu
|
|
)
|
|
{
|
|
register struct InstanceStruct *pInstance;
|
|
HRESULT lError;
|
|
|
|
H245TRACE (dwInst,4,"H245SendPDU <-");
|
|
|
|
// Check for valid instance handle
|
|
pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(H245_ERROR_INVALID_INST));
|
|
return H245_ERROR_INVALID_INST;
|
|
}
|
|
|
|
lError = FsmOutgoing(pInstance, pPdu, 0);
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE (dwInst,4,"H245SendPDU -> OK");
|
|
InstanceUnlock(pInstance);
|
|
return lError;
|
|
} // H245SendPDU()
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* TYPE: H245 API
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* PROCEDURE: H245SystemControl
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* HRESULT H245SystemControl
|
|
* ( H245_INST_T dwInst,
|
|
* DWORD Request ,
|
|
* VOID *pData
|
|
* )
|
|
*
|
|
* Description:
|
|
* This function should not be used by clients who
|
|
* normally interface to the H.245 subsystem. It is
|
|
* defined here to help during development and debug
|
|
* of the H.245 subsystem.
|
|
*
|
|
* This is a roll your own.. and can do what
|
|
* ever the user needs.. It's a hook to allow
|
|
* IOCTL (unix) calls that can either be
|
|
* passed to lower stack elements (AT&T Streams IOCTL
|
|
* would be an example - :) or simply to get or put
|
|
* information to the H245 SubSytem.
|
|
*
|
|
* Input
|
|
* dwInst Instance handle returned by H245Init
|
|
* Request Requested system control
|
|
* pData In the case of sending information
|
|
* down to H.245 this is an input
|
|
* parameter, and it's data format
|
|
* is determined by the Request.
|
|
* output
|
|
* pData In the case of retrieving information
|
|
* from H.245 this can be an output
|
|
* parameter, and it's data format is
|
|
* determined by the Request. It may not
|
|
* have valid data if the request is a
|
|
* synchronous request. (See Request Options).
|
|
* Call Type:
|
|
*
|
|
* Synchronous
|
|
*
|
|
* Request Options:
|
|
*
|
|
* H245_SYSCON_GET_STATS Retrieves Statistics
|
|
* from H.245 subsystem
|
|
* parameter pData = &H245_SYSCON_STAT_T
|
|
* H245_ SYSCON_RESET_STATS Resets the statistics
|
|
* pData = NULL
|
|
* H245_SYS_TRACE Set Trace Level
|
|
* pData = &DWORD (Trace Level)
|
|
*
|
|
* Return Values:
|
|
* See Request Options
|
|
*
|
|
* Errors:
|
|
* H245_ERROR_OK
|
|
*
|
|
* RETURN:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
H245DLL HRESULT
|
|
H245SystemControl (
|
|
H245_INST_T dwInst,
|
|
unsigned long dwRequest,
|
|
void * pData
|
|
)
|
|
{
|
|
HRESULT lError;
|
|
DWORD dwTemp;
|
|
|
|
H245TRACE(dwInst,4,"H245SystemControl <-");
|
|
|
|
if (dwRequest == H245_SYSCON_DUMP_TRACKER)
|
|
{
|
|
register struct InstanceStruct *pInstance = InstanceLock(dwInst);
|
|
if (pInstance == NULL)
|
|
{
|
|
lError = H245_ERROR_INVALID_INST;
|
|
}
|
|
else
|
|
{
|
|
dump_tracker(pInstance);
|
|
InstanceUnlock(pInstance);
|
|
lError = H245_ERROR_OK;
|
|
}
|
|
}
|
|
else if (pData == NULL)
|
|
{
|
|
lError = H245_ERROR_PARAM;
|
|
}
|
|
else
|
|
{
|
|
lError = H245_ERROR_OK;
|
|
switch (dwRequest)
|
|
{
|
|
case H245_SYSCON_GET_FSM_N100:
|
|
*((DWORD *)pData) = (DWORD) uN100;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get N100 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T101:
|
|
*((DWORD *)pData) = (DWORD) uT101;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T101 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T102:
|
|
*((DWORD *)pData) = (DWORD) uT102;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T102 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T103:
|
|
*((DWORD *)pData) = (DWORD) uT103;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T103 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T104:
|
|
*((DWORD *)pData) = (DWORD) uT104;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T104 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T105:
|
|
*((DWORD *)pData) = (DWORD) uT105;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T105 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T106:
|
|
*((DWORD *)pData) = (DWORD) uT106;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T106 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T107:
|
|
*((DWORD *)pData) = (DWORD) uT107;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T107 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T108:
|
|
*((DWORD *)pData) = (DWORD) uT108;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T108 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_GET_FSM_T109:
|
|
*((DWORD *)pData) = (DWORD) uT109;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Get T109 = %d",*((DWORD *)pData));
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_N100:
|
|
dwTemp = (DWORD) uN100;
|
|
uN100 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set N100 = %d",uN100);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T101:
|
|
dwTemp = (DWORD) uT101;
|
|
uT101 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T101 = %d",uT101);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T102:
|
|
dwTemp = (DWORD) uT102;
|
|
uT102 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T102 = %d",uT102);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T103:
|
|
dwTemp = (DWORD) uT103;
|
|
uT103 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T103 = %d",uT103);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T104:
|
|
dwTemp = (DWORD) uT104;
|
|
uT104 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T104 = %d",uT104);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T105:
|
|
dwTemp = (DWORD) uT105;
|
|
uT105 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T105 = %d",uT105);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T106:
|
|
dwTemp = (DWORD) uT106;
|
|
uT106 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T106 = %d",uT106);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T107:
|
|
dwTemp = (DWORD) uT107;
|
|
uT107 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T107 = %d",uT107);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T108:
|
|
dwTemp = (DWORD) uT108;
|
|
uT108 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T108 = %d",uT108);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_SET_FSM_T109:
|
|
dwTemp = (DWORD) uT109;
|
|
uT109 = (unsigned int) *((DWORD *)pData);
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set T109 = %d",uT109);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
case H245_SYSCON_TRACE_LVL:
|
|
dwTemp = TraceLevel;
|
|
TraceLevel = *(DWORD *)pData;
|
|
H245TRACE(dwInst,20,"H245SystemControl: Set TraceLevel = %d",TraceLevel);
|
|
*((DWORD *)pData) = dwTemp;
|
|
break;
|
|
|
|
default:
|
|
lError = H245_ERROR_NOTIMP;
|
|
} // switch
|
|
} // else
|
|
|
|
if (lError != H245_ERROR_OK)
|
|
H245TRACE(dwInst,1,"H245SystemControl -> %s",map_api_error(lError));
|
|
else
|
|
H245TRACE(dwInst,4,"H245SystemControl -> OK");
|
|
return lError;
|
|
} // H245SystemControl()
|
|
|