--- a/Symbian3/PDK/Source/GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita Fri Jun 11 12:39:03 2010 +0100
+++ b/Symbian3/PDK/Source/GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita Fri Jun 11 15:24:34 2010 +0100
@@ -1,423 +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_d0e566412_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_d0e566485_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>
+<?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_d0e553988_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_d0e554061_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