|
|
/***********************************************************************
* * * 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()
|