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

📄 rasin.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 3 页
字号:
 * input  : ras             - RAS module to use
 *          tx              - Incoming transaction
 *          trStage         - Transaction stage. Indicates if it's a reject
 *                            or a confirm
 *          nodeId          - Message to send if not done through stage
 *          storeInRPOOL    - Indicate if we want to store this message
 *                            for future retransmissions
 * output : none
 * return : If an error occurs, the function returns a negative value.
 *          If no error occurs, the function returns a non-negative value.
 ************************************************************************/
int rasSendResponse(
    IN rasModule*   ras,
    IN rasInTx*     tx,
    IN cmRASTrStage trStage,
    IN int          nodeId,
    IN RvBool       storeInRPOOL)
{
    rasInTxKey* key;
    int responseNodeId;
    int status = 0;

    if (nodeId < 0)
    {
        /* No specific message - send the response in the property database */
        if (tx->responseSet == rasNoResponseSet)
        {
            /* The application didn't set any response - let's take the default one */
            __pvtBuildByFieldIds(responseNodeId, ras->hVal, tx->txProperty, {_q931(response) LAST_TOKEN}, 0, NULL);
            pvtSetTree(ras->hVal, responseNodeId, ras->hVal, ras->defaultMessages[tx->transactionType][trStage]);
        }
        else
            responseNodeId = pvtGetChild(ras->hVal, tx->txProperty, __q931(response), NULL);
    }
    else
        responseNodeId = nodeId;

    if (responseNodeId < 0)
    {
        RvLogError(&ras->log,
            (&ras->log, "rasSendResponse: Problems in handling the response message (transaction 0x%p)", tx));
        return responseNodeId;
    }

    if (trStage == cmRASTrStageConfirm)
    {
        int         destNodeId = 1;
        cmRASParam  param = (cmRASParam)-1;

        /* See if we have to create Q931 addresses in confirm messages */
        switch (tx->transactionType)
        {
            case cmRASRegistration:
                param = cmRASParamCallSignalAddress;
                __pvtGetNodeIdByFieldIds(destNodeId, ras->hVal, tx->txProperty, {_q931(response) _anyField _q931(callSignalAddress) LAST_TOKEN});
                break;

            case cmRASAdmission:
                param = cmRASParamDestCallSignalAddress;
                __pvtGetNodeIdByFieldIds(destNodeId, ras->hVal, tx->txProperty, {_q931(response) _anyField _q931(destCallSignalAddress) LAST_TOKEN});
                break;

            default:
                destNodeId = 1;
        }

        if (destNodeId < 0)
        {
            cmTransportAddress addr;
            if (cmGetLocalCallSignalAddress(ras->app, &addr) >= 0)
                rasSetParam(ras, (HRAS)tx, cmRASTrStageConfirm, param, 0, sizeof(addr), (char*)&addr);
        }
    }

    /* Set the sequence number in the response to match the one in the request */
    key = (rasInTxKey *)hashGetKey(ras->inHash, tx->hashValue);
    __pvtBuildByFieldIds(status, ras->hVal, responseNodeId, {_anyField _q931(requestSeqNum) LAST_TOKEN}, (RvInt32)(key->seqNumber), NULL);
    if (status < 0) return status;

    /* Send the message. We always send through the unicast port */
    status = rasEncodeAndSend(ras, (HRAS)tx, trStage, responseNodeId, RV_FALSE, &tx->destAddress, storeInRPOOL, &tx->encodedMsg);
    if (status < 0)
    {
        RvLogError(&ras->log,
            (&ras->log, "rasSendResponse: Couldn't send the message 0x%p: %d", tx, status));
        return status;
    }

    /* Change the state of this transaction */
    tx->state = rasTxStateReplySent;

    return 0;
}








/************************************************************************
 *
 *                              Public functions
 *
 ************************************************************************/


/************************************************************************
 * rasIncomingHashFunc
 * purpose: Incoming transactions hash function
 *          This function returns as the hash key the actual sequence
 *          number of the transaction without fooling around with it
 * input  : param       - Parameter we're going to hash
 *          paramSize   - Size of the parameter
 *          hashSize    - Size of the hash table itself
 * output : none
 * return : Hash value to use
 ************************************************************************/
RvUint32 rasIncomingHashFunc(
    IN void *param,
    IN int paramSize,
    IN int hashSize)
{
    rasInTxKey* key = (rasInTxKey *)param;
    if (paramSize);
    return (addrhash(&key->address, key->seqNumber) % hashSize);
}


/************************************************************************
 * rasIncomingHashCompare
 * purpose: Compare keys in the outgoing hash table
 * input  : key1, key2  - Keys to compare
 *          keySize     - Size of each key
 * return : RV_TRUE if elements are the same
 *          RV_FALSE otherwise
 ************************************************************************/
RvBool rasIncomingHashCompare(IN void *key1, IN void* key2, IN RvUint32 keySize)
{
    rasInTxKey* txKey1 = (rasInTxKey *)key1;
    rasInTxKey* txKey2 = (rasInTxKey *)key2;

    RV_UNUSED_ARG(keySize);

    return
        ((txKey1->seqNumber == txKey2->seqNumber) &&
         (txKey1->msgType == txKey2->msgType) &&
         (addrcmp(&txKey1->address, &txKey2->address) == 0));
}


