CAF: Leg Creation Samples
Contents |
Creating a Standalone Outgoing Call Leg
PTRCTBCMC_CALL_LEG_ATTRIBUTE ptrOutgoingLegAttribute; ptrOutgoingLegAttribute = tbnew CTBCMC_CALL_LEG_ATTRIBUTE(); ptrOutgoingLegAttribute->GetCalledNumber() = "123-4567"; ptrOutgoingLegAttribute->GetCallingNumber() = "987-6543"; ptrOutgoingLegAttribute->GetNetworkAccessPoint() = "NAP_SS7_MONTREAL"; PCTBCMCLeg pCallLeg = tbnew CTBCMCLeg( ++mun32LegId, ptrOutgoingLegAttribute, this, 0, &mLegMutex ); pCallLeg->CreateCall();
Bridging an Incoming Call Leg (using CTBCAFBridge )
TBX_VOID CTBS2GWSimpleCall::OnCallLegPresent ( IN TBCMC_LEG_ID in_LegId, IN CTBCMC_CALL_LEG_ATTRIBUTE_COMMON & in_CallLegAttribute, IN CTBCMC_PROTOCOL_ATTRIBUTE & in_ProtocolAttribute ) { TBX_RESULT Result; PITBCAFCallFlow pBridge; PTRCTBCMC_CALL_LEG_ATTRIBUTE ptrIncomingLegAttribute; PTRCTBCMC_PROTOCOL_ATTRIBUTE ptrIncomingLegProtocolAttributes; PTRCTBCMC_PROTOCOL_ATTRIBUTE ptrAcceptCallProtAttribute; PTRCTBCMC_CALL_LEG_ATTRIBUTE ptrOutgoingLegAttribute; PTRCTBCMC_PROTOCOL_ATTRIBUTE ptrOutgoingLegProtocolAttributes; /*--------------------------------------------------------------------------------------------------------------------------- | Code section *--------------------------------------------------------------------------------------------------------------------------*/ CAFCODE( CTBS2GWSimpleCall::OnCallLegPresent ) { // Create smart pointers to incoming call leg attributes so behaviors can keep reference to it if needed ptrIncomingLegAttribute = tbnew CTBCMC_CALL_LEG_ATTRIBUTE( *(in_CallLegAttribute.GetCallLegAttribute()) ); ptrIncomingLegProtocolAttributes = tbnew CTBCMC_PROTOCOL_ATTRIBUTE( in_ProtocolAttribute, TBX_TRUE ); // Build default protocol attributes object so behaviors can modify // attributes used to Accept the incoming call leg ptrAcceptCallProtAttribute = tbnew CTBCMC_PROTOCOL_ATTRIBUTE(); // Build default protocol attributes object so behaviors can modify // attributes used to create the outgoing call leg ptrOutgoingLegProtocolAttributes = tbnew CTBCMC_PROTOCOL_ATTRIBUTE(); // Create an empty outgoing call leg attribute object ptrOutgoingLegAttribute = tbnew CTBCMC_CALL_LEG_ATTRIBUTE(); // Fill some information in the outgoing call leg attributes from the incoming leg attributes // *** Warning: Don't use operator=. We dont wan't to copy EVERYTHING, but only information // common to both incoming and outgoing legs, such as calling/called number. // Function CopyLegAttributeFrom() takes care of copying relevant information. ptrOutgoingLegAttribute->CopyLegAttributeFrom( *(ptrIncomingLegAttribute.Get()) ); // Create the call (i.e. which contains 2 call legs) pBridge = tbnew CTBCAFBridge( 0, this ); TBCAF_EXIT_ON_NULL( pBridge, TBX_RESULT_FAIL, "Failed to allocate call." ); /* Prepare the chain of behaviors */ PITBCAFCallFlow pPreviousBehavior = pBridge; /* Add the example behavior to the chain of behaviors */ pPreviousBehavior = tbnew CTBS2GWCallBehaviorExample( pPreviousBehavior ); // Add legs information Result = pBridge->AddIncoming( in_LegId, ptrIncomingLegAttribute, ptrIncomingLegProtocolAttributes, ptrAcceptCallProtAttribute ); TBCAF_EXIT_ON_ERROR(Result, "AddIncoming Failed." ); // Provide an uninitialized PTRCTBCMC_PROTOCOL_ATTRIBUTE Result = pBridge->AddOutgoing( ptrOutgoingLegAttribute, ptrOutgoingLegProtocolAttributes ); TBCAF_EXIT_ON_ERROR(Result, "AddOutgoing Failed." ); Result = pBridge->InitCall( &pBridge ); if( pBridge == NULL ) { /* Note: If this return value is NULL, this means the InitCall function has initialized no call leg's state machine (failed to) and destroyed itself immediately (it normally destroys itself later when the state machine of all call legs has terminated). The above line of code shall thus be the last of the function to avoid accessing any member of "this" here. */ TBX_EXIT_CLEANUP( Result ); } TBCAF_EXIT_ON_ERROR(Result, "InitCall Failed." ); TBX_EXIT_SUCCESS( TBX_RESULT_OK ); } /*--------------------------------------------------------------------------------------------------------------------------- | Exception handling section *--------------------------------------------------------------------------------------------------------------------------*/ CAF_EXCEPTION_HANDLING /*--------------------------------------------------------------------------------------------------------------------------- | Error handling section *--------------------------------------------------------------------------------------------------------------------------*/ CAF_ERROR_HANDLING( CAF_VERBOSE ) { if( pBridge == NULL ) { // Try to refuse the call leg CTBCMCLeg::RefuseLeg( in_LegId, in_CallLegAttribute ); } } /*--------------------------------------------------------------------------------------------------------------------------- | Cleanup section *--------------------------------------------------------------------------------------------------------------------------*/ CAF_CLEANUP { } RETURN_VOID; }
InitCall() will create each leg added from AddIncoming() and AddOutgoing() and incoming and outgoing call leg will be joined when we receive the notification OnCallLegAnswered() indicating that the outgoing call has been answered by the remote peer.
Pitfall
It's mandatory that the call leg and protocol attribute objects passed to AddIncoming() and AddOutgoing() remain valid until function InitCall() returns.
Creating a Media-only Leg
If you are using a nap of type NAP_MEDIA_TDM:
PTRCTBCMC_MEDIA_ONLY_LEG_ATTRIBUTE ptrLegAttribute; PTBCMC_MEDIA_DESCRIPTION pMediaDesc; ptrLegAttribute = tbnew CTBCMC_MEDIA_ONLY_LEG_ATTRIBUTE(); pMediaDesc = &ptrLegAttribute->GetProfile().GetMediaDescription(); ptrLegAttribute->GetNetworkAccessPoint() = "NAP_MEDIA_TDM"; pMediaDesc->Type = TBCMC_MEDIA_TYPE_AUDIO; pMediaDesc->Transport = TBCMC_MEDIA_TRANSPORT_TDM; pMediaDesc->Settings.TdmAudio.Type = TBCMC_MEDIA_SETTINGS_TYPE_TDM_AUDIO; pMediaDesc->Settings.TdmAudio.un8Timeslot = 5; Strncpy ( pMediaDesc->Settings.TdmAudio.szTrunkName, "TRUNK_TORONTO_1", sizeof(pMediaDesc->Settings.TdmAudio.szTrunkName) ); PCTBCMCLeg pCallLeg = tbnew CTBCMCLeg( ++mun32LegId, ptrLegAttribute, this, 0, &mLegMutex ); pCallLeg->CreateCall();
If you are using a nap of type NAP_MEDIA_VOIP:
TBX_RESULT Result; TBX_SDP_INFO SdpInfo; PTRCTBCMC_MEDIA_ONLY_LEG_ATTRIBUTE ptrLegAttribute; PTBCMC_MEDIA_DESCRIPTION pMediaDesc; ptrLegAttribute = tbnew CTBCMC_MEDIA_ONLY_LEG_ATTRIBUTE(); pMediaDesc = &ptrLegAttribute->GetProfile().GetMediaDescription(); ptrLegAttribute->GetNetworkAccessPoint() = "NAP_MEDIA_VOIP"; pMediaDesc->Type = TBCMC_MEDIA_TYPE_AUDIO; pMediaDesc->Transport = TBCMC_MEDIA_TRANSPORT_IP; pMediaDesc->Settings.PacketAudio.Type = TBCMC_MEDIA_SETTINGS_TYPE_PACKET_AUDIO; // Set Local SDP Result = BuildSdpInfo("", 0, SdpInfo); // No IP specified, Toolpack will choose one TBCAF_EXIT_ON_ERROR( Result, "BuildSdpInfo failed." ); ptrLegAttribute->GetProfile().SetLocalSDP(SdpInfo); // Set Peer SDP Result = BuildSdpInfo("10.0.0.15", 5000, SdpInfo); // Using peer IP address and port TBCAF_EXIT_ON_ERROR( Result, "BuildSdpInfo failed." ); ptrLegAttribute->GetProfile().SetPeerSDP(SdpInfo); PCTBCMCLeg pCallLeg = tbnew CTBCMCLeg( ++mun32LegId, ptrLegAttribute, this, 0, &mLegMutex ); pCallLeg->CreateCall();
Note that you have two possibilities to build a TBX_SDP_INFO structure. The first one is like in the example (BuildSdpInfo()) where you can build manually your TBX_SDP_INFO structure and the second one is when you have an sdp info in text format. There is a function that will parse the text and build a TBX_SDP_INFO structure from it.
TBXMediaLibSdpParse ( IN PTBX_CHAR in_pszSdp, OUT PTBX_SDP_INFO out_pSdpInfo, IN TBX_MEDIA_SDP_PARSE_OPTIONS in_Options );
To see how to build a TBX_SDP_INFO structure, refer to Filling an SDP Structure.