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

📄 cat.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:

/*

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 "rvmemory.h"
#include "rvinternal.h"
#include "ra.h"
#include "hash.h"
#include "catdb.h"
#include "cat.h"


#ifdef __cplusplus
extern "C" {
#endif


/************************************************************************
 *
 *                              Private constants
 *
 ************************************************************************/

/* Additional number of keys for call - we use this value to make sure
   the hash table is bigger than the number of elements by a reasonable
   size */
#define CAT_ADDITIONAL_KEYS (3)


/* Key index handling association for version 1 endpoints. This one is used
   with or without a destCallSignalAddress field in it. */
#define CAT_ASSOCIATION_KEY (4)




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


/* todo: move to somewhere else */
/************************************************************************
 * addrcmp
 * purpose: Compare between 2 transport addresses
 * input  : addr1   - First address
 *          addr2   - Second address
 * output : none
 * return : 0 if both addresses are the same one
 *          Non-zero value othetwise
 ************************************************************************/
int addrcmp(IN cmTransportAddress* addr1, IN cmTransportAddress* addr2)
{
    if ((addr1->ip == addr2->ip) &&
        (addr1->port == addr2->port))
        return 0; /* Match */

    return 1; /* Doesn't match */
}


/************************************************************************
 * addrhash
 * purpose: Calculate a hash value for an address. This function can
 *          be used as part of a hash function, but not as the hash
 *          function itself.
 * input  : addr    - Address to hash
 *          hashKey - Starting hash value
 * output : none
 * return : Calculated hash value
 ************************************************************************/
int addrhash(
    IN cmTransportAddress*  addr,
    IN RvUint32             hashKey)
{
    /* We hash each address type differently */
    switch (addr->type)
    {
        case cmTransportTypeIPStrictRoute:
        case cmTransportTypeIPLooseRoute:
        case cmTransportTypeNSAP:
            /* No hashing for these guys - they're not really supported... */
            break;

        case cmTransportTypeIP:
        default:
            /* Hash by IP and PORT fields */
            hashKey = hashKey << 1 ^ addr->ip;
            hashKey = hashKey << 1 ^ addr->port;
            break;
      }

    return hashKey;
}


/************************************************************************
 * catHashKey
 * purpose: CAT key hashing function
 *          It uses different hashing method for different keys
 * input  : param       - Parameter we're going to hash (catKeyStruct)
 *          paramSize   - Size of the parameter
 *          hashSize    - Size of the hash table itself
 * output : none
 * return : Hash value to use
 ************************************************************************/
static RvUint32 catHashKey(
    IN void *param,
    IN int paramSize,
    IN int hashSize)
{
    catStruct*  key;
    RvUint32    hashKey = 0;
    RvUint32    bytes, keyValue;
    RvUint8*    ptr;

    if (paramSize);
    key = ((catKeyStruct *)param)->key;
    keyValue = ((catKeyStruct *)param)->keyValue;

    /* We take into consideration only the fields that are set in the keyValue */
    if ((keyValue & catCallId) != 0)
    {
        bytes = sizeof(key->callID);
        ptr = (RvUint8*)key->callID;
        while (bytes-- > 0) hashKey = hashKey << 1 ^ *ptr++;
    }
    if ((keyValue & catAnswerCall) != 0)
    {
        hashKey = hashKey << 1 ^ (key->answerCall);
    }
    if ((keyValue & catCRV) != 0)
    {
        bytes = sizeof(key->crv);
        ptr = (RvUint8*)&key->crv;
        while (bytes-- > 0) hashKey = hashKey << 1 ^ *ptr++;
    }
    if ((keyValue & catRasCRV) != 0)
    {
        bytes = sizeof(key->rasCRV);
        ptr = (RvUint8*)&key->rasCRV;
        while (bytes-- > 0) hashKey = hashKey << 1 ^ *ptr++;
    }
    if ((keyValue & catDestCallSignalAddr) != 0)
    {
        hashKey = addrhash(&key->destCallSignalAddr, hashKey);
    }
    if ((keyValue & catRasSrcAddr) != 0)
    {
        hashKey = addrhash(&key->rasSrcAddr, hashKey);
    }
    if ((keyValue & catSrcCallSignalAddr) != 0)
    {
        hashKey = addrhash(&key->srcCallSignalAddr, hashKey);
    }
    if ((keyValue & catCID) != 0)
    {
        bytes = sizeof(key->cid);
        ptr = (RvUint8*)key->cid;
        while (bytes-- > 0) hashKey = hashKey << 1 ^ *ptr++;
    }

    return (hashKey % hashSize);
}


