Symbian3/SDK/Source/GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 13 48780e181b38
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-CF17532E-5E90-5124-8F05-AA72B848F17F" xml:lang="en"><title>SIP
Example: Usage of the SIP Stack</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>The SIP sample application is a game that can be played between two users
that use two different machines. The following figure illustrates the sample
application. </p>
<fig id="GUID-A0E243BE-E697-5856-8C08-6039AAE6A05A">
<image href="GUID-155C5B39-CB9B-5405-B9BB-EB34CA7C43BC_d0e338662_href.png" placement="inline"/>
</fig>
<p>All users who want to play the game must register to the server with their
identities. This informs the server that the user is active and prepared to
participate in the game. If User 1 wants to play the game with User 2 then
it must send a request to User 2 through the server. When User 2 accepts the
request and acknowledges it then the two users can start playing. A user can
disconnect from playing the game by sending a message. If a user wants to
be deactivated then it can deregister from the server. </p>
<p>This application is developed using the key features of the Symbian SIP
stack. It shows how to create profiles and do SIP registration using the profiles,
how to set up a SIP session and send an instant message using the SIP. For
example you can set up the SIP server using Brekeke and you can download the
same from <xref href="http://www.brekeke.com/download/download_sip_2_0.php" scope="external">http://www.brekeke.com/download/download_sip_2_0.php</xref>. </p>
<section><title>Features of the game</title> <p>The main features of the game
are: </p> <ul>
<li id="GUID-8767E5EC-04F6-5D19-B77A-94C6E7BF10B7"><p> <b>Register or deregister </b> -
A user registers to the server with a unique identity before playing the game.
This identity is the SIP URI of the user. The user registers by sending a
SIP REGISTER message to the SIP server and is active. A user deactivates by
deregistering to the server. This activity is done by sending the SIP REGISTER
message with the expires header set to 0. For more information on registering
or deregistering to the server see, <xref href="GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita#GUID-CF17532E-5E90-5124-8F05-AA72B848F17F/GUID-2C4A1BCE-CD8E-5BDC-84D1-2C5DDBF8A142">Registering
or deregistering an user</xref>. </p> </li>
<li id="GUID-1547D0C9-4B7C-568F-9C5D-A2BE20F9B362"><p> <b>Invite another user</b> -
A user invites another user to play the game by entering the SIP URI of the
other user in the INVITE message. For more information on inviting another
user to play the game see, <xref href="GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita#GUID-CF17532E-5E90-5124-8F05-AA72B848F17F/GUID-7D5CB45C-614B-58DF-8EE4-1AB2DB02CE1C">Inviting
a participant for session setup</xref>. </p> </li>
<li id="GUID-94802B8B-C10B-5ADB-A5E0-0FC436790427"><p> <b>Send a message to
another user</b> - A user can send an instant message to another user. For
more information on how to send an instant message to another user see, <xref href="GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita#GUID-CF17532E-5E90-5124-8F05-AA72B848F17F/GUID-0E7C6F87-C90B-5888-B1F7-33ED0D7393F5">Sending
an instant message</xref>. </p> </li>
<li id="GUID-55484DA7-37DC-566B-95F8-066E19AA5790"><p> <b>Disconnect from
playing the game</b> - A user can disconnect from playing the game by sending
a SIP BYE message to the other user. </p> </li>
</ul> </section>
<section id="GUID-3A9BE5C5-A9A2-54A8-B525-6750E562EF97"><title>How to play
the game</title> <p>The following snapshot shows the different tabs available
in the game. </p> <fig id="GUID-15C8B95B-4B8C-5701-80B1-C0D7B39AF422">
<image href="GUID-0E21EAE4-BF71-55FD-9561-EA5530696627_d0e338735_href.png" placement="inline"/>
</fig> <p>The following list describes the different tabs available in the
game: </p> <ul>
<li id="GUID-CDB3E759-F01D-5D02-B8AA-7E901C1984BE"><p> <b>Invite for game</b> -
This tab allows you to invite a user to play the game. When you invoke this
tab, a UI screen appears which asks the user to provide the SIP URI of the
second user with whom the user wants to play the game. The SIP URI of the
second user is then sent to the SIP stack which passes on the invite request
to the second user. The second user can accept or reject the invite. If the
second user accepts the invite then it acknowledges by sending a message that
it is prepared to start playing the game. If the second user rejects the invite
then it cannot play the game. </p> </li>
<li id="GUID-4A4F6318-1FDD-540A-BF87-72B19BE56A97"><p> <b>Enable profile</b> -
This tab allows you to enable a profile. When you invoke this tab, a UI screen
appears where the user enters the values. A profile is created using these
values and the user registers with the SIP server. </p> </li>
<li id="GUID-A9F95A0B-4E44-52C6-AD0B-E2BDFA4C8CCE"><p> <b>Send instant msg</b> -
This tab allows you to send a message to another user. When you invoke this
tab, a message with the address of the recipient is sent to the SIP stack.
The SIP stack sends this message to the recipient address. </p> </li>
<li id="GUID-4334DC63-8AAB-581C-A779-FBBBD44C4227"><p> <b>End game</b> - This
tab allows you to disconnect from playing the game. When you invoke this tab,
a BYE message is sent to the other user and the game is terminated. </p> </li>
</ul> </section>
<section id="GUID-2C4A1BCE-CD8E-5BDC-84D1-2C5DDBF8A142"><title>Registering
or deregistering an user</title> <p>An application can register to the SIP
Server using: </p> <ul>
<li id="GUID-620D3765-E3A1-55B9-900F-562486A01D6B"><p>the <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> class
and its methods </p> </li>
<li id="GUID-DDC990A1-BFDC-5CA4-A392-EAADFB8C3921"><p>the SIP Profile Agent </p> </li>
</ul> <p>This sample application uses the SIP Profile Agent method to do SIP
registration. To use this method you need a SIP profile setting, and you must
create a SIP profile before you start using the application. <b>Note</b>:
A list of SIP profile settings can be found in the <xref href="GUID-68AE6070-0410-3671-9E68-A7785B8271CD.dita"><apiname>CSIPProfile</apiname></xref> class. </p> <p>The
SIP profile agent method provides APIs for: </p> <ul>
<li id="GUID-68A120EA-45B6-5909-8DD1-B125A1249C13"><p>Registering and Deregistering </p> </li>
<li id="GUID-50AA5E67-EA40-5844-873B-77DAAE94480F"><p>Listening to registration
events </p> </li>
<li id="GUID-300245B5-2B62-5382-B492-8BE8759E48E3"><p>Creating, modifying,
and deleting the SIP profile settings that the profile agent plug-in implementations
use for SIP registration. </p> </li>
</ul> <p>The following code from <filepath>SIPExProfileQueryDlg.cpp</filepath> shows
how the sample application stores the settings entered by users on the SIP
profile store. </p> <codeblock id="GUID-8D76FE52-F0E5-5F57-AD38-0AE8694D3AA4" xml:space="preserve">//Create a new profile
    CSIPManagedProfile* profile = iMProfileRegistry-&gt;CreateL(iProfileData.iServiceProfile);
   
