cmpreservation.c
来自「基于h323协议的软phone」· C语言 代码 · 共 1,152 行 · 第 1/3 页
C
1,152 行
/***********************************************************************
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 "cm.h"
#include "cmintr.h"
#include "cmCall.h"
#include "cmControl.h"
#include "transportint.h"
#include "transutil.h"
#include "transnet.h"
#include "q931asn1.h"
#include "cmQ931.h"
#include "h245.h"
#include "cmcallobj.h"
#include "cmpreservation.h"
#ifdef __cplusplus
extern "C" {
#endif
RvBool q931T301Timeout(void* context);
RvBool channelTimeoutEventsHandler(void*hsChan);
/************************************************************************
* encodeIntoBuffer
* purpose: encode a nodeID into the buffer, adding to it's length.
* input : hVal - pvt thingie
* nodeId - nodeId to encode
* bufferLen - Size of the buffer
* length - pointer to the legth done so far
* ret - current status
* output : buffer - The buffer with the encoded nodeId
* length - updated length done
* ret - updated return value
* return : none
************************************************************************/
static void encodeIntoBuffer(
IN HPVT hVal,
IN int nodeId,
OUT RvUint8 * buffer,
IN RvSize_t bufferLen,
INOUT RvSize_t * length,
INOUT RvH323HaResult * ret
)
{
int encLen = 0;
int len = bufferLen - *length - sizeof(int);
if( (nodeId < 0) || (*ret < 0) )
return;
if( (len > 0) &&
(cmEmEncode(hVal, nodeId, buffer+*length+sizeof(int), len, &encLen) >= 0) )
{
/* copy the length before the encoded buffer */
memcpy((void*)(buffer+*length), (void*)&encLen, sizeof(int));
*length += encLen+sizeof(int);
}
else
{
*length = bufferLen;
*ret = RvH323HaNotEnoughBuffer;
}
}
/************************************************************************
* decodeFromBuffer
* purpose: decode the buffer into a node Id.
* input : hVal - pvt thingie
* nodeId - pointer to nodeId to decode to
* length - Size of the buffer
* lenDone - pointer to the legth done so far
* buffer - The buffer with the encoded nodeId
* output : lenDone - updated length done
* return : negative on error
************************************************************************/
static RvStatus decodeFromBuffer(
IN HPVT hVal,
IN HPST hSyn,
IN int * nodeId,
IN RvUint8 * buffer,
IN RvSize_t length,
INOUT RvSize_t * lenDone
)
{
int decLen = 0;
int decoded = 0;
if((length-*lenDone) >= sizeof(int))
memcpy((void*)&decLen, (void*)(buffer+*lenDone), sizeof(int));
else
{
*nodeId = -1;
return RV_ERROR_UNKNOWN;
}
*lenDone += sizeof(int);
*nodeId = pvtAddRoot(hVal,hSyn,0,NULL);
if((cmEmDecode(hVal, *nodeId, buffer+*lenDone, decLen, &decoded) < 0) ||
(decLen != decoded))
{
pvtDelete(hVal, *nodeId);
*nodeId = -1;
return RV_ERROR_UNKNOWN;
}
*lenDone += decLen;
return RV_OK;
}
/************************************************************************
* callToBuffer
* purpose: Create a buffer of the call, the session, its property, and
* its channels.
* input : call - Call element to buffer
* bufferLen - Size of the buffer
* output : buffer - The buffer to which the call will be added
* bufferLen - Size used or size needed if not enough allocated
* return : negative on error
************************************************************************/
static RvH323HaResult callToBuffer(
IN callElem * call,
OUT RvUint8 * buffer,
INOUT RvSize_t * bufferLen
)
{
RvSize_t length = 0;
RvH323HaResult ret = RvH323HaOK;
H245Channel * chanList, * curChan, * chanArray[20];
H245Control * ctrl;
HPVT hVal= ((cmElem *)emaGetInstance((EMAElement)call))->hVal;
int i = 0;
/* copy the call to the buffer */
if((length+sizeof(callElem)) <= *bufferLen)
{
memcpy((void*)(buffer+length), (void*)call, sizeof(callElem));
if(call->timer)
ret = RvH323HaTimerWarning;
}
else
ret = RvH323HaNotEnoughBuffer;
length += sizeof(callElem);
/* copy the control element to the buffer */
ctrl = (H245Control *)cmiGetControl((HCALL)call);
if((ret >=0) && ((length+sizeof(H245Control)) <= *bufferLen))
{
memcpy((void*)(buffer+length), (void*)ctrl, sizeof(H245Control));
if( (ctrl->outCap.timer != NULL) ||
(ctrl->msd.timer != NULL) ||
(ctrl->roundTrip.timer != NULL) ||
(ctrl->outRequestMode.timer != NULL) )
{
ret = RvH323HaTimerWarning;
}
}
else
ret = RvH323HaNotEnoughBuffer;
length += sizeof(H245Control);
/* encode the capabilities into the buffer, if they exists */
encodeIntoBuffer(hVal, ctrl->outCap.termNodeId, buffer, *bufferLen, &length, &ret);
encodeIntoBuffer(hVal, ctrl->inCap.termNodeId, buffer, *bufferLen, &length, &ret);
/* copy the session to the buffer, if one exists */
if(call->hsTransSession)
{
cmTransSession * session = (cmTransSession *) call->hsTransSession;
if((ret >= 0) && (length+sizeof(cmTransSession)) <= *bufferLen)
{
memcpy((void*)(buffer+length), (void*)session, sizeof(cmTransSession));
}
else
ret = RvH323HaNotEnoughBuffer;
length += sizeof(cmTransSession);
}
/* encode the property into the buffer, if it exists */
if( call->property >= 0)
{
encodeIntoBuffer(hVal, call->property, buffer, *bufferLen, &length, &ret);
}
else
{
for(i=cmEnumSetupSendingComplete; (i<cmEnumLast) && (ret >= 0); i++)
encodeIntoBuffer(hVal, call->paramNodeId[i], buffer, *bufferLen, &length, &ret);
}
i=0;
/* copy channels to buffer, but also an array of the channel pointer by the order they are linked */
curChan = chanList = (H245Channel *) cmiGetChannelListForCtrl(cmiGetControl((HCALL)call));
while(curChan)
{
chanArray[i] = curChan;
curChan = curChan->pNext;
i++;
}
if( (ret >= 0) && (length+i*sizeof(H245Channel *)+sizeof(int) <= *bufferLen) )
{
/* copy the channel array first, it will help us later when we need to decipher which channel
is which's partner */
memcpy((void*)(buffer+length), (void*)&i, sizeof(int));
memcpy((void*)(buffer+length+sizeof(int)), (void*)chanArray, (RvSize_t)(i*sizeof(H245Channel *)));
}
else
ret = RvH323HaNotEnoughBuffer;
length += i*sizeof(H245Channel *)+sizeof(int);
curChan = chanList;
while(curChan)
{
if( (ret >= 0) && (length+sizeof(H245Channel) <= *bufferLen) )
{
/* copy the channel */
memcpy((void*)(buffer+length), (void*)curChan, sizeof(H245Channel));
if(curChan->pTimer || curChan->pRequestCloseTimer || curChan->pMediaLoopTimer)
ret = RvH323HaTimerWarning;
encodeIntoBuffer(hVal, curChan->pChannelParams.data.h225Params.redEncID, buffer, *bufferLen, &length, &ret);
encodeIntoBuffer(hVal, curChan->pChannelParams.data.h225Params.transCapID, buffer, *bufferLen, &length, &ret);
encodeIntoBuffer(hVal, curChan->requestCloseParamID, buffer, *bufferLen, &length, &ret);
encodeIntoBuffer(hVal, curChan->dataTypeID, buffer, *bufferLen, &length, &ret);
encodeIntoBuffer(hVal, curChan->pChannelParams.data.h225Params.separateStackID, buffer, *bufferLen, &length, &ret);
}
else
ret = RvH323HaNotEnoughBuffer;
length += sizeof(H245Channel);
curChan = curChan->pNext;
}
*bufferLen = length;
return ret;
}
RVAPI RvH323HaResult RVCALLCONV RvH323HaGetCallBuffer(
IN HCALL hsCall,
OUT RvUint8 * buffer,
INOUT RvSize_t * length
)
{
callElem * call = (callElem *) hsCall;
cmTransSession * session;
cmTransHost * Q931Connection;
cmTransHost * annexEConnection;
cmTransHost * H245Connection;
int ret = RvH323HaOK;
/* Lock EVERYTHING */
if((call == NULL) || !emaLock((EMAElement)call))
{
*length = 0;
return RvH323HaError;
}
session = (cmTransSession *)call->hsTransSession;
if(session && !emaLock((EMAElement)session))
{
*length = 0;
emaUnlock((EMAElement)call);
return RvH323HaError;
}
Q931Connection = session->Q931Connection;
annexEConnection = session->annexEConnection;
H245Connection = session->H245Connection;
if(Q931Connection && !emaLock((EMAElement)Q931Connection))
{
*length = 0;
if(session) emaUnlock((EMAElement)session);
emaUnlock((EMAElement)call);
return RvH323HaError;
}
if(annexEConnection && !emaLock((EMAElement)annexEConnection))
{
*length = 0;
if(Q931Connection) emaUnlock((EMAElement)Q931Connection);
if(session) emaUnlock((EMAElement)session);
emaUnlock((EMAElement)call);
return RvH323HaError;
}
if(H245Connection && !emaLock((EMAElement)H245Connection))
{
*length = 0;
if(annexEConnection) emaUnlock((EMAElement)annexEConnection);
if(Q931Connection) emaUnlock((EMAElement)Q931Connection);
if(session) emaUnlock((EMAElement)session);
emaUnlock((EMAElement)call);
return RvH323HaError;
}
/* ok, all is locked */
/* now, check if we are in a stable enough state to encode the call */
/* if we are in the middle of a Fast Start prcedure, no go. */
if((call->fastStartIndexes[0] != (RvUint8)-1) || (call->fastStartNodes[0] != -1) || (call->fastStartNodesAck[0] != -1))
{
ret = RvH323HaImpossible;
}
/* if there are both H245 listening socket and connecting socket, no way. */
else if(H245Connection && H245Connection->h245Listen && H245Connection->hTpkt)
{
ret = RvH323HaImpossible;
}
/* if there are messages waiting on the hosts or sessions, close, but no cigar */
else if( (session && session->firstMessage) )
{
ret = RvH323HaImpossible;
}
/* if we have a stable enough state, go on to create the buffer */
if(ret >= 0)
{
ret = callToBuffer(call, buffer, length);
}
/* now, unlock all */
if(H245Connection) emaUnlock((EMAElement)H245Connection);
if(annexEConnection) emaUnlock((EMAElement)annexEConnection);
if(Q931Connection) emaUnlock((EMAElement)Q931Connection);
if(session) emaUnlock((EMAElement)session);
emaUnlock((EMAElement)call);
return ret;
}
RVAPI RvStatus RVCALLCONV RvH323HaAddCall(
IN HAPP hApp,
IN HAPPCALL haCall,
IN RvUint8 * buffer,
IN RvSize_t length
)
{
cmElem * app = (cmElem *) hApp;
cmTransGlobals * transGlobals = (cmTransGlobals *)app->hTransport;
callElem call;
callElem * newCall = NULL;
H245Control control;
H245Control * newControl;
cmTransSession session;
cmTransSession * newSession = NULL;
int property = -1;
H245Channel chanArray[20], * chanPtrArray[20];
H245Channel * newChannelArray[20];
RvSize_t chanArraySize = 0;
int i, j;
RvSize_t lenDone = 0;
RvBool isNewCall = RV_TRUE;
EMAElement * emaElem = NULL;
if(buffer == NULL)
return RV_ERROR_UNKNOWN;
memset(&session, 0, sizeof(session)); /* Here to remove warning in release mode compilation */
/* Get the call from the buffer */
if((length-lenDone) >= sizeof(callElem))
memcpy((void*)&call, (void*)(buffer+lenDone), sizeof(callElem));
else
return RV_ERROR_UNKNOWN;
lenDone += sizeof(callElem);
/* search for the same call in the hash */
while((emaElem = emaGetNext(app->hCalls, emaElem)) != NULL)
{
if( (((callElem*)emaElem)->crv == call.crv) &&
(!strncmp((char*)((callElem*)emaElem)->callId, (char*)call.callId, 16)) )
{
/* found call, this is an update */
H245Channel * curChan, * nextChan;
H245Control * ctrl;
newCall = (callElem*)emaElem;
if(!(m_callget(newCall, preservedCall)))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?