⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmcall.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
 * output : none
 * return : none
 ************************************************************************/
void dequeueCallStates(
    IN cmElem*              app,
    IN callElem*            call,
    IN cmCallState_e        state,
    IN cmCallStateMode_e    stateMode)
{
    int nesting;

    call->q_numStates++;
    while ((call->q_numStates > 0) && (call->state != cmCallStateIdle)) /* Idle is the "last stop" */
    {
        /* cmCallStateInit is reserved for the use of the queue as a state that should be
           in the queue, but always not-handled. This way, we can for example use cmEvNewCall()
           as if it is a queued state to make sure all event callbacks are handled after it */
        if (state != cmCallStateInit)
        {
            /* handle the next state - its a real one */
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ENTER)
             static char *stateModes[]=
               {(char*)"",
                (char*)"cmCallStateModeDisconnectedBusy",
                (char*)"cmCallStateModeDisconnectedNormal",
                (char*)"cmCallStateModeDisconnectedReject",
                (char*)"cmCallStateModeDisconnectedUnreachable",
                (char*)"cmCallStateModeDisconnectedUnknown",
                (char*)"cmCallStateModeDisconnectedLocal",
                (char*)"cmCallStateModeConnectedControl",


                (char*)"cmCallStateModeConnectedCallSetup",
                (char*)"cmCallStateModeConnectedCall",
                (char*)"cmCallStateModeConnectedConference",

                (char*)"cmCallStateModeOfferingCreate",
                (char*)"cmCallStateModeOfferingInvite",
                (char*)"cmCallStateModeOfferingJoin",
                (char*)"cmCallStateModeOfferingCapabilityNegotiation",
                (char*)"cmCallStateModeOfferingCallIndependentSupplementaryService",
                (char*)"cmCallStateModeDisconnectedIncompleteAddress"};


            static char *states[]=
               {(char*)"cmCallStateDialtone",
                (char*)"cmCallStateProceeding",
                (char*)"cmCallStateRingBack",
                (char*)"cmCallStateConnected",
                (char*)"cmCallStateDisconnected",
                (char*)"cmCallStateIdle",
                (char*)"cmCallStateOffering",
                (char*)"cmCallStateTransfering",
                (char*)"",(char*)"",
                (char*)"cmCallStateIncompleteAddress",
                (char*)"cmCallStateWaitAddressAck"};

            int use_statemode;

            use_statemode = ((state==cmCallStateDisconnected)||(state==cmCallStateConnected)||(state==cmCallStateOffering));
            cmiCBEnter((HAPP)app,"cmEvCallStateChanged(haCall=0x%p,hsCall=0x%p,state=%s,stateMode=%s)",
                emaGetApplicationHandle((EMAElement)call), call, states[state],
                use_statemode ? stateModes[stateMode+1] : "");
#endif
            nesting=emaPrepareForCallback((EMAElement)call);
            {
                call->state=state;
                call->stateMode=stateMode;

                if (app->cmMyCallEvent.cmEvCallStateChanged)
                    app->cmMyCallEvent.cmEvCallStateChanged((HAPPCALL)emaGetApplicationHandle((EMAElement)call),(HCALL)call,state,stateMode);
                else if (state==cmCallStateIdle)
                {
                    /* If the application has no state-change callback, we should close the call on IDLE state */
                    cmCallClose((HCALL)call);
                }

                /* If callback didn't delete the call and it's a connected one, check
                   if the control has already connected as well */
                if ( (!emaWasDeleted((EMAElement)call)) &&
                     (state == cmCallStateConnected)    &&
                     (stateMode == cmCallStateModeConnectedCallSetup) )
                   notifyControlState((HCALL)call);
            }
#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_LEAVE)
            cmiCBExit((HAPP)app,"cmEvCallStateChanged");
#endif
            emaReturnFromCallback((EMAElement)call,nesting);
        }


        /* reduce state number */
        call->q_numStates--;
        if(call->q_numStates)
        {
            /* get next state from the queue */
            if (call->q_states[call->q_nextState] != RV_H323CALL_STATE_DUMMY)
            {
                state = (cmCallState_e) call->q_states[call->q_nextState];
                stateMode = (cmCallStateMode_e) call->q_stateModes[call->q_nextState];
            }
            else
                state = cmCallStateInit;
            call->q_nextState = (RvUint8) ( (call->q_nextState+1)%RV_H323CALL_STATE_MAX );
        }
    }
}