/************************************************************************
 * catCompareKey
 * purpose: Comparison function for 2 key structs in CAT
 * input  : givenKey    - The key given by the user (catKeyStruct type)
 *                        The keyValue field of this struct is discarded
 *                        in the comparison process.
 *          storedKey   - Key inside hash table (catKeyStruct type)
 *          keySize     - Size of each key
 * return : RV_TRUE if elements are the same
 *          RV_FALSE otherwise
 ************************************************************************/
static RvBool catCompareKey(IN void* givenKey, IN void* storedKey, IN RvUint32 keySize)
{
    /* We check the fields one by one, looking for each flag that exist in both keys */
    catStruct*  searchFor;
    catStruct*  trueKey;
    RvUint32    keyValue;

    if (keySize);

    searchFor = ((catKeyStruct *)givenKey)->key;
    trueKey = ((catKeyStruct *)storedKey)->key;
    keyValue = ((catKeyStruct *)storedKey)->keyValue;

    /* First let's make sure we're dealing with the same type of key from
       the different types of keys stored inside CAT */
    if ((searchFor->flags & keyValue) == keyValue)
    {
        /* Check each of the key parts that are set in this struct */
        if ((keyValue & catCallId) != 0)
            if (memcmp(searchFor->callID, trueKey->callID, sizeof(trueKey->callID)) != 0)
                return RV_FALSE; /* CallID doesn't match */
        if ((keyValue & catAnswerCall) != 0)
            if (searchFor->answerCall != trueKey->answerCall)
                return RV_FALSE; /* answerCall doesn't match */
        if ((keyValue & catCRV) != 0)
            if (searchFor->crv != trueKey->crv)
                return RV_FALSE; /* Q931CRV doesn't match */
        if ((keyValue & catRasCRV) != 0)
            if (searchFor->rasCRV != trueKey->rasCRV)
                return RV_FALSE; /* RAS-CRV doesn't match */
        if ((keyValue & catDestCallSignalAddr) != 0)
            if (addrcmp(&searchFor->destCallSignalAddr, &trueKey->destCallSignalAddr) != 0)
                return RV_FALSE; /* DestAddress doesn't match */
        if ((keyValue & catRasSrcAddr) != 0)
            if (addrcmp(&searchFor->rasSrcAddr, &trueKey->rasSrcAddr) != 0)
                return RV_FALSE; /* RasSrcAddr doesn't match */
        if ((keyValue & catSrcCallSignalAddr) != 0)
            if (addrcmp(&searchFor->srcCallSignalAddr, &trueKey->srcCallSignalAddr) != 0)
                return RV_FALSE; /* SrcAddress doesn't match */
        if ((keyValue & catCID) != 0)
            if (memcmp(searchFor->cid, trueKey->cid, sizeof(trueKey->cid)) != 0)
                return RV_FALSE; /* CID doesn't match */
    }
    else
        return RV_FALSE;

    /* If we're here it means that the elements match */
    return RV_TRUE;
}


/************************************************************************
 * catCheckDestCallSignalAddress
 * purpose: This function checks if we are currently handling something
 *          that might generate keys with destCallSignalAddress although
 *          this field is missing. We do this for Version 1 endpoits that
 *          have no other way of being pin-pointed (this means that we
 *          don't have their CallId).
 * input  : cat     - CAT instance to use
 *          key     - Key to check and update
 * return : RV_OK on success, other on failure
 ************************************************************************/
