upnp/upnpstack/upnphttptransfer/src/httptransferbase.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:12:20 +0200
changeset 0 f5a58ecadc66
permissions -rw-r--r--
Revision: 201003

/** @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