/************************************************************************
 * notifyState
 * purpose: Notify the application about the state of the call
 * input  : hsCall      - Stack handle for the call
 *          state       - State of call
 *          stateMode   - Mode of the state
 * output : none
 * return : none
 ************************************************************************/
void notifyState(IN HCALL hsCall, IN cmCallState_e state, IN cmCallStateMode_e stateMode)
{
    callElem*call=(callElem*)hsCall;
    cmElem* app=(cmElem*)emaGetInstance((EMAElement)call);

    /* check if a state is already being handled */
    if (call->q_numStates)
    {
        int newState;
        int oldState;
        if (call->q_numStates >= RV_H323CALL_STATE_MAX)
        {
            /* we may be in a state-loop - this shouldn't happen! */
            RvLogError(&app->logERR,
                (&app->logERR, "notifyState: We have a loop for hsCall=0x%p", hsCall));
            return;
        }

        /* place the new state in the state queue */
        newState = (call->q_nextState + call->q_numStates - 1) % RV_H323CALL_STATE_MAX;
        oldState = (newState+RV_H323CALL_STATE_MAX-1)%RV_H323CALL_STATE_MAX;
        if((call->q_states[oldState] != state) || (call->q_stateModes[oldState] != stateMode))
        {
            /* Seems like this state is not the same state as its predecessor - add it in */
            call->q_states[newState] = (RvUint8) state;
            call->q_stateModes[newState] = (RvUint8) stateMode;
            call->q_numStates++;
        }
        return;
    }

    /* No current states - handle it as is */

    /* don't report the same state twice */
    if ( (call->state == state) && (call->stateMode == stateMode) )
        return;

    /* enter state handle */
    dequeueCallStates(app, call, state, stateMode);
}


/************************************************************************
 * notifyControlState
 * purpose: Notify the application about the state of the control
 *          This function checks the control state and uses the call state
 *          notification function.
 * input  : hsCall      - Stack handle for the call
 * output : none
 * return : none
 ************************************************************************/
void notifyControlState(IN HCALL hsCall)
{
    callElem*call=(callElem*)hsCall;
    if (m_callget(call,control))
    {
        switch(controlGetState(cmiGetControl((HCALL)call)))
        {
            case ctrlConnected:
                notifyState((HCALL)call,cmCallStateConnected,cmCallStateModeConnectedCall);
            break;
            case ctrlConference:
                notifyState((HCALL)call,cmCallStateConnected,cmCallStateModeConnectedConference);
            break;
            default:
                /* Do nothing */
            break;
        }
    }
}


/************************************************************************
 * callStartOK
 * purpose: Deal with an outgoing or incoming call in the Q931 side, after
 *          RAS was done (or skiped)
 * input  : call    - Stack handle for the call to dial
 * output : none
 * return : Non-negative value on success
 *          Negative value on failure
 ************************************************************************/
