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 + -
显示快捷键?