static RvStatus catCheckDestCallSignalAddress(
    IN      catModule   *cat,
    INOUT   catStruct   *key)
{
    if ((key->flags & catCallId) != 0)
    {
        /* We have a CallID for this one - no need to work on this one since
           it's version 2 or up */
        return RV_OK;
    }

    if ((key->flags & catDestCallSignalAddr) != 0)
    {
        /* We have the destCallSignalAddress for this call already, so there's
           nothing more we can or should do here. */
        return RV_OK;
    }

    /* Check if we have all the fields for the CID association related key. If only
       destCallSignalAddress is missing - we might as well think that it's there and
       go on with it */
    if (((key->flags | catDestCallSignalAddr) & cat->keyTypes[CAT_ASSOCIATION_KEY]) ==
        cat->keyTypes[CAT_ASSOCIATION_KEY])
    {
        /* We might as well think that we have it... */
        key->flags |= catDestCallSignalAddr;
        memset(&key->destCallSignalAddr, 0, sizeof(key->destCallSignalAddr));
    }

    return RV_OK;
}



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


/************************************************************************
 * catConstruct
 * purpose: Create a CAT instance
 * input  : numCalls        - Number of calls supported by CAT
 *          isGatekeeper    - Is this a gatekeeper or an endpoint
 *          cidAssociation  - RV_TRUE if we want to associate calls by their CID
 *                            RV_FALSE if we don't want to associate calls by their CID
 *          compare15bitCrv - Use 15bit comparison on CRV instead of 16bit
 * output : none
 * return : Handle to CAT instance on success
 *          NULL on failure
 ************************************************************************/
RVHCAT catConstruct(
    IN RvUint32     numCalls,
    IN RvBool       isGatekeeper,
    IN RvBool       compare15bitCrv,
    IN RvBool       cidAssociation)
{
    catModule*  cat;

    /* Allocate the CAT instance */
    if(RvMemoryAlloc(NULL, (void**)&cat, sizeof(catModule)) != RV_OK)
        return NULL;

    if (isGatekeeper)
        cat->numSimultKeys = 5;
    else
        cat->numSimultKeys = 4;

    RvLogSourceConstruct(RvLogGet(), &cat->log, RV_LOG_LIBCODE_H323, "CAT", "Call Association Table");
    RvLogDebug(&cat->log,
        (&cat->log, "catConstruct: compare15bitCrv=%d,cidAssociation=%d", compare15bitCrv, cidAssociation));
    cat->compare15bitCrv = compare15bitCrv;

    /* Set the keys we can handle */
    cat->keyTypes[0] = catCallId | catAnswerCall | catDestCallSignalAddr;
    cat->keyTypes[1] = catRasCRV | catRasSrcAddr;
    cat->keyTypes[2] = catCallId | catAnswerCall;
    cat->keyTypes[3] = catCallId | catRasCRV;
    if (cidAssociation == RV_TRUE)
        cat->keyTypes[CAT_ASSOCIATION_KEY] = catCID | catAnswerCall | catDestCallSignalAddr;
    else
        cat->keyTypes[CAT_ASSOCIATION_KEY] = catSrcCallSignalAddr | catAnswerCall | catDestCallSignalAddr;

    /* Allocate the hash */
    cat->hash =
        hashConstruct((int)(numCalls * (cat->numSimultKeys + CAT_ADDITIONAL_KEYS)),
                      (int)(numCalls * cat->numSimultKeys),
                      catHashKey,
                      catCompareKey,
                      sizeof(catKeyStruct),
                      sizeof(catDataStruct*),
                      "CAT HASH");

    /* Allocate the calls */
    cat->calls =
        raConstruct(sizeof(catDataStruct), (int)numCalls, RV_FALSE, "CAT CALLS");

    if ((cat->hash == NULL) || (cat->calls == NULL))
    {
        if (cat->hash != NULL) hashDestruct(cat->hash);
        if (cat->calls != NULL) raDestruct(cat->calls);
        return NULL;
    }

    /* Allocate a mutex */
    RvLockConstruct(&cat->lock);

    return (RVHCAT)cat;
}


/************************************************************************
 * catDestruct
 * purpose: Delete a CAT instance
 * input  : hCat    - CAT instance handle
 * output : none
 * return : Non-negative value on success
 *          Negative value on failure
 ************************************************************************/
int catDestruct(IN RVHCAT hCat)
{
    catModule* cat;

    if (hCat == NULL) return RV_ERROR_UNKNOWN;
    cat = (catModule *)hCat;

    hashDestruct(cat->hash);
    raDestruct(cat->calls);
    RvLockDestruct(&cat->lock);
    RvLogSourceDestruct(RvLogGet(), &cat->log);
    RvMemoryFree(cat);
    return 0;

⌨️ 快捷键说明

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