|
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_d0e319026_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_d0e319099_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->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->SetParameter(KSIPDefaultProfile,ETrue); |
|
110 |
|
111 //Save the profile to persistent store |
|
112 iMProfileRegistry->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->DefaultProfileL(); |
|
126 else |
|
127 { |
|
128 const TDesC8* aor = NULL; |
|
129 iProfile->GetParameter( KSIPUserAor, aor ); |
|
130 iProfileRegistry->EnableL( *iProfile, *this ); |
|
131 |
|
132 //Check if the profile was immediately set to the registered state |
|
133 iProfile->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->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->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& aEngine, |
|
186 const TDesC8& aSipUri ) |
|
187 { |
|
188 //Retrieve the active profile and connection |
|
189 CSIPProfile& prof = aEngine.Profile(); |
|
190 CSIPConnection& 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->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 <RegistryInfo.rh> |
|
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 "<SIP_CLIENT ALLOW_STARTING=\"YES\">\ |
|
254 <SIP_HEADERS>\ |
|
255 <ACCEPT value=\"application/sdp\"/>\ |
|
256 <ACCEPT value=\"SIPEx/InstantMessage\"/>\ |
|
257 </SIP_HEADERS>\ |
|
258 <SDP_LINES>\ |
|
259 <LINE name=\"m\" value=\"application 0 TCP SIPEx\"/>\ |
|
260 </SDP_LINES>\ |
|
261 </SIP_CLIENT>"); |
|
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& 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& /*aRequestUri*/, |
|
284 const RPointerArray<CSIPHeaderBase>& /*aHeaders*/, |
|
285 const TDesC8& /*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->SetExecutableNameL( appInfo.iFullName ); |
|
303 #else |
|
304 cmdLine->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& aEngine, |
|
317 CSIPServerTransaction* aTransaction ) |
|
318 { |
|
319 _LIT8( KLogEntry, "180 Ringing sent" ); |
|
320 .. |
|
321 .. |
|
322 aEngine.Observer()->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& aFrom, |
|
335 const TUint32 aIapId ) |
|
336 { |
|
337 iEnded = EFalse; |
|
338 |
|
339 TBool retVal( EFalse ); |
|
340 TRAPD( ignore, retVal = aContext->AcceptInvitationL( aFrom ) ); |
|
341 if ( iEnded ) |
|
342 { |
|
343 return; |
|
344 } |
|
345 if( retVal ) |
|
346 { |
|
347 StatusInfo( aContext, KGameStarting() ); |
|
348 ChangeState( aContext, aContext->iStateAcceptingSIP ); |
|
349 aContext->ResetGame(); |
|
350 aContext->SetPeer( CSIPExEngine::EServer ); |
|
351 Info( aContext, KListening() ); |
|
352 TInetAddr addr; |
|
353 TRAP( ignore, addr = |
|
354 aContext->SocketEngineL()->StartListeningL( aIapId ) ); |
|
355 Info( aContext, KAccepting() ); |
|
356 TRAP( ignore, aContext->SIPEngine()->AcceptInviteL( addr ) ); |
|
357 Info( aContext, KWaitingRemoteConn() ); |
|
358 } |
|
359 else |
|
360 { |
|
361 TRAP( ignore, aContext->SIPEngine()->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& aFrom ) |
|
369 { |
|
370 HBufC* from = HBufC::NewLC( aFrom.Length() ); |
|
371 from->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& aMessage, |
|
386 const TDesC8& 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->SetToHeaderL( toHeader ); |
|
396 |
|
397 //Create the fromHeader value using the information from the profile |
|
398 |
|
399 const TDesC8* aor = NULL; |
|
400 iProfile->GetParameter( KSIPUserAor, aor ); |
|
401 CSIPAddress* addr = CSIPAddress::DecodeL( *aor ); |
|
402 CSIPFromHeader* fromHeader = CSIPFromHeader::NewL( addr ); |
|
403 reqElem->SetFromHeaderL( fromHeader ); |
|
404 reqElem->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& msgElem = reqElem->MessageElements(); |
|
409 CSIPContentTypeHeader* ct = CSIPContentTypeHeader::NewLC( KMediaType, KMediaSubType ); |
|
410 msgElem.SetContentL( aMessage.AllocL(), ct ); |
|
411 |
|
412 //Get the current connection |
|
413 |
|
414 CSIPConnection& 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> |