upnpavcontroller/upnpavcontrollerhelper/src/upnplocalitemresolver.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 23:05:22 +0200
branchRCL_3
changeset 5 62c8a2d3d275
parent 0 7f85d04be362
permissions -rw-r--r--
Revision: 201002 Kit: 201007

/*
* Copyright (c) 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:      Resolver for local items
*
*/






// INCLUDE FILES
// upnp stack api's
#include <upnpitem.h>

// upnpframework / avcontroller api
#include "upnpavcontroller.h" // avcontroller service
#include "upnpavbrowsingsession.h" // browsing session
#include "upnpavdevice.h" // device (for creating a session)
#include <upnpfilesharing.h>

// upnpframework / avcontroller helper api
#include "upnpitemresolverfactory.h" // optimisation flags
#include "upnpitemresolverobserver.h" // MUPnPItemResolverObserver
#include "upnpfileutility.h" // IsFileProtected
#include "upnpresourceselector.h" // MUPnPResourceSelector

// upnpframework / internal api's
#include "upnpmetadatafetcher.h" // CreateItemFromFileLC
#include "upnpcommonutils.h" // ReplacePlaceHolderInURIL

// avcontrollerhelper internal
#include "upnplocalitemresolver.h"

#include "upnpconstantdefs.h" // for upnp-specific stuff
#include "upnpitemutility.h" // for GetResElements
#include "upnpsecaccesscontroller.h" // CUpnpSecAccessController
#include "upnpperiodic.h"

_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt");
#include "upnplog.h"

// CONSTANTS
const TInt KCancelWaitMaximum =   4000000;
const TInt KCancelWaitResolution = 500000;
const TInt KUnshareWait =  1000000;