/************************************************************************
 * rasHandleRequest
 * purpose: Handle an incoming request message
 * input  : ras             - RAS module to use
 *          chanType        - Channel the message came from (uni/multi)
 *          srcAddress      - Address of the sender
 *          messageBuf      - The message buffer to send
 *          messageLength   - The length of the message in bytes
 *          messageNodeId   - Node ID of message root. If negative, then
 *                            message is decoded from given buffer and hook
 *                            is called
 *          messageType     - Message type of the reply
 *          seqNum          - requestSeqNum field value of the message
 * output : hMsgContext     - Incoming message context. Used mostly by security
 *                            If the returned value is different than NULL,
 *                            then the message context is not used by the
 *                            transaction and should be released
 * return : Non-negative value on success
 *          Negative value on failure
 ************************************************************************/
int rasHandleRequest(
    IN  rasModule*       ras,
    IN  rasChanType      chanType,
    IN  cmRASTransport*  srcAddress,
    IN  RvUint8*         messageBuf,
    IN  RvUint32         messageLength,
    IN  int              messageNodeId,
    IN  rasMessages      messageType,
    IN  RvUint32         seqNum,
    OUT void**           hMsgContext)
{
    rasInTx*    tx;
    rasInTxKey  key;
    void*       hashValue;
    int         status;

    RvLockGet(&ras->lockInHash);

    /* Make sure we clean up the incoming database */
    status = rasGarbageCollection(ras);

    /* Find the transaction */
    memcpy(&key.address, srcAddress, sizeof(cmRASTransport));
    key.seqNumber = seqNum;
    key.msgType = messageType;
    hashValue = hashGetElement(ras->inHash, hashFind(ras->inHash, &key));
    if (hashValue != NULL)
        tx = *((rasInTx **)hashValue);
    else
        tx = NULL;

    if (tx == NULL)
    {
        /* New message to handle */
        HAPPRAS     haRas = NULL;
        RvBool      callRelated = RV_FALSE;
        rasMessages newType;
        RvUint32    newSeqNum;
        RvBool      notifyApp = RV_TRUE;
        HAPPCALL    haCall = NULL;

        RvLockRelease(&ras->lockInHash);

        if (messageNodeId < 0)
        {
            /* Decode the message - it's first time we're here */
            status =
                rasDecodeAndRecv(ras, messageBuf, messageLength, (RvBool)(chanType == rasChanMulticast), srcAddress,
                                 &messageNodeId, &newType, &newSeqNum, hMsgContext);

            /* Make sure the application didn't change the sequence number or type of message */
            if ((status >= 0) && ((newSeqNum != seqNum) || (messageType != newType)))
            {
                /* Reroute the message to check it again... */
                return rasRouteMessage(ras, chanType, srcAddress, messageBuf, messageLength, messageNodeId, newType, newSeqNum, hMsgContext);
            }
        }
        else
            status = 0;

        if (status >= 0)
        {
            /* Decode the message and put it in a new transaction */
            tx = rasNewTx(ras, messageNodeId, &messageNodeId);
        }

        if (tx == NULL)
            return RV_ERROR_UNKNOWN;

        /* Make sure to notify the application of an incoming RAS message */
        if (ras->evMessages.cmEvRasMessageReceive != NULL)
        {
            /* An internal callback - no log for this one */
            ras->evMessages.cmEvRasMessageReceive(messageNodeId, cmRASTrStageRequest, (HRAS)tx, ras->evMessages.hAppRasMsg);
        }

        /* Insert the key to the hash and unlock it */
        RvLockGet(&ras->lockInHash);
        tx->hashValue = hashAdd(ras->inHash, &key, &tx, RV_FALSE);
        RvLockRelease(&ras->lockInHash);

        if (tx->hashValue == NULL)
        {
            if (tx->txProperty >= 0)
                pvtDelete(ras->hVal, tx->txProperty);
            emaDelete((EMAElement)tx);
            RvLogError(&ras->log,
                (&ras->log, "rasHandleRequest: Error inserting hash value for a new incoming transaction"));
            return RV_ERROR_OUTOFRESOURCES;
        }

        /* Set known values for this transaction */
        tx->isMulticast = (chanType == rasChanMulticast);
        memcpy(&tx->destAddress, srcAddress, sizeof(cmRASTransport));
        tx->responseSet = rasNoResponseSet;
        tx->state = rasTxStateIdle;
        tx->transactionType = rasMessageInfo[messageType].transaction;

        /* Calculate the time this transaction will timeout */
        tx->stopTime = (RvInt32)Rv64Divide(RvTimestampGet(), RV_TIME64_NSECPERSEC) + 
                       (rasCfgGetRetries(ras) * rasCfgGetTimeout(ras));

        /* Check if the TX belongs to a call */
        status = rasLookupCall(ras, tx, &tx->hsCall, &callRelated);
        if ((status < 0) || (callRelated && !emaLock((EMAElement)tx->hsCall)))
        {
            /* Remove this transaction from the hash table */
            RvLockGet(&ras->lockInHash);
            hashDelete(ras->inHash, tx->hashValue);
            RvLockRelease(&ras->lockInHash);

            /* Kill the Tx and get the hell out of here */
            if (tx->txProperty >= 0)
                pvtDelete(ras->hVal, tx->txProperty);
            emaDelete((EMAElement)tx);
            return status;
        }

        /* Use callback to notify the application about the incoming request */
        emaMark((EMAElement)tx);

        /* Make sure we update the registration information if we have to */
        if (messageType == rasMsgUnregistrationRequest)
        {
            rasUpdateRegInfo(ras, -1);
        }

        if (callRelated)
        {
            haCall = (HAPPCALL)emaGetApplicationHandle((EMAElement)tx->hsCall);
            emaUnlock((EMAElement)tx->hsCall);

            /* For IRQ - we'll set the perCallInfo inside IRR by the call information */

⌨️ 快捷键说明

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