📄 rasin.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.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "rvinternal.h"
#include "rvtimestamp.h"
#include "cmintr.h"
#include "cmdebprn.h"
#include "rasutils.h"
#include "rasparams.h"
#include "rasirr.h"
#include "rasin.h"
/*todo: put this in some better place*/
int addrhash(
IN cmTransportAddress* addr,
IN RvUint32 hashKey);
int addrcmp(
IN cmTransportAddress* addr1,
IN cmTransportAddress* addr2);
/************************************************************************
*
* Private functions
*
************************************************************************/
/************************************************************************
* rasKillInTx
* purpose: Kill an incoming transaction through the garbage collection
* mechanism.
* input : ras - RAS module to use
* tx - Incoming transaction to kill
* output : none
* return : Non-negative value on success
* Negative value on failure
************************************************************************/
int rasKillInTx(
IN rasModule* ras,
IN rasInTx* tx)
{
/* Lock the transaction itself - we'll delete it before unlocking it... */
if(emaLock((EMAElement)tx))
{
/* We assume that the hash table is already locked from outside */
/* Delete the hash entry - locked from outside */
hashDelete(ras->inHash, tx->hashValue);
/* Delete, Unlock and Release */
emaDelete((EMAElement)tx);
/* Free RPOOL block */
if (tx->encodedMsg != NULL)
rpoolFree(ras->messages, tx->encodedMsg);
emaUnlock((EMAElement)tx);
}
return 0;
}
/************************************************************************
* rasGarbageCollection
* purpose: Clean the incoming transaction list from old transactions that
* are no more relevant to us.
* input : ras - RAS module to use
* output : none
* return : Non-negative value on success
* Negative value on failure
************************************************************************/
int rasGarbageCollection(
IN rasModule* ras)
{
RvInt32 currTime; /* in seconds */
rasInTx* tx;
RvLockGet(&ras->lockGarbage);
/* We go through the list of transactions until we find a transaction whose
stopTime is greater than the current time - this means that this transaction
should not be closed and so are all of the other transactions after it */
currTime = (RvInt32)Rv64Divide(RvTimestampGet(), RV_TIME64_NSECPERSEC);
tx = ras->firstTx;
/* Continue until there are no transactions left - we'll stop in the middle
if we'll have to */
while (tx != NULL)
{
if (tx->stopTime > currTime)
{
/* We shouldn't continue anymore */
break;
}
/* Deallocate this transaction */
ras->firstTx = tx->next;
rasKillInTx(ras, tx);
tx = ras->firstTx;
}
if (ras->firstTx == NULL) ras->lastTx = NULL;
RvLockRelease(&ras->lockGarbage);
return 0;
}
/************************************************************************
* rasNewTx
* purpose: Create a new transaction for an incoming message
* input : ras - RAS module to use
* rootId - Message node for transaction
* output : newRoot - New message node for transaction
* return : Transaction's handle on success
* NULL on failure
************************************************************************/
static rasInTx* rasNewTx(
IN rasModule* ras,
IN int rootId,
OUT int* newRoot)
{
rasInTx* tx = NULL;
int status = 0;
int propId, requestId;
*newRoot = RV_ERROR_UNKNOWN;
/* Make sure we're supporting incoming transactions */
if (ras->inRa == NULL)
return NULL;
/* Create a root and decode this message */
propId = pvtAddRoot(ras->hVal, ras->synProperty, 0, NULL);
requestId = pvtAdd(ras->hVal, propId, __q931(request), 0, NULL, NULL);
if (requestId >= 0)
status = pvtMoveTree(ras->hVal, requestId, rootId);
else
{
pvtDelete(ras->hVal, rootId);
status = requestId;
}
/* New transaction - allocate a place for it */
if (status >= 0)
{
*newRoot = requestId;
tx = (rasInTx *)emaAdd(ras->inRa, NULL);
if (tx == NULL)
{
/* Let's see if we have a closed transaction we can discard of */
if (ras->firstTx != NULL)
{
/* Kill this one and take its place */
RvLockGet(&ras->lockInHash);
RvLockGet(&ras->lockGarbage);
tx = ras->firstTx;
ras->firstTx = tx->next;
if (ras->firstTx == NULL) ras->lastTx = NULL;
rasKillInTx(ras, tx);
RvLockRelease(&ras->lockGarbage);
RvLockRelease(&ras->lockInHash);
/* Try to allocate a space again */
tx = (rasInTx *)emaAdd(ras->inRa, NULL);
}
if (tx == NULL)
status = RV_ERROR_OUTOFRESOURCES;
}
}
if (status < 0)
{
pvtDelete(ras->hVal, propId);
RvLogError(&ras->log,
(&ras->log, "rasNewTx: Not enough memory to allocate a new incoming transaction"));
return NULL;
}
memset(tx, 0, sizeof(rasInTx));
tx->txProperty = propId;
return tx;
}
/************************************************************************
* rasLookupCall
* purpose: Find a call matching the incoming transaction
* input : ras - RAS module to use
* tx - Incoming transaction
* output : hsCall - Call handle for the call
* NULL if message is not related to any call
* callRelated - Indication if this transaction is call related or not
* return : Non-negative value on success (even if call wasn't found)
* Negative value on failure
************************************************************************/
static int rasLookupCall(
IN rasModule* ras,
IN rasInTx* tx,
OUT HCALL* hsCall,
OUT RvBool* callRelated)
{
RVHCATCALL hCatCall;
catStruct key;
*hsCall = NULL;
switch (tx->transactionType)
{
case cmRASGatekeeper:
case cmRASRegistration:
case cmRASUnregistration:
case cmRASUnknown:
case cmRASNonStandard:
case cmRASResourceAvailability:
case cmRASUnsolicitedIRR:
case cmRASLocation:
/* These are never related to calls */
*callRelated = RV_FALSE;
return 0;
case cmRASAdmission:
case cmRASDisengage:
case cmRASBandwidth:
case cmRASInfo:
case cmRASServiceControl:
{
/* Get the keys for CAT */
if (rasCreateCatKey(ras, tx, &key) < 0)
{
*callRelated = RV_FALSE; /* No actual key for CAT was found */
return 0;
}
/* Make sure the transaction is call specific (not IRQ with CRV=0) */
if ((tx->transactionType == cmRASInfo) && (key.rasCRV == 0x8000))
{
*callRelated = RV_FALSE; /* IRQ not on a specific call */
return 0;
}
break;
}
default:
RvLogExcep(&ras->log,
(&ras->log, "rasLookupCall: Bad transaction type %d", tx->transactionType));
return RV_ERROR_UNKNOWN;
}
/* Search for the call */
*callRelated = RV_TRUE;
hCatCall = catFind(ras->hCat, &key);
if (hCatCall != NULL)
{
/* Update the list of keys on ARQs */
if (tx->transactionType == cmRASAdmission)
catUpdate(ras->hCat, hCatCall, &key);
*hsCall = catGetCallHandle(ras->hCat, hCatCall);
/* call was found */
return 0;
}
if (tx->transactionType == cmRASAdmission)
{
/* The New call arrived */
if (ras->evRASNewCall(ras->app, &hCatCall, &key) >= 0)
{
*hsCall = catGetCallHandle(ras->hCat, hCatCall);
return 0;
}
}
RvLogWarning(&ras->log,
(&ras->log, "rasLookupCall: Can't find call for this transaction (%d)", tx->transactionType));
/* Even without a call for this transaction we're going to give it to the user */
return 0;
}
/************************************************************************
* rasSendResponse
* purpose: Sends a response message on an incoming request, whether its
* a confirm or a reject message
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -