📄 transutil.c
字号:
/***********************************************************************
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.
***********************************************************************/
#include "transport.h"
#include "transportint.h"
#include "transnet.h"
#include "transutil.h"
#include "transStates.h"
#include "q931asn1.h"
#include "h245.h"
#include "msg.h"
#include "cm.h"
#include "emanag.h"
#include "cat.h"
#include "cmutils.h"
#include "prnutils.h"
#include "pvaltreeStackApi.h"
#include "psyntreeStackApi.h"
#include "rvhost.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus*/
#define ADDR_IN_CLASSD(i) (((i) & 0xf0000000ul) == 0xe0000000ul)
static RvBool isMulticastIP(IN RvUint32 ip)
{
ip = RvConvertNetworkToHost32(ip);
return ADDR_IN_CLASSD(ip);
}
/**************************************************************************************
* createMessage
*
* Purpose: creates a skeleton message of the given type and fills in the CRV and callId
* of the given session.
* Input: transGlobals - The global data of the module.
* msgType - which message to create
* CRV - CRV to use.
* callId - call Identifier to use.
*
* Output: node - the created message.
*
* Returned Value: RV_TRUE - success
**************************************************************************************/
RvBool createMessage(cmTransGlobals *transGlobals,
cmCallQ931MsgType msgType,
RvUint16 CRV,
RvUint8 *callId,
int *node)
{
int newMessage, messageNode = -1, res;
/* create a skeleton message */
if (transGlobals->sessionEventHandlers.cmEvTransGetMessageNode)
{
RvLogInfo(&transGlobals->hLog,
(&transGlobals->hLog, "cmEvTransGetMessageNode(hPvt = %x, msgType=%d)",
transGlobals->hPvt, msgType));
transGlobals->sessionEventHandlers.cmEvTransGetMessageNode(
transGlobals->hAppATrans,
msgType,
&messageNode);
}
/* copy the message and add session data to the message */
newMessage = pvtAddRoot(transGlobals->hPvt, NULL, 0, NULL);
if (newMessage >= 0)
{
RvInt32 temp = CRV;
pvtSetTree(transGlobals->hPvt, newMessage, transGlobals->hPvt, messageNode);
__pvtBuildByFieldIds(res, transGlobals->hPvt, newMessage,
{
_q931(callReferenceValue)
_q931(twoBytes)
LAST_TOKEN
},
temp, NULL);
if (res >= 0)
{
__pvtBuildByFieldIds(res, transGlobals->hPvt, newMessage,
{ _q931(message)
_anyField
_q931(userUser)
_q931(h323_UserInformation)
_q931(h323_uu_pdu)
_q931(h323_message_body)
_anyField
_q931(callIdentifier)
_q931(guid)
LAST_TOKEN
},
16, (char *)callId);
}
else
{
pvtDelete(transGlobals->hPvt, newMessage);
return RV_FALSE;
}
}
else
{
pvtDelete(transGlobals->hPvt, newMessage);
return RV_FALSE;
}
cleanMessage(transGlobals->hPvt, newMessage);
if (node)
*node = newMessage;
return RV_TRUE;
}
/**************************************************************************************
* findHostInHash
*
* Purpose: To look for an existing host with the same address as the given one.
* If a suitable host is found, i.e. identical in address and type,
* we check it to be connected (the prefered state). If it's not we look for
* another one which is connected. If none was found we bring a suitable host
* that is not connected. If such a host doesn't exist either, return NULL.
* Input: transGlobals - The global data of the module.
* remoteAddress - The address of the looked for host.
* isMultiplexed - Do we need a host which is multiplexed or not
* isAnnexE - the type of the connection (TPKT or annex E).
*
* Output: None.
*
* Returned Value: A pointer to the found host element or NULL if not found
**************************************************************************************/
cmTransHost *findHostInHash(IN cmTransGlobals *transGlobals,
IN cmTransportAddress *remoteAddress,
IN RvBool isMultiplexed,
IN RvBool isAnnexE)
{
void *loc;
hostKey key;
RvBool found = RV_FALSE;
cmTransHost *host = NULL;
cmTransHost *lastNonActiveHost = NULL;
/* build the key to look by */
key.ip = remoteAddress->ip;
key.port = (RvUint32)remoteAddress->port;
key.type = isAnnexE;
/* lock the hash for the search */
RvLockGet(&transGlobals->lockHash);
/* for non annex E go over all hosts that satisfy the key, i.e. address+type */
if (!isAnnexE)
{
for (loc = hashFind(transGlobals->hHashHosts,(void *)&key);
(loc != NULL) && (!found);
loc = hashFindNext(transGlobals->hHashHosts, (void *)&key, loc))
{
RvLogInfo(&transGlobals->hLog,
(&transGlobals->hLog, "hashFind = %x [hostKey: ip=%x port=%d type=%d]",
loc,key.ip, key.port, key.type));
host = *(cmTransHost **)hashGetElement(transGlobals->hHashHosts, loc);
/* if both host and session are multiplexed, we found our host */
if ( (host->isMultiplexed) && (host->remoteIsMultiplexed) && (isMultiplexed) )
found = RV_TRUE;
else
/* if both host and session are not multiplexed, but the host is available for
the session, i.e. not servicing another session, we found it */
if ( (!host->isMultiplexed) && (!isMultiplexed) && (!host->firstSession) )
found = RV_TRUE;
if (found)
{
/* if the host is not yet connected, try to look for a connected one,
but remember the last non connected one to be used if no connected
one would be found */
if ( (host->state != hostConnected) && (host->state != hostBusy) )
{
found = RV_FALSE;
lastNonActiveHost = host;
}
}
}
}
else
{
/* for annex E hosts there should be just one suitable host element */
loc = hashFind(transGlobals->hHashHosts,(void *)&key);
RvLogInfo(&transGlobals->hLog,
(&transGlobals->hLog, "hashFind = %x [hostKey: ip=%x port=%d type=%d]",
loc,key.ip, key.port, key.type));
if (loc)
{
host = *(cmTransHost **)hashGetElement(transGlobals->hHashHosts, loc);
found = RV_TRUE;
}
}
RvLockRelease(&transGlobals->lockHash);
/* if we found a suitable host, return it, else return a NULL */
if (found)
return host;
else
return lastNonActiveHost;
}
/**************************************************************************************
* transEncodeMessage
*
* Purpose: to get the given message encoded, either by a callback or by the cmEmEncode.
* Input: host - The host on which the message is to be sent
* session - The session on whose behalf the message is to be sent.
* transGlobals - The global data of the transport module.
* pvtNode - the message to be encoded
* buffer - the buffer into which to encode
*
* Output: encMsgSize - The size of the encoded message.
*
* Returned Value: cmTransErr - in case that the encoding failed, cmTransOK - otherwise
**************************************************************************************/
TRANSERR transEncodeMessage(cmTransHost *host,
cmTransSession *session,
cmTransGlobals *transGlobals,
int pvtNode,
RvUint8 *buffer,
int *encMsgSize)
{
HATRANSHOST haTransHost = NULL;
HATRANSSESSION haTransSession;
int encSize;
int encRes = 0;
TRANSERR encTransRes = cmTransOK;
int headersSize = TPKT_HEADER_SIZE + MSG_HEADER_SIZE;
TRANSTYPE type;
/* determine the application handles of the host and session */
haTransSession = (HATRANSSESSION)emaGetApplicationHandle((EMAElement)session);
if (host)
haTransHost = (HATRANSHOST)emaGetApplicationHandle((EMAElement)host);
/* determine the type of message, if there is no host then it's a H.245 tunneled message,
otherwise it's either a H.245 message or a Q.931 according to the host's type */
type = cmTransH245Type;
if (host)
if ( (host->type == cmTransQ931Conn) )
type = cmTransQ931Type;
/* Report and encode the given message */
if (!host)
{
RvPstFieldId fieldId;
int nodeId;
char *ret;
nodeId = pvtChild(transGlobals->hPvt, pvtNode);
nodeId = pvtChild(transGlobals->hPvt, nodeId);
pvtGet(transGlobals->hPvt,
nodeId,
&fieldId,
NULL, NULL, NULL);
ret = pstGetFieldNamePtr(transGlobals->synProtH245, fieldId);
RvLogDebug(&transGlobals->hTPKTCHAN,
(&transGlobals->hTPKTCHAN, "New TUNNELED message (call %d-%x) sent --> %s:",
emaGetIndex((EMAElement)haTransSession), haTransSession, ret));
pvtPrintInternal(transGlobals->hPvt, pvtNode, &transGlobals->hTPKTCHAN, msGetDebugLevel());
}
if ( (transGlobals->hostEventHandlers.cmEvTransSendRawMessage) && (host) )
{
int sessNumOfLocks, hostNumOfLocks;
RvLogInfo(&transGlobals->hLog,
(&transGlobals->hLog,
"cmEvTransSendRawMessage(host=%d(%x), haHost=%x, session=%d, hsSession=%x, pvtNode=%d)",
emaGetIndex((EMAElement)host), host, haTransHost, emaGetIndex((EMAElement)session),
haTransSession, pvtNode));
sessNumOfLocks = emaPrepareForCallback((EMAElement)session);
hostNumOfLocks = emaPrepareForCallback((EMAElement)host);
encTransRes = transGlobals->hostEventHandlers.cmEvTransSendRawMessage(
(HSTRANSHOST)host,
haTransHost,
(HSTRANSSESSION) session,
haTransSession,
pvtNode,
transGlobals->codingBufferSize - headersSize,
&buffer[headersSize],
&encSize);
emaReturnFromCallback((EMAElement)session, sessNumOfLocks);
emaReturnFromCallback((EMAElement)host, hostNumOfLocks);
}
else
encRes = cmEmEncode(transGlobals->hPvt,
pvtNode,
&buffer[headersSize],
transGlobals->codingBufferSize - headersSize,
&encSize);
if (encMsgSize)
*encMsgSize = encSize;
if ( (encRes < 0) || ( (encTransRes != cmTransOK) && (encTransRes != cmTransIgnoreMessage) ) )
{
if (transGlobals->sessionEventHandlers.cmEvTransBadMessage)
{
int numOfLocks;
RvLogInfo(&transGlobals->hLog,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -