📄 cmautorascall.c
字号:
/***********************************************************************
Copyright (c) 2002 RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Ltd.. No part of this document may be reproduced in any
form whatsoever without written prior approval by RADVISION Ltd..
RADVISION Ltd. reserve the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
***********************************************************************/
/************************************************************************
* cmAutoRasCall
* -------------
* This file provides the calls part of the automatic RAS module.
* This includes the following features:
*
* - Handling incoming DRQs
* - Responding automatically to IRQ with IRR on calls
* - Responding automatically to BRQ with BCF on calls
************************************************************************/
#include "q931asn1.h"
#include "cmintr.h"
#include "cmdebprn.h"
#include "cmras.h"
#include "cmCrossReference.h"
#include "cmAutoRasCall.h"
#include "cmAutoRasAltGK.h"
#include "cmCall.h"
#include "rasdef.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Private functions declaration */
static int autoRasPrepareARQ(IN autorasEndpoint* autoras, IN HCALL hsCall);
/************************************************************************
*
* Private functions
*
************************************************************************/
/************************************************************************
* autoRasWaitRegistration
* purpose: Wait to see if endpoint got registered before beginning to
* dial this call. This function is called for the call every
* second to see if the registration status has changed.
* input : context - autoras call handle
* output : none
* return : none
************************************************************************/
RvBool autoRasWaitRegistration(IN void* context)
{
autorasEndpoint* autoras;
autorasCall* call = (autorasCall *)context;
HCALL hsCall;
RvBool done = RV_FALSE;
hsCall = cmiGetByAutoRas((HAUTORASCALL)call);
if (emaLock((EMAElement)hsCall))
{
autoras = (autorasEndpoint *)cmiGetAutoRasHandle((HAPP)emaGetInstance((EMAElement)hsCall));
/* Let's check the registration status once more */
switch (autoras->internalState)
{
case autorasRegistered:
/* We're registered - send ARQ */
if (autoRasPrepareARQ(autoras, hsCall) < 0)
{
/* Notify that we can't make this call */
autoras->event(hsCall, NULL, cmiAutoRasEvFailedOnARQ);
}
done = RV_TRUE;
break;
case autorasRegFailed:
/* Endpoint failed to register... */
done = RV_TRUE;
autoras->event(hsCall, NULL, cmiAutoRasEvCantRegister);
break;
case autorasRegNotTried:
/* This case should never relly happen */
case autorasRegTrying:
/* Do nothing in this case - we'll get back to here in a second with the timer */
break;
}
if (done)
/* We've got to stop the timer */
call->timer = (RvTimer *)NULL;
emaUnlock((EMAElement)hsCall);
}
return !(done);
}
/************************************************************************
* autoRasCallIdleState
* purpose: Set the automatic RAS information of the call to the idle state
* This will close any pending transactions for the call.
* input : autoras - Automatic RAS handle
* call - Automatic RAS information for the call
* output : none
* return : none
************************************************************************/
void autoRasCallIdleState(IN autorasEndpoint* autoras, IN autorasCall* call)
{
if (call->tx != NULL)
{
/* Remove the transaction */
cmRASClose(call->tx);
call->tx = NULL;
}
if (call->irrTx != NULL)
{
/* Remove the transaction */
cmRASClose(call->irrTx);
call->irrTx = NULL;
}
/* Stop the IRR timer */
RvH323TimerCancel(autoras->hTimers, &call->irrTimer);
RvH323TimerCancel(autoras->hTimers, &call->timer);
call->callState = autorasCallIdle;
}
int autoRasRegAndSend
(
IN autorasEndpoint* autorasE,
IN autorasCall* autorasC,
IN cmTransportAddress * GkAddr,
IN cmAlias * GkIdPtr
);
/************************************************************************
* autoRasCallSendToNextGK
* purpose: Resend a request to the next GK
* input : autorasE - Automatic RAS EP module
* autorasC - Automatic RAS call module
* output : none
* return : Non-negative value on success
* Negative value on failure
************************************************************************/
int autoRasCallSendToNextGK(IN autorasEndpoint * autorasE, IN autorasCall * autorasC)
{
/* ok, so we already got everything in, except cmRASParamDestinationIpAddress
and GK ID. let's go get'em! */
int tmpNode;
cmTransportAddress GKAddr;
cmAlias GKID;
char GKIDstr[128];
RvInt32 needToRegister = 0;
int ret;
int GkNodeId = autoRasGetNextAltGkNode(autorasE, autorasC);
if (GkNodeId < 0)
{
/* damn, no more GKs! we failed! */
return RV_ERROR_UNKNOWN;
}
/* Get GK address */
tmpNode = pvtGetChild(autorasE->hVal, GkNodeId, __q931(rasAddress), NULL);
if((tmpNode<0) || (cmVtToTA(autorasE->hVal, tmpNode, (cmTransportAddress *) &GKAddr)<0))
{
/* failed again ! */
return RV_ERROR_UNKNOWN;
}
cmRASSetParam(autorasC->tx, cmRASTrStageRequest, cmRASParamDestinationIpAddress, 0, sizeof(GKAddr), (char *)&GKAddr);
/* Get GK ID */
GKID.string = GKIDstr;
tmpNode = pvtGetChild(autorasE->hVal, GkNodeId, __q931(gatekeeperIdentifier), NULL);
if((tmpNode>=0) &&
((GKID.length = (unsigned short) pvtGetString(autorasE->hVal, tmpNode, 128, GKIDstr))>0))
cmRASSetParam(autorasC->tx, cmRASTrStageRequest, cmRASParamGatekeeperID, 0, sizeof(GKID), (char *)&GKID);
/* Do we need to register first ? */
tmpNode = pvtGetChildByFieldId(autorasE->hVal, GkNodeId, __q931(needToRegister), &needToRegister, (RvBool *)NULL);
if(!autorasC->isTempRdrn && (tmpNode>=0) && needToRegister)
{
/* ok, relax, it's just a minor setback, we'll quickly register and get back in business */
autoRasRegAndSend(autorasE, autorasC, &GKAddr, &GKID);
return 0;
}
/* Send the request */
ret = cmRASRequest(autorasC->tx);
if (ret < 0)
{
cmRASClose(autorasC->tx);
autorasC->tx = NULL;
}
return ret;
}
int autoRasDiscRegAndSend
(
IN autorasEndpoint* autorasE,
IN autorasCall* autorasC
);
/************************************************************************
* autoRasSendAftReg
* purpose: Callback function indicating the response of an RRQ sent to
* an Alt GK in order to send another transaction to it.
* input : haRas - Application's handle (autoras in this context)
* hsRas - RAS Transaction handle
* trStage - Stage of response
* output : none
* return : non-negative value on success
* negative value on failure
************************************************************************/
int RVCALLCONV autoRasSendAftReg
(
IN HAPPRAS haRas,
IN HRAS hsRas,
IN cmRASTrStage trStage
)
{
int ret = RV_ERROR_UNKNOWN;
autorasCall* autorasC = (autorasCall *)haRas;
HCALL hsCall = cmiGetByAutoRas((HAUTORASCALL)autorasC);
autorasEndpoint* autorasE = (autorasEndpoint *)cmiGetAutoRasHandle((HAPP)emaGetInstance((EMAElement)hsCall));
switch(trStage)
{
case cmRASTrStageConfirm:
{
/* cool, now let's send the ARQ */
ret = cmRASRequest(autorasC->tx);
if (ret >= 0)
autorasC->callState = autorasCallConnecting;
else
{
cmRASClose(autorasC->tx);
autorasC->tx = NULL;
}
break;
}
case cmRASTrStageReject:
{
int chNodeId;
int responseId = cmiRASGetResponse(hsRas);
autorasC->wasRejected = RV_TRUE; /* was rejected by at least one GK */
/* Check out the reason */
__pvtGetNodeIdByFieldIds(chNodeId, autorasE->hVal, responseId, {_anyField _q931(rejectReason) _q931(discoveryRequired) LAST_TOKEN});
if (chNodeId >= 0)
{
/* We have to try all over again, this time for GRQ */
autoRasDiscRegAndSend(autorasE, autorasC);
return 0;
}
/* Let's try the next GK */
if ((ret=autoRasCallSendToNextGK(autorasE, autorasC)) >= 0)
break;
/* Drek. could not send the RRQ, maybe because there are no more GKs. */
autorasC->wasRejected = RV_FALSE;
autorasC->isTempRdrn = RV_FALSE;
autorasE->event(hsCall, hsRas, cmiAutoRasEvCallRejected);
break;
}
case cmRASTrStageTimeout:
{
/* Let's try the next GK */
if ((ret=autoRasCallSendToNextGK(autorasE, autorasC)) < 0)
{
/* Drek. could not send the RRQ, maybe because there are no more GKs. */
if(autorasC->wasRejected)
{
/* ARJ - notify the CM about it */
autorasC->wasRejected = RV_FALSE;
autorasC->isTempRdrn = RV_FALSE;
autorasE->event(hsCall, hsRas, cmiAutoRasEvCallRejected);
break;
}
autorasE->event(hsCall, hsRas, cmiAutoRasEvTimedout);
/* See if we should try to register again */
if(autorasC->isTempRdrn)
{
/* just a temp redirection. forget it. */
autorasC->isTempRdrn = RV_FALSE;
break;
}
if (pvtGetChild(autorasE->hVal, autorasE->confNode, __q931(dontRegisterOnTimeout), NULL) < 0)
{
/* We should change the status to not registered */
autorasE->state = cmIdle;
autoRasCallIdleState(autorasE, autorasC);
/* Make sure we're trying to register again */
if ((autorasE->internalState != autorasRegTrying) && (autorasE->internalState != autorasRegFailed))
cmRegister(autorasE->hApp);
}
}
break;
}
default:
/* This shouldn't happen... */
break;
}
if (hsRas == autorasE->registrationTx)
{
cmRASClose(hsRas);
autorasE->registrationTx = NULL;
}
return ret;
}
/************************************************************************
* autoRasRegAndSend
* purpose: Make a registration to an AltGK, with the haRas of autorasC
* input : autorasE - Automatic RAS module for an EP
* autorasC - Automatic RAS module for a call
* GkAddr - Pointer to the address of the GK used
* GkIdPtr - Pointer to the GK ID of the GK used
* output : none
* return : Non-negative value on success
* Negative value on failure
************************************************************************/
int autoRasRegAndSend
(
IN autorasEndpoint* autorasE,
IN autorasCall* autorasC,
IN cmTransportAddress * GkAddr,
IN cmAlias * GkIdPtr
)
{
int ret = 0;
/* get rid of the old tx before creating the new one */
if (autorasE->registrationTx != NULL)
{
cmRASClose(autorasE->registrationTx);
autorasE->registrationTx = NULL;
}
ret = cmRASStartTransaction(autorasE->hApp, (HAPPRAS)autorasC,
&autorasE->registrationTx, cmRASRegistration, GkAddr, NULL);
if (ret >= 0)
{
/* Set the parameters of the message */
cmRASSetParam(autorasE->registrationTx, cmRASTrStageRequest, cmRASParamDiscoveryComplete, 0, (RvInt32)autorasE->discoveryComplete, NULL);
cmRASSetParam(autorasE->registrationTx, cmRASTrStageRequest, cmRASParamKeepAlive, 0, 0, NULL);
if(GkIdPtr)
cmRASSetParam(autorasE->registrationTx, cmRASTrStageRequest, cmRASParamGatekeeperID, 0, sizeof(*GkIdPtr), (char *) GkIdPtr);
/* Make sure next time we know nothing about a GCF */
autorasE->discoveryComplete = RV_FALSE;
/* Set the response handler for this message */
cmiRASSetTrEventHandler(autorasE->registrationTx, autoRasSendAftReg);
/* Send the request */
ret = cmRASRequest(autorasE->registrationTx);
}
return ret;
}
/************************************************************************
* autoRasRegAndSendAftDisc
* purpose: Callback function indicating the response to a GRQ sent to
* an Alt GK.
* input : haRas - Application's handle (autoras in this context)
* hsRas - RAS Transaction handle
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -