mmsharing/mmshavailability/src/musavacapabilityquery.cpp
changeset 0 f0cf47e981f9
child 32 73a1feb507fb
--- /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 <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 ) ;
+        
+        }
+    
+    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;
+    }