fotaapplication/fotaserver/src/FotaDlClient.cpp
changeset 44 39aa16f3fdc2
child 73 ae69c2e8bc34
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fotaapplication/fotaserver/src/FotaDlClient.cpp	Tue Jul 06 15:14:24 2010 +0300
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2005 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:   Fota download client 
+ *
+ */
+#include <XQConversions>
+#include "FotaDlClient.h"
+#include "FotaDlMgrClient.h"
+
+// -----------------------------------------------------------------------------
+// The constructor of this class
+// -----------------------------------------------------------------------------
+DownloadClient::DownloadClient(DownloadManagerClient* Observer)
+    {
+    FLOG(_L("DownloadClient::DownloadClient >>"));
+    
+    iFotaDlMgrClient = Observer;
+    iTotalSize = -1;
+    iSpaceChecked = 0;
+    iDownload = NULL;
+    iClientinterrupted = false;
+    iClientError = ErrorNone;
+    iContentType = TUnknownType;
+    
+    FLOG(_L("DownloadClient::DownloadClient <<"));
+    }
+
+// -----------------------------------------------------------------------------
+// The destructor of this class 
+// -----------------------------------------------------------------------------
+DownloadClient::~DownloadClient()
+    {
+    FLOG(_L("DownloadClient::~DownloadClient >>"));
+
+    if (iDownload)
+        {
+        disconnect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
+                SLOT(DownloadEventRecieved(DownloadEvent *)));
+
+        //Do not delete iDownload as it is owned by download manager.
+        //delete iDownload;
+        iDownload = NULL;
+        }
+    //Don't delete as it is not owned
+    iFotaDlMgrClient = NULL;
+
+    FLOG(_L("DownloadClient::~DownloadClient <<"));
+    }
+
+// -----------------------------------------------------------------------------
+// Creates a single download with the download manager
+// -----------------------------------------------------------------------------
+TInt DownloadClient::CreateDownload(const QString &url, DownloadType type)
+    {
+    FLOG(_L("DownloadClient::CreateDownload >>"));
+
+    TInt ret = ENotOk;
+
+    iDownload = iFotaDlMgrClient->Manager()->createDownload(url, type); //Step 6
+
+    if (iDownload)
+        {
+        connect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
+                SLOT(DownloadEventRecieved(DownloadEvent *)));
+        ret = EOk;
+        }
+    else
+        {
+        FLOG(_L("Download creation is unsuccessful!"));
+        }
+
+    FLOG(_L("DownloadClient::CreateDownload, ret = %d <<"), ret);
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// Sets the required attributes for the single download.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::SetDownloadAttributes()
+    {
+    FLOG(_L("DownloadClient::SetDownloadAttributes >>"));
+
+    int ret(EOk);
+
+    iDownload->setAttribute(ProgressInterval, 100); //Step 7
+    iDownload->setAttribute(Priority, High); //Step 8
+
+    //Setting the default path
+    iDownload->setAttribute(DestinationPath, DefaultPath);
+
+    iDownload->setAttribute(FileName, PackageName);
+
+    FLOG(_L("DownloadClient::SetDownloadAttributes, ret = %d <<"), ret);
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// Starts the single download. Download should be created and attributes set before this.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::Start()
+    {
+    FLOG(_L("DownloadClient::Start >>"));
+
+    iClientinterrupted = false;
+    iDownload->start(); //Step 9
+
+    FLOG(_L("DownloadClient::Start <<"));
+    return EOk;
+
+    }
+
+// -----------------------------------------------------------------------------
+// Gets the attribute of the single download
+// -----------------------------------------------------------------------------
+inline QVariant DownloadClient::GetDownloadAttribute(DownloadAttribute attr)
+    {
+    FLOG(_L("DownloadClient::GetDownloadAttribute >>"));
+
+    QVariant val;
+
+    val = iDownload->attribute(attr);
+
+    FLOG(_L("DownloadClient::GetDownloadAttribute<<"));
+    return val;
+    }
+
+// -----------------------------------------------------------------------------
+// Pauses the single download.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::Pause(TClientErrorType aReason)
+    {
+    FLOG(_L("DownloadClient::Pause >>"));
+
+    iClientinterrupted = true;
+    iClientError = aReason;
+
+    iDownload->pause();
+
+    FLOG(_L("DownloadClient::Pause <<"));
+    return EOk;
+    }
+
+// -----------------------------------------------------------------------------
+// Resumes the single download.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::Resume()
+    {
+    FLOG(_L("DownloadClient::Resume >>"));
+
+    int ret(ENotOk);
+    iSpaceChecked = true;
+
+    if (!iDownload)
+        {
+        QList<Download*> dls =
+                iFotaDlMgrClient->Manager()->currentDownloads();
+        int count = dls.count();
+        FLOG(_L("Number of current downloads = %d"), count);
+
+        if (count)
+            {
+            iDownload = dls[0];
+            FLOG(_L("Connecting to download event"));
+            connect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
+                    SLOT(DownloadEventRecieved(DownloadEvent *)));
+            FLOG(_L("Connecting to download events done"));
+            }
+
+        }
+    iClientinterrupted = false;
+    iClientError = ErrorNone;
+
+    if (iDownload)
+        {
+        FLOG(_L("B4 Download Start"));
+        iDownload->start();
+        ret = EOk;
+        FLOG(_L("After Download Start"));
+        }
+
+    FLOG(_L("DownloadClient::Resume, ret = %d <<"), ret);
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// Cancels the single download.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::Cancel(TClientErrorType aReason)
+    {
+    FLOG(_L("DownloadClient::Cancel >>"));
+
+    iClientinterrupted = true;
+    iClientError = aReason;
+
+    iDownload->cancel();
+
+    FLOG(_L("DownloadClient::Cancel <<"));
+    return EOk;
+    }
+
+// -----------------------------------------------------------------------------
+// Restarts the single download. This is equivalent to cancel and start on Download.
+// -----------------------------------------------------------------------------
+TInt DownloadClient::Restart()
+    {
+    FLOG(_L("DownloadClient::Restart >>"));
+
+    QString path(NULL);
+    int size = iTotalSize;
+    TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(size, path);
+
+    if (avail == EFitsToReservation || avail == EFitsToFileSystem)
+        {
+        //FLOG(_L("Space is available for download at %S"), TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
+        
+        if (iContentType == TOmaDL10Download)
+            {
+            ReadDescriptorData();
+            }
+        Resume();
+        }
+    else
+        {
+        FLOG(_L("Space not available. Download is stopped!"));
+        TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory, size));
+        }
+
+    FLOG(_L("DownloadClient::Restart >>"));
+
+    return EOk;
+    }
+
+// -----------------------------------------------------------------------------
+// The slot which receives all the single download events.
+// -----------------------------------------------------------------------------
+bool DownloadClient::DownloadEventRecieved(DownloadEvent *event)
+    {
+    FLOG(_L("DownloadClient::event >>"));
+
+    DownloadEvent::Event type = (DownloadEvent::Event) event->type();
+    bool eventHandled = false;
+    int err0(NoError);
+
+    FLOG(_L("Download Event Type: %d"), type);
+
+    switch (type)
+        {
+        case DownloadEvent::Started:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Started"));
+            iProgress = true;
+            iDlState = Download::Created;
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::HeadersReceived:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::HeadersReceived"));
+            iProgress = true;
+            iDlState = Download::Created;
+
+            QString contenttype =
+                    GetDownloadAttribute(ContentType).toString();
+            HBufC* s_contenttype = XQConversions::qStringToS60Desc(contenttype);
+            FLOG(_L("Content type received is %S"), s_contenttype);
+            delete s_contenttype;
+
+            iContentType = CheckContentType(contenttype);
+
+            if (iContentType == THttpDownload)
+                {
+                FLOG(_L("Content type: Http; checking the size of download"));
+                if (!iSpaceChecked)
+                    {
+
+                    iTotalSize = GetDownloadAttribute(TotalSize).toInt();
+
+                    FLOG(_L("Size of the firmware update as received is %d"),
+                            iTotalSize);
+
+                    if (iTotalSize > 0)
+                        {
+                        QString path(NULL);
+
+                        TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(
+                                iTotalSize, path);
+
+                        if (avail == EFitsToReservation || avail
+                                == EFitsToFileSystem)
+                            {
+                            //FLOG(_L("Space is available for download at %S"),TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
+                            iFotaDlMgrClient->DeleteDiskReservation(path);
+                            iDownload->setAttribute(DestinationPath, path);
+                            }
+                        else
+                            {
+                            FLOG(
+                                    _L("Space not available. Download is stopped!"));
+                            Pause(NeedMoreMemory);
+                            TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory));
+                            break;
+                            }
+
+                        iSpaceChecked = true;
+                        iFotaDlMgrClient->StartDownloadProgress(
+                                QString::null, QString::null, iTotalSize);
+                        }
+                    }
+                }
+            else if (iContentType == TUnknownType)
+                {
+                FLOG(_L("Content type unknown; hence cancelling download !"));
+                Cancel(InvalidContentType);
+                }
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::InProgress:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::InProgress"));
+
+            iProgress = true;
+            iDlState = Download::InProgress;
+            UpdateDownloadProgress();
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::Completed:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Completed"));
+            iProgress = false;
+            iDlState = Download::Completed;
+            iTotalSize = 0;
+            UpdateDownloadProgress();
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::Paused:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Paused"));
+            iProgress = false;
+            iDlState = Download::Paused;
+
+            eventHandled = true;
+            break;
+            }
+        case DownloadEvent::Failed:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Failed"));
+            iProgress = false;
+            iDlState = Download::Failed;
+
+            eventHandled = true;
+            break;
+            }
+        case DownloadEvent::Cancelled:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Cancelled"));
+            iProgress = false;
+            iDlState = Download::Cancelled;
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::NetworkLoss:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::NetworkLoss"));
+            iProgress = false;
+            iDlState = Download::Paused;
+
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::Error:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::Error"));
+            iProgress = false;
+           // iDlState = (Download::State) GetDownloadAttribute(State).toInt();
+            iDlState = Download::Failed;
+            eventHandled = true;
+            break;
+            }
+
+        case DownloadEvent::DescriptorReady:
+            {
+            FLOG(_L("DownloadEventRecieved - DownloadEvent::DescriptorReady"));
+            iProgress = true;
+            iDlState = Download::InProgress;
+            iContentType = TOmaDL10Download;
+
+            iTotalSize = GetDownloadAttribute(DescriptorSize).toInt();
+            QString path(NULL);
+            if (iTotalSize > 0)
+                {
+
+                TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(
+                        iTotalSize, path);
+
+                if (avail == EFitsToReservation || avail == EFitsToFileSystem)
+                    {
+                    //FLOG(_L("Space is available for download at %S"), TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
+                    iFotaDlMgrClient->DeleteDiskReservation(path);
+                    }
+                else
+                    {
+                    FLOG(_L("Space not available. Download is stopped!"));
+                    TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory));
+                    break;
+                    }
+                }
+            ReadDescriptorData();
+            Resume();
+            SetSubDownloadAttributes();
+
+            eventHandled = true;
+            break;
+            }
+        case DownloadEvent::CreatingConnection:
+            {
+            FLOG(
+                    _L("DownloadEventRecieved - DownloadEvent::CreatingConnection"));
+            iProgress = true;
+            iDlState = Download::InProgress;
+
+            eventHandled = true;
+            break;
+            }
+        case DownloadEvent::ConnectionNeeded:
+        case DownloadEvent::ConnectionDisconnected:
+            {
+            FLOG(
+                    _L("DownloadEventRecieved - DownloadEvent::ConnectionNeeded/ConnectionDisconnected"));
+            iProgress = false;
+            iDlState = Download::Paused;
+            err0 = ConnectionFailed;
+            eventHandled = true;
+            break;
+            }
+
+        default:
+            {
+            FLOG(_L("DownloadEventRecieved - Skipped this event: %d"), type);
+            break;
+            }
+        }
+
+    if (iProgress == false)
+        {
+
+        if (iClientinterrupted)
+            {
+            //Client has requested for cancellation. Hence provide the same error code
+            err0 = iClientError;
+            HandleClientInterrupt(iDlState, err0);
+            }
+        else
+            {
+            //Download Manager has cancelled download. Hence provide the last error code.
+            if (err0 == NoError)
+                err0 = GetDownloadAttribute(LastError).toInt();
+
+            HandleDownloadComplete(iDlState, err0);
+            }
+
+        }
+
+    FLOG(_L("DownloadClient::event <<"));
+
+    return eventHandled;
+    }
+
+// -----------------------------------------------------------------------------
+// Called to update the progress of download to fota server. This fetches the percentage
+// of download from download manager.
+// -----------------------------------------------------------------------------
+inline void DownloadClient::UpdateDownloadProgress()
+    {
+    FLOG(_L("DownloadClient::UpdateDownloadProgress >>"));
+
+    // Remaining size calculation
+    int prog = GetDownloadAttribute(Percentage).toInt();
+    iFotaDlMgrClient->UpdateDownloadProgress(prog);
+
+    FLOG(_L("DownloadClient::UpdateDownloadProgress, progress = %d <<"), prog);
+    }
+
+// -----------------------------------------------------------------------------
+// Called to read the OMA DL1.0 download descriptor. This will update the fota server with size and version.
+// -----------------------------------------------------------------------------
+void DownloadClient::ReadDescriptorData()
+    {
+    FLOG(_L("DownloadClient::ReadDescriptorData >>"));
+
+    QString name = GetDownloadAttribute(DescriptorName).toString(); // "name" in OMA dd
+    QString version = GetDownloadAttribute(DescriptorVersion).toString(); // "version" in OMA dd
+    QString type = GetDownloadAttribute(DescriptorType).toString(); // "type" in OMA dd
+    int size = GetDownloadAttribute(DescriptorSize).toInt(); // "size" in OMA dd
+    QString vendor = GetDownloadAttribute(DescriptorVendor).toString(); // "vendor" in OMA dd
+    QString description =
+            GetDownloadAttribute(DescriptorDescription).toString(); // "description" in OMA dd
+    QString nxturl = GetDownloadAttribute(DescriptorNextURL).toString(); // "nextURL" in OMA dd
+
+    TDownloadType gottype = CheckContentType(type);
+
+    if (gottype == THttpDownload)
+        {
+        iFotaDlMgrClient->StartDownloadProgress(name, version, size);
+        }
+    else
+        {
+        FLOG(
+                _L("The content type in descriptor is not appropriate! Hence cancelling download"));
+        Cancel(InvalidContentType);
+        }
+
+    FLOG(_L("DownloadClient::ReadDescriptorData <<"));
+    }
+
+// -----------------------------------------------------------------------------
+// Called when download is complete, either successfully or unsuccessfully.
+// The arguments to this function is read to know the actual status.
+// -----------------------------------------------------------------------------
+void DownloadClient::HandleDownloadComplete(Download::State dlstate, int err0)
+    {
+    FLOG(_L("DownloadClient::HandleDownloadComplete, idlstate = %d, err0 = %d>>"), dlstate, err0);
+
+    iFotaDlMgrClient->HandleDownloadEvent(dlstate, err0);
+
+    FLOG(_L("DownloadClient::HandleDownloadComplete <<"));
+    }
+
+// -----------------------------------------------------------------------------
+// Called to handle the post download interrupt operation when client cancels/pauses download.
+// -----------------------------------------------------------------------------
+void DownloadClient::HandleClientInterrupt(Download::State dlstate, int err0)
+    {
+    FLOG(_L("DownloadClient::HandleClientInterrupt, idlstate = %d, err0 = %d >>"), dlstate, err0);
+
+    iFotaDlMgrClient->HandleClientInterrupt(dlstate, err0);
+
+    FLOG(_L("DownloadClient::HandleClientInterrupt <<"));
+    }
+
+// -----------------------------------------------------------------------------
+// Called to validate the content type of the download as received in header.
+// -----------------------------------------------------------------------------
+TDownloadType DownloadClient::CheckContentType(const QString aContent)
+    {
+    FLOG(_L("DownloadClient::CheckContentType >>"));
+
+    TDownloadType type(TUnknownType);
+
+    QString semicollon(";");
+    QString contenttype = aContent;
+
+    int index = aContent.indexOf(semicollon, 0);
+
+    if (index > 0)
+        {
+        contenttype.chop(aContent.length() - index);
+        }
+
+    if (contenttype.compare(ContentTypeHttp) == 0)
+        type = THttpDownload;
+    else if (contenttype.compare(ContentTypeOmaDl) == 0)
+        type = TOmaDL10Download;
+
+    FLOG(_L("DownloadClient::CheckContentType, type = %d<<"), type);
+
+    return type;
+    }
+
+void DownloadClient::SetSubDownloadAttributes()
+    {
+    FLOG(_L("DownloadClient::SetSubDownloadAttributes >>"));
+
+    QList<Download*> dls = iDownload->subDownloads();
+
+    if (dls.count() > 0)
+        {
+        Download* subdl = dls[0];
+
+        subdl->setAttribute(FileName, PackageName);
+        }
+    else
+        {
+        FLOG(_L("Error: There are no sub downloads!"));
+        }
+
+    FLOG(_L("DownloadClient::SetSubDownloadAttributes <<"));
+    }
+
+//End of file