/*********************************************************************** * * * Filename: mlse.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: MLSE.C $ * $Revision: 1.4 $ * $Modtime: 09 Dec 1996 13:34:24 $ * $Log: S:/STURGEON/SRC/H245/SRC/VCS/MLSE.C_v $ * * Rev 1.4 09 Dec 1996 13:34:46 EHOWARDX * Updated copyright notice. * * Rev 1.3 04 Jun 1996 13:57:24 EHOWARDX * Fixed Release build warnings. * * Rev 1.2 30 May 1996 23:39:14 EHOWARDX * Cleanup. * * Rev 1.1 28 May 1996 14:25:42 EHOWARDX * Tel Aviv update. * * Rev 1.0 09 May 1996 21:06:30 EHOWARDX * Initial revision. * * Rev 1.1 09 May 1996 19:48:26 EHOWARDX * Change TimerExpiryF function arguements. * * Rev 1.0 15 Apr 1996 10:46:58 EHOWARDX * Initial revision. * * ***********************************************************************/ #include "precomp.h" #include "h245api.h" #include "h245com.h" #include "h245fsm.h" #include "mlse.h" // Out-going/In-coming MLSE states #define MLSE_NOT_LOOPED 0 // NOT LOOPED #define MLSE_WAIT 1 // AWAITING RESPONSE #define MLSE_LOOPED 1 // LOOPED extern unsigned int uT102; /*********************************************************************** * * LOCAL FUNCTIONS * ***********************************************************************/ /* * NAME * T102ExpiryF - Callback function called by the timer * * * PARAMETERS * INPUT dwInst current instance of H245 * INPUT id timer id * INPUT pObject pointer to a State Entity * * * RETURN VALUE * OK */ int T102ExpiryF(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId, void *pObject) { return FsmTimerEvent(pInstance, dwTimerId, pObject, T102Expiry); } // T102ExpiryF() static void BuildMaintenanceLoopOffCommand(PDU_t *pPdu) { pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = mntnncLpOffCmmnd_chosen; } // BuildMaintenanceLoopOffCommand() /*********************************************************************** * * OUT-GOING FINITE STATE MACHINE FUNCTIONS * ***********************************************************************/ /* * NAME * MLSE0_LOOP_requestF - LOOP.request from API in NOT LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE0_LOOP_requestF (Object_t *pObject, PDU_t *pPdu) { HRESULT lError; ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_NOT_LOOPED); H245TRACE(pObject->dwInst, 2, "MLSE0_LOOP_request:%d", pObject->Key); // Save type from PDU pObject->u.mlse.wLoopType = pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice; // Send Maintenance Loop Request PDU to remote peer lError = sendPDU(pObject->pInstance, pPdu); // Set timer T102 pObject->State = MLSE_WAIT; FsmStartTimer(pObject, T102ExpiryF, uT102); return lError; } // MLSE0_LOOP_request /* * NAME * MLSE1_MaintenanceLoopAckF - MaintenanceLoopAck in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_MaintenanceLoopAckF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_MaintenanceLoopAck:%d", pObject->Key); // Reset timer T102 FsmStopTimer(pObject); // Send LOOP.confirm to client pObject->State = MLSE_LOOPED; H245FsmConfirm(pPdu, H245_CONF_MLSE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE1_MaintenanceLoopAck /* * NAME * MLSE1_MaintenanceLoopRejF - MaintenanceLoopReject in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_MaintenanceLoopRejF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_MaintenanceLoopRej:%d", pObject->Key); // Reset timer T102 FsmStopTimer(pObject); // Send RELEASE.indication to client pObject->State = MLSE_NOT_LOOPED; H245FsmConfirm(pPdu, H245_CONF_MLSE_REJECT, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE1_MaintenanceLoopRej /* * NAME * MLSE1_OUT_RELEASE_requestF - RELEASE.request from API in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_OUT_RELEASE_requestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_OUT_RELEASE_request:%d", pObject->Key); // Send MaintenanceLoopOffCommand PDU to remote peer pObject->State = MLSE_NOT_LOOPED; BuildMaintenanceLoopOffCommand(pPdu); return sendPDU(pObject->pInstance, pPdu); } // MLSE1_OUT_RELEASE_request /* * NAME * MLSE1_T102ExpiryF - timer T102 Expiry in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_T102ExpiryF (Object_t *pObject, PDU_t *pPdu) { PDU_t * pOut; HRESULT lError; ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); ASSERT(pPdu == NULL); H245TRACE(pObject->dwInst, 2, "MLSE1_T102Expiry:%d", pObject->Key); // Send MaintenanceLoopOffCommand PDU to remote peer pOut = MemAlloc(sizeof(*pOut)); if (pOut == NULL) { H245TRACE(pObject->dwInst, 2, "MLSE1_T102ExpiryF: memory allocation failed"); return H245_ERROR_NOMEM; } BuildMaintenanceLoopOffCommand(pOut); lError = sendPDU(pObject->pInstance, pOut); MemFree(pOut); // Send RELEASE.indication to client // SOURCE := MLSE pObject->State = MLSE_NOT_LOOPED; H245FsmConfirm(NULL, H245_CONF_MLSE_EXPIRED, pObject->pInstance, pObject->dwTransId, FSM_OK); return lError; } // MLSE1_T102Expiry /* * NAME * MLSE2_MaintenanceLoopRejF - MaintenanceLoopReject in LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE2_MaintenanceLoopRejF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE2_MaintenanceLoopRej:%d", pObject->Key); pObject->State = MLSE_NOT_LOOPED; #if defined(SDL_COMPLIANT) // Send ERROR.indication(B) to client // TBD #endif // Send RELEASE.indication to client // SOURCE := MLSE H245FsmConfirm(pPdu, H245_CONF_MLSE_REJECT, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE2_MaintenanceLoopRej /* * NAME * MLSE2_OUT_RELEASE_requestF - RELEASE.request from API in LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE2_OUT_RELEASE_requestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_OUT); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE2_OUT_RELEASE_request:%d", pObject->Key); // Send MaintenanceLoopOffCommand PDU to remote peer pObject->State = MLSE_NOT_LOOPED; BuildMaintenanceLoopOffCommand(pPdu); return sendPDU(pObject->pInstance, pPdu); } // MLSE2_OUT_RELEASE_request /*********************************************************************** * * IN-COMING FINITE STATE MACHINE FUNCTIONS * ***********************************************************************/ /* * NAME * MLSE0_MaintenanceLoopRequestF - MaintenanceLoopRequest received in NOT LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE0_MaintenanceLoopRequestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_NOT_LOOPED); H245TRACE(pObject->dwInst, 2, "MLSE0_MaintenanceLoopRequest:%d", pObject->Key); // Save type from PDU pObject->u.mlse.wLoopType = pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice; // Send LOOP.indication to client pObject->State = MLSE_WAIT; H245FsmIndication(pPdu, H245_IND_MLSE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE0_MaintenanceLoopRequest /* * NAME * MLSE1_MaintenanceLoopRequestF - MaintenanceLoopRequest received in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_MaintenanceLoopRequestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_MaintenanceLoopRequest:%d", pObject->Key); // Save type from PDU pObject->u.mlse.wLoopType = pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice; #if defined(SDL_COMPLIANT) // Send RELEASE.indication to client H245FsmIndication(pPdu, H245_IND_MLSE_RELEASE, pObject->pInstance, pObject->dwTransId, FSM_OK); #endif // Send LOOP.indication to client H245FsmIndication(pPdu, H245_IND_MLSE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE1_MaintenanceLoopRequest /* * NAME * MLSE1_MaintenanceLoopReleaseF - MaintenanceLoopOffCommand received in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_MaintenanceLoopOffCommandF(Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_MaintenanceLoopOffCommand:%d", pObject->Key); // Send RELEASE.indication to client pObject->State = MLSE_NOT_LOOPED; H245FsmIndication(pPdu, H245_IND_MLSE_RELEASE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE1_MaintenanceLoopOffCommand /* * NAME * MLSE1_LOOP_responseF - LOOP.response from API in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_LOOP_responseF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_LOOP_response:%d", pObject->Key); // Send MaintenanceLoopAck PDU to remote peer pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice = pObject->u.mlse.wLoopType; switch (pObject->u.mlse.wLoopType) { case systemLoop_chosen: break; case mediaLoop_chosen: pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop = (WORD)pObject->Key; break; case logicalChannelLoop_chosen: pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.logicalChannelLoop = (WORD)pObject->Key; break; default: H245TRACE(pObject->dwInst, 1, "Invalid loop type %d", pObject->u.mlse.wLoopType); } // switch pObject->State = MLSE_LOOPED; return sendPDU(pObject->pInstance, pPdu); } // MLSE1_LOOP_response /* * NAME * MLSE1_IN_RELEASE_requestF - RELEASE.request from API in AWAITING RESPONSE state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE1_IN_RELEASE_requestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_WAIT); H245TRACE(pObject->dwInst, 2, "MLSE1_IN_RELEASE_request:%d", pObject->Key); // Send MaintenanceLoopReject PDU to remote peer pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice = pObject->u.mlse.wLoopType; switch (pObject->u.mlse.wLoopType) { case systemLoop_chosen: break; case mediaLoop_chosen: pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop = (WORD)pObject->Key; break; case logicalChannelLoop_chosen: pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.logicalChannelLoop = (WORD)pObject->Key; break; default: H245TRACE(pObject->dwInst, 1, "Invalid loop type %d", pObject->u.mlse.wLoopType); } // switch pObject->State = MLSE_NOT_LOOPED; return sendPDU(pObject->pInstance, pPdu); } // MLSE1_IN_RELEASE_request /* * NAME * MLSE2_MaintenanceLoopRequestF - MaintenanceLoopRequest received in LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE2_MaintenanceLoopRequestF (Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_LOOPED); H245TRACE(pObject->dwInst, 2, "MLSE2_MaintenanceLoopRequest:%d", pObject->Key); // Save type from PDU pObject->u.mlse.wLoopType = pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice; pObject->State = MLSE_WAIT; #if defined(SDL_COMPLIANT) // Send RELEASE.indication to client H245FsmIndication(pPdu, H245_IND_MLSE_RELEASE, pObject->pInstance, pObject->dwTransId, FSM_OK); #endif // Send LOOP.indication to client H245FsmIndication(pPdu, H245_IND_MLSE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE2_MaintenanceLoopRequest /* * NAME * MLSE2_MaintenanceLoopReleaseF - MaintenanceLoopOffCommand received in LOOPED state * * * PARAMETERS * INPUT pObject pointer to State Entity * INPUT pPdu pointer to PDU * * RETURN VALUE * Error return codes defined in h245com.h */ HRESULT MLSE2_MaintenanceLoopOffCommandF(Object_t *pObject, PDU_t *pPdu) { ASSERT(pObject->Entity == MLSE_IN); ASSERT(pObject->State == MLSE_LOOPED); H245TRACE(pObject->dwInst, 2, "MLSE2_MaintenanceLoopOffCommand:%d", pObject->Key); // Send RELEASE.indication to client pObject->State = MLSE_NOT_LOOPED; H245FsmIndication(pPdu, H245_IND_MLSE_RELEASE, pObject->pInstance, pObject->dwTransId, FSM_OK); return 0; } // MLSE2_MaintenanceLoopOffCommand