choke uploadProgress signals
[profile/ivi/qtbase.git] / src / network / access / qhttpthreaddelegate_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QHTTPTHREADDELEGATE_H
43 #define QHTTPTHREADDELEGATE_H
44
45
46 //
47 //  W A R N I N G
48 //  -------------
49 //
50 // This file is not part of the Qt API.  It exists for the convenience
51 // of the Network Access API.  This header file may change from
52 // version to version without notice, or even be removed.
53 //
54 // We mean it.
55 //
56
57 #include <QObject>
58 #include <QThreadStorage>
59 #include <QNetworkProxy>
60 #include <QSslConfiguration>
61 #include <QSslError>
62 #include <QList>
63 #include <QNetworkReply>
64 #include "qhttpnetworkrequest_p.h"
65 #include "qhttpnetworkconnection_p.h"
66 #include <QSharedPointer>
67 #include "qsslconfiguration.h"
68 #include "private/qnoncontiguousbytedevice_p.h"
69 #include "qnetworkaccessauthenticationmanager_p.h"
70
71 #ifndef QT_NO_HTTP
72
73 QT_BEGIN_NAMESPACE
74
75 class QAuthenticator;
76 class QHttpNetworkReply;
77 class QEventLoop;
78 class QNetworkAccessCache;
79 class QNetworkAccessCachedHttpConnection;
80
81 class QHttpThreadDelegate : public QObject
82 {
83     Q_OBJECT
84 public:
85     explicit QHttpThreadDelegate(QObject *parent = 0);
86
87     ~QHttpThreadDelegate();
88
89     // incoming
90     bool ssl;
91 #ifndef QT_NO_SSL
92     QSslConfiguration incomingSslConfiguration;
93 #endif
94     QHttpNetworkRequest httpRequest;
95     qint64 downloadBufferMaximumSize;
96     qint64 readBufferMaxSize;
97     qint64 bytesEmitted;
98     // From backend, modified by us for signal compression
99     QSharedPointer<QAtomicInt> pendingDownloadData;
100     QSharedPointer<QAtomicInt> pendingDownloadProgress;
101 #ifndef QT_NO_NETWORKPROXY
102     QNetworkProxy cacheProxy;
103     QNetworkProxy transparentProxy;
104 #endif
105     QSharedPointer<QNetworkAccessAuthenticationManager> authenticationManager;
106     bool synchronous;
107
108     // outgoing, Retrieved in the synchronous HTTP case
109     QByteArray synchronousDownloadData;
110     QList<QPair<QByteArray,QByteArray> > incomingHeaders;
111     int incomingStatusCode;
112     QString incomingReasonPhrase;
113     bool isPipeliningUsed;
114     qint64 incomingContentLength;
115     QNetworkReply::NetworkError incomingErrorCode;
116     QString incomingErrorDetail;
117 #ifndef QT_NO_BEARERMANAGEMENT
118     QSharedPointer<QNetworkSession> networkSession;
119 #endif
120
121 protected:
122     // The zerocopy download buffer, if used:
123     QSharedPointer<char> downloadBuffer;
124     // The QHttpNetworkConnection that is used
125     QNetworkAccessCachedHttpConnection *httpConnection;
126     QByteArray cacheKey;
127     QHttpNetworkReply *httpReply;
128
129     // Used for implementing the synchronous HTTP, see startRequestSynchronously()
130     QEventLoop *synchronousRequestLoop;
131
132 signals:
133     void authenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *);
134 #ifndef QT_NO_NETWORKPROXY
135     void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *);
136 #endif
137 #ifndef QT_NO_SSL
138     void sslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
139     void sslConfigurationChanged(const QSslConfiguration);
140 #endif
141     void downloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64);
142     void downloadProgress(qint64, qint64);
143     void downloadData(QByteArray);
144     void error(QNetworkReply::NetworkError, const QString);
145     void downloadFinished();
146 public slots:
147     // This are called via QueuedConnection from user thread
148     void startRequest();
149     void abortRequest();
150     void readBufferSizeChanged(qint64 size);
151     void readBufferFreed(qint64 size);
152
153     // This is called with a BlockingQueuedConnection from user thread
154     void startRequestSynchronously();
155 protected slots:
156     // From QHttp*
157     void readyReadSlot();
158     void finishedSlot();
159     void finishedWithErrorSlot(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
160     void synchronousFinishedSlot();
161     void synchronousFinishedWithErrorSlot(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
162     void headerChangedSlot();
163     void synchronousHeaderChangedSlot();
164     void dataReadProgressSlot(qint64 done, qint64 total);
165     void cacheCredentialsSlot(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
166 #ifndef QT_NO_SSL
167     void sslErrorsSlot(const QList<QSslError> &errors);
168 #endif
169
170     void synchronousAuthenticationRequiredSlot(const QHttpNetworkRequest &request, QAuthenticator *);
171 #ifndef QT_NO_NETWORKPROXY
172     void synchronousProxyAuthenticationRequiredSlot(const QNetworkProxy &, QAuthenticator *);
173 #endif
174
175 protected:
176     // Cache for all the QHttpNetworkConnection objects.
177     // This is per thread.
178     static QThreadStorage<QNetworkAccessCache *> connections;
179
180 };
181
182 // This QNonContiguousByteDevice is connected to the QNetworkAccessHttpBackend
183 // and represents the PUT/POST data.
184 class QNonContiguousByteDeviceThreadForwardImpl : public QNonContiguousByteDevice
185 {
186     Q_OBJECT
187 protected:
188     bool wantDataPending;
189     qint64 m_amount;
190     char *m_data;
191     QByteArray m_dataArray;
192     bool m_atEnd;
193     qint64 m_size;
194 public:
195     QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s)
196         : QNonContiguousByteDevice(),
197           wantDataPending(false),
198           m_amount(0),
199           m_data(0),
200           m_atEnd(aE),
201           m_size(s)
202     {
203     }
204
205     ~QNonContiguousByteDeviceThreadForwardImpl()
206     {
207     }
208
209     const char* readPointer(qint64 maximumLength, qint64 &len)
210     {
211         if (m_amount > 0) {
212             len = m_amount;
213             return m_data;
214         }
215
216         if (m_atEnd) {
217             len = -1;
218         } else if (!wantDataPending) {
219             len = 0;
220             wantDataPending = true;
221             emit wantData(maximumLength);
222         } else {
223             // Do nothing, we already sent a wantData signal and wait for results
224             len = 0;
225         }
226         return 0;
227     }
228
229     bool advanceReadPointer(qint64 a)
230     {
231         if (m_data == 0)
232             return false;
233
234         m_amount -= a;
235         m_data += a;
236
237         // To main thread to inform about our state
238         emit processedData(a);
239
240         // FIXME possible optimization, already ask user thread for some data
241
242         return true;
243     }
244
245     bool atEnd()
246     {
247         if (m_amount > 0)
248             return false;
249         else
250             return m_atEnd;
251     }
252
253     bool reset()
254     {
255         m_amount = 0;
256         m_data = 0;
257
258         // Communicate as BlockingQueuedConnection
259         bool b = false;
260         emit resetData(&b);
261         return b;
262     }
263
264     qint64 size()
265     {
266         return m_size;
267     }
268
269 public slots:
270     // From user thread:
271     void haveDataSlot(QByteArray dataArray, bool dataAtEnd, qint64 dataSize)
272     {
273         wantDataPending = false;
274
275         m_dataArray = dataArray;
276         m_data = const_cast<char*>(m_dataArray.constData());
277         m_amount = dataArray.size();
278
279         m_atEnd = dataAtEnd;
280         m_size = dataSize;
281
282         // This will tell the HTTP code (QHttpNetworkConnectionChannel) that we have data available now
283         emit readyRead();
284     }
285
286 signals:
287     // void readyRead(); in parent class
288     // void readProgress(qint64 current, qint64 total); happens in the main thread with the real bytedevice
289
290     // to main thread:
291     void wantData(qint64);
292     void processedData(qint64);
293     void resetData(bool *b);
294 };
295
296 QT_END_NAMESPACE
297
298 #endif // QT_NO_HTTP
299
300 #endif // QHTTPTHREADDELEGATE_H