upnp/upnpstack/upnphttptransfer/src/httptransferbase.cpp
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/upnphttptransfer/src/httptransferbase.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,605 @@
+/** @file
+* 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:  Base class for downloader / uploader classes
+*
+*/
+
+
+// System include files
+#include <escapeutils.h>
+
+// User include files
+#include "httptransferbase.h"
+#include "httptransferobserver.h"
+#include "httpfile.h"
+#include "httptransferworker.h"
+#include "httpworkerobserver.h"
+
+// Definitions
+enum TTransferStates 
+    {
+    ETransferNextFile
+    };
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::CHttpTransferBase()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+CHttpTransferBase::CHttpTransferBase() : CActive( EPriorityStandard ) 
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::~CHttpTransferBase()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+CHttpTransferBase::~CHttpTransferBase()
+    {
+    if( IsActive() )
+        {
+        CActive::Cancel();
+        }
+
+    // Reset array and destroy all the items in it
+    iFileQueue.ResetAndDestroy();
+    iWorkerArray.ResetAndDestroy();
+    iWaitQueue.ResetAndDestroy();
+    }
+
+// --------------------------------------------------------------------------
+// CHttpDownloader::CancelAll
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::CancelAll()
+    {
+    // Reset arrays and destroy all the items in them
+    iFileQueue.ResetAndDestroy();
+    iWaitQueue.ResetAndDestroy();
+
+    for( TInt i=0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( iWorkerArray[i]->ProcessOnGoing() )
+            {
+            iWorkerArray[i]->CancelTransfer();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::Cancel
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpTransferBase::CancelTransfer( TAny* aKey )
+    {
+    TInt retval = KErrNotFound;
+
+    // Find the item corresponding aKey and delete it and
+    // remove from the wait queue
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            retval = KErrNone;
+            delete iWaitQueue[i];
+            iWaitQueue.Remove(i);
+            iWaitQueue.Compress();
+            }
+        }
+
+    // Find the item corresponding aKey and delete it and
+    // remove from the file queue
+    for ( TInt i = 0; i < iFileQueue.Count(); i++ )
+        {
+        if ( iFileQueue[i]->Key() == aKey )
+            {
+            retval = KErrNone;
+            delete iFileQueue[i];
+            iFileQueue.Remove(i);
+            iFileQueue.Compress();
+            }
+        }
+
+    // Check if some of the ongoing processes has to be canceled
+    for ( TInt i = 0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( iWorkerArray[i]->ProcessOnGoing() )
+            {
+            if ( iWorkerArray[i]->Key() == aKey )
+                {
+                retval = KErrNone;
+                iWorkerArray[i]->CancelTransfer();
+                }
+            }
+        }
+
+    return retval;
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::TrackProgress
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C TInt CHttpTransferBase::TrackProgress( TAny* aKey, TBool aValue )
+    {
+    TInt retval = KErrNotFound;
+
+    // Find the corresponding file from iWaitQueue
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            retval = KErrNone;
+            iWaitQueue[i]->TrackProgress( aValue );
+            }
+        }
+
+    // Find the corresponding instance of CHttpFile from iFileQueue and
+    // switch the tracking of the progress on
+    for ( TInt i = 0; i < iFileQueue.Count(); i++)
+        {
+        if ( iFileQueue[i]->Key() == aKey )
+            {
+            retval = KErrNone;
+            iFileQueue[i]->TrackProgress( aValue );
+            }
+        }
+
+    // Check if processed files have to be tracked
+    for ( TInt i = 0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( iWorkerArray[i]->ProcessOnGoing() && 
+             iWorkerArray[i]->Key() == aKey ) 
+            {
+            retval = KErrNone;
+            iWorkerArray[i]->TrackProgress( aValue );    
+            }
+        }
+
+    return retval;
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::SetHeaderL
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//    
+EXPORT_C void CHttpTransferBase::SetHeaderL( TAny* aKey,
+                                             const TDesC8& aFieldName, 
+                                             const TDesC8& aFieldValue )
+    {
+    TBool keyExists = EFalse;
+
+    // Go through iWaitQueue and if there is file mathich the key set headers
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            keyExists = ETrue;
+            iWaitQueue[i]->SetHeaderL( aFieldName, aFieldValue );
+            }
+        }
+
+    // Go through workers and set the headers to the downloaded file which
+    // has matching key
+    for ( TInt i = 0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( iWorkerArray[i]->Key() == aKey )
+            {
+            // if the worker is not waiting -> leave
+            if ( !iWorkerArray[i]->IsWaiting() )
+                {
+                User::Leave( KErrGeneral );
+                }
+
+            ( iWorkerArray[i]->ProcessedFile() )->
+                           SetHeaderL( aFieldName, aFieldValue );
+            keyExists = ETrue;
+            }
+        }
+
+    if ( !keyExists )
+        {
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::CreateAndQueueHttpFile()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::CreateAndQueueHttpFileL( const TDesC8& aUri,
+                                                 const TDesC& aTargetPath,
+                                                 TAny* aKey )
+    {
+    CHttpFile* httpfile = CHttpFile::NewL( aKey, aUri, aTargetPath );
+    iFileQueue.Append( httpfile );
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::CreateAndQueueHttpFile()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::CreateAndQueueHttpFileL( const TDesC8& aUri,
+                                                 const RFile& aFileHandle,
+                                                 TAny* aKey )
+    {
+    CHttpFile* httpfile = CHttpFile::NewL( aKey, aUri, aFileHandle );
+    iFileQueue.Append( httpfile );
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::NextFile
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+CHttpFile* CHttpTransferBase::NextFile()
+    {
+    CHttpFile* newFile = NULL;
+
+    // If iFileQueue has files
+    if ( iFileQueue.Count() > 0 )
+        {
+        // Set the new processed file
+        newFile = iFileQueue[0];
+
+        // Set the queue
+        iFileQueue.Remove(0);
+        iFileQueue.Compress();
+        }
+
+    return newFile;
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::StartTransferL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::StartTransferL( TAny* aKey )
+    {
+    TBool keyExists = EFalse;
+
+    // go through workerarray and if there is worker which has 
+    // corresponding key -> start the transfer
+    for(TInt i=0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( iWorkerArray[i]->Key() == aKey )
+            {
+            iWorkerArray[i]->StartProcessL();
+            keyExists = ETrue;
+            }
+        }
+
+    // Leave if the key does not exist
+    if ( !keyExists )
+        {
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::SetProperty()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::SetPropertyL( TAny* aKey,
+                                               THttpPropertyType aProperty, 
+                                               const TDesC& aValue )
+    {
+
+    switch ( aProperty )
+        {
+        // This case is used to set targetUri. This is used in upnp upload
+        case ETargetURI:
+            {
+            TBool keyExists = EFalse;
+            HBufC8* uri = EscapeUtils::ConvertFromUnicodeToUtf8L( aValue );
+            CleanupStack::PushL( uri );
+
+            for ( TInt i=0; i < iWorkerArray.Count(); i++ )
+                {
+                if ( iWorkerArray[i]->Key() == aKey )
+                    {
+                    ( iWorkerArray[i]->ProcessedFile() )->
+                                                    SetUriL( uri->Des() );
+                    keyExists = ETrue;
+                    }
+                }
+
+            CleanupStack::PopAndDestroy( uri );
+
+            // the key was not found
+            if ( !keyExists )
+                {
+                User::Leave( KErrNotFound );
+                }
+
+            break;
+            }
+
+        default:
+            {
+            
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::GetPropertyL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C const HBufC* CHttpTransferBase::GetPropertyL( 
+                                                TAny* aKey,
+                                                THttpPropertyType aProperty )
+    {
+    const HBufC* retval = NULL;
+
+    switch ( aProperty )
+        {
+        // Client can receive the path of the transferred file using this
+        case ETargetPath:
+            {
+            TBool keyExists = EFalse;
+
+            // Goes through workerarray and returns the path of the file
+            // which matches the key
+            for ( TInt i = 0; i < iWorkerArray.Count(); i++ )
+                {
+                if ( iWorkerArray[i]->Key() == aKey )
+                    {
+                    retval = iWorkerArray[i]->Path();
+                    keyExists = ETrue;
+                    }
+                }
+
+            // the key was not found
+            if ( !keyExists )
+                {
+                User::Leave( KErrNotFound );
+                }
+
+            break;
+            }
+
+        default:
+            {
+            
+            break;
+            }
+        }
+
+    return retval;
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::InsertFileIntoWaitQueueL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::InsertFileIntoWaitQueueL(
+                                                    TAny* aKey,
+                                                    const TDesC& aTargetPath,
+                                                    const TDesC8& aUri )
+    {
+    // Checks first if the key already exists in iWaitQueue or in iFileQueue
+    // if does -> leave
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        }
+
+    for ( TInt i = 0; i < iFileQueue.Count(); i++ )
+        {
+        if ( iFileQueue[i]->Key() == aKey )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        }
+
+    // if key is valid create CHttpFile and insert it to iWaitQueue
+    CHttpFile* httpfile = CHttpFile::NewL( aKey, aUri, aTargetPath );
+    iWaitQueue.Append( httpfile );
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::InsertFileIntoWaitQueueL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::InsertFileIntoWaitQueueL(
+                                                    TAny* aKey,
+                                                    const RFile& aFileHandle,
+                                                    const TDesC8& aUri )
+    {
+    // Checks first if the key already exists in iWaitQueue or in iFileQueue
+    // if does -> leave
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        }
+
+    for ( TInt i = 0; i < iFileQueue.Count(); i++ )
+        {
+        if ( iFileQueue[i]->Key() == aKey )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        }
+
+    // if key is valid create CHttpFile and insert it to iWaitQueue
+    CHttpFile* httpfile = CHttpFile::NewL( aKey, aUri, aFileHandle );
+    iWaitQueue.Append( httpfile );
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::MoveToFileQueue()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CHttpTransferBase::MoveToTransferQueueL( TAny* aKey )
+    {
+    TBool keyExists = EFalse;
+    CHttpFile* waitFile = NULL;
+
+    for ( TInt i = 0; i < iWaitQueue.Count(); i++ )
+        {
+        if ( iWaitQueue[i]->Key() == aKey )
+            {
+            keyExists = ETrue;
+
+            // Removes the file from iWaitQueue
+            waitFile = iWaitQueue[i];
+
+            // Set the queue
+            iWaitQueue.Remove(i);
+            iWaitQueue.Compress();
+            }
+        }
+
+    // If the key does not exist -> leaves
+    if ( !keyExists )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    // Appends the file to iFileQueue
+    iFileQueue.Append( waitFile );
+
+    // start the transfer
+    ActivateNewTransferRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::ActivateNewTransferRequest()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::ActivateNewTransferRequest()
+    {
+    if ( !IsActive() )
+        {
+        SetActive();
+        TRequestStatus* pStatus = &iStatus;
+        User::RequestComplete( pStatus, ETransferNextFile );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::ProcessNextFileL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::ProcessNextFileL()
+    {
+    // Check that there is workers available
+    for ( TInt i = 0; i < iWorkerArray.Count(); i++ )
+        {
+        if ( !iWorkerArray[i]->ProcessOnGoing() )
+            {
+            CHttpFile* nextFile = NULL;
+
+            nextFile = NextFile();
+
+            if ( nextFile )
+                {
+                // sets the file and sets the state to EWaitingForStart
+                iWorkerArray[i]->SetFileL( *nextFile );
+
+                // Set worker which is handled to pointer so that 
+                // if it leaves the worker can be terminated
+                iActiveWorker = iWorkerArray[i];
+
+                iObserver->ReadyForTransferL( nextFile->Key() );
+
+                iActiveWorker = NULL;
+                }
+            }
+        }
+    }
+
+
+// From base class CActive
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::DoCancel()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::DoCancel()
+    {
+    CancelAll();
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::RunL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::RunL()
+    {
+    ProcessNextFileL();
+    }
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::RunError()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+TInt CHttpTransferBase::RunError( TInt aError )
+    {
+    // Terminate worker which leaved
+    if ( iActiveWorker )
+        {
+        // Cancels the transfer and 
+        // informs the client through TransferCompleted()
+        iObserver->TransferCompleted( iActiveWorker->Key(), aError );
+        iActiveWorker->CancelTransfer();
+        iActiveWorker = NULL;
+        }
+
+    return KErrNone;
+    }
+
+
+// From base class MHttpWorkerObserver
+
+// --------------------------------------------------------------------------
+// CHttpTransferBase::ProcessNextFileL()
+// (See comments in header file)
+// --------------------------------------------------------------------------
+//
+void CHttpTransferBase::WorkerCompleted()
+    {
+    ActivateNewTransferRequest();
+    }
+
+// end of file