1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QNETWORKREPLYHTTPIMPL_P_H
41 #define QNETWORKREPLYHTTPIMPL_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists for the convenience
48 // of the Network Access API.  This header file may change from
49 // version to version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtNetwork/private/qtnetworkglobal_p.h>
55 #include "qnetworkrequest.h"
56 #include "qnetworkreply.h"
57 
58 #include "QtCore/qpointer.h"
59 #include "QtCore/qdatetime.h"
60 #include "QtCore/qsharedpointer.h"
61 #include "QtCore/qscopedpointer.h"
62 #include "QtCore/qtimer.h"
63 #include "qatomic.h"
64 
65 #include <QtNetwork/QNetworkCacheMetaData>
66 #include <private/qhttpnetworkrequest_p.h>
67 #include <private/qnetworkreply_p.h>
68 #include <QtNetwork/QNetworkProxy>
69 #include <QtNetwork/QNetworkSession> // ### Qt6: Remove include
70 
71 #ifndef QT_NO_SSL
72 #include <QtNetwork/QSslConfiguration>
73 #endif
74 
75 QT_REQUIRE_CONFIG(http);
76 
77 QT_BEGIN_NAMESPACE
78 
79 class QIODevice;
80 
81 class QNetworkReplyHttpImplPrivate;
82 class QNetworkReplyHttpImpl: public QNetworkReply
83 {
84     Q_OBJECT
85 public:
86     QNetworkReplyHttpImpl(QNetworkAccessManager* const, const QNetworkRequest&, QNetworkAccessManager::Operation&, QIODevice* outgoingData);
87     virtual ~QNetworkReplyHttpImpl();
88 
89     void close() override;
90     void abort() override;
91     qint64 bytesAvailable() const override;
92     bool isSequential () const override;
93     qint64 size() const override;
94     qint64 readData(char*, qint64) override;
95     void setReadBufferSize(qint64 size) override;
96     bool canReadLine () const override;
97 
98     Q_DECLARE_PRIVATE(QNetworkReplyHttpImpl)
99     Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
100     Q_PRIVATE_SLOT(d_func(), bool start(const QNetworkRequest &))
101     Q_PRIVATE_SLOT(d_func(), void _q_cacheLoadReadyRead())
102     Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
103     Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
104     Q_PRIVATE_SLOT(d_func(), void _q_transferTimedOut())
105 #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
106     Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
107     Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
108     Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
109     Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
110 #endif
111     Q_PRIVATE_SLOT(d_func(), void _q_finished())
112     Q_PRIVATE_SLOT(d_func(), void _q_error(QNetworkReply::NetworkError, const QString &))
113 
114     // From reply
115     Q_PRIVATE_SLOT(d_func(), void replyDownloadData(QByteArray))
116     Q_PRIVATE_SLOT(d_func(), void replyFinished())
117     Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
118                                                         int, QString, bool, QSharedPointer<char>,
119                                                         qint64, qint64, bool))
120     Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
121     Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
122     Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
123 #ifndef QT_NO_SSL
124     Q_PRIVATE_SLOT(d_func(), void replyEncrypted())
125     Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *))
126     Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&))
127     Q_PRIVATE_SLOT(d_func(), void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *))
128 #endif
129 #ifndef QT_NO_NETWORKPROXY
130     Q_PRIVATE_SLOT(d_func(), void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth))
131 #endif
132 
133     Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
134     Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
135     Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
136     Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
137     Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
138     Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
139     Q_PRIVATE_SLOT(d_func(), void _q_metaDataChanged())
140     Q_PRIVATE_SLOT(d_func(), void onRedirected(const QUrl &, int, int))
141     Q_PRIVATE_SLOT(d_func(), void followRedirect())
142 
143 #ifndef QT_NO_SSL
144 protected:
145     void ignoreSslErrors() override;
146     void ignoreSslErrorsImplementation(const QList<QSslError> &errors) override;
147     void setSslConfigurationImplementation(const QSslConfiguration &configuration) override;
148     void sslConfigurationImplementation(QSslConfiguration &configuration) const override;
149 #endif
150 
151 signals:
152     // To HTTP thread:
153     void startHttpRequest();
154     void abortHttpRequest();
155     void readBufferSizeChanged(qint64 size);
156     void readBufferFreed(qint64 size);
157 
158     void startHttpRequestSynchronously();
159 
160     void haveUploadData(const qint64 pos, const QByteArray &dataArray, bool dataAtEnd, qint64 dataSize);
161 };
162 
163 class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
164 {
165 #if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
166     bool startWaitForSession(QSharedPointer<QNetworkSession> &session);
167 #endif
168 
169 public:
170 
171     static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);
172 
173     QNetworkReplyHttpImplPrivate();
174     ~QNetworkReplyHttpImplPrivate();
175 
176     bool start(const QNetworkRequest &newHttpRequest);
177     void _q_startOperation();
178 
179     void _q_cacheLoadReadyRead();
180 
181     void _q_bufferOutgoingData();
182     void _q_bufferOutgoingDataFinished();
183 
184     void _q_cacheSaveDeviceAboutToClose();
185 
186     void _q_transferTimedOut();
187     void setupTransferTimeout();
188 
189 #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
190     void _q_networkSessionConnected();
191     void _q_networkSessionFailed();
192     void _q_networkSessionStateChanged(QNetworkSession::State);
193     void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
194 #endif
195     void _q_finished();
196 
197     void finished();
198     void error(QNetworkReply::NetworkError code, const QString &errorString);
199     void _q_error(QNetworkReply::NetworkError code, const QString &errorString);
200     void _q_metaDataChanged();
201 
202     void checkForRedirect(const int statusCode);
203 
204     // incoming from user
205     QNetworkAccessManager *manager;
206     QNetworkAccessManagerPrivate *managerPrivate;
207     QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread
208     bool synchronous;
209 
210     State state;
211 
212     // from http thread
213     int statusCode;
214     QString reasonPhrase;
215 
216     // upload
217     QNonContiguousByteDevice* createUploadByteDevice();
218     QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
219     qint64 uploadByteDevicePosition;
220     bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
221     QIODevice *outgoingData;
222     QSharedPointer<QRingBuffer> outgoingDataBuffer;
223     void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); // dup?
224     void onRedirected(const QUrl &redirectUrl, int httpStatus, int maxRedirectsRemainig);
225     void followRedirect();
226     qint64 bytesUploaded;
227 
228 
229     // cache
230     void createCache();
231     void completeCacheSave();
232     void setCachingEnabled(bool enable);
233     bool isCachingEnabled() const;
234     bool isCachingAllowed() const;
235     void initCacheSaveDevice();
236     QIODevice *cacheLoadDevice;
237     bool loadingFromCache;
238 
239     QIODevice *cacheSaveDevice;
240     bool cacheEnabled; // is this for saving?
241 
242 
243     QUrl urlForLastAuthentication;
244 #ifndef QT_NO_NETWORKPROXY
245     QNetworkProxy lastProxyAuthentication;
246 #endif
247 
248 
249     bool migrateBackend();
250     bool canResume() const;
251     void setResumeOffset(quint64 offset);
252     quint64 resumeOffset;
253     qint64 preMigrationDownloaded;
254 
255     qint64 bytesDownloaded;
256     qint64 bytesBuffered;
257 
258     QTimer *transferTimeout;
259 
260     // Only used when the "zero copy" style is used.
261     // Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
262     qint64 downloadBufferReadPosition;
263     qint64 downloadBufferCurrentSize;
264     QSharedPointer<char> downloadBufferPointer;
265     char* downloadZerocopyBuffer;
266 
267     // Will be increased by HTTP thread:
268     QSharedPointer<QAtomicInt> pendingDownloadDataEmissions;
269     QSharedPointer<QAtomicInt> pendingDownloadProgressEmissions;
270 
271 
272 #ifndef QT_NO_SSL
273     QScopedPointer<QSslConfiguration> sslConfiguration;
274     bool pendingIgnoreAllSslErrors;
275     QList<QSslError> pendingIgnoreSslErrorsList;
276 #endif
277 
278     QNetworkRequest redirectRequest;
279 
280     bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
281     void invalidateCache();
282     bool sendCacheContents(const QNetworkCacheMetaData &metaData);
283     QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const;
284 
285 
286     void postRequest(const QNetworkRequest& newHttpRequest);
287     QNetworkAccessManager::Operation getRedirectOperation(QNetworkAccessManager::Operation currentOp, int httpStatus);
288     QNetworkRequest createRedirectRequest(const QNetworkRequest &originalRequests, const QUrl &url, int maxRedirectsRemainig);
289     bool isHttpRedirectResponse() const;
290 
291 public:
292     // From HTTP thread:
293     void replyDownloadData(QByteArray);
294     void replyFinished();
295     void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &,
296                                bool, QSharedPointer<char>, qint64, qint64, bool);
297     void replyDownloadProgressSlot(qint64,qint64);
298     void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
299     void httpError(QNetworkReply::NetworkError error, const QString &errorString);
300 #ifndef QT_NO_SSL
301     void replyEncrypted();
302     void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
303     void replySslConfigurationChanged(const QSslConfiguration &newSslConfiguration);
304     void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *);
305 #endif
306 #ifndef QT_NO_NETWORKPROXY
307     void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
308 #endif
309 
310     // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
311     void resetUploadDataSlot(bool *r);
312     void wantUploadDataSlot(qint64);
313     void sentUploadDataSlot(qint64, qint64);
314 
315     // From user's QNonContiguousByteDevice
316     void uploadByteDeviceReadyReadSlot();
317 
318     Q_DECLARE_PUBLIC(QNetworkReplyHttpImpl)
319 };
320 
321 QT_END_NAMESPACE
322 
323 #endif
324