upnpavcontroller/upnpavcontrollerserver/src/upnpuploadsession.cpp
changeset 0 7f85d04be362
child 30 5ec426854821
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpavcontroller/upnpavcontrollerserver/src/upnpuploadsession.cpp	Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,938 @@
+/*
+* 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:      server impl. of session against media server
+*
+*/
+
+
+
+
+
+
+// INCLUDE FILES
+// System
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+
+// upnp stack api
+#include <upnpitem.h>
+#include <upnpattribute.h>
+#include <upnpstring.h>
+#include <upnpdlnaprotocolinfo.h>
+#include <upnpavcontrolpoint.h>
+
+// upnpframework / avcontroller helper api
+#include "upnpconstantdefs.h" // for upnp-specific stuff
+#include "upnpitemutility.h" // FindElementByNameL, GetResElements
+
+// upnpframework / xmlparser api
+#include "upnpxmlparser.h"
+
+// upnpframework / internal api's
+#include "upnpcdsreselementutility.h"
+#include "httpuploader.h"
+#include "upnpmetadatafetcher.h"
+#include "upnpcommonutils.h"
+
+// INTERNAL INCLUDES
+#include "upnpuploadsession.h"
+#include "upnpfiletransferitem.h"
+#include "upnpavcontrollerserver.h"
+#include "upnpfiletransferitem.h"
+#include "upnpavdeviceextended.h"
+#include "upnpavdispatcher.h"
+#include "upnpaverrorhandler.h"
+#include "upnpresourcehelper.h"
+
+_LIT( KComponentLogfile, "upnpavcontrollerserver.txt");
+#include "upnplog.h"
+
+// CONSTANTS
+_LIT8( KImportUri,              "importUri" );
+_LIT8( KAsterisk,               "*" );
+const TUint32 KBufferSize       = 0x40000; // 256K
+const TInt KParallerTransfers   = 1;
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::NewL
+// See upnpuploadsession.h
+// --------------------------------------------------------------------------
+CUPnPUploadSession* CUPnPUploadSession::NewL( CUpnpAVControllerServer&
+    aServer, TInt aSessionId, const TDesC8& aUuid )
+    {
+    CUPnPUploadSession* self = new (ELeave) CUPnPUploadSession(
+        aServer, aSessionId );
+    CleanupStack::PushL( self );    
+    self->ConstructL( aUuid );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::CUPnPUploadSession
+// See upnpuploadsession.h
+// --------------------------------------------------------------------------
+CUPnPUploadSession::CUPnPUploadSession( CUpnpAVControllerServer& aServer,
+    TInt aSessionId ) :
+    CUPnPFileTransferSessionBase( aServer, aSessionId ),
+    iResourceIndex( KErrNotFound ),
+    iAsyncError( KErrNone ),
+    iIPSessionId( KErrNotFound ),
+    iSchedulerStopped( ETrue )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::~CUPnPUploadSession
+// See upnpuploadsession.h
+// --------------------------------------------------------------------------
+CUPnPUploadSession::~CUPnPUploadSession()
+    {
+    __LOG( "CUPnPUploadSession::~CUPnPUploadSession" );
+
+    delete iUploader;
+    iResources.ResetAndDestroy();
+    
+    __LOG( "CUPnPUploadSession::~CUPnPUploadSession - end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ConstructL
+// See upnpuploadsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::ConstructL( const TDesC8& aUuid )
+    {
+    __LOG( "CUPnPUploadSession::ConstructL" );
+    
+    CUPnPFileTransferSessionBase::ConstructL( aUuid );
+
+    iUploader = CHttpUploader::NewL( *this, (TUint32)iServer.IAP(),
+        KBufferSize, KParallerTransfers );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPDownloadSession::TransferProgress
+// See upnpdownloadsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::TransferProgress( TAny* aKey, TInt aBytes,
+    TInt aTotalBytes )
+    {
+    __LOG( "CUPnPUploadSession::TransferProgress" );
+    
+    if( iProgressTrackingEnabled )
+        {
+        TUpnpFileTransferEvent item;
+        TInt err = FindItemByKey( item, (TInt)aKey );
+        if( err == KErrNone )
+            {
+            item.iStatus = KErrNone;
+            item.iParam2 = aTotalBytes;
+            item.iParam1 = aBytes;
+            item.iEvent = TUpnpFileTransferEvent::ETransferProgress;
+
+            Complete( item );
+            }
+        else
+            {
+            __LOG( "TransferProgress - Not enabled!" );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ReadyForTransfer
+// See upnpdownloadsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::ReadyForTransferL( TAny* aKey )
+    {
+    __LOG( "CUPnPUploadSession::ReadyForTransferL" );
+    
+    TUpnpFileTransferEvent event;
+    if( FindItemByKey( event, (TInt)aKey, iResourceIndex ) == KErrNone )
+        {
+        ReadyForTransferL( event );
+        
+        event.iEvent = TUpnpFileTransferEvent::ETransferStarted;
+        Complete( event );
+        }
+    else
+        {
+        __LOG( "ReadyForTransfer - Key not found" );
+        
+        // Not found
+        event.iStatus = KErrGeneral;
+        event.iParam2 = 0;
+        event.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
+        
+        Complete( event );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::TransferCompleted
+// See upnpdownloadsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::TransferCompleted( TAny* aKey, TInt aStatus )
+    {
+    __LOG2( "CUPnPUploadSession::TransferCompleted, key = %d, status = %d",
+            (TInt)aKey, aStatus );
+    
+    TUpnpFileTransferEvent item;
+    TInt index;
+    TInt err = FindItemByKey( item, (TInt)aKey, index );
+    if( err == KErrNone )
+        {
+        item.iStatus = UPnPAVErrorHandler::ConvertToSymbianErrorCode( aStatus,
+        EUPnPHTTPError );
+        
+        item.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
+        Complete( item );
+                
+        iTransferItems.Remove( index );
+        delete iResources[ index ];
+        iResources.Remove( index );
+        }
+    else
+        {
+        __LOG( "TransferCompleted - Key not found" );
+        
+        // Not found
+        if( aStatus == KErrCancel )
+            {
+            item.iStatus = aStatus;
+            }
+        else
+            {
+            item.iStatus = KErrGeneral;    
+            }    
+        
+        item.iParam2 = 0;
+        item.iEvent = TUpnpFileTransferEvent::ETransferCompleted;
+        
+        Complete( item );
+        } 
+    
+    if( aStatus == KErrDisconnected )
+        {
+        __LOG( "TransferCompleted - Target device lost" );
+        
+        TInt count = iTransferItems.Count();
+        for( TInt i = 0; i < count; i++ )
+            {
+            iUploader->CancelTransfer( (TAny*)iTransferItems[i].iKey );
+
+            if( iResources[ i ]->ItemId() )
+                {
+                // Send destroyobject
+                __LOG( "CancelAllUploadsL - sending destroyobject" );
+                TRAP_IGNORE( iServer.ControlPoint().CdsDestroyObjectActionL(
+                    iDevice->Uuid(), *iResources[ i ]->ItemId() ) );  
+                }
+            }
+        iResources.ResetAndDestroy();    
+        iTransferItems.Reset();
+        }      
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::CdsCreateObjectResponse
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::CdsCreateObjectResponse(
+    const TDesC8& /*aUuid*/,
+    TInt aSessionId,
+    TInt aErr,
+    const TDesC8& /*aContainerID*/, 
+    const TDesC8& /*aElements*/, 
+    const TDesC8& aObjectID, 
+    const TDesC8& aResult )
+    {
+    __LOG1( "CUPnPUploadSession::CdsCreateObjectResponse: %d" , aErr );
+    
+    __ASSERTD( iIPSessionId == aSessionId, __FILE__, __LINE__ );
+    
+    __ASSERTD( iTransferItems.Count() == iResources.Count(), __FILE__, 
+               __LINE__ );
+    
+    iServer.Dispatcher().UnRegister( iIPSessionId );
+    iIPSessionId = KErrNotFound;
+    
+    aErr = UPnPAVErrorHandler::ConvertToSymbianErrorCode( aErr,
+        EUPnPContentDirectoryError );
+
+    if( aErr == KErrNone )
+        {
+        TRAP( aErr, HandleObjectResponseL( aObjectID, aResult ) );
+        }        
+    
+    iAsyncError = aErr;
+    StopWait();
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::StartUploadL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::StartUploadL( const RMessage2& aMessage )
+    {
+    __LOG( "CUPnPUploadSession::StartUploadL" );
+    
+    __ASSERTD( iTransferItems.Count() == iResources.Count(), __FILE__, 
+               __LINE__ );
+    
+    CUpnpFileTransferItem* tmpTransferItem = CUpnpFileTransferItem::NewLC();
+        
+    ReadTransferItemFromMessageL( aMessage, 1 ,tmpTransferItem );
+        
+    if( CheckIfKeyExists( tmpTransferItem->Key() ) )
+        {
+        User::Leave( KErrInUse );
+        }
+    
+    TUpnpFileTransferEvent transferItem;        
+    transferItem.iKey = tmpTransferItem->Key();
+            
+    CUpnpItem* tmpUpnpItem = UPnPMetadataFetcher::CreateItemFromFileLC( 
+        tmpTransferItem->Path() );
+        
+    tmpUpnpItem->SetIdL( KNullDesC8 );
+    tmpUpnpItem->SetParentIdL( KContainerIdAny );
+    tmpUpnpItem->SetRestricted( EFalse );
+
+    const CUpnpElement& resEl = UPnPItemUtility::FindElementByNameL(
+        *tmpUpnpItem, KElementRes );
+
+    const CUpnpAttribute* pInfo = UPnPItemUtility::FindAttributeByName(
+        resEl, KAttributeProtocolInfo );  
+      
+    if( iDevice->DlnaCompatible() )
+        {
+        // Dlna device, additional checks required
+        __LOG( "StartUploadL - DLNA device" );
+        
+        TPtrC8 objectClass = tmpUpnpItem->ObjectClass(); 
+        if( objectClass.Find( KClassAudio ) != KErrNotFound &&
+            iDevice->AudioUpload() )
+            {
+            // Trying to upload audio and it's supported
+            }
+        else if( objectClass.Find( KClassImage ) != KErrNotFound &&
+            iDevice->ImageUpload() )
+            {
+            // Trying to upload images and it's supported
+            }
+        else if(  objectClass.Find( KClassVideo ) != KErrNotFound &&
+            iDevice->VideoUpload() )
+            {
+            // Trying to upload video and it's supported
+            }
+        else
+            {
+            // Unknown media type, or copy not supported
+            __LOG( "StartUploadL - Unknown media type, or copy not \
+supported" );
+            User::Leave( KErrNotSupported );
+            }    
+
+            if( iDevice->ValidateTransfer( pInfo->Value() ) )
+                {
+                __LOG( "StartUploadL - Match by protocolInfo succeeded" );
+                // Continue with DLNA upload
+                // ProtocolInfo is in DLNA format
+                }
+            else
+                {
+                __LOG( "StartUploadL - Match by protocolInfo failed, upload \
+as UPnP content" );
+                // Continue with UPnP upload
+                // Check the protocolInfo
+                ProtocolInfoToUPnPL( pInfo );
+                }        
+        }
+    else
+        {
+        __LOG( "StartUploadL - UPnP Device -> UPnP upload" );
+        // Continue with UPnP upload
+        // Check the protocolInfo
+        ProtocolInfoToUPnPL( pInfo );        
+        }
+        
+    iUploader->InsertFileIntoWaitQueueL( (TAny*)transferItem.iKey,
+        tmpTransferItem->Path(), KNullDesC8 );
+    
+    SetHeadersL( pInfo->Value(), (TAny*)transferItem.iKey );
+    
+    iTransferItems.Append( transferItem );
+    
+    CUPnPResourceHelper* helper = CUPnPResourceHelper::NewL();
+    CleanupStack::Pop( tmpUpnpItem );
+    helper->SetItem( tmpUpnpItem ); // Transfer ownership
+    iResources.Append( helper );
+    
+    iUploader->MoveToTransferQueueL( (TAny*)transferItem.iKey );
+    
+    CleanupStack::PopAndDestroy( tmpTransferItem );
+    
+    aMessage.Complete( KErrNone );
+    
+    __LOG( "CUPnPUploadSession::StartUploadL - end " );    
+    }
+    
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::CancelUploadL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::CancelUploadL( const RMessage2& aMessage )
+    {
+    __LOG( "CUPnPUploadSession::CancelUploadL" );          
+    
+    __ASSERTD( iTransferItems.Count() == iResources.Count(), __FILE__,
+               __LINE__ );
+    
+    TInt key = aMessage.Int1();
+
+    TInt index;
+    if( CheckIfKeyExists( key, index ) )
+        {
+        iUploader->CancelTransfer( (TAny*)key );
+        aMessage.Complete( KErrNone );
+        iTransferItems.Remove( index );
+        if( iResources[ index ]->ItemId() )
+            {
+            // Send destroyobject
+            iServer.ControlPoint().CdsDestroyObjectActionL( iDevice->Uuid(),
+                *iResources[ index ]->ItemId() );
+            }
+        delete iResources[index ];
+        iResources.Remove( index );   
+        }
+    else
+        {
+        aMessage.Complete( KErrNotFound );
+        }        
+    
+    __LOG( "CUPnPUploadSession::CancelUploadL - end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::CancelAllUploadsL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::CancelAllUploadsL( const RMessage2& aMessage )
+    {
+    __LOG( "CUPnPUploadSession::CancelAllUploadsL" );          
+    
+    __ASSERTD( iTransferItems.Count() == iResources.Count(), __FILE__,
+               __LINE__ );
+        
+    TInt count = iTransferItems.Count();
+    for( TInt i = 0; i < count; i++ )
+        {
+        iUploader->CancelTransfer( (TAny*)iTransferItems[i].iKey );
+
+        if( iResources[ i ]->ItemId() )
+            {
+            // Send destroyobject
+            __LOG( "CancelAllUploadsL - sending destroyobject" );
+            iServer.ControlPoint().CdsDestroyObjectActionL( iDevice->Uuid(),
+                *iResources[ i ]->ItemId() );  
+            }
+        }
+    iResources.ResetAndDestroy();
+    iTransferItems.Reset();
+    iEventQueu.Reset();
+
+    // Scheduler loop started, stop it and ignore createobject-resp
+    __LOG( "CancelAllUploadsL - Un register" );
+    iServer.Dispatcher().UnRegister( iIPSessionId );
+    iIPSessionId = KErrNotFound;
+    iAsyncError = KErrCancel;
+
+    __LOG( "CancelAllUploadsL - Stop scheduler loop" );
+    StopWait();
+
+    aMessage.Complete( KErrNone );
+
+    __LOG( "CUPnPUploadSession::CancelAllUploadsL - end" );
+    }
+    
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::StartTrackingUploadProgressL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::StartTrackingUploadProgressL( const RMessage2&
+    aMessage )
+    {
+    __LOG( "CUPnPUploadSession::StartTrackingUploadProgressL" );
+    
+    TInt key = aMessage.Int1();
+    if( CheckIfKeyExists( key ) )
+        {
+        iUploader->TrackProgress( (TAny*)key, ETrue );
+        iProgressTrackingEnabled = ETrue;
+        aMessage.Complete( KErrNone );
+        }
+    else
+        {
+        aMessage.Complete( KErrNotFound );
+        }    
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::StopTrackingUploadProgressL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::StopTrackingUploadProgressL( const RMessage2&
+    aMessage )
+    {
+    __LOG( "CUPnPUploadSession::StopTrackingUploadProgressL" );
+    
+    TInt key = aMessage.Int1();
+    if( CheckIfKeyExists( key ) )
+        {
+        iUploader->TrackProgress( (TAny*)key, EFalse );
+        iProgressTrackingEnabled = EFalse;        
+        aMessage.Complete( KErrNone );
+        }
+    else
+        {
+        aMessage.Complete( KErrNotFound );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::GetUploadEventL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::GetUploadEventL( const RMessage2& aMessage )
+    {
+    __LOG( "CUPnPUploadSession::GetUploadEventL" );
+    
+    if( iEventQueu.Count() )
+        {
+        // There are events in the queu, write the first queued event back
+        // to client
+        __LOG1( "GetUploadEventL - events in queu, count = %d",
+            iEventQueu.Count() );
+        TPckg<TUpnpFileTransferEvent> resp1( iEventQueu[0] );
+        aMessage.Write( 1, resp1  ); // Write response using slot 1
+        aMessage.Complete( KErrNone );
+        
+        iEventQueu.Remove( 0 );
+        }
+    else
+        {
+        __ASSERTD( !iEventMsg, __FILE__, __LINE__ );
+        __LOG( "GetUploadEventL - Store msg" );
+        iEventMsg = new (ELeave) RMessage2( aMessage );
+        } 
+    __LOG( "CUPnPUploadSession::GetUploadEventL - end" );
+    }
+    
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::CancelGetUploadEventL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::CancelGetUploadEventL( const RMessage2& aMessage )
+    {
+    __LOG( "CUPnPUploadSession::CancelGetUploadEventL" );          
+    
+    if( iEventMsg )
+        {
+        iEventMsg->Complete( KErrCancel );
+        delete iEventMsg; iEventMsg = NULL;
+        }
+    aMessage.Complete( KErrNone );    
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::DeviceDisappearedL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::DeviceDisappearedL(
+    CUpnpAVDeviceExtended& aDevice )
+    {
+    __LOG( "CUPnPUploadSession::DeviceDisappearedL" );
+
+    if( aDevice.Uuid().Compare( iDevice->Uuid() ) == 0 )
+        {
+        TUpnpFileTransferEvent event;
+        event.iEvent = TUpnpFileTransferEvent::EDeviceDisconnected;
+
+        Complete( event );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::SetHeadersL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::SetHeadersL( const TDesC8& aInfo, TAny* aKey )
+    {
+    CUpnpDlnaProtocolInfo* tmpInfo = CUpnpDlnaProtocolInfo::NewL( aInfo );
+    CleanupStack::PushL( tmpInfo );
+
+    // Set the content-type header
+    iUploader->SetHeaderL( aKey, KContentType,
+        tmpInfo->ThirdField() );
+    
+    // Set the expect header
+    iUploader->SetHeaderL( aKey, KExpectHeader, K100Continue );
+
+    CleanupStack::PopAndDestroy( tmpInfo );            
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ReadyForTransferL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::ReadyForTransferL( TUpnpFileTransferEvent& aEvent )
+    {
+    __LOG( "CUPnPUploadSession::ReadyForTransferL" );
+    
+    if ( !iSchedulerStopped || iWait.IsStarted() )
+        {
+        __LOG1( "CUPnPUploadSession::ReadyForTransferL\
+        IsStarted = %d", (TInt)iWait.IsStarted() );
+        __LOG1( "CUPnPUploadSession::ReadyForTransferL\
+        iSchedulerStopped = %d", (TInt)iSchedulerStopped );
+        User::Leave( KErrNotReady );
+        }
+
+    __ASSERTD( iTransferItems.Count() == iResources.Count(), __FILE__, 
+               __LINE__ );
+    
+    CUpnpItem* tmpUpnpItem = iResources[ iResourceIndex ]->Item();
+    if( !tmpUpnpItem )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    
+    HBufC8* xmlDoc = CUPnPXMLParser::XmlForCreateObjectLC(
+        *tmpUpnpItem );
+    
+    iIPSessionId = iServer.ControlPoint().CdsCreateObjectActionL(
+        iDevice->Uuid(), KContainerIdAny, *xmlDoc );
+
+    if( iIPSessionId > 0 )
+        {
+        // Register
+        iServer.Dispatcher().RegisterL( iIPSessionId, *this );
+        }
+    else
+        {
+        User::Leave( iIPSessionId );
+        }                             
+    
+    CleanupStack::PopAndDestroy( xmlDoc );
+    
+    iWait.Start();
+    
+    __LOG1( "CUPnPUploadSession::ReadyForTransferL\
+        iAsyncError = %d", iAsyncError );
+
+    User::LeaveIfError( iAsyncError );
+
+    const CUpnpElement& resEl = UPnPItemUtility::FindElementByNameL(
+        *iResources[ iResourceIndex ]->Item(), KElementRes );
+
+    const CUpnpAttribute* pInfo = UPnPItemUtility::FindAttributeByName(
+        resEl, KAttributeProtocolInfo );  
+
+    CUpnpDlnaProtocolInfo* tmpInfo = CUpnpDlnaProtocolInfo::NewL(
+        pInfo->Value() );
+    CleanupStack::PushL( tmpInfo );      
+    
+    // Set DLNA specific headers    
+    if( tmpInfo->PnParameter().Length() )
+        {
+        // DLNA content, set the content-features header
+        iUploader->SetHeaderL( (TAny*)aEvent.iKey, KContentFeatures,
+            tmpInfo->FourthField() );        
+
+        // Check if background mode is available and use it if it is
+        if( tmpInfo->DlnaFlag( UpnpDlnaProtocolInfo::TM_B_FLAG ) )
+            {
+            __LOG( "ReadyForTransferL - Use background mode" );
+            
+            iUploader->SetHeaderL( (TAny*)aEvent.iKey, KTransferMode,
+                KBackgroundMode );  
+            }
+        else
+            {
+            // Background is not available for some reason.
+            // Check if media specific transfer mode is available
+            if( UPnPCommonUtils::IsImageSupported( tmpInfo->ProtocolInfoL() ) )
+                {
+                // Uploading image, alternative for background is interactive
+                if( tmpInfo->DlnaFlag( UpnpDlnaProtocolInfo::TM_I_FLAG ) )
+                    {
+                    __LOG( "ReadyForTransferL - Use interactive mode" );
+                    iUploader->SetHeaderL( (TAny*)aEvent.iKey, KTransferMode,
+                        KInteractiveMode );
+                    }
+                else
+                    {
+                    // Target DMS does not support appropriate transfer mode
+                    __LOG( "ReadyForTransferL - No appropriate mode" );
+                    // Still, give a try and use background
+                    iUploader->SetHeaderL( (TAny*)aEvent.iKey, KTransferMode,
+                        KBackgroundMode );  
+                    }            
+                }
+            else if( UPnPCommonUtils::IsAudioSupported(
+                        tmpInfo->ProtocolInfoL() ) ||
+                    UPnPCommonUtils::IsVideoSupported(
+                        tmpInfo->ProtocolInfoL() ) )
+                {
+                // Uploading A/V, alternative for background is streaming
+                if( tmpInfo->DlnaFlag( UpnpDlnaProtocolInfo::TM_S_FLAG ) )
+                    {
+                    __LOG( "ReadyForTransferL - Use streaming mode" );
+                    iUploader->SetHeaderL( (TAny*)aEvent.iKey, KTransferMode,
+                    KStreamingMode );
+                    }
+                else
+                    {
+                    // Target DMS does not support appropriate transfer mode
+                    __LOG( "ReadyForTransferL - No appropriate mode" );
+                    // Still, give a try and use background
+                    iUploader->SetHeaderL( (TAny*)aEvent.iKey, KTransferMode,
+                        KBackgroundMode );  
+                    }                 
+                }
+            else
+                {
+                __LOG( "ReadyForTransferL - Unknown media type" );
+                }    
+                        
+            }            
+
+        }                
+    
+    CleanupStack::PopAndDestroy( tmpInfo ); 
+    
+    iUploader->SetPropertyL( (TAny*)aEvent.iKey,
+        CHttpTransferBase::ETargetURI,
+        *iResources[ iResourceIndex ]->Resource() );
+            
+    iUploader->StartTransferL( (TAny*)aEvent.iKey );
+        
+    __LOG( "CUPnPUploadSession::ReadyForTransferL - end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ParseCreateObjectResponseL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::HandleObjectResponseL( const TDesC8& aObjectID,
+    const TDesC8& aResult )
+    {
+    __LOG( "CUPnPUploadSession::HandleObjectResponseL" );          
+    
+    HBufC8* importUri = ParseCreateObjectResponseL( aResult );
+    CleanupStack::PushL( importUri );
+
+    HBufC8* tmpUri = UpnpString::EncodeXmlStringL( importUri );
+    CleanupStack::PopAndDestroy( importUri );
+    CleanupStack::PushL( tmpUri );
+        
+    HBufC* tmpUri16 = UpnpString::ToUnicodeL( *tmpUri );
+    CleanupStack::PopAndDestroy( tmpUri );
+          
+    iResources[ iResourceIndex ]->SetResource( tmpUri16 );
+        
+    HBufC8* tmpID = aObjectID.AllocL();
+    iResources[ iResourceIndex ]->SetItemId( tmpID );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ParseCreateObjectResponseL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+HBufC8* CUPnPUploadSession::ParseCreateObjectResponseL(
+    const TDesC8& aResponse )
+    {
+    __LOG( "CUPnPUploadSession::ParseCreateObjectResponseL" );          
+    
+    HBufC8* importURI = NULL;
+    
+    CUPnPXMLParser* parser = CUPnPXMLParser::NewL();
+    CleanupStack::PushL( parser );
+    
+    RPointerArray<CUpnpObject> array;
+    CleanupResetAndDestroyPushL( array );
+    
+    parser->ParseResultDataL( array, aResponse );
+    
+    TInt count = array.Count();
+    
+    // Lets find the first item with an import URI and use that
+    for( TInt i = 0; i < count; i++ )
+        {
+        importURI = ImportURIFromItemL( *array[ i ] );
+        if( importURI )
+            {
+             // Transfer ownership, casting is safe
+             // (array[ 0 ]->ObjectType() == EUPnPItem)
+            CUpnpItem* item = static_cast<CUpnpItem*>( array[ i ] );
+            iResources[ iResourceIndex ]->SetItem( item );
+            array.Remove( i );
+            i = count;
+            }
+        }
+    if( !importURI ) // no suitable items, leave
+        {
+        User::Leave( KErrGeneral );
+        }
+            
+    CleanupStack::PopAndDestroy( &array );
+    CleanupStack::PopAndDestroy( parser );  
+              
+    if( !UpnpCdsResElementUtility::IsUriAbsolute( *importURI ) )
+        {
+        // Import uri is not absolute, upload not supported. leave.
+        delete importURI; importURI = NULL;
+        User::Leave( KErrGeneral );
+        }
+      
+    return importURI;
+    }       
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ImportURIFromItemL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+HBufC8* CUPnPUploadSession::ImportURIFromItemL( const CUpnpObject& aObject )
+    {
+    HBufC8* importURI = NULL;
+    if( aObject.ObjectType() == EUPnPItem )
+        {
+        // Get the res-elements
+        RUPnPElementsArray elArray;
+        CleanupClosePushL( elArray );
+        UPnPItemUtility::GetResElements( aObject, elArray );
+        
+        // Find the import uri 
+        TInt count = elArray.Count();           
+        for( TInt i = 0; i < count; i++ )
+            {
+            const CUpnpAttribute* attribute = NULL;
+            attribute = &UPnPItemUtility::FindAttributeByNameL(
+                *elArray[ i ], KImportUri );
+            if( attribute )
+                {
+                // import uri found
+                i = count;
+                importURI = attribute->Value().AllocL();
+                }
+            }            
+        CleanupStack::PopAndDestroy( &elArray );        
+        }
+    return importURI;
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPUploadSession::ProtocolInfoToUPnPL
+// See upnpbrowsingsession.h
+// --------------------------------------------------------------------------
+void CUPnPUploadSession::ProtocolInfoToUPnPL( const CUpnpAttribute* aInfo )
+    {
+    __LOG( "CUPnPUploadSession::ProtocolInfoToUPnPL" );
+    
+    CUpnpDlnaProtocolInfo* destInfo =
+        CUpnpDlnaProtocolInfo::NewL( aInfo->Value() );
+    CleanupStack::PushL( destInfo );
+    
+    if( destInfo->PnParameter().Length() )
+        {
+        __LOG( "ProtocolInfoToUPnPL - Convert to UPnP" );
+        
+        CUpnpProtocolInfo* targetInfo = CUpnpProtocolInfo::NewL();
+        CleanupStack::PushL( targetInfo );
+        
+        targetInfo->SetFirstFieldL( destInfo->FirstField() );
+        targetInfo->SetSecondFieldL( KAsterisk );
+        targetInfo->SetThirdFieldL( destInfo->ThirdField() );
+        targetInfo->SetFourthFieldL( KAsterisk );
+        
+        // A bit dirty const cast.. but makes implementation much easier
+        CUpnpAttribute* bute = const_cast<CUpnpAttribute*>( aInfo );
+        bute->SetValueL( targetInfo->ProtocolInfoL() );
+        
+        CleanupStack::PopAndDestroy( targetInfo );
+        }
+    else
+        {
+        __LOG( "ProtocolInfoToUPnPL - UPnP content -> do nothing" );
+        // Not DLNA content, do nothing
+        }    
+        
+    CleanupStack::PopAndDestroy( destInfo );
+    }
+
+//---------------------------------------------------------------------------
+// CUPnPUploadSession::StopWait()
+// See upnpbrowsingsession.h
+//---------------------------------------------------------------------------
+//
+void CUPnPUploadSession::StopWait()
+    {
+    __LOG( "ProtocolInfoToUPnPL::StopWait" );
+    if ( iWait.IsStarted() )
+        {
+        if ( iWait.CanStopNow() )
+            {
+            __LOG( "ProtocolInfoToUPnPL::StopWait - stop" );
+            iWait.AsyncStop();
+            iSchedulerStopped = ETrue;
+            }
+        else
+            {
+            __LOG( "CUPnPUploadSession::StopWait\
+- not able to stop now, use callback" );
+            iSchedulerStopped = EFalse;
+            iWait.AsyncStop( TCallBack(
+                                SchedulerStoppedCallBack,
+                                this ) );
+            }
+        }
+    }
+
+//---------------------------------------------------------------------------
+// CUPnPUploadSession::SchedulerStoppedCallBack()
+// See upnpbrowsingsession.h
+//---------------------------------------------------------------------------
+//
+TInt CUPnPUploadSession::SchedulerStoppedCallBack( TAny* aPtr )
+    {
+    CUPnPUploadSession* self = 
+        static_cast<CUPnPUploadSession*>( aPtr );
+    self->DoSchedulerStoppedCallBack();
+    return 0;
+    }
+
+//---------------------------------------------------------------------------
+// CUPnPUploadSession::DoSchedulerStoppedCallBack()
+// See upnpbrowsingsession.h
+//---------------------------------------------------------------------------
+//
+void CUPnPUploadSession::DoSchedulerStoppedCallBack()
+    {
+    __LOG( "ProtocolInfoToUPnPL::DoSchedulerStoppedCallBack" );
+    iSchedulerStopped = ETrue;
+    }
+
+// End of file