diff -r 000000000000 -r f0cf47e981f9 mmsharing/mmshavailability/src/musavacapabilityquery.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmsharing/mmshavailability/src/musavacapabilityquery.cpp Thu Dec 17 08:44:37 2009 +0200 @@ -0,0 +1,455 @@ +/* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// -------------------------------------------------------------------------- +// 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& /*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 ) ; + + } + + 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; + }