Symbian3/SDK/Source/GUID-CF17532E-5E90-5124-8F05-AA72B848F17F.dita
changeset 7 51a74ef9ed63
child 8 ae94777fff8f
equal deleted inserted replaced
6:43e37759235e 7:51a74ef9ed63
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-CF17532E-5E90-5124-8F05-AA72B848F17F" xml:lang="en"><title>SIP
       
    13 Example: Usage of the SIP Stack</title><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>The SIP sample application is a game that can be played between two users
       
    15 that use two different machines. The following figure illustrates the sample
       
    16 application. </p>
       
    17 <fig id="GUID-A0E243BE-E697-5856-8C08-6039AAE6A05A">
       
    18 <image href="GUID-155C5B39-CB9B-5405-B9BB-EB34CA7C43BC_d0e344859_href.png" placement="inline"/>
       
    19 </fig>
       
    20 <p>All users who want to play the game must register to the server with their
       
    21 identities. This informs the server that the user is active and prepared to
       
    22 participate in the game. If User 1 wants to play the game with User 2 then
       
    23 it must send a request to User 2 through the server. When User 2 accepts the
       
    24 request and acknowledges it then the two users can start playing. A user can
       
    25 disconnect from playing the game by sending a message. If a user wants to
       
    26 be deactivated then it can deregister from the server. </p>
       
    27 <p>This application is developed using the key features of the Symbian SIP
       
    28 stack. It shows how to create profiles and do SIP registration using the profiles,
       
    29 how to set up a SIP session and send an instant message using the SIP. For
       
    30 example you can set up the SIP server using Brekeke and you can download the
       
    31 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>
       
    32 <section><title>Features of the game</title> <p>The main features of the game
       
    33 are: </p> <ul>
       
    34 <li id="GUID-8767E5EC-04F6-5D19-B77A-94C6E7BF10B7"><p> <b>Register or deregister </b> -
       
    35 A user registers to the server with a unique identity before playing the game.
       
    36 This identity is the SIP URI of the user. The user registers by sending a
       
    37 SIP REGISTER message to the SIP server and is active. A user deactivates by
       
    38 deregistering to the server. This activity is done by sending the SIP REGISTER
       
    39 message with the expires header set to 0. For more information on registering
       
    40 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
       
    41 or deregistering an user</xref>. </p> </li>
       
    42 <li id="GUID-1547D0C9-4B7C-568F-9C5D-A2BE20F9B362"><p> <b>Invite another user</b> -
       
    43 A user invites another user to play the game by entering the SIP URI of the
       
    44 other user in the INVITE message. For more information on inviting another
       
    45 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
       
    46 a participant for session setup</xref>. </p> </li>
       
    47 <li id="GUID-94802B8B-C10B-5ADB-A5E0-0FC436790427"><p> <b>Send a message to
       
    48 another user</b> - A user can send an instant message to another user. For
       
    49 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
       
    50 an instant message</xref>. </p> </li>
       
    51 <li id="GUID-55484DA7-37DC-566B-95F8-066E19AA5790"><p> <b>Disconnect from
       
    52 playing the game</b> - A user can disconnect from playing the game by sending
       
    53 a SIP BYE message to the other user. </p> </li>
       
    54 </ul> </section>
       
    55 <section id="GUID-3A9BE5C5-A9A2-54A8-B525-6750E562EF97"><title>How to play
       
    56 the game</title> <p>The following snapshot shows the different tabs available
       
    57 in the game. </p> <fig id="GUID-15C8B95B-4B8C-5701-80B1-C0D7B39AF422">
       
    58 <image href="GUID-0E21EAE4-BF71-55FD-9561-EA5530696627_d0e344932_href.png" placement="inline"/>
       
    59 </fig> <p>The following list describes the different tabs available in the
       
    60 game: </p> <ul>
       
    61 <li id="GUID-CDB3E759-F01D-5D02-B8AA-7E901C1984BE"><p> <b>Invite for game</b> -
       
    62 This tab allows you to invite a user to play the game. When you invoke this
       
    63 tab, a UI screen appears which asks the user to provide the SIP URI of the
       
    64 second user with whom the user wants to play the game. The SIP URI of the
       
    65 second user is then sent to the SIP stack which passes on the invite request
       
    66 to the second user. The second user can accept or reject the invite. If the
       
    67 second user accepts the invite then it acknowledges by sending a message that
       
    68 it is prepared to start playing the game. If the second user rejects the invite
       
    69 then it cannot play the game. </p> </li>
       
    70 <li id="GUID-4A4F6318-1FDD-540A-BF87-72B19BE56A97"><p> <b>Enable profile</b> -
       
    71 This tab allows you to enable a profile. When you invoke this tab, a UI screen
       
    72 appears where the user enters the values. A profile is created using these
       
    73 values and the user registers with the SIP server. </p> </li>
       
    74 <li id="GUID-A9F95A0B-4E44-52C6-AD0B-E2BDFA4C8CCE"><p> <b>Send instant msg</b> -
       
    75 This tab allows you to send a message to another user. When you invoke this
       
    76 tab, a message with the address of the recipient is sent to the SIP stack.
       
    77 The SIP stack sends this message to the recipient address. </p> </li>
       
    78 <li id="GUID-4334DC63-8AAB-581C-A779-FBBBD44C4227"><p> <b>End game</b> - This
       
    79 tab allows you to disconnect from playing the game. When you invoke this tab,
       
    80 a BYE message is sent to the other user and the game is terminated. </p> </li>
       
    81 </ul> </section>
       
    82 <section id="GUID-2C4A1BCE-CD8E-5BDC-84D1-2C5DDBF8A142"><title>Registering
       
    83 or deregistering an user</title> <p>An application can register to the SIP
       
    84 Server using: </p> <ul>
       
    85 <li id="GUID-620D3765-E3A1-55B9-900F-562486A01D6B"><p>the <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> class
       
    86 and its methods </p> </li>
       
    87 <li id="GUID-DDC990A1-BFDC-5CA4-A392-EAADFB8C3921"><p>the SIP Profile Agent </p> </li>
       
    88 </ul> <p>This sample application uses the SIP Profile Agent method to do SIP
       
    89 registration. To use this method you need a SIP profile setting, and you must
       
    90 create a SIP profile before you start using the application. <b>Note</b>:
       
    91 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
       
    92 SIP profile agent method provides APIs for: </p> <ul>
       
    93 <li id="GUID-68A120EA-45B6-5909-8DD1-B125A1249C13"><p>Registering and Deregistering </p> </li>
       
    94 <li id="GUID-50AA5E67-EA40-5844-873B-77DAAE94480F"><p>Listening to registration
       
    95 events </p> </li>
       
    96 <li id="GUID-300245B5-2B62-5382-B492-8BE8759E48E3"><p>Creating, modifying,
       
    97 and deleting the SIP profile settings that the profile agent plug-in implementations
       
    98 use for SIP registration. </p> </li>
       
    99 </ul> <p>The following code from <filepath>SIPExProfileQueryDlg.cpp</filepath> shows
       
   100 how the sample application stores the settings entered by users on the SIP
       
   101 profile store. </p> <codeblock id="GUID-8D76FE52-F0E5-5F57-AD38-0AE8694D3AA4" xml:space="preserve">//Create a new profile
       
   102     CSIPManagedProfile* profile = iMProfileRegistry-&gt;CreateL(iProfileData.iServiceProfile);
       
   103    
       
   104 //Copy attributes entered by the user to the new profile        
       
   105     iNewProfile = profile;
       
   106     profile = CopyDataToProfileL();
       
   107 
       
   108 //Set the profile to default and save some settings
       
   109     TInt err= profile-&gt;SetParameter(KSIPDefaultProfile,ETrue);
       
   110    
       
   111 //Save the profile to persistent store                
       
   112     iMProfileRegistry-&gt;SaveL( *profile );
       
   113 </codeblock> <p>The applications can start SIP registration or deregistration
       
   114 using the <codeph>Enable</codeph> or <codeph>Disable</codeph> methods from
       
   115 the SIP profile API. </p> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
       
   116 how to register using the profile agent. </p> <codeblock id="GUID-F4398335-6AC0-5E10-B04D-6846A3CDE1D5" xml:space="preserve">//Check for the existing profile
       
   117     if ( iProfile )
       
   118         {
       
   119         delete iProfile;
       
   120         iProfile = NULL;
       
   121         }
       
   122     TBool registered( EFalse );
       
   123     
       
   124 //Leaves with KErrNotFound if default profile is not found
       
   125     iProfile = iProfileRegistry-&gt;DefaultProfileL();
       
   126  else
       
   127         {
       
   128         const TDesC8* aor = NULL;
       
   129   iProfile-&gt;GetParameter( KSIPUserAor, aor );      
       
   130   iProfileRegistry-&gt;EnableL( *iProfile, *this );
       
   131 
       
   132     //Check if the profile was immediately set to the registered state
       
   133     iProfile-&gt;GetParameter( KSIPProfileRegistered, registered );
       
   134         }
       
   135 </codeblock> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
       
   136 how to deregister using the profile agent. </p> <codeblock id="GUID-B13F8581-D36B-5AE1-A821-84FD3B010575" xml:space="preserve">if ( iProfile )
       
   137         {
       
   138         iProfileRegistry-&gt;Disable( *iProfile );
       
   139         delete iProfile;
       
   140         iProfile = NULL;        
       
   141         }</codeblock> <p>The SIP profile API also provides a notification
       
   142 method that is used by an application to monitor profile related events. </p> <p>The
       
   143 following code from <filepath>SIPExProfileQueryDlg.cpp</filepath> shows the
       
   144 profile related events that the sample applications monitors. </p> <codeblock id="GUID-34230A3A-EA20-56B9-AFC0-F9AC92BE2F3E" xml:space="preserve">void ProfileRegistryEventOccurred( 
       
   145     TUint32 aProfileId, 
       
   146     TEvent aEvent )
       
   147     {
       
   148     switch (aEvent)
       
   149         {
       
   150         case MSIPProfileRegistryObserver::EProfileRegistered:
       
   151             {
       
   152             HandleProfileRegistered( aProfileId );
       
   153             break;
       
   154             }
       
   155         case MSIPProfileRegistryObserver::EProfileDeregistered:
       
   156             {
       
   157             HandleProfileDeregistered( aProfileId );
       
   158             break;
       
   159             }
       
   160         case MSIPProfileRegistryObserver::EProfileDestroyed:
       
   161             {
       
   162             HandleProfileDestroyed( aProfileId );
       
   163             break;
       
   164             }
       
   165         default:
       
   166             {
       
   167             // MSIPProfileRegistryObserver::EProfileCreated and MSIPProfileRegistryObserver::EProfileUpdated are ignored
       
   168             break;
       
   169             }
       
   170         }
       
   171     }
       
   172 void ProfileRegistryErrorOccurred( 
       
   173     TUint32 /* aSIPProfileId */,
       
   174     TInt aError )
       
   175     {
       
   176     iObserver-&gt;ProfileError( aError );
       
   177     }
       
   178 </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>
       
   179 <section id="GUID-7D5CB45C-614B-58DF-8EE4-1AB2DB02CE1C"><title>Inviting a
       
   180 participant for session setup</title> <p>The sample application uses the SIP
       
   181 INVITE method to setup a session between two users. In this case, the application
       
   182 does not accept any SDP parameters from the user and instead sends fixed SDP
       
   183 values. </p> <p>The following code from <filepath>SIPExSIPIdleState.cpp</filepath> shows
       
   184 how the application sends an INVITE message. </p> <codeblock id="GUID-B8E774F0-D6C0-5631-83E3-5D87DF03D044" xml:space="preserve">void SendInviteL( 
       
   185     CSIPExSIPEngine&amp; aEngine,
       
   186     const TDesC8&amp; aSipUri )
       
   187     {
       
   188     //Retrieve the active profile and connection
       
   189     CSIPProfile&amp; prof = aEngine.Profile();
       
   190     CSIPConnection&amp; conn = aEngine.ConnectionL();
       
   191 
       
   192  //Create CUri8 from the passed descriptor. This value is given by the user
       
   193     CUri8* uri8 = aEngine.ConvertToUri8LC( aSipUri );
       
   194     
       
   195     //Get dialog association, save for future use
       
   196     //The ownership of uri8 is transferred
       
   197     CSIPInviteDialogAssoc* dialogAssoc =
       
   198         CSIPInviteDialogAssoc::NewL( conn, uri8, prof );
       
   199         aEngine.SetDialogAssoc( *dialogAssoc ); //Ownership is transferred!!
       
   200 
       
   201     //Create the necessary message elements
       
   202     CSIPMessageElements* msgElements = aEngine.CreateMessageElementsLC();
       
   203 
       
   204     //Send the INVITE in the dialog
       
   205     //The ownership of msgElements is transferred
       
   206     INVITE SENT OUT
       
   207     CSIPClientTransaction* tx = dialogAssoc-&gt;SendInviteL( msgElements );
       
   208  }
       
   209 </codeblock> </section>
       
   210 <section id="GUID-BADF4C98-FB28-50F1-AC00-F8764CBF2B12"><title>Handling an
       
   211 incoming invite</title> <p>An application that wants to receive an incoming
       
   212 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
       
   213 when the SIP requests are received outside the SIP dialog. The application
       
   214 must state the capabilities, that is the supported content types and media
       
   215 formats. This is done using the SIP headers and SDP m-lines either in the
       
   216 code of the plug-in, that is in <codeph>const KCapabilities</codeph> or in
       
   217 the opaque_data field of the resource file. </p> <p>The capabilities can be
       
   218 provided to the plug-ins in two ways: </p> <ul>
       
   219 <li id="GUID-04021FC9-D7F1-592E-A286-3E3C905880EB"><p>The data is provided
       
   220 in the ECOM resource file. </p> </li>
       
   221 <li id="GUID-ABBC862D-2930-5268-9FE9-2D8C7CA6C656"><p>In the interface implementation
       
   222 from where it is used to determine the target client. </p> </li>
       
   223 </ul> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
       
   224 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;
       
   225 RESOURCE REGISTRY_INFO theInfo
       
   226     {
       
   227     // UID for the DLL
       
   228     dll_uid = 0xA00001EC;
       
   229     // Declare array of interface info
       
   230     interfaces = 
       
   231         {
       
   232         INTERFACE_INFO 
       
   233             {
       
   234             // UID of interface that is implemented
       
   235             interface_uid = 0x102010DD;
       
   236             implementations = 
       
   237                 {
       
   238                 IMPLEMENTATION_INFO
       
   239                     {
       
   240                     implementation_uid = 0xA00001EC;
       
   241                     version_no = 1;
       
   242                     // SIPEx UID: Must match to the one SIPEx passes to CSIP::NewL.    
       
   243                     default_data = "A00001EB";
       
   244                     }
       
   245                 };
       
   246             }
       
   247         };
       
   248     }</codeblock> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
       
   249 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
       
   250 //File : SIPExResolverPlugin.cpp
       
   251 
       
   252 _LIT8(KCapabilities,
       
   253 "&lt;SIP_CLIENT ALLOW_STARTING=\"YES\"&gt;\
       
   254 &lt;SIP_HEADERS&gt;\
       
   255 &lt;ACCEPT value=\"application/sdp\"/&gt;\
       
   256 &lt;ACCEPT value=\"SIPEx/InstantMessage\"/&gt;\
       
   257 &lt;/SIP_HEADERS&gt;\
       
   258 &lt;SDP_LINES&gt;\
       
   259 &lt;LINE name=\"m\" value=\"application 0 TCP SIPEx\"/&gt;\
       
   260 &lt;/SDP_LINES&gt;\
       
   261 &lt;/SIP_CLIENT&gt;");
       
   262 
       
   263 
       
   264 </codeblock> <p>When there is an incoming <codeph>Invite Request</codeph> with
       
   265 SDP parameters the SIP stack passes the request to the Client Resolver to
       
   266 get the resolved client for that request. The Client Resolver gets the capabilities
       
   267 for all the applications that implement the Client Resolver API. </p> <p>The
       
   268 following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows how
       
   269 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
       
   270 //File : SIPExResolverPlugin.cpp
       
   271 
       
   272 const TDesC8&amp; CSIPExResolverPlugin::Capabilities()
       
   273     {
       
   274     return KCapabilities;
       
   275     }</codeblock> <p>When the target client is identified, the Client Resolver
       
   276 gets the ChannelID from the plug-in implementation and requests the resolved
       
   277 client to connect to the SIP implementation on that UID. <b>Note</b>: The
       
   278 ChannelID is same as Application UID3 </p> <p>The following code from <filepath>SIPExResolverPlugin.cpp</filepath> shows
       
   279 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
       
   280 //File : SIPExResolverPlugin.cpp
       
   281   
       
   282   TUid CSIPExResolverPlugin::ChannelL( RStringF /*aMethod*/,
       
   283     const TDesC8&amp; /*aRequestUri*/,
       
   284     const RPointerArray&lt;CSIPHeaderBase&gt;&amp; /*aHeaders*/,
       
   285     const TDesC8&amp; /*aContent*/,
       
   286     const CSIPContentTypeHeader* /*aContentType*/)
       
   287     {
       
   288     return iApplicationUID;
       
   289     }
       
   290 
       
   291 //Code for asking an application to connect on UID 
       
   292 //File : SIPExResolverPlugin.cpp
       
   293 
       
   294  void CSIPExResolverPlugin::ConnectL( TUid aUid )
       
   295     {
       
   296     //Launch application is based on UID passed from the SIP stack
       
   297     
       
   298     TApaAppInfo appInfo;
       
   299     User::LeaveIfError( iApaSession.GetAppInfo( appInfo, aUid ) );
       
   300     CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
   301 #ifdef EKA2
       
   302     cmdLine-&gt;SetExecutableNameL( appInfo.iFullName );
       
   303 #else
       
   304     cmdLine-&gt;SetLibraryNameL( appInfo.iFullName );
       
   305 #endif
       
   306     User::LeaveIfError( iApaSession.StartApp( *cmdLine ) );
       
   307     CleanupStack::PopAndDestroy( cmdLine ); 
       
   308     }</codeblock> <p>When the resolved client connects, the INVITE is forwarded
       
   309 to the client and it starts ringing (180 Ringing) and sends the provisional
       
   310 response to the calling party. This part is implemented in <xref href="GUID-D891F857-2AE0-3112-8A9D-8648F98F96AC.dita"><apiname>InviteReceivedL</apiname></xref> as
       
   311 shown in the following code. </p> <p>The following code from <filepath>SIPExSIPIdleState.cpp</filepath> shows
       
   312 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()... 
       
   313 //File : SIPExSIPIdleState.cpp    
       
   314 
       
   315 void CSIPExSIPIdleState::InviteReceivedL( 
       
   316     CSIPExSIPEngine&amp; aEngine,
       
   317     CSIPServerTransaction* aTransaction )
       
   318     {
       
   319     _LIT8( KLogEntry, "180 Ringing sent" );
       
   320     ..
       
   321     ..
       
   322     aEngine.Observer()-&gt;WriteLog( KLogEntry );
       
   323     ..
       
   324    }</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
       
   325 or not. The game starts or does not start depends on action taken. </p> <p>The
       
   326 following code from <filepath>SIPExStateRegistered.cpp</filepath> shows how
       
   327 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
       
   328 //listening socket and signal the SIP engine to send Accepted to the remote peer.
       
   329 
       
   330 //File : SIPExStateRegistered.cpp
       
   331 
       
   332 void TSIPExStateRegistered::InviteReceived( 
       
   333     CSIPExEngine* aContext, 
       
   334     const TDesC8&amp; aFrom, 
       
   335     const TUint32 aIapId )
       
   336     {
       
   337     iEnded = EFalse;
       
   338     
       
   339     TBool retVal( EFalse );
       
   340     TRAPD( ignore, retVal = aContext-&gt;AcceptInvitationL( aFrom ) );
       
   341     if ( iEnded )
       
   342         {
       
   343         return;
       
   344         }
       
   345     if( retVal )
       
   346         {
       
   347         StatusInfo( aContext, KGameStarting() );
       
   348         ChangeState( aContext, aContext-&gt;iStateAcceptingSIP );
       
   349         aContext-&gt;ResetGame();
       
   350         aContext-&gt;SetPeer( CSIPExEngine::EServer );
       
   351         Info( aContext, KListening() );
       
   352         TInetAddr addr;
       
   353         TRAP( ignore, addr = 
       
   354                         aContext-&gt;SocketEngineL()-&gt;StartListeningL( aIapId ) );
       
   355         Info( aContext, KAccepting() );
       
   356         TRAP( ignore, aContext-&gt;SIPEngine()-&gt;AcceptInviteL( addr ) );
       
   357         Info( aContext, KWaitingRemoteConn() );
       
   358         }
       
   359     else 
       
   360         {
       
   361         TRAP( ignore, aContext-&gt;SIPEngine()-&gt;DeclineInviteL() );
       
   362         Info( aContext, KInviteDeclined() );
       
   363         }
       
   364     }
       
   365 </codeblock> <p>When the game observer accepts the invitation the following
       
   366 code from <filepath>SIPExGameEngine.cpp</filepath> is run. </p> <codeblock id="GUID-91EF56AD-266F-5EE8-B8C0-37C1A6529C48" xml:space="preserve">//File : SIPExGameEngine.cpp
       
   367 
       
   368 TBool CSIPExEngine::AcceptInvitationL( const TDesC8&amp; aFrom )
       
   369     {
       
   370     HBufC* from = HBufC::NewLC( aFrom.Length() );
       
   371     from-&gt;Des().Copy( aFrom );
       
   372     TBool retVal = iGameObserver.AcceptInvitationL( *from );
       
   373     CleanupStack::PopAndDestroy( from );
       
   374     return retVal;
       
   375     }</codeblock> </section>
       
   376 <section id="GUID-0E7C6F87-C90B-5888-B1F7-33ED0D7393F5"><title>Sending an
       
   377 instant message</title> <p>This sample application allows a user to send an
       
   378 Instant Message (IM) to another user. The user requires SIP URI of the other
       
   379 user and the message content that the user must enter. The application then
       
   380 creates a MESSAGE (request message) with these parameters and uses <xref href="GUID-D8168DEA-50CC-342B-AEF1-4703B50794A6.dita"><apiname>SendRequestL()</apiname></xref> to
       
   381 send it. </p> <p>The following code from <filepath>SIPExSIPEngine.cpp</filepath> shows
       
   382 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.
       
   383 //This is implemented with the MESSAGE method and is sent outside of a dialog.
       
   384 
       
   385 CreateIML(const TDesC8&amp; aMessage,
       
   386     const TDesC8&amp; aSipUri )
       
   387     {
       
   388     _LIT8( KMediaType, "SIPEx" );    // Part of content type
       
   389     _LIT8( KMediaSubType, "InstantMessage" );    // Part of content type
       
   390 
       
   391 //Create the necessary elements of the IM
       
   392     
       
   393 CSIPRequestElements* reqElem = CreateReqElementsLC( aSipUri );
       
   394     CSIPToHeader* toHeader = CreateToHeaderLC( aSipUri );
       
   395     reqElem-&gt;SetToHeaderL( toHeader );
       
   396     
       
   397 //Create the fromHeader value using the information from the profile
       
   398 
       
   399  const TDesC8* aor = NULL;
       
   400  iProfile-&gt;GetParameter( KSIPUserAor, aor ); 
       
   401  CSIPAddress* addr = CSIPAddress::DecodeL( *aor );
       
   402  CSIPFromHeader* fromHeader = CSIPFromHeader::NewL( addr );
       
   403  reqElem-&gt;SetFromHeaderL( fromHeader );
       
   404  reqElem-&gt;SetMethodL( SIPStrings::StringF( SipStrConsts::EMessage ) );
       
   405 
       
   406 //Get reference to the message elements from the request elements, create and insert content type header (ownership of the content type object is transferred)
       
   407 
       
   408     CSIPMessageElements&amp; msgElem = reqElem-&gt;MessageElements();
       
   409     CSIPContentTypeHeader* ct =    CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType );
       
   410     msgElem.SetContentL( aMessage.AllocL(), ct );
       
   411     
       
   412 //Get the current connection
       
   413 
       
   414 CSIPConnection&amp; conn = ConnectionL();
       
   415 
       
   416 //Send the request using the connection (ownership of the request elements object is transferred)
       
   417 
       
   418     CSIPClientTransaction* ctx = conn.SendRequestL( reqElem );
       
   419     delete ctx;
       
   420     }
       
   421 
       
   422 </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>
       
   423 </conbody></concept>