|
1 /* |
|
2 * Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Sent SWIS capability query (OPTIONS) |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "musavacapabilityquery.h" |
|
20 #include "muslogger.h" |
|
21 #include "mussettings.h" |
|
22 #include "mussettingskeys.h" |
|
23 #include "musavacapability.h" |
|
24 #include "musavacapabilitycontext.h" |
|
25 #include "mussesseioninformationapi.h" |
|
26 #include "musavacapabilityexchange.h" |
|
27 #include "mmusavacapabilityqueryobserver.h" |
|
28 |
|
29 #include <sipconnection.h> |
|
30 #include <sipclienttransaction.h> |
|
31 #include <sipmessageelements.h> |
|
32 #include <sipresponseelements.h> |
|
33 #include <sdpdocument.h> |
|
34 #include <sipcontenttypeheader.h> |
|
35 #include <sdpattributefield.h> |
|
36 #include <sipcontactheader.h> |
|
37 #include <sipstrings.h> |
|
38 #include <sipaddress.h> |
|
39 #include <e32property.h> |
|
40 #include <escapeutils.h> |
|
41 #include <badesca.h> |
|
42 |
|
43 |
|
44 // -------------------------------------------------------------------------- |
|
45 // C++ constructor |
|
46 // -------------------------------------------------------------------------- |
|
47 // |
|
48 CMusAvaCapabilityQuery::CMusAvaCapabilityQuery( |
|
49 CMusAvaCapability& aCapability, |
|
50 CSIPConnection& aSIPConnection, |
|
51 CSIPProfile& aProfile ) |
|
52 |
|
53 : CMusAvaCapabilityQueryBase( aCapability, aSIPConnection, aProfile ), |
|
54 iRetrying( EFalse ) |
|
55 { |
|
56 } |
|
57 |
|
58 // -------------------------------------------------------------------------- |
|
59 // Symbian two-phase constructor |
|
60 // -------------------------------------------------------------------------- |
|
61 // |
|
62 CMusAvaCapabilityQuery* CMusAvaCapabilityQuery::NewL( |
|
63 CMusAvaCapability& aCapability, |
|
64 CSIPConnection& aSIPConnection, |
|
65 CSIPProfile& aProfile, |
|
66 const TDesC& aSipAddress ) |
|
67 |
|
68 { |
|
69 MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::NewL" ) |
|
70 |
|
71 CMusAvaCapabilityQuery* self = NULL; |
|
72 |
|
73 self = new (ELeave) CMusAvaCapabilityQuery( aCapability, |
|
74 aSIPConnection, |
|
75 aProfile ); |
|
76 CleanupStack::PushL( self ); |
|
77 self->ConstructL( aSipAddress ); |
|
78 CleanupStack::Pop( self ); |
|
79 |
|
80 MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::NewL" ) |
|
81 return self; |
|
82 } |
|
83 |
|
84 // -------------------------------------------------------------------------- |
|
85 // Symbian second-phase constructor |
|
86 // -------------------------------------------------------------------------- |
|
87 // |
|
88 void CMusAvaCapabilityQuery::ConstructL( const TDesC& aSipAddress ) |
|
89 { |
|
90 MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::ConstructL" ) |
|
91 |
|
92 CMusAvaCapabilityQueryBase::ConstructL( aSipAddress ); |
|
93 |
|
94 MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::ConstructL" ) |
|
95 } |
|
96 |
|
97 // -------------------------------------------------------------------------- |
|
98 // C++ destructor |
|
99 // -------------------------------------------------------------------------- |
|
100 // |
|
101 CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery() |
|
102 { |
|
103 MUS_LOG( |
|
104 "mus: [MUSAVA] -> CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery" ) |
|
105 |
|
106 delete iTimer; |
|
107 |
|
108 MUS_LOG( |
|
109 "mus: [MUSAVA] <- CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery" ) |
|
110 } |
|
111 |
|
112 // -------------------------------------------------------------------------- |
|
113 // CMusAvaCapabilityQuery::Prepare |
|
114 // -------------------------------------------------------------------------- |
|
115 // |
|
116 void CMusAvaCapabilityQuery::Prepare( |
|
117 RPointerArray<CSIPHeaderBase>& /*aRequestHeaders*/ ) |
|
118 { |
|
119 MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::Prepare" ) |
|
120 |
|
121 if ( !Retrying() ) |
|
122 { |
|
123 MUS_LOG( "mus: [MUSAVA] query prepared" ) |
|
124 SetState( ECapabilityQueryPrepared ); |
|
125 } |
|
126 |
|
127 MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::Prepare" ) |
|
128 } |
|
129 |
|
130 // -------------------------------------------------------------------------- |
|
131 // CMusAvaCapabilityQuery::DoCompletedL |
|
132 // -------------------------------------------------------------------------- |
|
133 // |
|
134 void CMusAvaCapabilityQuery::DoCompletedL( |
|
135 const CSIPClientTransaction& aResponse ) |
|
136 { |
|
137 MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::DoCompletedL" ) |
|
138 |
|
139 const CSIPResponseElements* response = aResponse.ResponseElements(); |
|
140 User::LeaveIfError( !response ? KErrGeneral : KErrNone ); |
|
141 |
|
142 TUint statusCode = response->StatusCode(); |
|
143 |
|
144 MUS_LOG1( "mus: [MUSAVA] result %d", statusCode ) |
|
145 |
|
146 switch ( statusCode ) |
|
147 { |
|
148 case KMUSAVASIP200: |
|
149 { |
|
150 DoCompleted200OKL( aResponse ); |
|
151 break; |
|
152 } |
|
153 case KMUSAVASIPNotImplemented: |
|
154 { |
|
155 MUS_LOG( "mus: [MUSAVA] => OK" ) |
|
156 SetResult( KCapabilityCapabilitesReady ); |
|
157 SetState( ECapabilityQueryCompleted ); |
|
158 break; |
|
159 } |
|
160 case KMUSAVASIPForbidden: |
|
161 { |
|
162 MUS_LOG( "mus: [MUSAVA] => FAILED" ) |
|
163 if ( MultimediaSharingSettings::OperatorVariantSettingL() == |
|
164 MusSettingsKeys::EOperatorSpecific ) |
|
165 { |
|
166 SetResult( KCapabilityCapabilitiesForbidden ); |
|
167 SetState( ECapabilityQueryCompleted ); |
|
168 // set forbidden property |
|
169 TInt result = |
|
170 RProperty::Set( |
|
171 NMusSessionInformationApi::KCategoryUid, |
|
172 NMusSessionInformationApi::KMUSForbidden, |
|
173 ( TInt ) NMusSessionInformationApi::EMUSForbidden ); |
|
174 MUS_LOG1( "mus: [MUSAVA] Property::Ser( KMUSForbidden )\ |
|
175 returns %d", result ) |
|
176 } |
|
177 else |
|
178 { |
|
179 SetResult( KCapabilityCapabilitesNotFound ); |
|
180 SetState( ECapabilityQueryCompleted ); |
|
181 } |
|
182 break; |
|
183 } |
|
184 case KMUSAVASIPUnsupportedURIScheme: |
|
185 MUS_LOG( "mus: [MUSAVA] Unsupported URI Schem" ) |
|
186 SetState( ECapabilityQueryCompleted ); |
|
187 break; |
|
188 case KMUSAVASIPNotFound: |
|
189 case KMUSAVASIPTimeout: |
|
190 case KMUSAVASIPTemporarilyUnavailable: |
|
191 { |
|
192 DoRetryL(); |
|
193 break; |
|
194 } |
|
195 default: |
|
196 { |
|
197 MUS_LOG( "mus: [MUSAVA] => FAILED" ) |
|
198 SetResult( KCapabilityCapabilitesNotFound ); |
|
199 SetState( ECapabilityQueryCompleted ); |
|
200 break; |
|
201 } |
|
202 } |
|
203 |
|
204 MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::DoCompletedL" ) |
|
205 } |
|
206 |
|
207 // -------------------------------------------------------------------------- |
|
208 // CMusAvaCapabilityQuery::DoCompleted200OKL |
|
209 // -------------------------------------------------------------------------- |
|
210 // |
|
211 void CMusAvaCapabilityQuery::DoCompleted200OKL( |
|
212 // const CSIPResponseElements& aResponse ) |
|
213 const CSIPClientTransaction& aResponse ) |
|
214 { |
|
215 SetState( ECapabilityQueryCompleted ); |
|
216 |
|
217 // check if P-Asserted-Identity header exists |
|
218 _LIT8( KHeader,"P-Asserted-Identity" ); |
|
219 RStringF p = SIPStrings::Pool().OpenFStringL( KHeader() ); |
|
220 CleanupClosePushL( p ); |
|
221 |
|
222 TInt count = MusAvaCapabilityContext::HeaderCount( p, |
|
223 aResponse.ResponseElements()->MessageElements() ); |
|
224 |
|
225 if ( count > 0 ) |
|
226 { |
|
227 TUint index = 0; |
|
228 const CSIPHeaderBase* pAssertedId = MusAvaCapabilityContext::Header( |
|
229 p, |
|
230 aResponse.ResponseElements()->MessageElements(), |
|
231 index ); |
|
232 |
|
233 if ( pAssertedId ) |
|
234 { // get SIP uri |
|
235 HBufC8* value = pAssertedId->ToTextValueLC(); |
|
236 CSIPAddress* address = CSIPAddress::DecodeL( *value ); |
|
237 CleanupStack::PushL( address ); |
|
238 |
|
239 const TDesC8& uriInPAssertedId = address->Uri8().Uri().UriDes(); |
|
240 if ( uriInPAssertedId.Length() > 0 ) |
|
241 { |
|
242 HBufC* uri = EscapeUtils::ConvertToUnicodeFromUtf8L( |
|
243 uriInPAssertedId ); |
|
244 CleanupStack::PushL( uri ); |
|
245 Capability().Exchange().QueryObserver(). |
|
246 CapabilitiesResolvedL( *uri ); |
|
247 CleanupStack::PopAndDestroy( uri ); |
|
248 } |
|
249 CleanupStack::PopAndDestroy( 2 ); //address, value |
|
250 } |
|
251 } |
|
252 CleanupStack::PopAndDestroy( 1 ); //p |
|
253 |
|
254 const CSIPContentTypeHeader* contentTypeHeader = NULL; |
|
255 |
|
256 const CSIPResponseElements* response = aResponse.ResponseElements(); |
|
257 |
|
258 contentTypeHeader = response->MessageElements().ContentType(); |
|
259 |
|
260 if ( contentTypeHeader && |
|
261 contentTypeHeader-> |
|
262 MediaType().Compare( KMUSAVASIPMediaTypeApplication ) == 0 && |
|
263 contentTypeHeader-> |
|
264 MediaSubtype().Compare( KMUSAVASIPMediaSubTypeSDP ) == 0 ) |
|
265 { |
|
266 CSdpDocument* sdp = |
|
267 CSdpDocument::DecodeL( response->MessageElements().Content() ); |
|
268 CleanupStack::PushL( sdp ); |
|
269 |
|
270 TBool codec = ValidateAndStoreCodecsL( *sdp ); |
|
271 TBool attributes = ValidateAttributesL( *sdp ); |
|
272 TBool featureTag = ValidateContactL( aResponse ); |
|
273 TBool operatorVariant = |
|
274 MultimediaSharingSettings::OperatorVariantSettingL() == |
|
275 MusSettingsKeys::EOperatorSpecific; |
|
276 |
|
277 if ( ( codec && attributes && featureTag ) || |
|
278 ( codec && !operatorVariant && featureTag ) ) |
|
279 |
|
280 { |
|
281 MUS_LOG( "mus: [MUSAVA] => OK" ) |
|
282 SetResult( KCapabilityCapabilitesReady ); |
|
283 } |
|
284 |
|
285 else |
|
286 { |
|
287 MUS_LOG( "mus: [MUSAVA] => FAILED due SDP validation" ) |
|
288 SetResult( KCapabilityCapabilitesNotFound ); |
|
289 } |
|
290 |
|
291 CleanupStack::PopAndDestroy( sdp ); |
|
292 |
|
293 } |
|
294 else |
|
295 { |
|
296 MUS_LOG( "mus: [MUSAVA] => FAILED due wrong content type" ) |
|
297 SetResult( KCapabilityCapabilitesNotFound ); |
|
298 } |
|
299 } |
|
300 |
|
301 // -------------------------------------------------------------------------- |
|
302 // CMusAvaCapabilityQuery::ValidateCodecL |
|
303 // -------------------------------------------------------------------------- |
|
304 // |
|
305 TBool CMusAvaCapabilityQuery::ValidateAndStoreCodecsL( CSdpDocument& aSDP ) |
|
306 { |
|
307 MUS_LOG("mus: [MUSAVA] -> CMusAvaCapabilityQuery::ValidateAndStoreCodecsL" ) |
|
308 |
|
309 TBool valid = EFalse; |
|
310 |
|
311 CDesCArrayFlat* codecs = CMusAvaCapability::ResolveCodecsL( aSDP ); |
|
312 CleanupStack::PushL( codecs ); |
|
313 |
|
314 Capability().Exchange().QueryObserver().VideoCodecsResolvedL( *codecs ); |
|
315 MUS_LOG1("mus: [MUSAVA] -> codecs count = %d", codecs->MdcaCount() ) |
|
316 |
|
317 if ( codecs->MdcaCount() > 0 ) |
|
318 { |
|
319 valid = ETrue; |
|
320 } |
|
321 |
|
322 codecs->Reset(); |
|
323 CleanupStack::PopAndDestroy( codecs ); |
|
324 |
|
325 MUS_LOG("mus: [MUSAVA] <- CMusAvaCapabilityQuery::ValidateAndStoreCodecsL" ) |
|
326 return valid; |
|
327 } |
|
328 |
|
329 // -------------------------------------------------------------------------- |
|
330 // CMusAvaCapabilityQuery::ValidateAttributesL |
|
331 // -------------------------------------------------------------------------- |
|
332 // |
|
333 TBool CMusAvaCapabilityQuery::ValidateAttributesL( CSdpDocument& aSDP ) |
|
334 { |
|
335 TBool valid = EFalse; |
|
336 |
|
337 const CSdpAttributeField* application = NULL; |
|
338 const CSdpAttributeField* type = NULL; |
|
339 RStringF attrTypeName = MusAvaCapabilityContext::SDPStringL( |
|
340 KCapabilitySDPAttributeNameType ); |
|
341 CleanupClosePushL( attrTypeName ); |
|
342 |
|
343 // "a=application:comgsma.rts" |
|
344 application = CMusAvaCapability::Attribute( |
|
345 MusAvaCapabilityContext::SDPStringL( |
|
346 SdpCodecStringConstants::EMediaApplication ), |
|
347 aSDP ); |
|
348 |
|
349 // "a=type:videolive" |
|
350 type = CMusAvaCapability::Attribute( attrTypeName, aSDP ); |
|
351 CleanupStack::PopAndDestroy();//attrTypeName |
|
352 |
|
353 if ( MultimediaSharingSettings::OperatorVariantSettingL() == |
|
354 MusSettingsKeys::EOperatorSpecific ) |
|
355 { |
|
356 valid = application && |
|
357 application->Value().Compare( KCapabilitySwisApplication ) == 0 && |
|
358 type && |
|
359 type->Value().Compare( KCapabilitySDPAttributeType ) == 0; |
|
360 } |
|
361 else |
|
362 { |
|
363 valid = ( application && |
|
364 application->Value().Compare( KCapabilitySwisApplication ) == 0 ) || |
|
365 ( type && |
|
366 type->Value().Compare( KCapabilitySDPAttributeType ) == 0 ) ; |
|
367 |
|
368 } |
|
369 |
|
370 return valid; |
|
371 } |
|
372 |
|
373 // -------------------------------------------------------------------------- |
|
374 // CMusAvaCapabilityQuery::ValidateContactL |
|
375 // -------------------------------------------------------------------------- |
|
376 // |
|
377 TBool CMusAvaCapabilityQuery::ValidateContactL( |
|
378 const CSIPClientTransaction& aResponse ) |
|
379 { |
|
380 TBool valid = EFalse; |
|
381 RStringF falseParam = MusAvaCapabilityContext::SIPStringL( |
|
382 KMUSAVASIPParamFalse ); |
|
383 CleanupClosePushL( falseParam ); |
|
384 |
|
385 const CSIPContactHeader* contact = |
|
386 MusAvaCapabilityContext::ContactHeaderL( aResponse ); |
|
387 |
|
388 if ( !contact ) |
|
389 { |
|
390 MUS_LOG( "STCE: => FAILED due lack of contact header" ) |
|
391 } |
|
392 else |
|
393 { |
|
394 if ( contact->HasParam( Capability().Feature() ) && |
|
395 !contact->HasParam( falseParam ) ) |
|
396 { |
|
397 valid = ETrue; |
|
398 } |
|
399 else |
|
400 { |
|
401 MUS_LOG( "STCE: => FAILED due wrong contact header" ) |
|
402 } |
|
403 } |
|
404 CleanupStack::PopAndDestroy();//falseParam |
|
405 |
|
406 return valid; |
|
407 } |
|
408 |
|
409 // -------------------------------------------------------------------------- |
|
410 // CMusAvaCapabilityQuery::DoRetryL |
|
411 // -------------------------------------------------------------------------- |
|
412 // |
|
413 void CMusAvaCapabilityQuery::DoRetryL() |
|
414 { |
|
415 |
|
416 if ( !iTimer ) |
|
417 { |
|
418 MUS_LOG( "mus: [MUSAVA] => RE-TRYING" ) |
|
419 |
|
420 iTimer = CMusAvaCapabilityTimer::NewL( *this ); |
|
421 iTimer->After( KCapabilityTimervalue ); |
|
422 Retrying() = ETrue; |
|
423 SetResult( KCapabilityQueryNotReady ); |
|
424 SetState( ECapabilityQueryCreated ); |
|
425 } |
|
426 else |
|
427 { |
|
428 MUS_LOG( "mus: [MUSAVA] => FAILED due failing retry" ) |
|
429 Retrying() = EFalse; |
|
430 SetResult( KCapabilityCapabilitesNotFound ); |
|
431 SetState( ECapabilityQueryCompleted ); |
|
432 delete iTimer; |
|
433 iTimer = NULL; |
|
434 } |
|
435 } |
|
436 |
|
437 // -------------------------------------------------------------------------- |
|
438 // CMusAvaCapabilityQuery::OnExpired |
|
439 // -------------------------------------------------------------------------- |
|
440 // |
|
441 void CMusAvaCapabilityQuery::OnExpiredL( TInt /*aStatus*/ ) |
|
442 { |
|
443 Retrying() = EFalse; |
|
444 |
|
445 ExecuteL(); |
|
446 } |
|
447 |
|
448 // -------------------------------------------------------------------------- |
|
449 // CMusAvaCapabilityQuery::Retrying |
|
450 // -------------------------------------------------------------------------- |
|
451 // |
|
452 TBool& CMusAvaCapabilityQuery::Retrying() |
|
453 { |
|
454 return iRetrying; |
|
455 } |