1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QNETWORKREPLYHTTPIMPL_P_H
6#define QNETWORKREPLYHTTPIMPL_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists for the convenience
13// of the Network Access API. This header file may change from
14// version to version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtNetwork/private/qtnetworkglobal_p.h>
20#include "qnetworkrequest.h"
21#include "qnetworkreply.h"
22
23#include "QtCore/qpointer.h"
24#include "QtCore/qdatetime.h"
25#include "QtCore/qsharedpointer.h"
26#include "QtCore/qscopedpointer.h"
27#include "QtCore/qtimer.h"
28#include "qatomic.h"
29
30#include <QtNetwork/QNetworkCacheMetaData>
31#include <private/qhttpnetworkrequest_p.h>
32#include <private/qnetworkreply_p.h>
33#include <QtNetwork/QNetworkProxy>
34
35#ifndef QT_NO_SSL
36#include <QtNetwork/QSslConfiguration>
37#endif
38
39Q_MOC_INCLUDE(<QtNetwork/QAuthenticator>)
40
41#include <private/qdecompresshelper_p.h>
42
43#include <memory>
44
45QT_REQUIRE_CONFIG(http);
46
47QT_BEGIN_NAMESPACE
48
49class QIODevice;
50
51class QNetworkReplyHttpImplPrivate;
52class QNetworkReplyHttpImpl: public QNetworkReply
53{
54 Q_OBJECT
55public:
56 QNetworkReplyHttpImpl(QNetworkAccessManager* const, const QNetworkRequest&, QNetworkAccessManager::Operation&, QIODevice* outgoingData);
57 virtual ~QNetworkReplyHttpImpl();
58
59 void close() override;
60 void abort() override;
61 qint64 bytesAvailable() const override;
62 bool isSequential () const override;
63 qint64 size() const override;
64 qint64 readData(char*, qint64) override;
65 void setReadBufferSize(qint64 size) override;
66 bool canReadLine () const override;
67
68 Q_DECLARE_PRIVATE(QNetworkReplyHttpImpl)
69 Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
70 Q_PRIVATE_SLOT(d_func(), void _q_cacheLoadReadyRead())
71 Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
72 Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
73 Q_PRIVATE_SLOT(d_func(), void _q_transferTimedOut())
74 Q_PRIVATE_SLOT(d_func(), void _q_finished())
75 Q_PRIVATE_SLOT(d_func(), void _q_error(QNetworkReply::NetworkError, const QString &))
76
77 // From reply
78 Q_PRIVATE_SLOT(d_func(), void replyDownloadData(QByteArray))
79 Q_PRIVATE_SLOT(d_func(), void replyFinished())
80 Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
81 Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
82 Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
83#ifndef QT_NO_SSL
84 Q_PRIVATE_SLOT(d_func(), void replyEncrypted())
85 Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *))
86 Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&))
87 Q_PRIVATE_SLOT(d_func(), void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *))
88#endif
89#ifndef QT_NO_NETWORKPROXY
90 Q_PRIVATE_SLOT(d_func(), void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth))
91#endif
92
93 Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
94 Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
95 Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64))
96 Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
97 Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
98 Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
99 Q_PRIVATE_SLOT(d_func(), void _q_metaDataChanged())
100 Q_PRIVATE_SLOT(d_func(), void onRedirected(const QUrl &, int, int))
101 Q_PRIVATE_SLOT(d_func(), void followRedirect())
102
103#ifndef QT_NO_SSL
104protected:
105 void ignoreSslErrors() override;
106 void ignoreSslErrorsImplementation(const QList<QSslError> &errors) override;
107 void setSslConfigurationImplementation(const QSslConfiguration &configuration) override;
108 void sslConfigurationImplementation(QSslConfiguration &configuration) const override;
109#endif
110
111signals:
112 // To HTTP thread:
113 void startHttpRequest();
114 void abortHttpRequest();
115 void readBufferSizeChanged(qint64 size);
116 void readBufferFreed(qint64 size);
117
118 void startHttpRequestSynchronously();
119
120 void haveUploadData(const qint64 pos, const QByteArray &dataArray, bool dataAtEnd, qint64 dataSize);
121};
122
123class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
124{
125public:
126
127 static QHttpNetworkRequest::Priority convert(QNetworkRequest::Priority prio);
128
129 QNetworkReplyHttpImplPrivate();
130 ~QNetworkReplyHttpImplPrivate();
131
132 void _q_startOperation();
133
134 void _q_cacheLoadReadyRead();
135
136 void _q_bufferOutgoingData();
137 void _q_bufferOutgoingDataFinished();
138
139 void _q_cacheSaveDeviceAboutToClose();
140
141 void _q_transferTimedOut();
142 void setupTransferTimeout();
143
144 void _q_finished();
145
146 void finished();
147 void error(QNetworkReply::NetworkError code, const QString &errorString);
148 void _q_error(QNetworkReply::NetworkError code, const QString &errorString);
149 void _q_metaDataChanged();
150
151 void checkForRedirect(const int statusCode);
152
153 // incoming from user
154 QNetworkAccessManager *manager;
155 QNetworkAccessManagerPrivate *managerPrivate;
156 QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread
157 bool synchronous;
158
159 State state;
160
161 // from http thread
162 int statusCode;
163 QString reasonPhrase;
164
165 // upload
166 QNonContiguousByteDevice* createUploadByteDevice();
167 std::shared_ptr<QNonContiguousByteDevice> uploadByteDevice;
168 qint64 uploadByteDevicePosition;
169 bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
170 QIODevice *outgoingData;
171 std::shared_ptr<QRingBuffer> outgoingDataBuffer;
172 void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); // dup?
173 void onRedirected(const QUrl &redirectUrl, int httpStatus, int maxRedirectsRemainig);
174 void followRedirect();
175 qint64 bytesUploaded;
176
177
178 // cache
179 void createCache();
180 void completeCacheSave();
181 void setCachingEnabled(bool enable);
182 bool isCachingEnabled() const;
183 bool isCachingAllowed() const;
184 void initCacheSaveDevice();
185 QIODevice *cacheLoadDevice;
186 bool loadingFromCache;
187
188 QIODevice *cacheSaveDevice;
189 bool cacheEnabled; // is this for saving?
190
191
192 QUrl urlForLastAuthentication;
193#ifndef QT_NO_NETWORKPROXY
194 QNetworkProxy lastProxyAuthentication;
195#endif
196
197
198 bool canResume() const;
199 void setResumeOffset(quint64 offset);
200 quint64 resumeOffset;
201
202 qint64 bytesDownloaded;
203 qint64 bytesBuffered;
204 // We use this to keep track of whether or not we need to emit readyRead
205 // when we deal with signal compression (delaying emission) + decompressing
206 // data (potentially receiving bytes that don't end up in the final output):
207 qint64 lastReadyReadEmittedSize = 0;
208
209 QTimer *transferTimeout;
210
211 // Only used when the "zero copy" style is used.
212 // Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
213 qint64 downloadBufferReadPosition;
214 qint64 downloadBufferCurrentSize;
215 QSharedPointer<char> downloadBufferPointer;
216 char* downloadZerocopyBuffer;
217
218 // Will be increased by HTTP thread:
219 std::shared_ptr<QAtomicInt> pendingDownloadDataEmissions;
220 std::shared_ptr<QAtomicInt> pendingDownloadProgressEmissions;
221
222
223#ifndef QT_NO_SSL
224 QScopedPointer<QSslConfiguration> sslConfiguration;
225 bool pendingIgnoreAllSslErrors;
226 QList<QSslError> pendingIgnoreSslErrorsList;
227#endif
228
229 QNetworkRequest redirectRequest;
230
231 QDecompressHelper decompressHelper;
232
233 bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
234 void invalidateCache();
235 bool sendCacheContents(const QNetworkCacheMetaData &metaData);
236 QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const;
237
238
239 void postRequest(const QNetworkRequest& newHttpRequest);
240 QNetworkAccessManager::Operation getRedirectOperation(QNetworkAccessManager::Operation currentOp, int httpStatus);
241 QNetworkRequest createRedirectRequest(const QNetworkRequest &originalRequests, const QUrl &url, int maxRedirectsRemainig);
242 bool isHttpRedirectResponse() const;
243
244public:
245 // From HTTP thread:
246 void replyDownloadData(QByteArray);
247 void replyFinished();
248 void replyDownloadMetaData(const QHttpHeaders &, int, const QString &,
249 bool, QSharedPointer<char>, qint64, qint64, bool, bool);
250 void replyDownloadProgressSlot(qint64,qint64);
251 void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
252 void httpError(QNetworkReply::NetworkError error, const QString &errorString);
253#ifndef QT_NO_SSL
254 void replyEncrypted();
255 void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
256 void replySslConfigurationChanged(const QSslConfiguration &newSslConfiguration);
257 void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *);
258#endif
259#ifndef QT_NO_NETWORKPROXY
260 void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
261#endif
262
263 // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread:
264 void resetUploadDataSlot(bool *r);
265 void wantUploadDataSlot(qint64);
266 void sentUploadDataSlot(qint64, qint64);
267
268 // From user's QNonContiguousByteDevice
269 void uploadByteDeviceReadyReadSlot();
270
271 Q_DECLARE_PUBLIC(QNetworkReplyHttpImpl)
272};
273
274QT_END_NAMESPACE
275
276#endif
277

source code of qtbase/src/network/access/qnetworkreplyhttpimpl_p.h