//Copy attributes entered by the user to the new profile        
    iNewProfile = profile;
    profile = CopyDataToProfileL();

//Set the profile to default and save some settings
    TInt err= profile-&gt;SetParameter(KSIPDefaultProfile,ETrue);
   
//Save the profile to persistent store                
    iMProfileRegistry-&gt;SaveL( *profile );
</codeblock> <p>The applications can start SIP registration or deregistration
using the <codeph>Enable</codeph> or <codeph>Disable</codeph> methods from
the SIP profile API. </p> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
how to register using the profile agent. </p> <codeblock id="GUID-F4398335-6AC0-5E10-B04D-6846A3CDE1D5" xml:space="preserve">//Check for the existing profile
    if ( iProfile )
        {
        delete iProfile;
        iProfile = NULL;
        }
    TBool registered( EFalse );
    
//Leaves with KErrNotFound if default profile is not found
    iProfile = iProfileRegistry-&gt;DefaultProfileL();
 else
        {
        const TDesC8* aor = NULL;
  iProfile-&gt;GetParameter( KSIPUserAor, aor );      
  iProfileRegistry-&gt;EnableL( *iProfile, *this );

    //Check if the profile was immediately set to the registered state
    iProfile-&gt;GetParameter( KSIPProfileRegistered, registered );
        }
