utilities/downloadmanager/src/progressivedownloadserver.cpp
changeset 16 3c88a81ff781
equal deleted inserted replaced
14:6aeb7a756187 16:3c88a81ff781
       
     1 /**
       
     2    This file is part of CWRT package **
       
     3 
       
     4    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). **
       
     5 
       
     6    This program is free software: you can redistribute it and/or modify
       
     7    it under the terms of the GNU (Lesser) General Public License as 
       
     8    published by the Free Software Foundation, version 2.1 of the License. 
       
     9    This program is distributed in the hope that it will be useful, but
       
    10    WITHOUT ANY WARRANTY; without even the implied warranty of 
       
    11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
       
    12    (Lesser) General Public License for more details. You should have 
       
    13    received a copy of the GNU (Lesser) General Public License along 
       
    14    with this program. If not, see <http://www.gnu.org/licenses/>.
       
    15 */
       
    16 
       
    17 #include "progressivedownloadserver.h"
       
    18 #include "download.h"
       
    19 #include "dmcommon.h"
       
    20 #include "dmcommoninternal.h"
       
    21 #include <QTcpSocket>
       
    22 #include <QHostAddress>
       
    23 
       
    24 #define SERVER_WAIT_INTERVAL 1000
       
    25 
       
    26 // private implementation
       
    27 class ProgressiveDownloadServerPrivate
       
    28 {
       
    29     DM_DECLARE_PUBLIC(ProgressiveDownloadServer);
       
    30 public:
       
    31     ProgressiveDownloadServerPrivate();
       
    32     ~ProgressiveDownloadServerPrivate();
       
    33     QTcpServer* m_serverSocket;
       
    34     QTcpSocket* m_clientConnection;
       
    35     Download* m_download;
       
    36     DownloadState m_previousDlState;
       
    37 };
       
    38 
       
    39 ProgressiveDownloadServerPrivate::ProgressiveDownloadServerPrivate()
       
    40 {
       
    41     m_serverSocket = 0;
       
    42     m_clientConnection = 0;
       
    43     m_download = 0;
       
    44     m_previousDlState = DlNone;
       
    45 }
       
    46 
       
    47 ProgressiveDownloadServerPrivate::~ProgressiveDownloadServerPrivate()
       
    48 {
       
    49     if (m_serverSocket) {
       
    50         delete m_serverSocket;
       
    51         m_serverSocket = 0;
       
    52     }
       
    53 }
       
    54 
       
    55 Q_DECL_EXPORT ProgressiveDownloadServer::ProgressiveDownloadServer(Download* download)
       
    56 {
       
    57     DM_INITIALIZE(ProgressiveDownloadServer);
       
    58     priv->m_download = download;
       
    59 
       
    60     // create server socket
       
    61     priv->m_serverSocket = new QTcpServer(this);
       
    62     connect(priv->m_serverSocket, SIGNAL(newConnection()), this, SLOT(handleConnection()));
       
    63 }
       
    64 
       
    65 ProgressiveDownloadServer::~ProgressiveDownloadServer()
       
    66 {
       
    67     stopServer();
       
    68     DM_UNINITIALIZE(ProgressiveDownloadServer);
       
    69 }
       
    70 
       
    71 // starts the server
       
    72 Q_DECL_EXPORT int ProgressiveDownloadServer::startServer(void)
       
    73 {
       
    74     DM_PRIVATE(ProgressiveDownloadServer);
       
    75     if (!priv->m_serverSocket->isListening()) {
       
    76         QHostAddress localHost(QHostAddress::LocalHost);
       
    77         if (!priv->m_serverSocket->listen(localHost))
       
    78             return -1;
       
    79     }
       
    80     return 0;
       
    81 }
       
    82 
       
    83 // stops the server
       
    84 Q_DECL_EXPORT int ProgressiveDownloadServer::stopServer(void)
       
    85 {
       
    86     DM_PRIVATE(ProgressiveDownloadServer);
       
    87     // unregister the event listener
       
    88     priv->m_download->unregisterEventReceiver(this);
       
    89 
       
    90     // send the server down signal
       
    91     if ((priv->m_clientConnection) && (priv->m_clientConnection->state() == QAbstractSocket::ConnectedState)) {
       
    92         QByteArray block;
       
    93         QDataStream out(&block, QIODevice::WriteOnly);
       
    94         out.setVersion(QDataStream::Qt_4_0);
       
    95         out << (quint16)ProgressiveDlServerDown;
       
    96         priv->m_clientConnection->write(block);
       
    97         priv->m_clientConnection->flush();
       
    98 
       
    99         // wait till the data is written
       
   100         if (priv->m_clientConnection->waitForBytesWritten(SERVER_WAIT_INTERVAL))
       
   101             return 0;
       
   102         else
       
   103             return -1;
       
   104     }
       
   105 
       
   106     if (priv->m_serverSocket->isListening())
       
   107         priv->m_serverSocket->close();
       
   108 
       
   109     return 0;
       
   110 }
       
   111 
       
   112 Q_DECL_EXPORT quint16 ProgressiveDownloadServer::serverPort(void)
       
   113 {
       
   114     DM_PRIVATE(ProgressiveDownloadServer);
       
   115     if (priv->m_serverSocket)
       
   116         return priv->m_serverSocket->serverPort();
       
   117     else
       
   118         return 0;
       
   119 }
       
   120 
       
   121 // last error occurred
       
   122 Q_DECL_EXPORT ProgressiveDlServerError ProgressiveDownloadServer::lastError(void)
       
   123 {
       
   124     DM_PRIVATE(ProgressiveDownloadServer);
       
   125     return priv->m_serverSocket->serverError();
       
   126 }
       
   127 
       
   128 // last error occurred
       
   129 Q_DECL_EXPORT QString ProgressiveDownloadServer::lastErrorString(void)
       
   130 {
       
   131     DM_PRIVATE(ProgressiveDownloadServer);
       
   132     return priv->m_serverSocket->errorString();
       
   133 }
       
   134 
       
   135 void ProgressiveDownloadServer::handleConnection(void)
       
   136 {
       
   137     DM_PRIVATE(ProgressiveDownloadServer);
       
   138     priv->m_clientConnection = priv->m_serverSocket->nextPendingConnection();
       
   139     connect(priv->m_clientConnection, SIGNAL(readyRead()),
       
   140             this, SLOT(handleRequest()));
       
   141     priv->m_download->registerEventReceiver(this);
       
   142 
       
   143     // right now only one client is supported
       
   144     priv->m_serverSocket->close();
       
   145 }
       
   146 
       
   147 void ProgressiveDownloadServer::handleRequest(void)
       
   148 {
       
   149     // handles the request from client
       
   150     DM_PRIVATE(ProgressiveDownloadServer);
       
   151     quint16 requestCode;
       
   152     QDataStream in(priv->m_clientConnection);
       
   153     in.setVersion(QDataStream::Qt_4_0);
       
   154 
       
   155     if (priv->m_clientConnection->bytesAvailable() < (int)sizeof(quint16))
       
   156         return;
       
   157 
       
   158     in >> requestCode;
       
   159     // act according to the request
       
   160     if ((ProgressiveOperation)requestCode == DlPause)
       
   161         priv->m_download->pause();
       
   162     else if ((ProgressiveOperation)requestCode == DlResume)
       
   163         priv->m_download->resume();
       
   164     else if ((ProgressiveOperation)requestCode == DlCancel)
       
   165         priv->m_download->cancel();
       
   166     else if ((ProgressiveOperation)requestCode == DlGetAttribute) {
       
   167         // getAttribute is synchronous, so send the response here
       
   168         quint16 attr;
       
   169         in >> attr;
       
   170         QVariant value;
       
   171         value = priv->m_download->getAttribute((DownloadAttribute)attr);
       
   172         QByteArray block;
       
   173         QDataStream out(&block, QIODevice::WriteOnly);
       
   174         out.setVersion(QDataStream::Qt_4_0);
       
   175         out << (quint16)ProgressiveDlGetAttribute;
       
   176         out << value;
       
   177         priv->m_clientConnection->write(block);
       
   178         priv->m_clientConnection->flush();
       
   179     }
       
   180 }
       
   181 
       
   182 bool ProgressiveDownloadServer::event(QEvent *event)
       
   183 {
       
   184     DM_PRIVATE(ProgressiveDownloadServer);
       
   185     DEventType type = (DEventType)event->type();
       
   186     QByteArray block;
       
   187     QDataStream out(&block, QIODevice::WriteOnly);
       
   188     out.setVersion(QDataStream::Qt_4_0);
       
   189 
       
   190     // handle the events from the download and send the response to the client
       
   191     switch(type) {
       
   192     case Progress:
       
   193         // send the response only once when it is resumed
       
   194         // to avoid continueously writing to the response buffer and increasing the ipc overhead 
       
   195         if (priv->m_previousDlState != DlInprogress) {
       
   196             priv->m_previousDlState = DlInprogress;
       
   197             out << (quint16)ProgressiveDlInprogress;
       
   198             priv->m_clientConnection->write(block);
       
   199             priv->m_clientConnection->flush();
       
   200         }
       
   201         break;
       
   202     case Paused:
       
   203         priv->m_previousDlState = DlPaused;
       
   204         out << (quint16)ProgressiveDlPaused;
       
   205         priv->m_clientConnection->write(block);
       
   206         priv->m_clientConnection->flush();
       
   207         break;
       
   208     case Completed:
       
   209         priv->m_previousDlState = DlCompleted;
       
   210         out << (quint16)ProgressiveDlCompleted;
       
   211         priv->m_clientConnection->write(block);
       
   212         priv->m_clientConnection->flush();
       
   213         break;
       
   214     case Failed:
       
   215         priv->m_previousDlState = DlFailed;
       
   216         out << (quint16)ProgressiveDlFailed;
       
   217         priv->m_clientConnection->write(block);
       
   218         priv->m_clientConnection->flush();
       
   219         break;
       
   220     case Cancelled:
       
   221         priv->m_previousDlState = DlCancelled;
       
   222         out << (quint16)ProgressiveDlCancelled;
       
   223         priv->m_clientConnection->write(block);
       
   224         priv->m_clientConnection->flush();
       
   225         break;
       
   226     case NetworkLoss:
       
   227         priv->m_previousDlState = DlPaused;
       
   228         out << (quint16)ProgressiveDlPaused;
       
   229         priv->m_clientConnection->write(block);
       
   230         priv->m_clientConnection->flush();
       
   231         break;
       
   232     default:
       
   233         break;
       
   234     }
       
   235     // event is consumed in any case.
       
   236     return true;
       
   237 }
       
   238        
       
   239