• CTBCAFBridge hpp 和 cpp 文件分析


    hpp 文件

    typedef class CTBCAFBridge *PCTBCAFBridge;
    class TBCAF_API CTBCAFBridge : public CTBCAFCallFlow
    {
    public:
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Constructor/Destructor
     *------------------------------------------------------------------------------------------------------------------------------*/
        /*!
         * rief   This constructor is used to create a call between two legs.
         *
         * param    in_pFreeListener    Free call listener that the leg will use when it is ready to be freed.
         *
         */
        CTBCAFBridge
        (
            IN    ITBCMCFreeListener<ITBCAFCallFlow> *    in_pFreeListener
        );
    
        /*!
         * rief   This constructor is used to sync a call between two legs.
         *
         * param    in_pFreeListener        Free call listener that the leg will use when it is ready to be freed.
         * param    in_LinkId                Synced link identifier.
         * param   in_JoinAttribute        Synced bridge information.
         * param    in_ptrSourceLeg            Source leg.
         * param    in_ptrDestinationLeg    Destination leg.
         *
         */
        CTBCAFBridge
        ( 
            IN        ITBCMCFreeListener<ITBCAFCallFlow> *    in_pFreeListener,
            IN        TBCMC_LINK_ID                            in_LinkId,
            IN        CTBCMC_JOIN_ATTRIBUTE &                    in_JoinAttribute,
            IN        PTRCTBCAFCallLeg                        in_ptrSourceLeg,
            IN        PTRCTBCAFCallLeg                        in_ptrDestinationLeg
        );
    
        /*!
         * rief   Clear all local resources.
         *
         */
        virtual ~CTBCAFBridge();
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Public API Definition
     *------------------------------------------------------------------------------------------------------------------------------*/
    
        /*! 
    ef ITBCAFCallFlow::GetAccountId */
        virtual TBX_UINT32 GetAccountId();
    
        /*!
         * rief   Set the options used when calls are joined.
         *
         * 
    emarks    This function must be called before OnCallLegAnswered is called
         *            (generally done immediately after constructing the object),
         *            as the "join" between the two legs is done at that moment, and
         *            options set later will be ignored.
         *
         */
        virtual TBX_RESULT SetOptions( const CTBCAFBridgeOptions& in_Options );
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Events Definition
     *------------------------------------------------------------------------------------------------------------------------------*/
        /*******************************************************************************************************************
         * Call Leg Interface
         ******************************************************************************************************************/
    
        /*! 
    ef ITBCAFCallFlow::OnCallLegAlerting */
        virtual TBX_RESULT OnCallLegAlerting( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef ITBCAFCallFlow::OnCallLegAnswered */
        virtual TBX_RESULT OnCallLegAnswered( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef ITBCAFCallFlow::OnCallLegTerminatingIndication */
        virtual TBX_RESULT OnCallLegTerminatingIndication( PCTBCAFCallLeg in_pCallLeg, TBCMC_CALL_REASON & in_Reason, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef ITBCAFCallFlow::OnCallLegTerminated */
        virtual TBX_RESULT OnCallLegTerminated( PCTBCAFCallLeg in_pCallLeg, TBCMC_CALL_REASON & in_Reason, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
        
        /*******************************************************************************************************************
         * Leg Interface
         ******************************************************************************************************************/
    
        /*! 
    ef ITBCAFCallFlow::OnLegEvent */
        virtual TBX_RESULT OnLegEvent( PCTBCAFCallLeg in_pCallLeg, PITBCMCEvent in_pEvent );
    
        /*! 
    ef ITBCAFCallFlow::OnLegError */
        virtual TBX_RESULT OnLegError( PCTBCAFCallLeg in_pCallLeg, CTBCMCLegError & in_Error );
    
        /*! 
    ef ITBCAFCallFlow::OnSyncDone */
        virtual TBX_RESULT OnSyncDone( PCTBCAFCallLeg in_pCallLeg );
    
        /*! 
    ef ITBCAFCallFlow::OnLegProfileChanged */
        virtual TBX_RESULT OnLegProfileChanged( PCTBCAFCallLeg in_pCallLeg, CTBCMC_MEDIA_PROFILE & in_MediaProfile, TBCMC_MEDIA_REASON_CODE in_Reason, TBCMC_CALL_REASON_CODE in_RefusedReason );
    
        /*******************************************************************************************************************
         * Tone Interface
         ******************************************************************************************************************/
    
        /*! 
    ef ITBCAFCallFlow::OnEventCollected */
        virtual TBX_RESULT OnEventCollected
        (
            PCTBCAFCallLeg                                in_pCallLeg,
            const CTBCAFString&                            in_strEvent,
            const CTBCMC_EVENT_COLLECTED_ATTRIBUTE&        in_EventAttr
        );
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Protected API Definition
     *------------------------------------------------------------------------------------------------------------------------------*/
    protected:
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoApplicationTransport */
        virtual TBX_RESULT OnSuppInfoApplicationTransport( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoCallProgress */
        virtual TBX_RESULT OnSuppInfoCallProgress( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoSuspend */
        virtual TBX_RESULT OnSuppInfoSuspend
        (
          IN    PCTBCAFCallLeg                    in_pCallLeg,
          IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
          IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
        );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoResume */
        virtual TBX_RESULT OnSuppInfoResume
        (
          IN    PCTBCAFCallLeg                    in_pCallLeg,
          IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
          IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
        );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoChargeUnit */
        virtual TBX_RESULT OnSuppInfoChargeUnit
        (
          IN    PCTBCAFCallLeg                    in_pCallLeg,
          IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
          IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
        );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoSS7Charge */
        virtual TBX_RESULT OnSuppInfoSS7Charge
        (
          IN    PCTBCAFCallLeg                    in_pCallLeg,
          IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
        );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoUnrecognizedMSU */
        virtual TBX_RESULT OnSuppInfoUnrecognizedMSU( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoConfusion */
        virtual TBX_RESULT OnSuppInfoConfusion
        ( 
          IN        PCTBCAFCallLeg                 in_pCallLeg, 
          IN        CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute 
        );
    
        /*! 
    ef CTBCAFCallFlow::OnSuppInfoDefault */
        virtual TBX_RESULT OnSuppInfoDefault
        ( 
          IN        PCTBCAFCallLeg                 in_pCallLeg, 
          IN        TBCMC_SUPP_INFO_MSG_TYPE     in_SuppInfoType, 
          IN        CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute 
        );
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Private API Definition
     *------------------------------------------------------------------------------------------------------------------------------*/
    private:
        /*!
         * rief   Check if both active legs (incoming and outgoing) are terminating/terminated, in which case
         *            this function also terminates all other legs and mixers.
         *
         * param    Reason to use to terminate other legs
         */
        TBX_VOID CheckTerminateRemainingLegsAndMixers
        (
          IN    TBCMC_CALL_REASON &                 in_Reason
        );
    
        /*!
         * rief   Get the appropriate reason code to use on a bridged leg according to the termination reason of the other leg.
         *
         * param    in_Reason                Reason used to terminate the first leg
         * param    out_ReasonForBridgedLeg    On output, will contain the reason to use when terminating the bridged leg.
         */
        TBX_VOID GetBridgedLegTermReason
        (
          IN    TBCMC_CALL_REASON &                 in_Reason,
          OUT    TBCMC_CALL_REASON &                 out_ReasonForBridgedLeg
        );
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Disable copy constructor and assignment operator
     *------------------------------------------------------------------------------------------------------------------------------*/
        TBCAF_DISABLE_DEFAULT_COPY_CONSTRUCTOR( CTBCAFBridge  );
        TBCAF_DISABLE_DEFAULT_ASSIGNEMENT_OPERATOR( CTBCAFBridge  );
    
    /*--------------------------------------------------------------------------------------------------------------------------------
    |  Protected Definition
    *------------------------------------------------------------------------------------------------------------------------------*/
    protected:
        CTBCAFBridgeOptions                        mOptions;
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Private Definition
     *------------------------------------------------------------------------------------------------------------------------------*/
    private:
        PITBCAFGwParamsDao                        mpGwParamsDao;
        TBX_UINT32                                mun32TerminatingLegId;
        TBX_BOOLEAN                                mfSuspended;
    };

    cpp 文件

    /*--------------------------------------------------------------------------------------------------------------------------------
     |
     |    Project:        CAF Gateway
     |
     |    Filename:       CTBCAFBridge.cpp
     |
     |    Copyright:      TelcoBridges 2002-2012, All Rights Reserved
     |
     |    Description:    This file contains the Gateway module.
     |
     |    Notes:          Tabs = 4
     |
     *-------------------------------------------------------------------------------------------------------------------------------
     |
     |    Revision:       $Revision: 157514 $
     |
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Includes
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    /* System includes */
    #include <tbcaf_includes.hh>
    #include <CTBCAFString.hpp>
    #include <CTBCAFBridge.hpp>
    #include <CTBCAFCallUtil.hpp>
    #include <CTBCMCLegError.hpp>
    #include <ITBCMCEvent.hpp>
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Namespace declaration
     *------------------------------------------------------------------------------------------------------------------------------*/
    namespace TBCAF
    {
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Defines
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Types
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Global variables
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Macros
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Function Prototypes
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Implementation
     *------------------------------------------------------------------------------------------------------------------------------*/
    
    
    CTBCAFBridge::CTBCAFBridge
    (
      IN    ITBCMCFreeListener<ITBCAFCallFlow> *    in_pFreeListener
    ) : CTBCAFCallFlow( in_pFreeListener )
    {
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::CTBCAFBridge )
        {
            mun32TerminatingLegId            = 0;
            mfSuspended                        = TBX_FALSE;
    
            LogTrace( TBCAF_TRACE_LEVEL_0, "CTBCAFBridge::CTBCAFBridge
    " );
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN_VOID;
    }
    
    
    CTBCAFBridge::CTBCAFBridge
    (
      IN    ITBCMCFreeListener<ITBCAFCallFlow> *    in_pFreeListener,
      IN    TBCMC_LINK_ID                            in_LinkId,
      IN    CTBCMC_JOIN_ATTRIBUTE &                 in_JoinAttribute,
      IN    PTRCTBCAFCallLeg                        in_ptrSourceLeg,
      IN    PTRCTBCAFCallLeg                        in_ptrDestinationLeg
    ) : CTBCAFCallFlow( in_pFreeListener, in_LinkId, in_JoinAttribute, in_ptrSourceLeg, in_ptrDestinationLeg )
    {
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::CTBCAFBridge )
        {
            mun32TerminatingLegId            = 0;
            mfSuspended                        = TBX_FALSE;
    
            LogTrace( TBCAF_TRACE_LEVEL_0, "CTBCAFBridge::CTBCAFBridge" );
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN_VOID;
    }
    
    
    CTBCAFBridge::~CTBCAFBridge()
    {
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::~CTBCAFBridge )
        {
            LogTrace( TBCAF_TRACE_LEVEL_0,    "CTBCAFBridge::~CTBCAFBridge
    " );
    
            /* Clear remaining legs and mixers */
            Clear();
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN_VOID;
    }
    
    
    
    
    TBX_UINT32 CTBCAFBridge::GetAccountId()
    {
        return 0;
    }
    
    
    
    TBX_UINT32 CTBCAFBridge::SetOptions( const CTBCAFBridgeOptions& in_Options )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::SetOptions )
        {
            mOptions = in_Options;
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    /*******************************************************************************************************************
     * Call Leg Interface
     ******************************************************************************************************************/
    
    
    
    TBX_RESULT CTBCAFBridge::OnCallLegAlerting
    (
      IN    PCTBCAFCallLeg                        in_pCallLeg,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &         in_ProtocolAttribute
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        PTRCTBCAFCallLeg    ptrCallLeg;
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnCallLegAlerting )
        {
            LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnCallLegAlerting for Leg 0x%08X
    ", in_pCallLeg->GetLegId() );
    
            ptrCallLeg = GetIncomingActiveLeg();
            if( ptrCallLeg != NULL)
            {
                /* Copy Charge information into incoming leg */
                ptrCallLeg->GetAttributes().GetChargeIndicator() = in_pCallLeg->GetAttributes().GetChargeIndicator();
    
                /* Copy echo canceler flag into incoming leg */
                ptrCallLeg->GetAttributes().GetEchoCanceller() = in_pCallLeg->GetAttributes().GetEchoCanceller();
    
                if( !ptrCallLeg->IsAlerted() )
                    ptrCallLeg->AlertCall();
    #if 0
                /* Try sending CPG with event alerting */
                {
                    CTBCMC_PROTOCOL_ATTRIBUTE    ExtraProtInfo;
                    TBCMC_CALL_PROTOCOL_TYPE     ProtocolType = ptrCallLeg->GetAttributes().GetProtocolType();
    
                    if (ProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SS7)
                    {
                        TBX_UINT16        un16BufferSize = 0;
                        TBX_UINT8        aun8Buffer [250];
    
                        TB640_SS7_ISUP_WRITE_EVENT_INFORMATION (
                            aun8Buffer,
                            &un16BufferSize,
                            0,
                            1, /*  (Event Indicator) -> 1 = Alerting (refer to Q.763) */
                            0); /* (Event Presentation Restriction Indicator) -> 0 = No indication (refer to Q.763) */
    
                        ExtraProtInfo.SetSS7Ie(un16BufferSize, aun8Buffer );
                        ptrCallLeg->SendCallSuppInfo( TBCMC_SUPP_INFO_MSG_TYPE_CALL_PROGRESS, &ExtraProtInfo);
                    }
                }
    #endif
            }
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    TBX_RESULT CTBCAFBridge::OnCallLegAnswered
    (
      IN    PCTBCAFCallLeg                        in_pCallLeg,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &         in_ProtocolAttribute
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        PTRCTBCAFCallLeg    ptrIncomingCallLeg;
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnCallLegAnswered )
        {
            LogTrace( TBCAF_TRACE_LEVEL_2, "Bridge::Answered for Leg 0x%08X
    ", in_pCallLeg->GetLegId() );
    
            ptrIncomingCallLeg = GetIncomingActiveLeg();
            if( ptrIncomingCallLeg != NULL )
            {
                TBX_BOOL    fNeedToJoin = TBX_TRUE;
    
                /* Copy echo canceler flag into incoming leg */
                ptrIncomingCallLeg->GetAttributes().GetEchoCanceller() = in_pCallLeg->GetAttributes().GetEchoCanceller();
    
                /* Check if already full-duplex joined with incoming call leg */
                CTBCMC_JOIN_ATTRIBUTE    JoinAttributes;
                if( in_pCallLeg->GetJoinedLegAttributes( ptrIncomingCallLeg->GetLegId(), &JoinAttributes ) )
                {
                    if( JoinAttributes.IsFullDuplex() )
                    {
                        /* Already full-duplex joined. No need to re-join */
                        fNeedToJoin = TBX_FALSE;
                    }
                }
    
                if( fNeedToJoin )
                {
                    in_pCallLeg->Join( ptrIncomingCallLeg.Get(), NULL, mOptions.mfWarnIfToneDetectionEnabled );
                }
                if (ptrIncomingCallLeg->IsAnswered() == TBX_FALSE)
                {
                    LogTrace( TBCAF_TRACE_LEVEL_1, "Bridge::AnswerCall, Answering bridged Leg 0x%08X",
                        ptrIncomingCallLeg->GetLegId());
    
                    ptrIncomingCallLeg->AnswerCall();
                }
            }
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    TBX_RESULT CTBCAFBridge::OnCallLegTerminatingIndication
    (
      IN    PCTBCAFCallLeg                    in_pCallLeg,
      IN    TBCMC_CALL_REASON &                 in_Reason,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        TBCMC_CALL_REASON                    Reason;
        PTRCTBCAFCallLeg                    ptrOtherCallLeg;
        TBCAF_TRACE_LEVEL                    TraceLevel = TBCAF_TRACE_LEVEL_3;
        PTBX_CHAR                            pszColor = "";
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnCallLegTerminatingIndication )
        {
            ptrOtherCallLeg = NULL;
    
    
            if
            (
                in_Reason.Reason == TBCMC_CALL_REASON_CODE_TOOLPACK_SYNC_DROP ||
                in_Reason.Reason == TBCMC_CALL_REASON_CODE_TOOLPACK_RESOURCE_NO_MORE_AVAILABLE
            )
            {
                TraceLevel = TBCAF_TRACE_LEVEL_3;
                pszColor = FYELLOW;
            }
            else if (in_Reason.Reason > TBCMC_CALL_REASON_CODE_TOOLPACK_NORMAL &&
                in_Reason.Reason <= TBCMC_CALL_REASON_CODE_TOOLPACK_LAST)
            {
                TraceLevel = TBCAF_TRACE_LEVEL_3;
                pszColor = FRED;
            }
    
            mun32TerminatingLegId = in_pCallLeg->GetLegId();
    
            LogTrace( TraceLevel, "EndCall: Leg=0x%08X (%s) %sReason=%u (%s)",
                in_pCallLeg->GetLegId(),
                in_pCallLeg->GetAttributes().GetNetworkAccessPoint().c_str(),
                pszColor,
                (unsigned int)in_Reason.Reason,
                TBCMC_CALL_REASON_CODE_TO_STRING( in_Reason.Reason ));
    
            memcpy (&Reason, &in_Reason, sizeof (Reason));
    
    #if 0    /* Bug #10617: No more required to unjoin, TerminateCall() will implicitly do that. */
            // Unjoin legs
            if( in_pCallLeg->IsJoined() )
            {
                in_pCallLeg->Unjoin();
            }
    #endif
    
            // Terminate other leg
            ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
            if( ptrOtherCallLeg != NULL )
            {
                TBCMC_CALL_REASON        ReasonForBridgedLeg;
                GetBridgedLegTermReason( Reason, ReasonForBridgedLeg );
    
                LogTrace( TBCAF_TRACE_LEVEL_1, "Bridge::OnCallLegTerminatingIndication, Terminating bridged Leg: 0x%08X",
                    ptrOtherCallLeg->GetLegId());
                ptrOtherCallLeg->TerminateCall( ReasonForBridgedLeg );
            }
    
            // Terminate leg
            in_pCallLeg->TerminateCall( Reason );
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    
    TBX_RESULT CTBCAFBridge::OnCallLegTerminated
    (
      IN    PCTBCAFCallLeg                    in_pCallLeg,
      IN    TBCMC_CALL_REASON &                 in_Reason,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        TBCMC_CALL_REASON                    Reason;
        PTRCTBCAFCallLeg                    ptrOtherCallLeg;
        TBCAF_TRACE_LEVEL                    TraceLevel = TBCAF_TRACE_LEVEL_3;
        PTBX_CHAR                            pszColor = "";
        
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnCallLegTerminated )
        {
            ptrOtherCallLeg = NULL;
    
            if
            (
                in_Reason.Reason == TBCMC_CALL_REASON_CODE_TOOLPACK_SYNC_DROP ||
                in_Reason.Reason == TBCMC_CALL_REASON_CODE_TOOLPACK_RESOURCE_NO_MORE_AVAILABLE
            )
            {
                TraceLevel = TBCAF_TRACE_LEVEL_3;
                pszColor = FYELLOW;
            }
            else if (in_Reason.Reason > TBCMC_CALL_REASON_CODE_TOOLPACK_NORMAL &&
                in_Reason.Reason <= TBCMC_CALL_REASON_CODE_TOOLPACK_LAST)
            {
                TraceLevel = TBCAF_TRACE_LEVEL_3;
                pszColor = FRED;
            }
            if (mun32TerminatingLegId == in_pCallLeg->GetLegId())
            {
                TraceLevel = TBCAF_TRACE_LEVEL_2;
            }
    
            LogTrace( TraceLevel, "LegTerminated: Leg=0x%08X %sReason=%u (%s)",
                in_pCallLeg->GetLegId(),
                pszColor,
                (unsigned int)in_Reason.Reason,
                TBCMC_CALL_REASON_CODE_TO_STRING( in_Reason.Reason ));
    
            memcpy (&Reason, &in_Reason, sizeof (Reason));
    
            // Terminate other leg
            ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
            if( ptrOtherCallLeg != NULL )
            {
                TBCMC_CALL_REASON        ReasonForBridgedLeg;
                GetBridgedLegTermReason( Reason, ReasonForBridgedLeg );
    
                ptrOtherCallLeg->TerminateCall( ReasonForBridgedLeg );
            }
    
            /* Check if other legs/mixers also need to be terminated */
            CheckTerminateRemainingLegsAndMixers( in_Reason );
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
            /* Call base class' handler */
            CTBCAFCallFlow::OnCallLegTerminated (in_pCallLeg, in_Reason, in_ProtocolAttribute);
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    TBX_VOID CTBCAFBridge::CheckTerminateRemainingLegsAndMixers
    (
      IN    TBCMC_CALL_REASON &                 in_Reason
    )
    {
        TBX_BOOL    fActiveInTerminating    = TBX_FALSE;
        TBX_BOOL    fActiveOutTerminating    = TBX_FALSE;
    
        /* As soon as one of the last active leg is terminating, drop all other legs */
        if( mptrActiveCallLegIn == NULL || mptrActiveCallLegIn->IsTerminating() )
        {
            fActiveInTerminating = TBX_TRUE;
        }
        if( mptrActiveCallLegOut == NULL || mptrActiveCallLegOut->IsTerminating() )
        {
            fActiveOutTerminating = TBX_TRUE;
        }
    
        if( fActiveInTerminating && fActiveOutTerminating )
        {
            LogTrace( TBCAF_TRACE_LEVEL_3, "CheckTerminateRemainingLegsAndMixers: All active legs terminating
    " );
    
            std::vector< PTRCTBCAFCallLeg >                aLegs;
            std::vector< PTRCTBCAFCallLeg >::iterator    itLeg;
            GetLegs( &aLegs );
            for( itLeg = aLegs.begin(); itLeg != aLegs.end(); ++itLeg )
            {
                if( !(*itLeg)->IsTerminating() )
                {
                    LogTrace( TBCAF_TRACE_LEVEL_3, "CheckTerminateRemainingLegsAndMixers:: Also terminating non-active leg Leg 0x%08X", (*itLeg)->GetLegId() );
                    (*itLeg)->TerminateCall( in_Reason );
                }
            }
    
            std::vector< PTRCTBCAFMixer >                aMixers;
            std::vector< PTRCTBCAFMixer >::iterator        itMixer;
            GetMixers( &aMixers );
            for( itMixer = aMixers.begin(); itMixer != aMixers.end(); ++itMixer )
            {
                if( !(*itMixer)->IsTerminating() )
                {
                    LogTrace( TBCAF_TRACE_LEVEL_3, "CheckTerminateRemainingLegsAndMixers:: Also terminating mixer 0x%08X", (*itMixer)->GetMixerId() );
                    (*itMixer)->MixerTerminate();
                }
            }
        }
    }
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoApplicationTransport( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute )
    {
        /* Forward this message */
        PTRCTBCAFCallLeg    ptrOtherLeg;
        ptrOtherLeg = GetOtherLegSmartPtr( in_pCallLeg );
        if( ptrOtherLeg != NULL )
        {
            TBCMC_CALL_PROTOCOL_TYPE     OtherProtocolType = ptrOtherLeg->GetAttributes().GetProtocolType();
    
            LogTrace( TBCAF_TRACE_LEVEL_2, "OnSuppInfoApplicationTransport: Leg 0x%08X APM received forward to %s
    ",
                ptrOtherLeg->GetLegId(),
                TBCMC_CALL_TYPE_TO_STRING(OtherProtocolType) );
    
            if( OtherProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SS7 )
            {
                /* Forward to other leg */
                ptrOtherLeg->SendCallSuppInfo( TBCMC_SUPP_INFO_MSG_TYPE_SS7_APP_TRANSPORT );
            }
            else if ( OtherProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SIP )
            {
                CTBCMC_PROTOCOL_ATTRIBUTE    ExtraProtInfo;
                ExtraProtInfo.SetSipStatusCode (SIP_STATUS_183_SESSION_PROGRESS);
                ptrOtherLeg->SendCallSuppInfo( TBCMC_SUPP_INFO_MSG_TYPE_CALL_PROGRESS, &ExtraProtInfo );
            }
        }
    
        return TBX_RESULT_OK;
    }
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoCallProgress( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute )
    {
        TBX_BOOLEAN                        fSendMsg = TBX_TRUE;
        TBCMC_SUPP_INFO_MSG_TYPE        SupInfoMsgType = TBCMC_SUPP_INFO_MSG_TYPE_NOT_USED;
        TBCMC_CALL_PROTOCOL_TYPE        ProtocolType = TBCMC_CALL_PROTOCOL_TYPE_UNSPECIFIED;
        CTBCMC_PROTOCOL_ATTRIBUTE        ProtocolAttribute;
        CTBCAFPtr<CTBCAFCallLeg>        pLegToSendCallProgress;
    
        (void)in_ProtocolAttribute; /* Argument not used in this function */
    
        if( in_ProtocolAttribute.GetPtr()->Cmn.Type == TBCMC_CALL_PROTOCOL_TYPE_SS7 &&
            in_ProtocolAttribute.GetPtr()->Ss7Attribute.ProtocolVariant == TBCMC_SS7_ISUP_PROTOCOL_VARIANT_SPIROU )
        {
            //In SPIROU, always forward CPG to the other leg
            pLegToSendCallProgress = GetOtherLegSmartPtr( in_pCallLeg );
        }
        else
        {
            /* 
             * Depending on the incoming call type, we need to send the proper call progress.  We'll let the
             * engine to insert the proper "default" IE until we are able to completely convert all protocols
             * and variants amongst them
             */
            pLegToSendCallProgress = GetIncomingActiveLeg();
            if ( pLegToSendCallProgress!= NULL && pLegToSendCallProgress->IsAnswered() )
            {
                fSendMsg = TBX_FALSE;        /* Never forward PROGRESS when the call is answered, unless for SPIROU */
            }
        }
    
        if( pLegToSendCallProgress != NULL )
        {
    
            ProtocolType = pLegToSendCallProgress->GetAttributes().GetCallLegAttribute()->GetProtocolType();
    
            /* 
             * Check which message type we need to send (different for SS7 or ISDN)
             * Note that we don't propagate the "CallProgress" toward SIP network.  We only do this for the
             * EarlyMedia case (which is handled by another behavior).
             */
            if ( ProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SS7 )
                SupInfoMsgType = TBCMC_SUPP_INFO_MSG_TYPE_SS7_CALL_PROGRESS;
            else if ( ProtocolType == TBCMC_CALL_PROTOCOL_TYPE_ISDN )
                SupInfoMsgType = TBCMC_SUPP_INFO_MSG_TYPE_ISDN_CALL_PROGRESS;
            else
                fSendMsg = TBX_FALSE;
    
            /* Send the progress message */
            if (fSendMsg)
            {
                pLegToSendCallProgress->SendCallSuppInfo
                (
                    SupInfoMsgType,
                    &ProtocolAttribute
                );                
            }
        }
    
        return TBX_RESULT_OK;
    }
    
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoSuspend
    (
      IN    PCTBCAFCallLeg                    in_pCallLeg,
      IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
    )
    {
        TBX_BOOL            fJoinPending;
        TBX_BOOL            fJoined            = in_pCallLeg->IsJoined( NULL, &fJoinPending );
        PTRCTBCAFCallLeg    ptrOtherCallLeg    = GetOtherLegSmartPtr( in_pCallLeg );
    
        LogTrace
        (
            TBCAF_TRACE_LEVEL_1,
            "CTBCAFBridge::OnSuppInfoSuspend (%s) for Leg 0x%08X Joined=%u",
            TBCMC_SUPP_INFO_MSG_TYPE_TO_STRING( in_SuppInfoType ),
            in_pCallLeg->GetLegId(),
            fJoined 
        );
    
        if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
        {
            // Forward suspend info to next leg
            ptrOtherCallLeg->SendCallSuppInfo( in_SuppInfoType );
        }
    
        if( fJoined || fJoinPending )
        {
            /* Temporary unjoin legs */
            if( in_SuppInfoType == TBCMC_SUPP_INFO_MSG_TYPE_SUSPEND )
            {
                /* When suspended, we unjoin completely */
                in_pCallLeg->Unjoin();
            }
            else if( ptrOtherCallLeg != NULL )
            {
                /* When in_pCallLeg is 'on hold', we join half-duplex from in_pCallLeg --> Other leg */
                CTBCMC_JOIN_ATTRIBUTE    JoinAttr;
                JoinAttr.IsFullDuplex() = TBX_FALSE;
                in_pCallLeg->Join( ptrOtherCallLeg.Get(), NULL, TBX_TRUE, &JoinAttr );
            }
            mfSuspended = TBX_TRUE;
        }
    
        return TBX_RESULT_OK;
    }
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoResume
    (
      IN    PCTBCAFCallLeg                    in_pCallLeg,
      IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
    )
    {
        TBX_BOOL            fJoinPending;
        TBX_BOOL            fUnjoinPending;
        TBX_BOOL            fJoined            = in_pCallLeg->IsJoined( NULL, &fJoinPending, &fUnjoinPending );
        PTRCTBCAFCallLeg    ptrOtherCallLeg    = GetOtherLegSmartPtr( in_pCallLeg );
        
        (void)in_ProtocolAttribute; /* Argument not used in this function */
    
        LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnSuppInfoResume (%s) for Leg 0x%08X Joined=%u%s%s Suspend=%u",
            TBCMC_SUPP_INFO_MSG_TYPE_TO_STRING( in_SuppInfoType ),
            in_pCallLeg->GetLegId(),
            fJoined,
            fJoinPending ? " (join pending)" : "",
            fUnjoinPending ? " (unjoin pending)" : "",
            (unsigned int)mfSuspended);
    
        if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
        {
            // Forward suspend info to next leg
            ptrOtherCallLeg->SendCallSuppInfo( in_SuppInfoType );
        }
    
        if( mfSuspended )
        {
            if( ptrOtherCallLeg != NULL )
            {
                /* Re-join legs */
                ptrOtherCallLeg->Join( in_pCallLeg, NULL, mOptions.mfWarnIfToneDetectionEnabled );
            }
            mfSuspended = TBX_FALSE;
        }
    
        return TBX_RESULT_OK;
    }
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoChargeUnit
    (
      IN    PCTBCAFCallLeg                    in_pCallLeg,
      IN    TBCMC_SUPP_INFO_MSG_TYPE         in_SuppInfoType,
      IN    CTBCMC_PROTOCOL_ATTRIBUTE &     in_ProtocolAttribute
    )
    {
        TBX_RESULT            Result = TBX_RESULT_INVALID_STATE;
        PTRCTBCAFCallLeg    ptrOtherCallLeg;
        ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
    
        if( in_SuppInfoType == TBCMC_SUPP_INFO_MSG_TYPE_CHARGE_UNIT )
        {
            if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
            {
                CTBCMC_PROTOCOL_ATTRIBUTE ProtocolAttribute;
                TBX_UINT8 in_un8ChargeUnitNumber;
                TBX_UINT8 in_un8MessageNumber;
    
                LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnSuppInfoChargeUnit (ITX) for Leg 0x%08X: Forwarding to leg 0x%08X",
                    in_pCallLeg->GetLegId(),
                    ptrOtherCallLeg->GetLegId() );
                
                switch( ptrOtherCallLeg->GetAttributes().GetCallLegAttribute()->GetProtocolType() )
                {
                    case TBCMC_CALL_PROTOCOL_TYPE_SS7: /* Only supported on ISUP and SIP */
                    case TBCMC_CALL_PROTOCOL_TYPE_SIP:
                        in_ProtocolAttribute.GetChargeNumber( in_un8ChargeUnitNumber, in_un8MessageNumber );
                        ProtocolAttribute.SetChargeNumber( in_un8ChargeUnitNumber, in_un8MessageNumber );
                        ProtocolAttribute.GetPtr()->Cmn.Type = ptrOtherCallLeg->GetAttributes().GetCallLegAttribute()->GetProtocolType();
    
                        ptrOtherCallLeg->SendCallSuppInfo(
                            TBCMC_SUPP_INFO_MSG_TYPE_CHARGE_UNIT, 
                            &ProtocolAttribute );
                        break;
                    default:
                        break;
                }
                Result = TBX_RESULT_OK;
            }
    
            LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnSuppInfoChargeUnit (ITX) for Leg 0x%08X: Acknowledging (TXA)",
                in_pCallLeg->GetLegId() );
    
            /* Acknowledge (TXA) */
            in_pCallLeg->SendCallSuppInfo( TBCMC_SUPP_INFO_MSG_TYPE_CHARGING_ACK, NULL );
        }
        else if( in_SuppInfoType == TBCMC_SUPP_INFO_MSG_TYPE_CHARGING_ACK )
        {
            LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnSuppInfoChargeUnit (TXA) for Leg 0x%08X: Received acknowledge",
                in_pCallLeg->GetLegId() );
            /* Don't forward this, this ack belongs to us. In fact, the specs says that:
               - Incoming ITX received => Forward to other leg, and return ack (TXA) to current leg
               - Then we expect a ack (TXA) from other leg in response to our forwarded ITX (here, we just got that ack) */
            /* Make sure we did not store SS7 raw data in the other leg, else it could cause problem for the next message we transmit*/ 
            if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
            {
                ptrOtherCallLeg->EmptySs7RawDataToTransmit();
            }
        }
        else
        {
            LogTrace( TBCAF_TRACE_LEVEL_ERROR, "OnSuppInfoChargeUnit: Unexpected supp info type %u", (unsigned int)in_SuppInfoType );
        }
    
        return Result;
    }
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoSS7Charge( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute )
    {
        /* Forward this message */
        PTRCTBCAFCallLeg    ptrOtherCallLeg;
        ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
        if( ptrOtherCallLeg != NULL )
        {
            CTBCMC_PROTOCOL_ATTRIBUTE    ExtraProtInfo;
            TBCMC_CALL_PROTOCOL_TYPE     OtherProtocolType = ptrOtherCallLeg->GetAttributes().GetProtocolType();
    
            LogTrace( TBCAF_TRACE_LEVEL_2, "OnSuppInfoSS7Charge: Leg 0x%08X CHG received forward to %s
    ",
                ptrOtherCallLeg->GetLegId(),
                TBCMC_CALL_TYPE_TO_STRING(OtherProtocolType) );
    
            if( OtherProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SS7 )
            {
                /* Forward to other leg */
                CTBCAFPtr<CTBCMCSs7RawData>    ptrSs7RawData;
                in_ProtocolAttribute.GetSs7RawData( &ptrSs7RawData );
    
                if ( ptrSs7RawData != NULL )
                {
                    TBCMC_SS7_ISUP_PROTOCOL_VARIANT        ProtocolVariant;
                    CTBCAFString                        strData;
                    PSS7_ISUP_MSG_CHG_STRUCT            pChgMsg;
                    TBX_BYTE                            abyIeBuffer [250];
                    TBX_UINT16                            un16IeBufferSize = 0;
    
                    ptrSs7RawData->GetSs7RawDataBuf( ProtocolVariant, strData );
                    pChgMsg = (PSS7_ISUP_MSG_CHG_STRUCT)strData.c_str();
    
                    if ( strData.Length() > SS7_ISUP_MSG_CHG_MIN_SIZE && 
                        pChgMsg->un8MsgId == SS7_ISUP_MESSAGE_CHG &&
                        pChgMsg->un8MandatoryOff == 0x02 &&                                            /* Pointer of mandatory IE */
                        (TBX_UINT32)pChgMsg->un8ChargeInfoSize + SS7_ISUP_MSG_CHG_MIN_SIZE <= strData.Length()    /* Charge information IE length */
                       )
                    {
                        /* Basic validation successful, we can use this ss7 raw data to write mandatory IEs */
                        /* Insert the 2 mandatory IEs */
                        TB640_SS7_ISUP_WRITE_CHARGE_INFO_TYPE
                        (
                            abyIeBuffer,
                            &un16IeBufferSize,
                            0,
                            pChgMsg->un8ChargeType                                /* Charge info type value */
                        );
    
                        TB640_SS7_ISUP_WRITE_CHARGE_INFO
                        (
                            abyIeBuffer,
                            &un16IeBufferSize,
                            0,
                            pChgMsg->un8ChargeInfoSize,
                            pChgMsg->aun8ChargeInfo                             /* Charge info array of bytes */
                        );
    
                        ExtraProtInfo.SetSS7Ie( un16IeBufferSize, abyIeBuffer );
    
                        ptrOtherCallLeg->SendCallSuppInfo
                        (
                            TBCMC_SUPP_INFO_MSG_TYPE_SS7_CHARGE,
                            &ExtraProtInfo
                        );
                    }
                }
            }
            else if ( OtherProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SIP )
            {
                ExtraProtInfo.SetSipStatusCode (SIP_STATUS_183_SESSION_PROGRESS);
                ptrOtherCallLeg->SendCallSuppInfo
                (
                    TBCMC_SUPP_INFO_MSG_TYPE_CALL_PROGRESS,
                    &ExtraProtInfo
                );
            }
        }
    
        return TBX_RESULT_OK;
    }
    
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoUnrecognizedMSU( PCTBCAFCallLeg in_pCallLeg, CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute )
    {
        TBX_RESULT            Result = TBX_RESULT_INVALID_STATE;
        PTRCTBCAFCallLeg    ptrOtherCallLeg;
    
        LogTrace( TBCAF_TRACE_LEVEL_2, "CTBCAFBridge::for Leg 0x%08X",
            in_pCallLeg->GetLegId() );
    
        ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
        if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
        {
            TBCMC_CALL_PROTOCOL_TYPE     ProtocolType = ptrOtherCallLeg->GetAttributes().GetProtocolType();
            
            if( ProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SS7 ||
                ProtocolType == TBCMC_CALL_PROTOCOL_TYPE_SIP )        /* For SIP-I, the message will be dropped in case of normal SIP */
            {
                /* Forward to other leg, using the raw buffer copied in CTBCAFCallBehaviorHeaderForward */
                ptrOtherCallLeg->SendCallSuppInfo( TBCMC_SUPP_INFO_MSG_TYPE_SS7_UNRECOGNIZED_MSU );
                
            }
            /*else
            {
                ptrOtherCallLeg->SetSs7RawDataToTransmit(NULL);
            }*/
            Result = TBX_RESULT_OK;
        }
    
        return Result;
    }
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoConfusion
    ( 
        IN        PCTBCAFCallLeg in_pCallLeg, 
        IN        CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute 
    )
    {
        LogTrace( TBCAF_TRACE_LEVEL_2, "CTBCAFBridge::OnSuppInfoConfusion for Leg 0x%08X",
            in_pCallLeg->GetLegId() );
    
        /* On confusion, we never forward to other call leg, so if SS7 raw data was forwarded, we want to remove it */
        PTRCTBCAFCallLeg    ptrOtherCallLeg;
        ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
        if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
        {
            CTBCAFPtr<CTBCMCSs7RawData> ptrNull; 
            ptrNull = NULL;
            ptrOtherCallLeg->EmptySs7RawDataToTransmit();
        }
    
        return TBX_RESULT_INVALID_STATE;
    }
    
    TBX_RESULT CTBCAFBridge::OnSuppInfoDefault
    ( 
        IN        PCTBCAFCallLeg in_pCallLeg, 
        IN        TBCMC_SUPP_INFO_MSG_TYPE     in_SuppInfoType, 
        IN        CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute 
    )
    {
        TBX_RESULT            Result = TBX_RESULT_INVALID_STATE;
    
        LogTrace( TBCAF_TRACE_LEVEL_2, "CTBCAFBridge::OnSuppInfoDefault for Leg 0x%08X",
            in_pCallLeg->GetLegId() );
    
        //For SPIROU, forward message to other leg by default
        if (in_ProtocolAttribute.GetPtr()->Cmn.Type == TBCMC_CALL_PROTOCOL_TYPE_SS7 &&
            in_ProtocolAttribute.GetPtr()->Ss7Attribute.ProtocolVariant == TBCMC_SS7_ISUP_PROTOCOL_VARIANT_SPIROU )
        {
            PTRCTBCAFCallLeg    ptrOtherCallLeg;
            ptrOtherCallLeg = GetOtherLegSmartPtr( in_pCallLeg );
            if( ptrOtherCallLeg != NULL && !ptrOtherCallLeg->IsTerminating() )
            {
                if( ptrOtherCallLeg->GetAttributes().GetProtocolType() == TBCMC_CALL_PROTOCOL_TYPE_SS7 )
                {
                    /* Forward to other leg */
                    ptrOtherCallLeg->SendCallSuppInfo( in_SuppInfoType, &in_ProtocolAttribute );
                }
                Result = TBX_RESULT_OK;
            }
        }
        return Result;
    }
    
    TBX_RESULT CTBCAFBridge::OnLegEvent
    (
      IN    PCTBCAFCallLeg                in_pCallLeg,
      IN    PITBCMCEvent                in_pEvent
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        CTBCMCLegError            LegError;
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnLegEvent )
        {
            LogTrace( TBCAF_TRACE_LEVEL_0, "CTBCAFBridge::OnLegEvent: 0x%08X
    ", in_pCallLeg->GetLegId() );
    
            switch( in_pEvent->GetType() )
            {
                case TBCMC_EVENT_TYPE_TIMEOUT:
                {
                    LogTrace( TBCAF_TRACE_LEVEL_ERROR, "CTBCAFBridge::OnLegEvent: Received unhandled timeout. A behavior should have catched it, but did not!
    " );
                } break;
    
                case TBCMC_EVENT_TYPE_TERMINATE:
                {
                    in_pCallLeg->TerminateCall( TBCMC_CALL_REASON_CODE_TOOLPACK_NORMAL );
                } break;
    
                default:
                    LogTrace( TBCAF_TRACE_LEVEL_2, "CTBCAFBridge::OnLegEvent: Unhandled event %u for leg 0x%08X
    ",
                        in_pEvent->GetType(),
                        in_pCallLeg->GetLegId() );
            }
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
            delete in_pEvent;
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    TBX_RESULT CTBCAFBridge::OnLegError
    (
      IN    PCTBCAFCallLeg                in_pCallLeg,
      IN    CTBCMCLegError &             in_Error
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnLegError )
        {
            if( in_Error.mMsgId == TBCMC_MSG_ID_CMD_CALL_LEG_TERMINATE )
            {
                LogTrace( TBCAF_TRACE_LEVEL_ERROR, "CTBCAFBridge::OnLegError for Leg 0x%08X Error(%s 0x%08x)
    ",
                    in_pCallLeg->GetLegId(), in_Error.what(), in_Error.mResult );
    
                /* Error upon call termination. Free leg immediately */
                if( in_pCallLeg->IsJoined() )
                {
                    in_pCallLeg->TerminateCall( TBCMC_CALL_REASON_CODE_TOOLPACK_RESOURCE_ERROR );
                }
                else
                {
                    in_pCallLeg->FreeLeg();
                }
            }
            else if( in_Error.IsDataPathErrors() )
            {
                TBCAF_TRACE_LEVEL        TraceLevel = TBCAF_TRACE_LEVEL_2;
                if( in_Error.mLegErrors.FromNetwork.fExcessiveIpPortChanges )
                {
                    /* This error is considered fatal */
                    TraceLevel = TBCAF_TRACE_LEVEL_ERROR;
                }
                LogTrace( TraceLevel, FRED "CTBCAFBridge::OnLegError for Leg 0x%08X Data path error(%s)
    ",
                    in_pCallLeg->GetLegId(), in_Error.GetDatapathErrorsStr().c_str() );
                if( TraceLevel == TBCAF_TRACE_LEVEL_ERROR)
                {
                    // Kick leg termination
                    in_pCallLeg->TerminateCall( TBCMC_CALL_REASON_CODE_TOOLPACK_RESOURCE_ERROR );
                }
            }
            else
            {
                TBCAF_TRACE_LEVEL    TraceLevel = TBCAF_TRACE_LEVEL_ERROR;
    
                if( in_pCallLeg->IsTerminating() )    TraceLevel = TBCAF_TRACE_LEVEL_0;
    
                LogTrace( TraceLevel, "CTBCAFBridge::OnLegError for Leg 0x%08X on MsgId 0x%08X Error(%s 0x%08x)
    ",
                    in_pCallLeg->GetLegId(), (unsigned int)in_Error.mMsgId, in_Error.what(), in_Error.mResult );
    
                #if 0    /* We no more drop the leg, here is not the right place to determine if an error is fatal to a leg or not
                           (for example, is it fatal that a call to PlayEvent has failed?  Behavior that made the operation can decide
                           but we can't take a generic decision here in the call flow class) */
                // Kick leg termination
                in_pCallLeg->TerminateCall( TBCMC_CALL_REASON_CODE_TOOLPACK_RESOURCE_ERROR );
                #endif
            }
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    /*******************************************************************************************************************
     * Leg Interface
     ******************************************************************************************************************/
    
    
    
    TBX_RESULT CTBCAFBridge::OnSyncDone
    (
      IN    PCTBCAFCallLeg                            in_pCallLeg
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
    
        PTRCTBCAFCallLeg    ptrOtherLeg;
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAFCODE( CTBCAFBridge::OnSyncDone )
        {
            TBCAFPrintCallLegInfo
            (
                TBCAF_TRACE_LEVEL_1,
                in_pCallLeg->GetLegId(),
                &in_pCallLeg->GetAttributes(),
                "CTBCAFBridge::OnSyncDone",
                this
            );
    
            /* Test that we have one active incoming and outgoing leg */
            if( mptrActiveCallLegIn == NULL || mptrActiveCallLegOut == NULL )
            {
                std::vector< PTRCTBCAFCallLeg >                aLegs;
                std::vector< PTRCTBCAFCallLeg >::iterator    itLeg;
    
                GetLegs( &aLegs );
    
                LogTrace( TBCAF_TRACE_LEVEL_3, "CTBCAFBridge::OnSyncDone Missing active leg => Terminating %u call legs
    ", aLegs.size() );
    
                for( itLeg = aLegs.begin(); itLeg != aLegs.end(); ++itLeg )
                {
                    (*itLeg)->TerminateCall( TBCMC_CALL_REASON_CODE_TOOLPACK_SYNC_DROP );
                }
            }
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Exception handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_EXCEPTION_HANDLING
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_ERROR_HANDLING( CAF_VERBOSE )
        {
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CAF_CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    
    TBX_RESULT CTBCAFBridge::OnEventCollected
    (
        PCTBCAFCallLeg                                in_pCallLeg,
        const CTBCAFString&                            in_strEvent,
        const CTBCMC_EVENT_COLLECTED_ATTRIBUTE&        in_EventAttr
    )
    {
        LogTrace( TBCAF_TRACE_LEVEL_1, "CTBCAFBridge::OnEventCollected for LegId 0x%08x: %s (duration %ums)
    ", in_pCallLeg->GetLegId(), in_strEvent.c_str(), in_EventAttr.un32EventDurationMs );
    
        /* Don't pass to base class CTBCAFCallFlow, not necessary */
        return TBX_RESULT_OK;
    }
    
    
    
    TBX_RESULT CTBCAFBridge::OnLegProfileChanged
    (
      IN    PCTBCAFCallLeg                in_pCallLeg,
      IN    CTBCMC_MEDIA_PROFILE &         in_MediaProfile,
      IN    TBCMC_MEDIA_REASON_CODE        in_Reason,
      IN    TBCMC_CALL_REASON_CODE        in_RefusedReason
    )
    {
    TBCAF_MUTEX_GET_SCOPE_BEGIN( &mMutex )
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Code section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CODE
        {
            TBCAFPrintCallLegInfo
            (
                TBCAF_TRACE_LEVEL_1,
                in_pCallLeg->GetLegId(),
                &in_pCallLeg->GetAttributes(),
                "CTBCAFBridge::OnLegProfileChanged",
                this
            );
    
            TBX_EXIT_SUCCESS( TBX_RESULT_OK );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Error handling section
         *--------------------------------------------------------------------------------------------------------------------------*/
        ERROR_HANDLING
        {
            LogTrace( TBCMC_TRACE_LEVEL_ERROR,
                "CTBCAFBridge::OnLegProfileChanged: %s (0x%08X) 0x%08X %s:%d",
                TBX_ERROR_DESCRIPTION,
                TBX_ERROR_LEVEL,
                (int)TBX_ERROR_RESULT,
                TBX_ERROR_FILE,
                TBX_ERROR_LINE );
        }
    
        /*---------------------------------------------------------------------------------------------------------------------------
         |  Cleanup section
         *--------------------------------------------------------------------------------------------------------------------------*/
        CLEANUP
        {
        }
    
        RETURN;
    TBCAF_MUTEX_GET_SCOPE_END( &mMutex )
    }
    
    TBX_VOID CTBCAFBridge::GetBridgedLegTermReason
    (
      IN    TBCMC_CALL_REASON &                 in_Reason,
      OUT    TBCMC_CALL_REASON &                 out_ReasonForBridgedLeg
    )
    {
        memcpy (&out_ReasonForBridgedLeg, &in_Reason, sizeof (out_ReasonForBridgedLeg));
        /* By default, the bridged leg should be terminated with the same reason as the other leg.
           However, some reason code with special signification must be remapped */
        switch( in_Reason.Reason )
        {
            case TBCMC_CALL_REASON_CODE_401_UNAUTHORIZED:
            case TBCMC_CALL_REASON_CODE_407_PROXY_AUTH_REQD:
                out_ReasonForBridgedLeg.Reason = TBCMC_CALL_REASON_CODE_403_FORBIDDEN;
                break;
            default:
                /* Already copied by the memcpy above */
                break;
        }
    }
    
    CTBCAFBridgeOptions::CTBCAFBridgeOptions()
     : mfWarnIfToneDetectionEnabled( TBX_TRUE )
    {
        
    }
    
    
    CTBCAFBridgeOptions::CTBCAFBridgeOptions( const CTBCAFBridgeOptions& in_Copy )
    {
        *this = in_Copy;
    }
    
        
    CTBCAFBridgeOptions::~CTBCAFBridgeOptions()
    {
    }
    
    
    const CTBCAFBridgeOptions & CTBCAFBridgeOptions::operator=( const CTBCAFBridgeOptions& in_Copy )
    {
        mfWarnIfToneDetectionEnabled     = in_Copy.mfWarnIfToneDetectionEnabled;
        return *this;
    }
    
    /*--------------------------------------------------------------------------------------------------------------------------------
     |  Namespace declaration
     *------------------------------------------------------------------------------------------------------------------------------*/
    } /* namespace TBCAF */
  • 相关阅读:
    【FROM】java控件重绘AWT/SWINGPainting in AWT and Swing (EN)
    linux yum使用管理详细使用
    远程控制 vc++实现
    java 鼠标事件Dragged和Moved 及java显示GIF在JLabel、JButton
    C语言字符串函数大全
    C# 训练场(四)创建系统热键,并向活动窗口输入信息
    潜移默化学会WPF(样式) DataGrid(转载)
    时间查询
    Sqlserver2012 根据数据库mdf文件生成log文件,解决无法附加mdf文件
    我知道的一些 ”运行“ 窗体下的命令,个人使用
  • 原文地址:https://www.cnblogs.com/lthxk-yl/p/5084880.html
Copyright © 2020-2023  润新知