Actions

CAF: Leg Creation Samples: Difference between revisions

m (really old article. Removed the needs revising category tag.)
mNo edit summary
 
Line 1: Line 1:
{{DISPLAYTITLE:CAF: Leg Creation Samples}}
== Creating a Standalone Outgoing Call Leg ==
== Creating a Standalone Outgoing Call Leg ==
     PTRCTBCMC_CALL_LEG_ATTRIBUTE ptrOutgoingLegAttribute;
     PTRCTBCMC_CALL_LEG_ATTRIBUTE ptrOutgoingLegAttribute;
Line 121: Line 122:


== Pitfall ==
== Pitfall ==
It's mandatory that the call leg and protocol attribute objects passed to AddIncoming() and AddOutgoing() remain valid until function InitCall() returns.
It is 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 ==
== Creating a Media-only Leg ==

Latest revision as of 10:32, 6 September 2022

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 is 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.