</codeblock> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
how to deregister using the profile agent. </p> <codeblock id="GUID-B13F8581-D36B-5AE1-A821-84FD3B010575" xml:space="preserve">if ( iProfile )
        {
        iProfileRegistry-&gt;Disable( *iProfile );
        delete iProfile;
        iProfile = NULL;        
        }</codeblock> <p>The SIP profile API also provides a notification
method that is used by an application to monitor profile related events. </p> <p>The
following code from <filepath>SIPExProfileQueryDlg.cpp</filepath> shows the
profile related events that the sample applications monitors. </p> <codeblock id="GUID-34230A3A-EA20-56B9-AFC0-F9AC92BE2F3E" xml:space="preserve">void ProfileRegistryEventOccurred( 
    TUint32 aProfileId, 
    TEvent aEvent )
    {
    switch (aEvent)
        {
        case MSIPProfileRegistryObserver::EProfileRegistered:
            {
            HandleProfileRegistered( aProfileId );
            break;
            }
        case MSIPProfileRegistryObserver::EProfileDeregistered:
            {
            HandleProfileDeregistered( aProfileId );
            break;
            }
        case MSIPProfileRegistryObserver::EProfileDestroyed:
            {
            HandleProfileDestroyed( aProfileId );
            break;
            }
        default:
            {
            // MSIPProfileRegistryObserver::EProfileCreated and MSIPProfileRegistryObserver::EProfileUpdated are ignored
            break;
            }
        }
    }
void ProfileRegistryErrorOccurred( 
    TUint32 /* aSIPProfileId */,
    TInt aError )
    {
    iObserver-&gt;ProfileError( aError );
    }
</codeblock> <p><b>Classes containing APIs in scope</b> </p> <p> <xref href="GUID-68AE6070-0410-3671-9E68-A7785B8271CD.dita"><apiname>CSIPProfile</apiname></xref>, <xref href="GUID-CDE67614-1A7A-3082-8D8D-71645668A0DE.dita"><apiname>CSIPManagedProfile</apiname></xref>, <xref href="GUID-E8D080AD-4494-3880-B5CE-3487CA7D76E9.dita"><apiname>CSIPProfileRegistry</apiname></xref>, <xref href="GUID-5266AB0D-705C-3011-A92B-DA82BC212999.dita"><apiname>CSIPManagedProfileRegistry</apiname></xref>, <xref href="GUID-91663686-42B7-3C88-B773-3C5343CDCFCE.dita"><apiname>MSIPProfileRegistryObserver</apiname></xref>. </p> </section>
<section id="GUID-7D5CB45C-614B-58DF-8EE4-1AB2DB02CE1C"><title>Inviting a
participant for session setup</title> <p>The sample application uses the SIP
INVITE method to setup a session between two users. In this case, the application
does not accept any SDP parameters from the user and instead sends fixed SDP
values. </p> <p>The following code from <filepath>SIPExSIPIdleState.cpp</filepath> shows
how the application sends an INVITE message. </p> <codeblock id="GUID-B8E774F0-D6C0-5631-83E3-5D87DF03D044" xml:space="preserve">void SendInviteL( 
    CSIPExSIPEngine&amp; aEngine,
    const TDesC8&amp; aSipUri )
    {
    //Retrieve the active profile and connection
    CSIPProfile&amp; prof = aEngine.Profile();
    CSIPConnection&amp; conn = aEngine.ConnectionL();

 //Create CUri8 from the passed descriptor. This value is given by the user
    CUri8* uri8 = aEngine.ConvertToUri8LC( aSipUri );
    
    //Get dialog association, save for future use
    //The ownership of uri8 is transferred
    CSIPInviteDialogAssoc* dialogAssoc =
        CSIPInviteDialogAssoc::NewL( conn, uri8, prof );
        aEngine.SetDialogAssoc( *dialogAssoc ); //Ownership is transferred!!

    //Create the necessary message elements
    CSIPMessageElements* msgElements = aEngine.CreateMessageElementsLC();

    //Send the INVITE in the dialog
    //The ownership of msgElements is transferred
    INVITE SENT OUT
    CSIPClientTransaction* tx = dialogAssoc-&gt;SendInviteL( msgElements );
 }
