⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmautorasep.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 4 页
字号:
/***********************************************************************
        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.
***********************************************************************/

/************************************************************************
 * cmAutoRasEP
 * -----------
 * This file provides the endpoint part of the automatic RAS module.
 * This includes the following features:
 *
 * - Automatic discovery and registration to a gatekeeper
 * - Unregistration of a gatekeeper
 * - Lightweight RRQs (timeToLive feature)
 * - Sending NSM and RAI messages
 * - Automatic responses to IRQ messages
 * - Enabling manual RAS to work with automatic RAS for endpoint related
 *   transactions
 ************************************************************************/

#include "q931asn1.h"
#include "cmintr.h"
#include "cmras.h"
#include "cmCrossReference.h"
#include "cmAutoRasEP.h"
#include "rasutils.h"
#include "cmdebprn.h"


#ifdef __cplusplus
extern "C" {
#endif


/* Private functions declaration */
static RvBool autoRasSendLightweightRRQ(IN void* context);
static RvBool autoRasRetry(IN void* context);
static int autoRasPrepareRRQ(IN autorasEndpoint* autoras, IN int GkNodeId);
static int autoRasTryToRegister(IN autorasEndpoint* autoras);
static void autoRasIdleAndRegister(IN autorasEndpoint* autoras);
static RvBool autorasTryToRegisterOnError(IN void* context);
static int autoRasPrepareGRQ(IN autorasEndpoint* autoras);





/************************************************************************
 *
 *                              Private functions
 *
 ************************************************************************/

/************************************************************************
 * autoRasEpSendToNextGK
 * purpose: Resend a request to the next GK
 * input  : autoras     - Automatic RAS EP module
 * output : none
 * return : Non-negative value on success
 *          Negative value on failure
 ************************************************************************/
static int autoRasEpSendToNextGK(IN autorasEndpoint * autoras)
{
    /* ok, so we already got everything in, except cmRASParamDestinationIpAddress
       and GK ID. let's go get'em! */
    int ret;
    int tmpNode, messageNode;
    cmTransportAddress GKAddr;
    cmAlias GKID;
    char GKIDstr[128];
    RvInt32 needToRegister = 0;
    RvBool isLwRrq = RV_FALSE, isRrq = RV_FALSE, isPartUrq = RV_FALSE, isUrq = RV_FALSE;

    int GkNodeId = autoRasGetNextAltGkNode(autoras, NULL);
    if (GkNodeId < 0)
    {
        /* damn, no more GKs! we failed! */
        return RV_ERROR_UNKNOWN;
    }

    /* first, see if this is a URQ or an RRQ */
    messageNode = cmGetProperty((HPROTOCOL)autoras->registrationTx);
    __pvtGetNodeIdByFieldIds(tmpNode, autoras->hVal, messageNode,
        {_q931(request) _q931(registrationRequest) LAST_TOKEN});
    if (RV_PVT_NODEID_IS_VALID(tmpNode))
    {
        RvInt32 keepAlive = 0;
        tmpNode = pvtGetChildByFieldId(autoras->hVal, tmpNode, __q931(keepAlive), &keepAlive, NULL);
        if (RV_PVT_NODEID_IS_VALID(tmpNode) && keepAlive)
            isLwRrq = RV_TRUE;
        else
            isRrq = RV_TRUE;
    }
    else
    {
        __pvtGetNodeIdByFieldIds(tmpNode, autoras->hVal, messageNode,
            {_q931(request) _q931(unregistrationRequest) LAST_TOKEN});
        if (RV_PVT_NODEID_IS_VALID(tmpNode))
        {
            tmpNode = pvtGetChild(autoras->hVal, tmpNode, __q931(endpointAlias), NULL);
            if (RV_PVT_NODEID_IS_VALID(tmpNode))
                isPartUrq = RV_TRUE;
            else
                isUrq = RV_TRUE;
        }
    }

    /* Skip GKs with needToRegister=true for URQ*/
    tmpNode = pvtGetChildByFieldId(autoras->hVal, GkNodeId, __q931(needToRegister), &needToRegister, (RvBool *)NULL);
    while(isUrq && !autoras->isTempRdrn && (tmpNode>=0) && needToRegister)
    {
        GkNodeId = autoRasGetNextAltGkNode(autoras, NULL);
        if (GkNodeId < 0)
        {
            /* damn, no more GKs! we failed! */
            return RV_ERROR_UNKNOWN;
        }
        tmpNode = pvtGetChildByFieldId(autoras->hVal, GkNodeId, __q931(needToRegister), &needToRegister, (RvBool *)NULL);
    }

    /* OK, now we should have a GK, and know what we are sending */
    /* if we are sending a LWRRQ, register instead */
    if(isLwRrq && !autoras->isTempRdrn && (tmpNode>=0) && needToRegister)
    {
        return autoRasPrepareRRQ(autoras, GkNodeId);;
    }
    /* if we are sending a PURQ, register first */
    if(isPartUrq && !autoras->isTempRdrn && (tmpNode>=0) && needToRegister)
    {
        /* ToDo: handle partial URQs when registration is requiered */
    }

    /* Get GK address */
    tmpNode = pvtGetChild(autoras->hVal, GkNodeId, __q931(rasAddress), NULL);
    if((tmpNode<0) || (cmVtToTA(autoras->hVal, tmpNode, (cmTransportAddress *) &GKAddr)<0))
    {
        /* failed again ! */
        return RV_ERROR_UNKNOWN;
    }
    cmRASSetParam(autoras->registrationTx, cmRASTrStageRequest, cmRASParamDestinationIpAddress, 0, sizeof(GKAddr), (char *)&GKAddr);

    /* Get GK ID */
    GKID.string = GKIDstr;
    tmpNode = pvtGetChild(autoras->hVal, GkNodeId, __q931(gatekeeperIdentifier), NULL);
    if((tmpNode>=0) &&
       ((GKID.length = (unsigned short) pvtGetString(autoras->hVal, tmpNode, 128, GKIDstr))>0))
        cmRASSetParam(autoras->registrationTx, cmRASTrStageRequest, cmRASParamGatekeeperID, 0, sizeof(GKID), (char *)&GKID);

    /* Send the request */
    ret = cmRASRequest(autoras->registrationTx);
    if (ret < 0)
    {
        cmRASClose(autoras->registrationTx);
        autoras->registrationTx = NULL;
    }

    return ret;
}

/************************************************************************
 * autoRasGatekeeperResponse
 * purpose: Callback function indicating the response of an GRQ
 * 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
 ************************************************************************/
static int RVCALLCONV autoRasGatekeeperResponse(
    IN  HAPPRAS          haRas,
    IN  HRAS             hsRas,
    IN  cmRASTrStage     trStage)
{
    autorasEndpoint* autoras = (autorasEndpoint *)haRas;
    int nodeID = cmGetProperty((HPROTOCOL)hsRas);

    /* See what we've got */
    switch(trStage)
    {
        case cmRASTrStageConfirm:
            /* GCF - we should continue to RRQ */
            autoras->discoveryComplete = RV_TRUE;

            /* Change the state ant notify application */
            autoras->state = cmDiscovered;
            autoRasChangeState(autoras, cmGatekeeperConfirm, cmiRASGetResponse(hsRas));

            /* getting the alternate gatekeepers from the message */
            __pvtGetNodeIdByFieldIds(nodeID, autoras->hVal, nodeID,
                {_q931(response) _anyField _q931(alternateGatekeeper) LAST_TOKEN});
            /* this function will set the new GK if needed, and get the new AltGKs list */
            setRasAlternateGatekeeper(autoras, NULL, nodeID);

            /* Go on to RRQ */
            autoRasPrepareRRQ(autoras, RV_ERROR_UNKNOWN);
            break;

        case cmRASTrStageReject:
        {
            /* GRJ - idle... */
            RvInt32 isMulticast = RV_FALSE;
            autoras->discoveryComplete = RV_TRUE;

            /* If we're in multicast - we don't continue... */
            cmRASGetParam(hsRas, cmRASTrStageRequest, cmRASParamMulticastTransaction, 0, &isMulticast, NULL);

            /* Change the state and notify application */
            autoras->state = cmIdle;
            autoRasChangeState(autoras, cmGatekeeperReject, cmiRASGetResponse(hsRas));

            if (!emaWasDeleted((EMAElement)hsRas) && !autoRasGotPermList(autoras))
            {
                /* getting the alternate gatekeepers from the message */
                __pvtGetNodeIdByFieldIds(nodeID, autoras->hVal, nodeID,
                    {_q931(response) _anyField _q931(altGKInfo) _q931(alternateGatekeeper) LAST_TOKEN});
                if(nodeID >= 0)
                { /* if there is AltGKs info in the message, put it in permAltGKs. NOTE: we put it
                    in permAltGK even if it is temporary, because we don't have anything else */
                    autoRasSetPermList(autoras, nodeID);
                }
            }

            if (isMulticast)
            {
                /* Ignore and wait for another reply */
                return 0;
            }

            /* Try all over again */
            autoRasTryToRegister(autoras);
            break;
        }

        case cmRASTrStageTimeout:
        {
            /* We've timed out - try again */
            autoRasIdleAndRegister(autoras);
            break;
        }

        default:
            break;
    }

    if(hsRas == autoras->registrationTx)
    {
        /* no one removed this tx yet. kill it. */
        cmRASClose(hsRas);
        autoras->registrationTx = NULL;
    }
    return 0;
}


/************************************************************************
 * autoRasRegistrationResponse
 * purpose: Callback function indicating the response of an RRQ
 * 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
 ************************************************************************/
static int RVCALLCONV autoRasRegistrationResponse(
 IN  HAPPRAS          haRas,
 IN  HRAS             hsRas,
 IN  cmRASTrStage     trStage)
{
    autorasEndpoint* autoras = (autorasEndpoint *)haRas;
    RvPvtNodeId nodeId;
    RvPvtNodeId responseId = cmiRASGetResponse(hsRas);
    RvPvtNodeId messageId;

    /* Skip the type of message and get to the message itself */
    messageId = pvtChild(autoras->hVal, responseId);

    /* See what we've got */
    switch(trStage)
    {
    case cmRASTrStageConfirm:
        {
            /* RCF received - update information and we're done */
            RvBool createLightWeight = RV_FALSE;

            if ( (nodeId=pvtGetChild(autoras->hVal, messageId, __q931(timeToLive), NULL)) >= 0)
            {
                /* We've got timeToLive - start counting for lightweight RRQs */
                RvInt32 timeToLive, timeout, preTimeToLiveRegistration=1;
                pvtGet(autoras->hVal, nodeId, NULL, NULL, &timeToLive, NULL);
                pvtGet(autoras->hVal, pvtGetChild(autoras->hVal, autoras->confNode, __q931(preTimeToLiveRegistration), NULL), NULL, NULL, &preTimeToLiveRegistration, NULL);

                if(timeToLive <= preTimeToLiveRegistration)
                    timeToLive = 1;
                else
                    timeToLive -= preTimeToLiveRegistration;

                timeout = RvMax(timeToLive-1, 1) * 1000;
	
                autoras->regTimer = RvH323TimerStart(autoras->hTimers, autoRasSendLightweightRRQ, autoras, timeout);
                createLightWeight = RV_TRUE;
            }

            /* getting the alternate gatekeepers from the message */
            nodeId = pvtGetChild(autoras->hVal, messageId, __q931(alternateGatekeeper), NULL);
            /* this function will set the new GK is needed, and get the new AltGKs list */
            setRasAlternateGatekeeper(autoras, NULL, nodeId);

            /* Notify the application about the registration */
            autoras->event(NULL, hsRas, cmiAutoRasEvGotRCF);

            /* Change the state and notify the application */
            autoras->state = cmRegistered;
            autoras->internalState = autorasRegistered; /* We're registered! */
            autoRasChangeState(autoras, cmRegistrationConfirm, responseId);

            /* Initialize the number of tries - when we fail, we should start from the beginning */
            autoras->regTries = 0;

            if(createLightWeight)
            {
                /* Create a Light Weight RRQ from current RRQ */
                RvPvtNodeId newRoot, regRequest, fromNode, toNode;
                int i;
                RvPvtNodeId requestId = cmiRASGetRequest(hsRas);
                /* array of fields to copy */
                short paths[] = { /* fileds from the H.225 standard */ _q931(rasAddress) _q931(endpointIdentifier) _q931(gatekeeperIdentifier) _q931(tokens) _q931(timeToLive) /* from here are the non-optional fields */ _q931(discoveryComplete) _q931(protocolIdentifier) _q931(terminalType) _q931(endpointVendor) _q931(willSupplyUUIEs) _q931(maintainConnection) LAST_TOKEN};
                short path[2] = {LAST_TOKEN, LAST_TOKEN};

                regRequest = pvtChild(autoras->hVal, requestId);

                /* move the current RRQ, and create a new one */
                newRoot = pvtAddRoot(autoras->hVal, ((cmElem*)(autoras->hApp))->synProtRAS, 0, NULL);
                pvtMoveTree(autoras->hVal, newRoot, regRequest);
                regRequest = pvtAdd(autoras->hVal, requestId, __q931(registrationRequest), 0, NULL, NULL);

                /* move the needed nodes into the LWRRQ */
                for(i=0; paths[i] != LAST_TOKEN; i++)
                {
                    path[0] = paths[i];
                    fromNode = pvtGetNodeIdByFieldIds(autoras->hVal, newRoot, path);
                    if(fromNode>=0)
                    {
                        toNode = pvtBuildByFieldIds(autoras->hVal, regRequest, path, 0, NULL);
                        pvtMoveTree(autoras->hVal, toNode, fromNode);
                    }
                }

                /* add the keepAlive value */
                pvtAdd(autoras->hVal, regRequest, __q931(keepAlive), RV_TRUE, NULL, NULL);

                /* build an empty callSignalAddress entry */
                pvtAdd(autoras->hVal, regRequest, __q931(callSignalAddress), 0, NULL, NULL);

                /* now copy the EP ID and the GK ID from the confirmation message */
                fromNode = pvtGetChild(autoras->hVal, messageId, __q931(gatekeeperIdentifier), NULL);
                if (RV_PVT_NODEID_IS_VALID(fromNode))
                {
                    toNode = pvtAdd(autoras->hVal, regRequest, __q931(gatekeeperIdentifier), 0, NULL, NULL);
                    pvtSetTree(autoras->hVal, toNode, autoras->hVal, fromNode);
                }
                fromNode = pvtGetChild(autoras->hVal, messageId, __q931(endpointIdentifier), NULL);
                if (RV_PVT_NODEID_IS_VALID(fromNode))
                {
                    toNode = pvtAdd(autoras->hVal, regRequest, __q931(endpointIdentifier), 0, NULL, NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -