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

533 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

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

/***********************************************************************
* *
* Filename: fsmapi.c *
* Module: H245 Finite State Machine Subsystem *
* *
***********************************************************************
* INTEL Corporation Proprietary Information *
* *
* This listing is supplied under the terms of a license agreement *
* with INTEL Corporation and may not be copied nor disclosed except *
* in accordance with the terms of that agreement. *
* *
* Copyright (c) 1996 Intel Corporation. All rights reserved. *
***********************************************************************
* *
* $Workfile: FSMAPI.C $
* $Revision: 1.12 $
* $Modtime: 09 Dec 1996 13:34:24 $
* $Log L:\mphone\h245\h245env\comm\h245_3\h245_fsm\vcs\src\fsmapi.c_v $
* *
***********************************************************************/
#include "precomp.h"
#include "h245api.h"
#include "h245com.h"
#include "h245fsm.h"
#include "h245deb.x"
extern char *EntityName[];
/*
* This table maps FSM stateless events into H.245 API events
*/
static WORD StatelessTable[NUM_EVENTS - NUM_STATE_EVENTS] =
{
H245_IND_NONSTANDARD_REQUEST, // NonStandardRequestPDU
H245_IND_NONSTANDARD_RESPONSE, // NonStandardResponsePDU
H245_IND_NONSTANDARD_COMMAND, // NonStandardCommandPDU
H245_IND_NONSTANDARD, // NonStandardIndicationPDU
H245_IND_MISC_COMMAND, // MiscellaneousCommandPDU
H245_IND_MISC, // MiscellaneousIndicationPDU
H245_IND_COMM_MODE_REQUEST, // CommunicationModeRequestPDU
H245_IND_COMM_MODE_RESPONSE, // CommunicationModeResponsePDU
H245_IND_COMM_MODE_COMMAND, // CommunicationModeCommandPDU
H245_IND_CONFERENCE_REQUEST, // ConferenceRequestPDU
H245_IND_CONFERENCE_RESPONSE, // ConferenceResponsePDU
H245_IND_CONFERENCE_COMMAND, // ConferenceCommandPDU
H245_IND_CONFERENCE, // ConferenceIndicationPDU
H245_IND_SEND_TERMCAP, // SendTerminalCapabilitySetPDU
H245_IND_ENCRYPTION, // EncryptionCommandPDU
H245_IND_FLOW_CONTROL, // FlowControlCommandPDU
H245_IND_ENDSESSION, // EndSessionCommandPDU
H245_IND_FUNCTION_NOT_UNDERSTOOD, // FunctionNotUnderstoodIndicationPDU
H245_IND_JITTER, // JitterIndicationPDU
H245_IND_H223_SKEW, // H223SkewIndicationPDU
H245_IND_NEW_ATM_VC, // NewATMVCIndicationPDU
H245_IND_USERINPUT, // UserInputIndicationPDU
H245_IND_H2250_MAX_SKEW, // H2250MaximumSkewIndicationPDU
H245_IND_MC_LOCATION, // MCLocationIndicationPDU
H245_IND_VENDOR_ID, // VendorIdentificationIndicationPDU
H245_IND_FUNCTION_NOT_SUPPORTED, // FunctionNotSupportedIndicationPDU
};
/*
* Configurable counter values
*/
unsigned int uN100 = 10; // Master Slave Determination
/*
* Configurable timer values
*/
unsigned int uT101 = 30000; // Capability Exchange
unsigned int uT102 = 30000; // Maintenance Loop
unsigned int uT103 = 30000; // Logical Channel Signalling
unsigned int uT104 = 30000; // H.223 Multiplex Table
unsigned int uT105 = 30000; // Round Trip Delay
unsigned int uT106 = 30000; // Master Slave Determination
unsigned int uT107 = 30000; // Request Multiplex Entry
unsigned int uT108 = 30000; // Send Logical Channel
unsigned int uT109 = 30000; // Mode Request
/*
* NAME
* ObjectCreate - create an State Entity object
*
*
* PARAMETERS
* INPUT pInst Pointer to FSM instance data
* INPUT Entity State Entity represented by object, e.g. LCSE_OUT
* INPUT Key Lookup key for distinguish multiple instances of SE
* INPUT dwTransId Transaction identifier to be sent up to client
*
* RETURN VALUE
* pObject Function succeeded
* NULL Memory allocation failed
*/
Object_t *
ObjectCreate(struct InstanceStruct *pInstance, Entity_t Entity, Key_t Key, DWORD_PTR dwTransId)
{
register Object_t * pObject;
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 4, "ObjectCreate: Entity=%s(%d) Key=%d dwTransID=0x%p",
EntityName[Entity], Entity, Key, dwTransId);
#else
H245TRACE(pInstance->dwInst, 4, "ObjectCreate: Entity=%d Key=%d dwTransID=0x%p",
Entity, Key, dwTransId);
#endif
pObject = (Object_t *)MemAlloc(sizeof(*pObject));
if (pObject == NULL)
{
H245TRACE(pInstance->dwInst, 1, "ObjectCreate: FSM Object memory allocation failed");
return NULL;
}
memset(pObject, 0, sizeof(*pObject));
/* copy primitive variables to my object */
pObject->pInstance = pInstance;
pObject->dwInst = pInstance->dwInst;
pObject->dwTransId = dwTransId;
pObject->Key = Key;
pObject->Entity = Entity;
pObject->pNext = pInstance->StateMachine.Object_tbl[Entity];
pInstance->StateMachine.Object_tbl[Entity] = pObject;
return pObject;
} // ObjectCreate()
/*
* NAME
* ObjectDestroy - deallocate an object created by ObjectCreate()
*
*
* PARAMETERS
* INPUT pInst pointer to FSM instance data
* INPUT id index into the object table
*
* RETURN VALUE
* FALSE object deallocated
* TRUE object not found
*/
int
ObjectDestroy(Object_t *pObject)
{
struct InstanceStruct * pInstance;
Object_t * pSearch;
Object_t * pPrev;
ASSERT(pObject != NULL);
ASSERT(pObject->uNestLevel == 0);
ASSERT(pObject->pInstance != NULL);
pInstance = pObject->pInstance;
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 4, "ObjectDestroy: Entity=%s(%d) Key=%d State=%d",
EntityName[pObject->Entity], pObject->Entity, pObject->Key, pObject->State);
#else
H245TRACE(pInstance->dwInst, 4, "ObjectDestroy: Entity=%d Key=%d State=%d",
pObject->Entity, pObject->Key, pObject->State);
#endif
if (pObject->dwTimerId)
{
H245TRACE(pObject->dwInst, 4, "ObjectDestroy: stoping timer");
FsmStopTimer(pObject);
}
if (pInstance->StateMachine.Object_tbl[pObject->Entity] == NULL)
{
H245TRACE(pInstance->dwInst, 1, "ObjectDestroy: no State Entity of specified type found");
return TRUE;
}
if (pInstance->StateMachine.Object_tbl[pObject->Entity] == pObject)
{
pInstance->StateMachine.Object_tbl[pObject->Entity] = pObject->pNext;
MemFree(pObject);
return FALSE;
}
pPrev = pInstance->StateMachine.Object_tbl[pObject->Entity];
pSearch = pPrev->pNext;
while (pSearch != NULL)
{
if (pSearch == pObject)
{
pPrev->pNext = pSearch->pNext;
MemFree(pObject);
return FALSE;
}
pPrev = pSearch;
pSearch = pSearch->pNext;
}
H245TRACE(pInstance->dwInst, 1, "ObjectDestroy: State Entity not found");
return TRUE;
} // ObjectDestroy()
/*
* NAME
* ObjectFind - given parsed information of a PDU, it searches the object table for
* an object with a matching id, type and category
*
*
* PARAMETERS
* INPUT pInst
* INPUT Category category of a given PDU
* INPUT Type type of the PDU
* INPUT pdu_id unique id shared by PDU and object (usually channel number or sequence number)
*
* RETURN VALUE
* pObject object found
* NULL object not found
*/
Object_t *
ObjectFind(struct InstanceStruct *pInstance, Entity_t Entity, Key_t Key)
{
register Object_t * pObject;
ASSERT(Entity < STATELESS);
pObject = pInstance->StateMachine.Object_tbl[Entity];
while (pObject != NULL)
{
if (pObject->Key == Key)
{
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 4, "ObjectFind(%s, %d) object found",
EntityName[Entity], Key);
#else
H245TRACE(pInstance->dwInst, 4, "ObjectFind(%d, %d) object found",
Entity, Key);
#endif
return pObject;
}
pObject = pObject->pNext;
}
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 4, "ObjectFind(%s, %d) object not found",
EntityName[Entity], Key);
#else
H245TRACE(pInstance->dwInst, 4, "ObjectFind(%d, %d) object not found",
Entity, Key);
#endif
return NULL;
} // ObjectFind()
/*
* NAME
* SendFunctionNotUnderstood - builds and sends Function Not Supported PDU
*
*
* PARAMETERS
* INPUT dwInst Current H.245 instance
* INPUT pPdu Not supported PDU
*
* RETURN VALUE
* H245_ERROR_OK
*/
HRESULT
SendFunctionNotUnderstood(struct InstanceStruct *pInstance, PDU_t *pPdu)
{
PDU_t * pOut;
HRESULT lError;
pOut = MemAlloc(sizeof(*pOut));
if (pOut == NULL)
{
return H245_ERROR_NOMEM;
}
switch (pPdu->choice)
{
case MltmdSystmCntrlMssg_rqst_chosen:
pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_request_chosen;
pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_request =
pPdu->u.MltmdSystmCntrlMssg_rqst;
break;
case MSCMg_rspns_chosen:
pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_response_chosen;
pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_response =
pPdu->u.MSCMg_rspns;
break;
case MSCMg_cmmnd_chosen:
pOut->u.indication.u.functionNotUnderstood.choice = FnctnNtUndrstd_command_chosen;
pOut->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_command =
pPdu->u.MSCMg_cmmnd;
break;
default:
// Can't reply to unsupported indication...
MemFree(pOut);
return H245_ERROR_OK;
} // switch (Type)
pOut->choice = indication_chosen;
pOut->u.indication.choice = functionNotUnderstood_chosen;
lError = sendPDU(pInstance, pOut);
MemFree(pOut);
return lError;
} // SendFunctionNotUnderstood()
/*
* NAME
* FsmOutgoing - process outbound PDU
*
*
* PARAMETERS
* INPUT pInst Pointer to FSM instance structure
* INPUT pPdu Pointer to PDU to send
* INPUT dwTransId Transaction identifier to use for response
*
* RETURN VALUE
* Error codes defined in h245com.h
*/
HRESULT
FsmOutgoing(struct InstanceStruct *pInstance, PDU_t *pPdu, DWORD_PTR dwTransId)
{
HRESULT lError;
Entity_t Entity;
Event_t Event;
Key_t Key;
int bCreate;
Object_t * pObject;
ASSERT(pInstance != NULL);
ASSERT(pPdu != NULL);
H245TRACE(pInstance->dwInst, 4, "FsmOutgoing");
#if defined(_DEBUG)
if (check_pdu(pInstance, pPdu))
return H245_ERROR_ASN1;
#endif // (DEBUG)
lError = PduParseOutgoing(pInstance, pPdu, &Entity, &Event, &Key, &bCreate);
if (lError != H245_ERROR_OK)
{
H245TRACE(pInstance->dwInst, 1,
"FsmOutgoing: PDU not recognized; Error=%d", lError);
return lError;
}
ASSERT(Entity < NUM_ENTITYS);
if (Entity == STATELESS)
{
H245TRACE(pInstance->dwInst, 4, "FsmOutgoing: Sending stateless PDU");
return sendPDU(pInstance, pPdu);
}
ASSERT(Event < NUM_STATE_EVENTS);
pObject = ObjectFind(pInstance, Entity, Key);
if (pObject == NULL)
{
if (bCreate == FALSE)
{
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 1,
"FsmOutgoing: State Entity %s(%d) not found; Key=%d",
EntityName[Entity], Entity, Key);
#else
H245TRACE(pInstance->dwInst, 1,
"FsmOutgoing: State Entity %d not found; Key=%d",
Entity, Key);
#endif
return H245_ERROR_PARAM;
}
pObject = ObjectCreate(pInstance, Entity, Key, dwTransId);
if (pObject == NULL)
{
H245TRACE(pInstance->dwInst, 1, "FsmOutgoing: State Entity memory allocation failed");
return H245_ERROR_NOMEM;
}
}
else
{
pObject->dwTransId = dwTransId;
}
return StateMachine(pObject, pPdu, Event);
} // FsmOutgoing()
/*
* NAME
* FsmIncoming - process inbound PDU
*
*
* PARAMETERS
* INPUT dwInst current H.245 instance
* INPUT pPdu pointer to a PDU structure
*
* RETURN VALUE
* error codes defined in h245com.h (not checked)
*/
HRESULT
FsmIncoming(struct InstanceStruct *pInstance, PDU_t *pPdu)
{
HRESULT lError;
Entity_t Entity;
Event_t Event;
Key_t Key;
int bCreate;
Object_t * pObject;
Object_t * pObject1;
ASSERT(pInstance != NULL);
ASSERT(pPdu != NULL);
H245TRACE(pInstance->dwInst, 4, "FsmIncoming");
lError = PduParseIncoming(pInstance, pPdu, &Entity, &Event, &Key, &bCreate);
if (lError != H245_ERROR_OK)
{
H245TRACE(pInstance->dwInst, 1,
"FsmIncoming: Received PDU not recognized", lError);
SendFunctionNotUnderstood(pInstance, pPdu);
return lError;
}
ASSERT(Entity < NUM_ENTITYS);
if (Entity == STATELESS)
{
H245TRACE(pInstance->dwInst, 4, "FsmIncoming: Received stateless PDU");
return H245FsmIndication(pPdu, (DWORD)StatelessTable[Event - NUM_STATE_EVENTS], pInstance, 0, H245_ERROR_OK);
}
ASSERT(Event < NUM_STATE_EVENTS);
if (Event == MaintenanceLoopOffCommandPDU)
{
// Special case MaintenanceLoopOff applies to ALL loops
ASSERT(Entity == MLSE_IN);
pObject = pInstance->StateMachine.Object_tbl[Entity];
if (pObject == NULL)
{
return H245_ERROR_OK;
}
lError = StateMachine(pObject, pPdu, Event);
pObject = pInstance->StateMachine.Object_tbl[Entity];
while (pObject)
{
if (pObject->uNestLevel == 0)
{
pObject1 = pObject;
pObject = pObject->pNext;
ObjectDestroy(pObject1);
}
else
{
pObject->State = 0;
pObject = pObject->pNext;
}
}
return lError;
} // if
pObject = ObjectFind(pInstance, Entity, Key);
if (pObject == NULL)
{
if (bCreate == FALSE)
{
#if defined(_DEBUG)
H245TRACE(pInstance->dwInst, 1,
"FsmIncoming: State Entity %s(%d) not found; Key=%d",
EntityName[Entity], Entity, Key);
#else
H245TRACE(pInstance->dwInst, 1,
"FsmIncoming: State Entity %d not found; Key=%d",
Entity, Key);
#endif
return H245_ERROR_PARAM;
}
pObject = ObjectCreate(pInstance, Entity, Key, 0);
if (pObject == NULL)
{
H245TRACE(pInstance->dwInst, 1, "FsmIncoming: State Entity memory allocation failed");
return H245_ERROR_NOMEM;
}
}
return StateMachine(pObject, pPdu, Event);
} // FsmIncoming()
// CAVEAT: Need to save dwInst since StateMachine() might deallocate pObject!
HRESULT
FsmTimerEvent(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId, Object_t *pObject, Event_t Event)
{
ASSERT(pInstance != NULL);
ASSERT(pObject != NULL);
ASSERT(pObject->pInstance == pInstance);
ASSERT(pObject->dwTimerId == dwTimerId);
H245TRACE(pInstance->dwInst, 4, "FsmTimerEvent");
pObject->dwTimerId = 0;
return StateMachine(pObject, NULL, Event);
} // FsmTimerEvent()