📄 rasin.c
字号:
* 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 + -