int callStartOK(IN callElem* call)
{
    cmElem* app=(cmElem*)emaGetInstance((EMAElement)call);
    int nodeId;
    cmTransportAddress tpkt;
    cmTransportAddress annexE;
    int ret=0;
    catStruct      callObj;

    /* See what's the direction of the call */
    if (m_callget(call,callInitiator))
    {
        /* Outgoing call - make sure we add it to the CAT */
        if ((ret = callObjectCreate(app, (HCALL)call, Outgoing, &callObj))<0)
            return ret;
        if ((call->hCatCall = catAdd(app->hCat, &callObj, (HCALL)call))==NULL)
            return RV_ERROR_OUTOFRESOURCES;

        {
            cmAnnexEUsageMode annexEBehavior=cmTransNoAnnexE;
            cmCallGetParam((HCALL)call,cmParamAnnexE,0,(int *)&annexEBehavior,NULL);
            cmTransSetSessionParam(call->hsTransSession, cmTransParam_isAnnexESupported,&annexEBehavior);
        }

        /* Findout the address of the call's Q931 destination and try to connect to it */
        nodeId=((call->routeCallSignalAddress>=0))?
                    call->routeCallSignalAddress:
                    call->callSignalAddress;
        cmVtToTA(app->hVal,nodeId, &tpkt);

        if (call->annexECallSignalAddress>=0)
            cmVtToTA(app->hVal,call->annexECallSignalAddress, &annexE);
        else
            annexE=tpkt;

        cmTransSetAddress(call->hsTransSession, NULL, &tpkt, &annexE, NULL, cmTransQ931Conn, RV_FALSE);

        ret = cmTransQ931Connect(call->hsTransSession);
    }
    else
    {
        /* Incoming call */
        RvBool incompleteAddress=0;
        {
            RVHCATCALL     hCatCall;

            /* CAT changes */
            if ((ret=callObjectCreate(app, (HCALL)call, Incoming, &callObj))<0)
                return ret;

            /* See if we've already got this call */
            if ((hCatCall=catFind(app->hCat, &callObj))!=NULL)
            {
                callElem*foundCall = (callElem*)catGetCallHandle(app->hCat, hCatCall);
                if (foundCall && m_callget(foundCall,callWithoutQ931))
                {
                    catUpdate(app->hCat, hCatCall, &callObj);
                    *foundCall=*call;
                    call=foundCall;
                }
            }
            else
            {
                /* No such call - add it to CAT as a new call */
                if ((call->hCatCall = catAdd(app->hCat, &callObj, (HCALL)call))==NULL)
                    return RV_ERROR_OUTOFRESOURCES;
            }

            /* Check if we've got a complete address or not */
            if (m_callget(call,remoteCanOverlapSend) && m_callget(call,enableOverlapSending))
                   incompleteAddress=1;
        }


        if (incompleteAddress)
        {
            /* Notify the application about the incomplete address */
            notifyState((HCALL)call,cmCallStateWaitAddressAck, (cmCallStateMode_e)0);
        }
        else
        {
            /* Continue to handle the incoming setup */
            enterCallSetupState(call);
        }

    }
    return ret;
}


typedef enum
{
    reasonReleaseComplete,
    reasonH245ConnectionClosed,
    reasonApplicationDrop,
    reasonDRQ,
    reasonQ931ConnectionClosed,
    reasonProtocolError
} dropReasonType;

/************************************************************************
 * reportDisconnectedState
 * purpose: Notify the application about a disconnected call
 * input  : call        - Stack handle for the call
 *          dropReason  - Reason the call was disconnected
 * output : none
 * return : none
 ************************************************************************/
void reportDisconnectedState(callElem*call,dropReasonType dropReason)
{
    cmCallState_e state=cmCallStateDisconnected;
    cmCallStateMode_e stateMode=cmCallStateModeDisconnectedNormal;
    RvBool doNotReport=RV_FALSE;

    /* Make sure we notify application about disconnections only if it knowns about this call */
    if (m_callget(call,notified))
    {
        switch(dropReason)
        {
            case reasonReleaseComplete:
            {
                int causeValue;
                cmReasonType reason;
                cmCallGetParam((HCALL)call,cmParamReleaseCompleteCause,0,&causeValue,NULL);
                cmCallGetParam((HCALL)call,cmParamReleaseCompleteReason,0,(int *)&reason,NULL);
                if (causeValue==17 || reason==cmReasonTypeInConf)
                    stateMode=cmCallStateModeDisconnectedBusy;
                if (causeValue==28)
                    stateMode=cmCallStateModeDisconnectedIncompleteAddress;
            }
            break;
            case reasonDRQ:
            break;
            case reasonApplicationDrop:
                stateMode=cmCallStateModeDisconnectedLocal;
            break;
            case reasonQ931ConnectionClosed:
            break;
            case reasonH245ConnectionClosed:
            break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -