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

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