</codeblock> </section>
<section id="GUID-BADF4C98-FB28-50F1-AC00-F8764CBF2B12"><title>Handling an
incoming invite</title> <p>An application that wants to receive an incoming
invite outside the dialog must implement the Client Resolver API. The <xref href="GUID-14EC2BB8-AE94-3052-8A0B-039BA6E9C610.dita"><apiname>CSipResolvedClient</apiname></xref> (<filepath>SipResolvedClient.h</filepath>) interface is implemented by clients to enable a client resolution mechanism
when the SIP requests are received outside the SIP dialog. The application
must state the capabilities, that is the supported content types and media
formats. This is done using the SIP headers and SDP m-lines either in the
code of the plug-in, that is in <codeph>const KCapabilities</codeph> or in
the opaque_data field of the resource file. </p> <p>The capabilities can be
provided to the plug-ins in two ways: </p> <ul>
<li id="GUID-04021FC9-D7F1-592E-A286-3E3C905880EB"><p>The data is provided
in the ECOM resource file. </p> </li>
<li id="GUID-ABBC862D-2930-5268-9FE9-2D8C7CA6C656"><p>In the interface implementation
from where it is used to determine the target client. </p> </li>
</ul> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
how the data is provided in the ECOM resource file. </p> <codeblock id="GUID-18FE5466-1BA2-57FD-BD3D-5818AFC35767" xml:space="preserve">#include &lt;RegistryInfo.rh&gt;
RESOURCE REGISTRY_INFO theInfo
    {
    // UID for the DLL
    dll_uid = 0xA00001EC;
    // Declare array of interface info
    interfaces = 
        {
        INTERFACE_INFO 
            {
            // UID of interface that is implemented
            interface_uid = 0x102010DD;
            implementations = 
                {
                IMPLEMENTATION_INFO
                    {
                    implementation_uid = 0xA00001EC;
                    version_no = 1;
                    // SIPEx UID: Must match to the one SIPEx passes to CSIP::NewL.    
                    default_data = "A00001EB";
                    }
                };
            }
        };
    }</codeblock> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
how the capabilities are defined in the plug-in. </p> <codeblock id="GUID-5D448F3C-CA4E-5EB2-9416-9383DC08A182" xml:space="preserve">//Code for defining capabilities in plugin
//File : SIPExResolverPlugin.cpp

_LIT8(KCapabilities,
"&lt;SIP_CLIENT ALLOW_STARTING=\"YES\"&gt;\
&lt;SIP_HEADERS&gt;\
&lt;ACCEPT value=\"application/sdp\"/&gt;\
&lt;ACCEPT value=\"SIPEx/InstantMessage\"/&gt;\
&lt;/SIP_HEADERS&gt;\
&lt;SDP_LINES&gt;\
&lt;LINE name=\"m\" value=\"application 0 TCP SIPEx\"/&gt;\
&lt;/SDP_LINES&gt;\
&lt;/SIP_CLIENT&gt;");


</codeblock> <p>When there is an incoming <codeph>Invite Request</codeph> with
SDP parameters the SIP stack passes the request to the Client Resolver to
get the resolved client for that request. The Client Resolver gets the capabilities
for all the applications that implement the Client Resolver API. </p> <p>The
following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows how
to get the capabilities for an application. </p> <codeblock id="GUID-819B95EE-5D9E-5BF6-BE49-1E00C3144CB8" xml:space="preserve">//Code for obtaining capabilities for an application
//File : SIPExResolverPlugin.cpp

const TDesC8&amp; CSIPExResolverPlugin::Capabilities()
    {
    return KCapabilities;
    }</codeblock> <p>When the target client is identified, the Client Resolver