// METHODS

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver:: NewL
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
CUPnPLocalItemResolver* CUPnPLocalItemResolver::NewL(
    const TDesC& aFilePath,
    MUPnPAVController& aAvController,
    MUPnPResourceSelector& aSelector,
    TInt aOptimisationFlags    )
    {
    CUPnPLocalItemResolver* self =
        new (ELeave )CUPnPLocalItemResolver(
        aAvController, aSelector, aOptimisationFlags );
    CleanupStack::PushL( self );
    self->ConstructL( aFilePath );
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::CUPnPLocalItemResolver
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
CUPnPLocalItemResolver::CUPnPLocalItemResolver(
    MUPnPAVController& aAvController,
    MUPnPResourceSelector& aSelector,
    TInt aOptimisationFlags )
    : CActive( EPriorityStandard )
    , iAvController( aAvController )
    , iSelector( aSelector )
    {
    CActiveScheduler::Add( this );
    iOptimisationFlags = aOptimisationFlags;
    iState = EStateIdle;
    }


// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::ConstructL
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::ConstructL(
    const TDesC& aFilePath )
    {
    __LOG1( "LocalItemResolver:ConstructL() 0x%d", TInt(this) );
    iFilePath = aFilePath.AllocL();
    iFileSharing = CUpnpFileSharing::NewL();    
    iAccessController = CUpnpSecAccessController::NewL();
    iWait = new (ELeave) CActiveSchedulerWait();
    iTimer = CUPnPPeriodic::NewL( CActive::EPriorityHigh );
    }


// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::~CUPnPLocalItemResolver
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
CUPnPLocalItemResolver::~CUPnPLocalItemResolver()
    {
    __LOG1( "LocalItemResolver destructor 0x%d", TInt(this) );
    
    Cleanup();
    
    if ( iTempSession )
        {
        iTempSession->RemoveObserver();
        iAvController.StopBrowsingSession( *iTempSession );
        }

    delete iFileSharing;
    iFileSharing = NULL;
    
    // cancel any async calls
    if ( IsActive() )
        {
         __LOG( "LocalItemResolver destructor RequestComplete" );
        TRequestStatus* stat = &iStatus;
        User::RequestComplete( stat, KErrNone );
        }
    
    Cancel();
      
    delete iFilePath;
    iFilePath = NULL;
    
    delete iAccessController;
    iAccessController = NULL;
    
    delete iSharedItem;
    iSharedItem = NULL;
        
    if( iTimer )
        {
        iTimer->Cancel();
        delete iTimer;
        iTimer = NULL;
        }
    
    if( iWait->IsStarted() )
        {
        iWait->AsyncStop();
        }
    delete iWait;
    iWait = NULL;
        
    __LOG( "LocalItemResolver destructor end" );
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::ResolveL
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::ResolveL(
    MUPnPItemResolverObserver& aObserver )
    {
    __LOG1( "LocalItemResolver:Resolve() 0x%d", TInt(this) );
    __ASSERTD( iState == EStateIdle, __FILE__, __LINE__ );
    iObserver = &aObserver;

    if ( iOptimisationFlags & UPnPItemResolverFactory::EOmitDrmCheck )
        {
        // no need to check DRM ! this branch is empty.
        }
    else
        {
        // check DRM
        if ( UPnPFileUtility::IsFileProtectedL( iFilePath->Des() ) )
            {
            User::Leave( KErrNotSupported );
            }
        }

    // create item metadata
    iState = EStateCreatingItem;
    CUpnpItem* item = UPnPMetadataFetcher::CreateItemFromFileLC(
        iFilePath->Des() );
    CleanupStack::Pop( item );
    __LOG1( "LocalItemResolver:Resolve CreateItemFromFileLC done 0x%d", TInt(this) );
    if( iSharedItem )
        {
        delete iSharedItem;
        iSharedItem = 0;
        }
    iSharedItem = item;

    // state check
    if ( iState == EStateCreatingItem )
        {
        // start local mediaserver
        if ( iOptimisationFlags & UPnPItemResolverFactory::EOmitLocalMSStart )
            {
            // omit mediaserver start - go directly to sharing.
            DoShareL();
            }
        else
            {
            // start a session for local MS keepalive
            CUpnpAVDevice* dummyDevice = CUpnpAVDevice::NewLC();
            dummyDevice->SetUuidL( KNullDesC8 );
            dummyDevice->SetDeviceType(CUpnpAVDevice::EMediaServer);    
            iTempSession = &iAvController.StartBrowsingSessionL( *dummyDevice );
            CleanupStack::PopAndDestroy( dummyDevice );

            iTempSession->SetObserver( *this );
            // request for start local MS
            iState = EStateStartingMS;
            iTempSession->ReserveLocalMSServicesL();
            }
        
        }
    else
        {
        __LOG( "LocalItemResolver: create item interrupted" );
		iState = EStateIdle;
        }
        
    __LOG( "LocalItemResolver:Resolve() END" );
    }


// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::DoCancel
// See upnplocalitemresolver.h
// --------------------------------------------------------------------------
void CUPnPLocalItemResolver::DoCancel()
    {
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::RunError
// See upnplocalitemresolver.h
// --------------------------------------------------------------------------
TInt CUPnPLocalItemResolver::RunError( TInt aError )
    {
    __LOG1( "CUPnPLocalItemResolver::RunError %d", aError );
    // should never be here.
    __PANICD( __FILE__, __LINE__ );
    return KErrNone;
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::RunL
// See upnplocalitemresolver.h
// --------------------------------------------------------------------------
void CUPnPLocalItemResolver::RunL()
    {
    __LOG2( "CUPnPLocalItemResolver::RunL iStatus=%d, iState=%d", 
        iStatus.Int(), iState );


	if ( iState == EStateSharing )
		{
		// If the sharing failed
        if( iStatus.Int() != KErrNone )
            {
            // Deny access to the files listed in res-elements
            SetAccesstoItemResources( *iSharedItem, EFalse );
            }
        
        if( iStatus.Int() == KErrNone )
    		{
    	    // replace the IP address in the URI
    	    __LOG( "LocalItemResolver:replacing IP in URI" );
    	    TInetAddr address;
    	    User::LeaveIfError( iMediaServer.Connect() );
    	    iMediaServer.GetAddress( address );
    	    UPnPCommonUtils::ReplacePlaceHolderInURIL(
    	        *iSharedItem, address );
    	    iMediaServer.Close();

    	    // select the resource
    	    iResource = &iSelector.SelectResourceL( *iSharedItem );
            }
               
        Complete( iStatus.Int() );
		}
		
    else if ( iState == EStateUnsharing )
		{	
		iTimer->Cancel();
		
        // Deny access to the files listed in res-elements
        SetAccesstoItemResources( *iSharedItem, EFalse );
        
        iResource = 0; // NOTE: no deletion !
        iState = EStateIdle;
        
        iWait->AsyncStop();
        }
        
    __LOG( "CUPnPLocalItemResolver::RunL end" );
    }
    
    
// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::ReserveLocalMSServicesCompleted
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::ReserveLocalMSServicesCompleted(
    TInt aError )
    {
    __LOG( "LocalItemResolver:MSServicesComplete" );
    __ASSERTD( iState == EStateStartingMS, __FILE__, __LINE__ );

    if ( aError == KErrNone )
        {
        TRAPD( err, DoShareL() );
        if( err != KErrNone )
            {
            __LOG1( "LocalItemResolver:MSServicesComplete\
 DoShareL failed %d", err );
            }
        }
    else
        {
        Complete( aError );
        }
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::DoShareL
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::DoShareL()
    {
    __LOG( "CUPnPLocalItemResolver::DoShareL start" );
    // share the item
    iState = EStateSharing;
    
    // Allow access to the files listed in res-elements
    SetAccesstoItemResources( *iSharedItem, ETrue );
    
    // Share the item
    iFileSharing->ShareItemL( KContainerIdRoot, *iSharedItem, iStatus );
        
    SetActive();
    __LOG( "CUPnPLocalItemResolver::DoShareL end" );
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::DoUnshareL
// See upnplocalitemresolver.h
// --------------------------------------------------------------------------
void CUPnPLocalItemResolver::DoUnshareL()
    {
    __LOG( "CUPnPLocalItemResolver::DoUnshareL" );

    iState = EStateUnsharing;
    
    TInt id;
    TLex8 idParser( iSharedItem->Id() );
    TInt status = idParser.Val( id );
    if ( status == KErrNone )
        {
        iFileSharing->UnshareItemL( id, iStatus );

        SetActive();
        }
    else
        {
        __LOG1( "CUPnPLocalItemResolver::DoUnshareL leave %d", status );
        User::Leave( status );
        }
        
    __LOG( "CUPnPLocalItemResolver::DoUnshareL - end" );
    }


// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::Item
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
const CUpnpItem& CUPnPLocalItemResolver::Item() const
    {
    __ASSERTD( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERTD( iSharedItem, __FILE__, __LINE__ );

    return *iSharedItem;
    }


// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::Resource
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
const CUpnpElement& CUPnPLocalItemResolver::Resource() const
    {
    __ASSERTD( iState == EStateReady, __FILE__, __LINE__ );
    __ASSERTD( iResource, __FILE__, __LINE__ );

    return *iResource;
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::Complete
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::Complete( TInt aError )
    {
    __LOG1( "LocalItemResolver:Complete() %d", aError );
    __ASSERTD( iState == EStateStartingMS || 
        iState == EStateSharing, __FILE__, __LINE__ );
        
    MUPnPItemResolverObserver& observer = *iObserver;
    iObserver = 0;
    if ( aError == KErrNone )
        {
        iState = EStateReady;
        }
    else
        {
        iState = EStateIdle;
        Cleanup();
        }

    observer.ResolveComplete( *this, aError );
    __LOG( "LocalItemResolver:Complete() END" );
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::Cleanup
// See upnplocalitemresolver.h
//---------------------------------------------------------------------------
void CUPnPLocalItemResolver::Cleanup()
    {
    __LOG1( "CUPnPLocalItemResolver:Cleanup() iState %d", iState );
    
    iObserver = 0;

    if ( iState == EStateCreatingItem )
        {
        // signal cancel, wait until create item exits
        iState = EStateCancel;
        for ( TInt t = KCancelWaitMaximum;
            t > 0 && iState != EStateIdle;
            t -= KCancelWaitResolution )
            {
            User::After( TTimeIntervalMicroSeconds32(
                KCancelWaitResolution ) );
            }
        }
    else if ( iState == EStateStartingMS )
        {
        if( iTempSession )
            {
            TRAP_IGNORE( iTempSession->CancelReserveLocalMSServicesL() );
            }
        }
    else if ( iState == EStateSharing )
		{
        // do nothing, cannot unshare item if sharing hasn't finished yet.
        __LOG( "CUPnPLocalItemResolver:Cleanup() sharing in progress, do nothing" );
		} 
    else if ( iState == EStateUnsharing )
		{
        // do nothing, unsharing is still in progress. This happens,
        // if we start shutting down while previous cleanup hasn't finished yet.
        __LOG( "CUPnPLocalItemResolver:Cleanup() unsharing in progress, do nothing" );
		}
    else if ( iState == EStateCancel )
		{
        // do nothing, we shouldn't be here
        __LOG( "CUPnPLocalItemResolver:Cleanup() cancelling, shouldn't be here.." );
		}
    else if ( iSharedItem )
        {
        TRAPD( error, DoUnshareL() );
        
        if( error == KErrNone )
            {
            // wait some time.. 
            // if unshare doesn't finish in time, just cancel andcontinue
            __LOG( "CUPnPLocalItemResolver:Cleanup() start timer" );
            iTimer->Start( KUnshareWait, KUnshareWait, TCallBack( TimerExpired, this ) );
            iWait->Start();
            
            iTimer->Cancel();
            }
        else
            {
            __LOG1( "CUPnPLocalItemResolver:Cleanup() unshare failed %d", error );
            }
        }

    __LOG( "CUPnPLocalItemResolver:Cleanup() end" );
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::SetAccesstoItemResources
// See upnplocalitemresolver.h
// --------------------------------------------------------------------------
void CUPnPLocalItemResolver::SetAccesstoItemResources(
                                                CUpnpItem& aItem,
                                                TBool aAccessAllowed )
    {
    __LOG( "CUPnPLocalItemResolver::SetAccesstoItemResources" );

    // Get all filenames and set the access for those.
    RUPnPElementsArray resElements;
    UPnPItemUtility::GetResElements( aItem, resElements );
    for( TInt i=0; i<resElements.Count(); i++ )
        {
        if( aAccessAllowed )
            {
            iAccessController->AddAllowedFile( resElements[i]->FilePath() );
            }
        else
            {
            iAccessController->RemoveAllowedFile(
                                        resElements[i]->FilePath() );
            }
        }
    resElements.Close();
    }

// --------------------------------------------------------------------------
// CUPnPLocalItemResolver::TimerExpired
// See upnplocalitemresolver.h
// -------------------------------------------------------------------------- 
TInt CUPnPLocalItemResolver::TimerExpired( TAny* aArg )
    {
    __LOG( "CUPnPLocalItemResolver::TimerExpired" );
    
    CUPnPLocalItemResolver* resolver =
        (static_cast<CUPnPLocalItemResolver*>( aArg ));
    
    resolver->iTimer->Cancel();
    resolver->iWait->AsyncStop();
    
    __LOG( "CUPnPLocalItemResolver::TimerExpired end" );
    return KErrNone;
    }