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 */