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
70#ifndef QT_NO_SSL
71#include <QtNetwork/QSslConfiguration>
72#endif
73
74Q_MOC_INCLUDE(<QtNetwork/QAuthenticator>)
75
76QT_REQUIRE_CONFIG(http);
77
78QT_BEGIN_NAMESPACE
79
80class QIODevice;
81
82class QNetworkReplyHttpImplPrivate;
83class QNetworkReplyHttpImpl: public QNetworkReply
84{
85 Q_OBJECT
86public:
87 QNetworkReplyHttpImpl(QNetworkAccessManager* const, const QNetworkRequest&, QNetworkAccessManager::Operation&, QIODevice* outgoingData);
88 virtual ~QNetworkReplyHttpImpl();
89
90 void close() override;
91 void abort() override;
92 qint64 bytesAvailable() const override;
93 bool isSequential () const override;
94 qint64 size() const override;
95 qint64 readData(char*, qint64) override;
96 void setReadBufferSize(qint64 size) override;
97 bool canReadLine () const override;
98
99 Q_DECLARE_PRIVATE(QNetworkReplyHttpImpl)
100 Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
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 Q_PRIVATE_SLOT(d_func(), void _q_finished())
106 Q_PRIVATE_SLOT(d_func(), void _q_error(QNetworkReply::NetworkError, const QString &))
107
108 // From reply
109 Q_PRIVATE_SLOT(d_func(), void replyDownloadData(QByteArray))
110 Q_PRIVATE_SLOT(d_func(), void replyFinished())
111 Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
112 int, QString, bool, QSharedPointer<char>,
113 qint64, qint64, bool))
114 Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
115 Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
116 Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
117#ifndef QT_NO_SSL
118 Q_PRIVATE_SLOT(d_func(), void replyEncrypted())
119 Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *))
120 Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&))
121 Q_PRIVATE_SLOT(d_func(), void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *))
122#endif
123#ifndef QT_NO_NETWORKPROXY
124 Q_PRIVATE_SLOT(d_func(), void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth))
125#endif
126
127 Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
128 Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
129 Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
130 Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
131 Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
132 Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
133 Q_PRIVATE_SLOT(d_func(), void _q_metaDataChanged())
134 Q_PRIVATE_SLOT(d_func(), void onRedirected(const QUrl &, int, int))
135 Q_PRIVATE_SLOT(d_func(), void followRedirect())
136
137#ifndef QT_NO_SSL
138protected:
139 void ignoreSslErrors() override;
140 void ignoreSslErrorsImplementation(const QList<QSslError> &errors) override;
141 void setSslConfigurationImplementation(const QSslConfiguration &configuration) override;
142 void sslConfigurationImplementation(QSslConfiguration &configuration) const override;
143#endif
144
145signals:
146 // To HTTP thread:
147 void startHttpRequest();
148 void abortHttpRequest();
149 void readBufferSizeChanged(qint64 size);
150 void readBufferFreed(qint64 size);
151
152 void startHttpRequestSynchronously();
153
154 void haveUploadData(const qint64 pos, const QByteArray &dataArray, bool dataAtEnd, qint64 dataSize);
155};
156
157class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
158{
159public:
160
161 static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio);
162
163 QNetworkReplyHttpImplPrivate();
164 ~QNetworkReplyHttpImplPrivate();
165
166 void _q_startOperation();
167
168 void _q_cacheLoadReadyRead();
169
170 void _q_bufferOutgoingData();
171 void _q_bufferOutgoingDataFinished();
172
173 void _q_cacheSaveDeviceAboutToClose();
174
175 void _q_transferTimedOut();
176 void setupTransferTimeout();
177
178 void _q_finished();
179
180 void finished();
181 void error(QNetworkReply::NetworkError code, const QString &errorString);
182 void _q_error(QNetworkReply::NetworkError code, const QString &errorString);
183 void _q_metaDataChanged();
184
185 void checkForRedirect(const int statusCode);
186
187 // incoming from user
188 QNetworkAccessManager *manager;
189 QNetworkAccessManagerPrivate *managerPrivate;
190 QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread
191 bool synchronous;
192
193 State state;
194
195 // from http thread
196 int statusCode;
197 QString reasonPhrase;
198
199 // upload
200 QNonContiguousByteDevice* createUploadByteDevice();
201 QSharedPointer<QNonContiguousByteDevice> uploadByteDevice;
202 qint64 uploadByteDevicePosition;
203 bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
204 QIODevice *outgoingData;
205 QSharedPointer<QRingBuffer> outgoingDataBuffer;
206 void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); // dup?
207 void onRedirected(const QUrl &redirectUrl, int httpStatus, int maxRedirectsRemainig);
208 void followRedirect();
209 qint64 bytesUploaded;
210
211
212 // cache
213 void createCache();
214 void completeCacheSave();
215 void setCachingEnabled(bool enable);
216 bool isCachingEnabled() const;
217 bool isCachingAllowed() const;
218 void initCacheSaveDevice();
219 QIODevice *cacheLoadDevice;
220 bool loadingFromCache;
221
222 QIODevice *cacheSaveDevice;
223 bool cacheEnabled; // is this for saving?
224
225
226 QUrl urlForLastAuthentication;
227#ifndef QT_NO_NETWORKPROXY
228 QNetworkProxy lastProxyAuthentication;
229#endif
230
231
232 bool canResume() const;
233 void setResumeOffset(quint64 offset);
234 quint64 resumeOffset;
235
236 qint64 bytesDownloaded;
237 qint64 bytesBuffered;
238
239 QTimer *transferTimeout;
240
241 // Only used when the "zero copy" style is used.
242 // Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
243 qint64 downloadBufferReadPosition;
244 qint64 downloadBufferCurrentSize;
245 QSharedPointer<char> downloadBufferPointer;
246 char* downloadZerocopyBuffer;
247
248 // Will be increased by HTTP thread:
249 QSharedPointer<QAtomicInt> pendingDownloadDataEmissions;
250 QSharedPointer<QAtomicInt> pendingDownloadProgressEmissions;
251
252
253#ifndef QT_NO_SSL
254 QScopedPointer<QSslConfiguration> sslConfiguration;
255 bool pendingIgnoreAllSslErrors;
256 QList<QSslError> pendingIgnoreSslErrorsList;
257#endif
258
259 QNetworkRequest redirectRequest;
260
261 bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
262 void invalidateCache();
263 bool sendCacheContents(const QNetworkCacheMetaData &metaData);
264 QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const;
265
266
267 void postRequest(const QNetworkRequest& newHttpRequest);
268 QNetworkAccessManager::Operation getRedirectOperation(QNetworkAccessManager::Operation currentOp, int httpStatus);
269 QNetworkRequest createRedirectRequest(const QNetworkRequest &originalRequests, const QUrl &url, int maxRedirectsRemainig);
270 bool isHttpRedirectResponse() const;
271
272public:
273 // From HTTP thread:
274 void replyDownloadData(QByteArray);
275 void replyFinished();
276 void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &,
277 bool, QSharedPointer<char>, qint64, qint64, bool);
278 void replyDownloadProgressSlot(qint64,qint64);
279 void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
280 void httpError(QNetworkReply::NetworkError error, const QString &errorString);
281#ifndef QT_NO_SSL
282 void replyEncrypted();
283 void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
284 void replySslConfigurationChanged(const QSslConfiguration &newSslConfiguration);
285 void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *);
286#endif
287#ifndef QT_NO_NETWORKPROXY
288 void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
289#endif
290
291 // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
292 void resetUploadDataSlot(bool *r);
293 void wantUploadDataSlot(qint64);
294 void sentUploadDataSlot(qint64, qint64);
295
296 // From user's QNonContiguousByteDevice
297 void uploadByteDeviceReadyReadSlot();
298
299 Q_DECLARE_PUBLIC(QNetworkReplyHttpImpl)
300};
301
302QT_END_NAMESPACE
303
304#endif
305