--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsharing/mmshavailability/src/musavacapabilityquery.cpp Fri Jun 11 13:36:18 2010 +0300
@@ -0,0 +1,458 @@
+/*
+* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+* Description: Sent SWIS capability query (OPTIONS)
+*
+*/
+
+
+#include "musavacapabilityquery.h"
+#include "muslogger.h"
+#include "mussettings.h"
+#include "mussettingskeys.h"
+#include "musavacapability.h"
+#include "musavacapabilitycontext.h"
+#include "mussesseioninformationapi.h"
+#include "musavacapabilityexchange.h"
+#include "mmusavacapabilityqueryobserver.h"
+
+#include <sipconnection.h>
+#include <sipclienttransaction.h>
+#include <sipmessageelements.h>
+#include <sipresponseelements.h>
+#include <sdpdocument.h>
+#include <sipcontenttypeheader.h>
+#include <sdpattributefield.h>
+#include <sipcontactheader.h>
+#include <sipstrings.h>
+#include <sipaddress.h>
+#include <e32property.h>
+#include <escapeutils.h>
+#include <badesca.h>
+
+
+// --------------------------------------------------------------------------
+// C++ constructor
+// --------------------------------------------------------------------------
+//
+CMusAvaCapabilityQuery::CMusAvaCapabilityQuery(
+ CMusAvaCapability& aCapability,
+ CSIPConnection& aSIPConnection,
+ CSIPProfile& aProfile )
+
+ : CMusAvaCapabilityQueryBase( aCapability, aSIPConnection, aProfile ),
+ iRetrying( EFalse )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// Symbian two-phase constructor
+// --------------------------------------------------------------------------
+//
+CMusAvaCapabilityQuery* CMusAvaCapabilityQuery::NewL(
+ CMusAvaCapability& aCapability,
+ CSIPConnection& aSIPConnection,
+ CSIPProfile& aProfile,
+ const TDesC& aSipAddress )
+
+ {
+ MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::NewL" )
+
+ CMusAvaCapabilityQuery* self = NULL;
+
+ self = new (ELeave) CMusAvaCapabilityQuery( aCapability,
+ aSIPConnection,
+ aProfile );
+ CleanupStack::PushL( self );
+ self->ConstructL( aSipAddress );
+ CleanupStack::Pop( self );
+
+ MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::NewL" )
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// Symbian second-phase constructor
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::ConstructL( const TDesC& aSipAddress )
+ {
+ MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::ConstructL" )
+
+ CMusAvaCapabilityQueryBase::ConstructL( aSipAddress );
+
+ MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::ConstructL" )
+ }
+
+// --------------------------------------------------------------------------
+// C++ destructor
+// --------------------------------------------------------------------------
+//
+CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery()
+ {
+ MUS_LOG(
+ "mus: [MUSAVA] -> CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery" )
+
+ delete iTimer;
+
+ MUS_LOG(
+ "mus: [MUSAVA] <- CMusAvaCapabilityQuery::~CMusAvaCapabilityQuery" )
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::Prepare
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::Prepare(
+ RPointerArray<CSIPHeaderBase>& /*aRequestHeaders*/ )
+ {
+ MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::Prepare" )
+
+ if ( !Retrying() )
+ {
+ MUS_LOG( "mus: [MUSAVA] query prepared" )
+ SetState( ECapabilityQueryPrepared );
+ }
+
+ MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::Prepare" )
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::DoCompletedL
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::DoCompletedL(
+ const CSIPClientTransaction& aResponse )
+ {
+ MUS_LOG( "mus: [MUSAVA] -> CMusAvaCapabilityQuery::DoCompletedL" )
+
+ const CSIPResponseElements* response = aResponse.ResponseElements();
+ User::LeaveIfError( !response ? KErrGeneral : KErrNone );
+
+ TUint statusCode = response->StatusCode();
+
+ MUS_LOG1( "mus: [MUSAVA] result %d", statusCode )
+
+ switch ( statusCode )
+ {
+ case KMUSAVASIP200:
+ {
+ DoCompleted200OKL( aResponse );
+ break;
+ }
+ case KMUSAVASIPNotImplemented:
+ {
+ MUS_LOG( "mus: [MUSAVA] => OK" )
+ SetResult( KCapabilityCapabilitesReady );
+ SetState( ECapabilityQueryCompleted );
+ break;
+ }
+ case KMUSAVASIPForbidden:
+ {
+ MUS_LOG( "mus: [MUSAVA] => FAILED" )
+ if ( MultimediaSharingSettings::OperatorVariantSettingL() ==
+ MusSettingsKeys::EOperatorSpecific )
+ {
+ SetResult( KCapabilityCapabilitiesForbidden );
+ SetState( ECapabilityQueryCompleted );
+ // set forbidden property
+ TInt result =
+ RProperty::Set(
+ NMusSessionInformationApi::KCategoryUid,
+ NMusSessionInformationApi::KMUSForbidden,
+ ( TInt ) NMusSessionInformationApi::EMUSForbidden );
+ MUS_LOG1( "mus: [MUSAVA] Property::Ser( KMUSForbidden )\
+ returns %d", result )
+ }
+ else
+ {
+ SetResult( KCapabilityCapabilitesNotFound );
+ SetState( ECapabilityQueryCompleted );
+ }
+ break;
+ }
+ case KMUSAVASIPUnsupportedURIScheme:
+ MUS_LOG( "mus: [MUSAVA] Unsupported URI Schem" )
+ SetState( ECapabilityQueryCompleted );
+ break;
+ case KMUSAVASIPNotFound:
+ case KMUSAVASIPTimeout:
+ case KMUSAVASIPTemporarilyUnavailable:
+ {
+ DoRetryL();
+ break;
+ }
+ default:
+ {
+ MUS_LOG( "mus: [MUSAVA] => FAILED" )
+ SetResult( KCapabilityCapabilitesNotFound );
+ SetState( ECapabilityQueryCompleted );
+ break;
+ }
+ }
+
+ MUS_LOG( "mus: [MUSAVA] <- CMusAvaCapabilityQuery::DoCompletedL" )
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::DoCompleted200OKL
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::DoCompleted200OKL(
+// const CSIPResponseElements& aResponse )
+ const CSIPClientTransaction& aResponse )
+ {
+ SetState( ECapabilityQueryCompleted );
+
+ // check if P-Asserted-Identity header exists
+ _LIT8( KHeader,"P-Asserted-Identity" );
+ RStringF p = SIPStrings::Pool().OpenFStringL( KHeader() );
+ CleanupClosePushL( p );
+
+ TInt count = MusAvaCapabilityContext::HeaderCount( p,
+ aResponse.ResponseElements()->MessageElements() );
+
+ if ( count > 0 )
+ {
+ TUint index = 0;
+ const CSIPHeaderBase* pAssertedId = MusAvaCapabilityContext::Header(
+ p,
+ aResponse.ResponseElements()->MessageElements(),
+ index );
+
+ if ( pAssertedId )
+ { // get SIP uri
+ HBufC8* value = pAssertedId->ToTextValueLC();
+ CSIPAddress* address = CSIPAddress::DecodeL( *value );
+ CleanupStack::PushL( address );
+
+ const TDesC8& uriInPAssertedId = address->Uri8().Uri().UriDes();
+ if ( uriInPAssertedId.Length() > 0 )
+ {
+ HBufC* uri = EscapeUtils::ConvertToUnicodeFromUtf8L(
+ uriInPAssertedId );
+ CleanupStack::PushL( uri );
+ Capability().Exchange().QueryObserver().
+ CapabilitiesResolvedL( *uri );
+ CleanupStack::PopAndDestroy( uri );
+ }
+ CleanupStack::PopAndDestroy( 2 ); //address, value
+ }
+ }
+ CleanupStack::PopAndDestroy( 1 ); //p
+
+ const CSIPContentTypeHeader* contentTypeHeader = NULL;
+
+ const CSIPResponseElements* response = aResponse.ResponseElements();
+
+ contentTypeHeader = response->MessageElements().ContentType();
+
+ if ( contentTypeHeader &&
+ contentTypeHeader->
+ MediaType().Compare( KMUSAVASIPMediaTypeApplication ) == 0 &&
+ contentTypeHeader->
+ MediaSubtype().Compare( KMUSAVASIPMediaSubTypeSDP ) == 0 )
+ {
+ CSdpDocument* sdp =
+ CSdpDocument::DecodeL( response->MessageElements().Content() );
+ CleanupStack::PushL( sdp );
+
+ TBool codec = ValidateAndStoreCodecsL( *sdp );
+ TBool attributes = ValidateAttributesL( *sdp );
+ TBool featureTag = ValidateContactL( aResponse );
+ TBool operatorVariant =
+ MultimediaSharingSettings::OperatorVariantSettingL() ==
+ MusSettingsKeys::EOperatorSpecific;
+
+ if ( ( codec && attributes && featureTag ) ||
+ ( codec && !operatorVariant && featureTag ) )
+
+ {
+ MUS_LOG( "mus: [MUSAVA] => OK" )
+ SetResult( KCapabilityCapabilitesReady );
+ }
+
+ else
+ {
+ MUS_LOG( "mus: [MUSAVA] => FAILED due SDP validation" )
+ SetResult( KCapabilityCapabilitesNotFound );
+ }
+
+ CleanupStack::PopAndDestroy( sdp );
+
+ }
+ else
+ {
+ MUS_LOG( "mus: [MUSAVA] => FAILED due wrong content type" )
+ SetResult( KCapabilityCapabilitesNotFound );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::ValidateCodecL
+// --------------------------------------------------------------------------
+//
+TBool CMusAvaCapabilityQuery::ValidateAndStoreCodecsL( CSdpDocument& aSDP )
+ {
+ MUS_LOG("mus: [MUSAVA] -> CMusAvaCapabilityQuery::ValidateAndStoreCodecsL" )
+
+ TBool valid = EFalse;
+
+ CDesCArrayFlat* codecs = CMusAvaCapability::ResolveCodecsL( aSDP );
+ CleanupStack::PushL( codecs );
+
+ Capability().Exchange().QueryObserver().VideoCodecsResolvedL( *codecs );
+ MUS_LOG1("mus: [MUSAVA] -> codecs count = %d", codecs->MdcaCount() )
+
+ if ( codecs->MdcaCount() > 0 )
+ {
+ valid = ETrue;
+ }
+
+ codecs->Reset();
+ CleanupStack::PopAndDestroy( codecs );
+
+ MUS_LOG("mus: [MUSAVA] <- CMusAvaCapabilityQuery::ValidateAndStoreCodecsL" )
+ return valid;
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::ValidateAttributesL
+// --------------------------------------------------------------------------
+//
+TBool CMusAvaCapabilityQuery::ValidateAttributesL( CSdpDocument& aSDP )
+ {
+ TBool valid = EFalse;
+
+ const CSdpAttributeField* application = NULL;
+ const CSdpAttributeField* type = NULL;
+ RStringF attrTypeName = MusAvaCapabilityContext::SDPStringL(
+ KCapabilitySDPAttributeNameType );
+ CleanupClosePushL( attrTypeName );
+
+ // "a=application:comgsma.rts"
+ application = CMusAvaCapability::Attribute(
+ MusAvaCapabilityContext::SDPStringL(
+ SdpCodecStringConstants::EMediaApplication ),
+ aSDP );
+
+ // "a=type:videolive"
+ type = CMusAvaCapability::Attribute( attrTypeName, aSDP );
+ CleanupStack::PopAndDestroy();//attrTypeName
+
+ if ( MultimediaSharingSettings::OperatorVariantSettingL() ==
+ MusSettingsKeys::EOperatorSpecific )
+ {
+ valid = application &&
+ application->Value().Compare( KCapabilitySwisApplication ) == 0 &&
+ type &&
+ type->Value().Compare( KCapabilitySDPAttributeType ) == 0;
+ }
+ else
+ {
+ valid = ( application &&
+ application->Value().Compare( KCapabilitySwisApplication ) == 0 ) ||
+ ( type &&
+ type->Value().Compare( KCapabilitySDPAttributeType ) == 0 ) ;
+
+ }
+
+ MusSettingsKeys::TFastMode mode = CMusAvaCapability::ResolveFastModeL( aSDP );
+ Capability().Exchange().QueryObserver().FastModeResolved( mode );
+
+ return valid;
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::ValidateContactL
+// --------------------------------------------------------------------------
+//
+TBool CMusAvaCapabilityQuery::ValidateContactL(
+ const CSIPClientTransaction& aResponse )
+ {
+ TBool valid = EFalse;
+ RStringF falseParam = MusAvaCapabilityContext::SIPStringL(
+ KMUSAVASIPParamFalse );
+ CleanupClosePushL( falseParam );
+
+ const CSIPContactHeader* contact =
+ MusAvaCapabilityContext::ContactHeaderL( aResponse );
+
+ if ( !contact )
+ {
+ MUS_LOG( "STCE: => FAILED due lack of contact header" )
+ }
+ else
+ {
+ if ( contact->HasParam( Capability().Feature() ) &&
+ !contact->HasParam( falseParam ) )
+ {
+ valid = ETrue;
+ }
+ else
+ {
+ MUS_LOG( "STCE: => FAILED due wrong contact header" )
+ }
+ }
+ CleanupStack::PopAndDestroy();//falseParam
+
+ return valid;
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::DoRetryL
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::DoRetryL()
+ {
+
+ if ( !iTimer )
+ {
+ MUS_LOG( "mus: [MUSAVA] => RE-TRYING" )
+
+ iTimer = CMusAvaCapabilityTimer::NewL( *this );
+ iTimer->After( KCapabilityTimervalue );
+ Retrying() = ETrue;
+ SetResult( KCapabilityQueryNotReady );
+ SetState( ECapabilityQueryCreated );
+ }
+ else
+ {
+ MUS_LOG( "mus: [MUSAVA] => FAILED due failing retry" )
+ Retrying() = EFalse;
+ SetResult( KCapabilityCapabilitesNotFound );
+ SetState( ECapabilityQueryCompleted );
+ delete iTimer;
+ iTimer = NULL;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::OnExpired
+// --------------------------------------------------------------------------
+//
+void CMusAvaCapabilityQuery::OnExpiredL( TInt /*aStatus*/ )
+ {
+ Retrying() = EFalse;
+
+ ExecuteL();
+ }
+
+// --------------------------------------------------------------------------
+// CMusAvaCapabilityQuery::Retrying
+// --------------------------------------------------------------------------
+//
+TBool& CMusAvaCapabilityQuery::Retrying()
+ {
+ return iRetrying;
+ }