gets the ChannelID from the plug-in implementation and requests the resolved
client to connect to the SIP implementation on that UID. <b>Note</b>: The
ChannelID is same as Application UID3 </p> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
how to get ChannelID for an application. </p> <codeblock id="GUID-3516BAD9-E116-59AA-9424-AEA7FB0DDADA" xml:space="preserve">//Code for obtaining ChannelID for an application
//File : SIPExResolverPlugin.cpp
  
  TUid CSIPExResolverPlugin::ChannelL( RStringF /*aMethod*/,
    const TDesC8&amp; /*aRequestUri*/,
    const RPointerArray&lt;CSIPHeaderBase&gt;&amp; /*aHeaders*/,
    const TDesC8&amp; /*aContent*/,
    const CSIPContentTypeHeader* /*aContentType*/)
    {
    return iApplicationUID;
    }

//Code for asking an application to connect on UID 
//File : SIPExResolverPlugin.cpp

 void CSIPExResolverPlugin::ConnectL( TUid aUid )
    {
    //Launch application is based on UID passed from the SIP stack
    
    TApaAppInfo appInfo;
    User::LeaveIfError( iApaSession.GetAppInfo( appInfo, aUid ) );
    CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
#ifdef EKA2
    cmdLine-&gt;SetExecutableNameL( appInfo.iFullName );
#else
    cmdLine-&gt;SetLibraryNameL( appInfo.iFullName );
#endif
    User::LeaveIfError( iApaSession.StartApp( *cmdLine ) );
    CleanupStack::PopAndDestroy( cmdLine ); 
    }</codeblock> <p>When the resolved client connects, the INVITE is forwarded
to the client and it starts ringing (180 Ringing) and sends the provisional
response to the calling party. This part is implemented in <xref href="GUID-D891F857-2AE0-3112-8A9D-8648F98F96AC.dita"><apiname>InviteReceivedL</apiname></xref> as
shown in the following code. </p> <p>The following code from <filepath>SIPExSIPIdleState.cpp</filepath> shows
how the application gets the INVITE and how the provisional response is sent. </p> <codeblock id="GUID-7775ADCE-4351-5D50-BD91-85C0FEBF47E5" xml:space="preserve">/Code for CSIPExSIPIdleState::InviteReceivedL()... 
//File : SIPExSIPIdleState.cpp    

void CSIPExSIPIdleState::InviteReceivedL( 
    CSIPExSIPEngine&amp; aEngine,
    CSIPServerTransaction* aTransaction )
    {
    _LIT8( KLogEntry, "180 Ringing sent" );
    ..
    ..
    aEngine.Observer()-&gt;WriteLog( KLogEntry );
    ..
   }</codeblock> <p>From this stage, the INVITE is sent to <codeph>InviteReceived</codeph> of <codeph>CSIPExEngine</codeph> in <filepath>SIPExGameEngine.cpp</filepath> from where it asks from the game observer if the user has accepted the invitation
or not. The game starts or does not start depends on action taken. </p> <p>The
following code from <filepath>SIPExStateRegistered.cpp</filepath> shows how
the acceptance is asked from the game observer. </p> <codeblock id="GUID-224959DA-DF2D-5969-85E1-2B71DC32C176" xml:space="preserve">//The acceptance is asked from the user and if accepted the game is reset, start
//listening socket and signal the SIP engine to send Accepted to the remote peer.

//File : SIPExStateRegistered.cpp

void TSIPExStateRegistered::InviteReceived( 
    CSIPExEngine* aContext, 
    const TDesC8&amp; aFrom, 
    const TUint32 aIapId )
    {
    iEnded = EFalse;
    
    TBool retVal( EFalse );
    TRAPD( ignore, retVal = aContext-&gt;AcceptInvitationL( aFrom ) );
    if ( iEnded )
        {
        return;
        }
    if( retVal )
        {
        StatusInfo( aContext, KGameStarting() );
        ChangeState( aContext, aContext-&gt;iStateAcceptingSIP );
        aContext-&gt;ResetGame();
        aContext-&gt;SetPeer( CSIPExEngine::EServer );
        Info( aContext, KListening() );
        TInetAddr addr;
        TRAP( ignore, addr = 
                        aContext-&gt;SocketEngineL()-&gt;StartListeningL( aIapId ) );
        Info( aContext, KAccepting() );
        TRAP( ignore, aContext-&gt;SIPEngine()-&gt;AcceptInviteL( addr ) );
        Info( aContext, KWaitingRemoteConn() );
        }
    else 
        {
        TRAP( ignore, aContext-&gt;SIPEngine()-&gt;DeclineInviteL() );
        Info( aContext, KInviteDeclined() );
        }
    }
</codeblock> <p>When the game observer accepts the invitation the following
code from <filepath>SIPExGameEngine.cpp</filepath> is run. </p> <codeblock id="GUID-91EF56AD-266F-5EE8-B8C0-37C1A6529C48" xml:space="preserve">//File : SIPExGameEngine.cpp

TBool CSIPExEngine::AcceptInvitationL( const TDesC8&amp; aFrom )
    {
    HBufC* from = HBufC::NewLC( aFrom.Length() );
    from-&gt;Des().Copy( aFrom );
    TBool retVal = iGameObserver.AcceptInvitationL( *from );
    CleanupStack::PopAndDestroy( from );
    return retVal;
    }</codeblock> </section>
<section id="GUID-0E7C6F87-C90B-5888-B1F7-33ED0D7393F5"><title>Sending an
instant message</title> <p>This sample application allows a user to send an
Instant Message (IM) to another user. The user requires SIP URI of the other
user and the message content that the user must enter. The application then
creates a MESSAGE (request message) with these parameters and uses <xref href="GUID-D8168DEA-50CC-342B-AEF1-4703B50794A6.dita"><apiname>SendRequestL()</apiname></xref> to
send it. </p> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
how to send an instant message. </p> <codeblock id="GUID-641C6039-11B4-5389-8876-D817D5541CCE" xml:space="preserve">//Create and send an instant message to a recipient defined with the parameters.
//This is implemented with the MESSAGE method and is sent outside of a dialog.

CreateIML(const TDesC8&amp; aMessage,
    const TDesC8&amp; aSipUri )
    {
    _LIT8( KMediaType, "SIPEx" );    // Part of content type
    _LIT8( KMediaSubType, "InstantMessage" );    // Part of content type

//Create the necessary elements of the IM
    
CSIPRequestElements* reqElem = CreateReqElementsLC( aSipUri );
    CSIPToHeader* toHeader = CreateToHeaderLC( aSipUri );
    reqElem-&gt;SetToHeaderL( toHeader );
    
//Create the fromHeader value using the information from the profile

 const TDesC8* aor = NULL;
 iProfile-&gt;GetParameter( KSIPUserAor, aor ); 
 CSIPAddress* addr = CSIPAddress::DecodeL( *aor );
 CSIPFromHeader* fromHeader = CSIPFromHeader::NewL( addr );
 reqElem-&gt;SetFromHeaderL( fromHeader );
 reqElem-&gt;SetMethodL( SIPStrings::StringF( SipStrConsts::EMessage ) );

//Get reference to the message elements from the request elements, create and insert content type header (ownership of the content type object is transferred)

    CSIPMessageElements&amp; msgElem = reqElem-&gt;MessageElements();
    CSIPContentTypeHeader* ct =    CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
    msgElem.SetContentL( aMessage.AllocL(), ct );
    
//Get the current connection

CSIPConnection&amp; conn = ConnectionL();

//Send the request using the connection (ownership of the request elements object is transferred)

    CSIPClientTransaction* ctx = conn.SendRequestL( reqElem );
    delete ctx;
    }

</codeblock> <p><b>Classes containing APIs in scope</b> </p> <p> <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref>, <xref href="GUID-7B5D0432-5C2C-3EFB-B9FA-8B4A0AA68FC0.dita"><apiname>CSIPToHeader</apiname></xref>, <xref href="GUID-AFEC85BE-5971-3043-B9A9-24048346AADE.dita"><apiname>CSIPFromHeader</apiname></xref>, <xref href="GUID-F8BF1190-F5D4-31EF-B060-A1430AA07DAC.dita"><apiname>CSIPAddress</apiname></xref>, <xref href="GUID-77CFD812-7238-3B84-80FF-475BD73C3506.dita"><apiname>CSIPMessageElements</apiname></xref>, <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref>. </p> </section>
</conbody></concept>