📄 cmctrlmsd.c
字号:
/*
NOTICE:
This document contains information that is proprietary to RADVISION LTD..
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD..
RADVISION LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
*/
#include "rvinternal.h"
#include "rvtimestamp.h"
#include "cmictrl.h"
#include "cmConf.h"
#include "caputils.h"
#include "strutils.h"
#include "cmchan.h"
#include "oidutils.h"
#include "stkutils.h"
#include "h245.h"
#include "cmCtrlMSD.h"
#include "cmdebprn.h"
#include "intutils.h"
#ifdef __cplusplus
extern "C" {
#endif
int cmcReadyEvent (H245Control* ctrl);
RvBool simulatedMessageH245(IN HCONTROL ctrl);
/**************************************************************************************/
/* Internal routines */
/**************************************************************************************/
/************************************************************************
* reportError
* purpose: To report of an error condition to the user, and return the state
* of the procedure to idle.
* input : ctrl - Control object
* output : none
* return : none
************************************************************************/
static void reportError(H245Control* ctrl)
{
HAPP hApp=(HAPP)emaGetInstance((EMAElement)cmiGetByControl((HCONTROL)ctrl));
cmElem *app = (cmElem*)hApp;
MasterSlaveInfo* msd=&ctrl->msd;
int nesting;
if (app->cmMySessionEvent.cmEvCallMasterSlaveStatus)
{
cmiCBEnter(hApp, "cmEvCallMasterSlaveStatus: haCall=0x%p, hsCall=0x%p, status=error.",(HAPPCALL)emaGetApplicationHandle((EMAElement)cmiGetByControl((HCONTROL)ctrl)), cmiGetByControl((HCONTROL)ctrl));
nesting=emaPrepareForCallback((EMAElement)cmiGetByControl((HCONTROL)ctrl));
(app->cmMySessionEvent.cmEvCallMasterSlaveStatus) ((HAPPCALL)emaGetApplicationHandle((EMAElement)cmiGetByControl((HCONTROL)ctrl)),
(HCALL)cmiGetByControl((HCONTROL)ctrl),
cmMSError);
emaReturnFromCallback((EMAElement)cmiGetByControl((HCONTROL)ctrl),nesting);
cmiCBExit(hApp, "cmEvCallMasterSlaveStatus.");
}
/* return the state to idle, the procedure is over */
msd->state=MsdStateIdle;
}
/************************************************************************
* sendErrorResponse
* purpose: To send a reject message due to an error condition.
* input : ctrl - Control object
* output : none
* return : none
************************************************************************/
static void sendErrorResponse(H245Control* ctrl)
{
HAPP hApp=(HAPP)emaGetInstance((EMAElement)cmiGetByControl((HCONTROL)ctrl));
HPVT hVal;
MasterSlaveInfo* msd=&ctrl->msd;
int nodeId;
int message;
hVal = ((cmElem *)hApp)->hVal;
/* close the timer, no response is expected to this message */
RvH323TimerCancel(cmGetTimersHandle(hApp),&msd->timer);
/* report the error to the user and reset the state to idle */
reportError(ctrl);
/* build and send the reject message */
message = pvtAddRoot(hVal,((cmElem*)hApp)->synProtH245,0,NULL);
__pvtBuildByFieldIds(nodeId,hVal,message, {_h245(response) _h245(masterSlaveDeterminationReject)
_h245(cause) _h245(identicalNumbers) LAST_TOKEN}, 0, NULL);
sendMessageH245((HCONTROL)ctrl, message);
pvtDelete(hVal,message);
}
/************************************************************************
* msdTimeoutEventsHandler
* purpose: Call back in case that no response was received after timeout has expired
* input : ctrl - Control object
* output : None.
* return : None.
************************************************************************/
RvBool msdTimeoutEventsHandler(void*_ctrl)
{
H245Control* ctrl=(H245Control*)_ctrl;
HAPP hApp=(HAPP)emaGetInstance((EMAElement)cmiGetByControl((HCONTROL)ctrl));
MasterSlaveInfo* msd=&ctrl->msd;
if (emaLock((EMAElement)cmiGetByControl((HCONTROL)ctrl)))
{
HPVT hVal = ((cmElem *)hApp)->hVal;
/* if it's on the first response from the remote, cancel the procedure */
if (msd->state==MsdStateOutgoingAwaitingResponse)
{
/* send a release message */
int message=pvtAddRoot(hVal,((cmElem*)hApp)->synProtH245,0,NULL);
pvtAddBranch2(hVal,message, __h245(indication), __h245(masterSlaveDeterminationRelease));
sendMessageH245((HCONTROL)ctrl, message);
pvtDelete(hVal,message);
/* inform the user of the error and return to idle state */
reportError(ctrl); /* Error A */
}
/* if it's after we sent an ack just report to the user and return to idle state */
else if (msd->state==MsdStateIncomingAwaitingResponse)
reportError(ctrl); /* Error A */
emaUnlock((EMAElement)cmiGetByControl((HCONTROL)ctrl));
}
return RV_TRUE;
}
/************************************************************************
* determineStatus
* purpose: The actual algorithm to determine the master & slave according to
* the terminal type and determination number.
* input : ctrl - Control object
* output : none
* return : none
************************************************************************/
static void determineStatus(H245Control* ctrl)
{
MasterSlaveInfo* msd=&ctrl->msd;
/* if the terminat type is the same we need to decide according to the determination
number */
if (msd->myTerminalType == msd->terminalType)
{
/* calculate the difference between the determination numbers using lower 24bits */
int n=(msd->statusDeterminationNumber - msd->myStatusDeterminationNumber + 0x1000000) % 0x1000000;
/* if the difference is zero, we can't decide,
otherwise if the difference is within the 24 bits, i.e. my number is smaller, we are slave
else we are master */
msd->status= (n & 0x7fffff) ? ((n<0x800000) ? MsdStatusMaster : MsdStatusSlave) : MsdStatusIndeterminate;
}
else
/* if there are different terminal types the bigger is masetr */
msd->status = (msd->terminalType < msd->myTerminalType) ? MsdStatusMaster : MsdStatusSlave;
}
/************************************************************************
* setAndSendMasterSlave
* purpose: To set the resonse into the control data structure,
* send an ACK to the remote,
* report the result to the user.
* input : ctrl - Control object
* isMaster - RV_TRUE if we are master
* output : none
* return : none
************************************************************************/
static void setAndSendMasterSlave(H245Control* ctrl,int isMaster, int report)
{
HAPP hApp=(HAPP)emaGetInstance((EMAElement)cmiGetByControl((HCONTROL)ctrl));
HPVT hVal;
cmElem* app = (cmElem*)hApp;
MasterSlaveInfo* msd=&ctrl->msd;
int nodeId, nesting, message, res;
hVal = ((cmElem *)hApp)->hVal;
/* set the result to the control DB */
ctrl->bIsMaster=isMaster;
msd->status=(isMaster) ? MsdStatusMaster : MsdStatusSlave;
/* send a response to the remote with the result */
message=pvtAddRoot(hVal,app->synProtH245,0,NULL);
__pvtBuildByFieldIds(nodeId,hVal,message, {_h245(response) _h245(masterSlaveDeterminationAck)
_h245(decision) LAST_TOKEN}, 0, NULL);
pvtAddBranch(hVal,nodeId,(isMaster)?__h245(slave):__h245(master));
res = sendMessageH245((HCONTROL)ctrl, message);
pvtDelete(hVal,message);
if (report)
{
/* The procedure is finished */
msd->state=MsdStateIdle;
/* report the result to the user */
if ((app->cmMySessionEvent.cmEvCallMasterSlaveStatus) && (res >= 0))
{
cmiCBEnter(hApp, "cmEvCallMasterSlaveStatus: haCall=0x%p, hsCall=0x%p, status=%s.",(HAPPCALL)emaGetApplicationHandle((EMAElement)cmiGetByControl((HCONTROL)ctrl)),cmiGetByControl((HCONTROL)ctrl), (isMaster)?"master":"slave");
nesting=emaPrepareForCallback((EMAElement)cmiGetByControl((HCONTROL)ctrl));
(app->cmMySessionEvent.cmEvCallMasterSlaveStatus)((HAPPCALL)emaGetApplicationHandle((EMAElement)cmiGetByControl((HCONTROL)ctrl)),(HCALL)cmiGetByControl((HCONTROL)ctrl), (RvUint32)((isMaster)?cmMSMaster:cmMSSlave));
emaReturnFromCallback((EMAElement)cmiGetByControl((HCONTROL)ctrl),nesting);
cmiCBExit(hApp, "cmEvCallMasterSlaveStatus.");
}
}
/* check if the H.245 openning formalities (i.e. TCS & MSD procedures) have ended,
if so, report to the user that the H.245 is ready for operation */
if (res >= 0)
cmcReadyEvent(ctrl);
}
/************************************************************************
* countCheckAndSend
* purpose: Retry mechanism. Check if retries expired, if not send a new
* request with a new determination number, else send a reject and
* finish the procedure.
* input : ctrl - Control object
* output : none
* return : none
************************************************************************/
static void countCheckAndSend(H245Control* ctrl)
{
HAPP hApp=(HAPP)emaGetInstance((EMAElement)cmiGetByControl((HCONTROL)ctrl));
cmElem * app = (cmElem *)hApp;
MasterSlaveInfo* msd=&ctrl->msd;
int nodeId, message, res;
/* check if retry expired, it's always 3 */
if (msd->count>=3)
{ /* >= N100 */ /*Error F */
/* send reject and terminate the procedure */
sendErrorResponse(ctrl);
}
else
{ /* < N100 */
HPVT hVal = app->hVal;
/* regenerate a new random 24 bit determination number */
{
RvRandom randomValue;
cmLock(hApp);
RvRandomGeneratorGetValue(&app->randomGenerator, &randomValue);
cmUnlock(hApp);
msd->myStatusDeterminationNumber =
(int)((randomValue * (RvUint32)Rv64Modulu(RvTimestampGet(), 0xffff)) % 0xffffff);
}
/* build a new request with the new number */
message=pvtAddRoot(hVal,app->synProtH245,0,NULL);
nodeId=pvtAddBranch2(hVal,message,__h245(request), __h245(masterSlaveDetermination));
pvtAdd(hVal,nodeId,__h245(statusDeterminationNumber),msd->myStatusDeterminationNumber, NULL,NULL);
pvtAdd(hVal,nodeId,__h245(terminalType),msd->myTerminalType, NULL, NULL);
/* advance the retries counter */
msd->count++;
/* send the message */
res = sendMessageH245((HCONTROL)ctrl, message);
pvtDelete(hVal,message);
if (res >= 0)
{
/* set the timer to wait for a response on the request */
RvInt32 timeout=9;
pvtGetChildValue2(hVal,((cmElem*)hApp)->h245Conf,__h245(masterSlave),__h245(timeout),&(timeout),NULL);
RvH323TimerCancel(cmGetTimersHandle(hApp), &msd->timer);
msd->timer=RvH323TimerStart(cmGetTimersHandle(hApp),msdTimeoutEventsHandler,(void*)ctrl,timeout*1000);
/* change the state so we know we are waiting for a response to our request */
msd->state=MsdStateOutgoingAwaitingResponse;
}
}
}
/*******************************************************************************
* processMSD
*
* Purpose: To respond to a MSD by building the appropriate message and sending
* it according to the status of the procedure
*
* Input: ctrl - The control elemnt
*
* Output: None.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -