--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/PDK/Source/GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita Fri Jan 22 18:26:19 2010 +0000
@@ -0,0 +1,423 @@
+<?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_d0e545888_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_d0e545961_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->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->SetParameter(KSIPDefaultProfile,ETrue);
+
+//Save the profile to persistent store
+ iMProfileRegistry->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->DefaultProfileL();
+ else
+ {
+ const TDesC8* aor = NULL;
+ iProfile->GetParameter( KSIPUserAor, aor );
+ iProfileRegistry->EnableL( *iProfile, *this );
+
+ //Check if the profile was immediately set to the registered state
+ iProfile->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->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->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& aEngine,
+ const TDesC8& aSipUri )
+ {
+ //Retrieve the active profile and connection
+ CSIPProfile& prof = aEngine.Profile();
+ CSIPConnection& 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->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 <RegistryInfo.rh>
+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,
+"<SIP_CLIENT ALLOW_STARTING=\"YES\">\
+<SIP_HEADERS>\
+<ACCEPT value=\"application/sdp\"/>\
+<ACCEPT value=\"SIPEx/InstantMessage\"/>\
+</SIP_HEADERS>\
+<SDP_LINES>\
+<LINE name=\"m\" value=\"application 0 TCP SIPEx\"/>\
+</SDP_LINES>\
+</SIP_CLIENT>");
+
+
+</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& 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& /*aRequestUri*/,
+ const RPointerArray<CSIPHeaderBase>& /*aHeaders*/,
+ const TDesC8& /*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->SetExecutableNameL( appInfo.iFullName );
+#else
+ cmdLine->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& aEngine,
+ CSIPServerTransaction* aTransaction )
+ {
+ _LIT8( KLogEntry, "180 Ringing sent" );
+ ..
+ ..
+ aEngine.Observer()->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& aFrom,
+ const TUint32 aIapId )
+ {
+ iEnded = EFalse;
+
+ TBool retVal( EFalse );
+ TRAPD( ignore, retVal = aContext->AcceptInvitationL( aFrom ) );
+ if ( iEnded )
+ {
+ return;
+ }
+ if( retVal )
+ {
+ StatusInfo( aContext, KGameStarting() );
+ ChangeState( aContext, aContext->iStateAcceptingSIP );
+ aContext->ResetGame();
+ aContext->SetPeer( CSIPExEngine::EServer );
+ Info( aContext, KListening() );
+ TInetAddr addr;
+ TRAP( ignore, addr =
+ aContext->SocketEngineL()->StartListeningL( aIapId ) );
+ Info( aContext, KAccepting() );
+ TRAP( ignore, aContext->SIPEngine()->AcceptInviteL( addr ) );
+ Info( aContext, KWaitingRemoteConn() );
+ }
+ else
+ {
+ TRAP( ignore, aContext->SIPEngine()->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& aFrom )
+ {
+ HBufC* from = HBufC::NewLC( aFrom.Length() );
+ from->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& aMessage,
+ const TDesC8& 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->SetToHeaderL( toHeader );
+
+//Create the fromHeader value using the information from the profile
+
+ const TDesC8* aor = NULL;
+ iProfile->GetParameter( KSIPUserAor, aor );
+ CSIPAddress* addr = CSIPAddress::DecodeL( *aor );
+ CSIPFromHeader* fromHeader = CSIPFromHeader::NewL( addr );
+ reqElem->SetFromHeaderL( fromHeader );
+ reqElem->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& msgElem = reqElem->MessageElements();
+ CSIPContentTypeHeader* ct = CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
+ msgElem.SetContentL( aMessage.AllocL(), ct );
+
+//Get the current connection
+
+CSIPConnection& 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>
\ No newline at end of file