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 QHTTPNETWORKCONNECTION_H
41#define QHTTPNETWORKCONNECTION_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 <QtNetwork/qnetworkrequest.h>
56#include <QtNetwork/qnetworkreply.h>
57#include <QtNetwork/qabstractsocket.h>
58#include <QtNetwork/qnetworksession.h>
59
60#include <qhttp2configuration.h>
61
62#include <private/qobject_p.h>
63#include <qauthenticator.h>
64#include <qnetworkproxy.h>
65#include <qbuffer.h>
66#include <qtimer.h>
67#include <qsharedpointer.h>
68
69#include <private/qhttpnetworkheader_p.h>
70#include <private/qhttpnetworkrequest_p.h>
71#include <private/qhttpnetworkreply_p.h>
72#include <private/qnetconmonitor_p.h>
73#include <private/http2protocol_p.h>
74
75#include <private/qhttpnetworkconnectionchannel_p.h>
76
77QT_REQUIRE_CONFIG(http);
78
79QT_BEGIN_NAMESPACE
80
81class QHttpNetworkRequest;
82class QHttpNetworkReply;
83class QHttpThreadDelegate;
84class QByteArray;
85class QHostInfo;
86#ifndef QT_NO_SSL
87class QSslConfiguration;
88class QSslContext;
89#endif // !QT_NO_SSL
90
91class QHttpNetworkConnectionPrivate;
92class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject
93{
94 Q_OBJECT
95public:
96
97 enum ConnectionType {
98 ConnectionTypeHTTP,
99 ConnectionTypeSPDY,
100 ConnectionTypeHTTP2,
101 ConnectionTypeHTTP2Direct
102 };
103
104#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
105 explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false,
106 ConnectionType connectionType = ConnectionTypeHTTP,
107 QObject *parent = nullptr, QSharedPointer<QNetworkSession> networkSession
108 = QSharedPointer<QNetworkSession>());
109 QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80,
110 bool encrypt = false, QObject *parent = nullptr,
111 QSharedPointer<QNetworkSession> networkSession = QSharedPointer<QNetworkSession>(),
112 ConnectionType connectionType = ConnectionTypeHTTP);
113#else
114 explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false,
115 ConnectionType connectionType = ConnectionTypeHTTP,
116 QObject *parent = 0);
117 QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80,
118 bool encrypt = false, QObject *parent = 0,
119 ConnectionType connectionType = ConnectionTypeHTTP);
120#endif
121 ~QHttpNetworkConnection();
122
123 //The hostname to which this is connected to.
124 QString hostName() const;
125 //The HTTP port in use.
126 quint16 port() const;
127
128 //add a new HTTP request through this connection
129 QHttpNetworkReply* sendRequest(const QHttpNetworkRequest &request);
130 void fillHttp2Queue();
131
132#ifndef QT_NO_NETWORKPROXY
133 //set the proxy for this connection
134 void setCacheProxy(const QNetworkProxy &networkProxy);
135 QNetworkProxy cacheProxy() const;
136 void setTransparentProxy(const QNetworkProxy &networkProxy);
137 QNetworkProxy transparentProxy() const;
138#endif
139
140 bool isSsl() const;
141
142 QHttpNetworkConnectionChannel *channels() const;
143
144 ConnectionType connectionType();
145 void setConnectionType(ConnectionType type);
146
147 QHttp2Configuration http2Parameters() const;
148 void setHttp2Parameters(const QHttp2Configuration &params);
149
150#ifndef QT_NO_SSL
151 void setSslConfiguration(const QSslConfiguration &config);
152 void ignoreSslErrors(int channel = -1);
153 void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1);
154 QSharedPointer<QSslContext> sslContext();
155 void setSslContext(QSharedPointer<QSslContext> context);
156#endif
157
158 void preConnectFinished();
159
160 QString peerVerifyName() const;
161 void setPeerVerifyName(const QString &peerName);
162
163public slots:
164 void onlineStateChanged(bool isOnline);
165
166private:
167 Q_DECLARE_PRIVATE(QHttpNetworkConnection)
168 Q_DISABLE_COPY_MOVE(QHttpNetworkConnection)
169 friend class QHttpThreadDelegate;
170 friend class QHttpNetworkReply;
171 friend class QHttpNetworkReplyPrivate;
172 friend class QHttpNetworkConnectionChannel;
173 friend class QHttp2ProtocolHandler;
174 friend class QHttpProtocolHandler;
175 friend class QSpdyProtocolHandler;
176
177 Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
178 Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo))
179 Q_PRIVATE_SLOT(d_func(), void _q_connectDelayedChannel())
180};
181
182
183// private classes
184typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
185
186
187class QHttpNetworkConnectionPrivate : public QObjectPrivate
188{
189 Q_DECLARE_PUBLIC(QHttpNetworkConnection)
190public:
191 static const int defaultHttpChannelCount;
192 static const int defaultPipelineLength;
193 static const int defaultRePipelineLength;
194
195 enum ConnectionState {
196 RunningState = 0,
197 PausedState = 1
198 };
199
200 enum NetworkLayerPreferenceState {
201 Unknown,
202 HostLookupPending,
203 IPv4,
204 IPv6,
205 IPv4or6
206 };
207
208 QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt,
209 QHttpNetworkConnection::ConnectionType type);
210 QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt,
211 QHttpNetworkConnection::ConnectionType type);
212 ~QHttpNetworkConnectionPrivate();
213 void init();
214
215 void pauseConnection();
216 void resumeConnection();
217 ConnectionState state;
218 NetworkLayerPreferenceState networkLayerState;
219
220 enum { ChunkSize = 4096 };
221
222 int indexOf(QAbstractSocket *socket) const;
223
224 QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request);
225 void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
226 void fillHttp2Queue();
227 bool dequeueRequest(QAbstractSocket *socket);
228 void prepareRequest(HttpMessagePair &request);
229 void updateChannel(int i, const HttpMessagePair &messagePair);
230 QHttpNetworkRequest predictNextRequest() const;
231
232 void fillPipeline(QAbstractSocket *socket);
233 bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel);
234
235 // read more HTTP body after the next event loop spin
236 void readMoreLater(QHttpNetworkReply *reply);
237
238 void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy);
239
240 void startHostInfoLookup();
241 void startNetworkLayerStateLookup();
242 void networkLayerDetected(QAbstractSocket::NetworkLayerProtocol protocol);
243
244 // private slots
245 void _q_startNextRequest(); // send the next request from the queue
246
247 void _q_hostLookupFinished(const QHostInfo &info);
248 void _q_connectDelayedChannel();
249
250 void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
251
252 QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket,
253 const QString &extraDetail = QString());
254
255 void removeReply(QHttpNetworkReply *reply);
256
257 QString hostName;
258 quint16 port;
259 bool encrypt;
260 bool delayIpv4;
261
262 // Number of channels we are trying to use at the moment:
263 int activeChannelCount;
264 // The total number of channels we reserved:
265 const int channelCount;
266 QTimer delayedConnectionTimer;
267 QHttpNetworkConnectionChannel *channels; // parallel connections to the server
268 bool shouldEmitChannelError(QAbstractSocket *socket);
269
270 qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const;
271 qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const;
272
273
274 void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode);
275 bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
276 struct ParseRedirectResult {
277 QUrl redirectUrl;
278 QNetworkReply::NetworkError errorCode;
279 };
280 ParseRedirectResult parseRedirectResponse(QHttpNetworkReply *reply);
281 // Used by the HTTP1 code-path
282 QUrl parseRedirectResponse(QAbstractSocket *socket, QHttpNetworkReply *reply);
283
284#ifndef QT_NO_NETWORKPROXY
285 QNetworkProxy networkProxy;
286 void emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth);
287#endif
288
289 //The request queues
290 QList<HttpMessagePair> highPriorityQueue;
291 QList<HttpMessagePair> lowPriorityQueue;
292
293 int preConnectRequests;
294
295 QHttpNetworkConnection::ConnectionType connectionType;
296
297#ifndef QT_NO_SSL
298 QSharedPointer<QSslContext> sslContext;
299#endif
300
301#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
302 QSharedPointer<QNetworkSession> networkSession;
303#endif
304
305 QHttp2Configuration http2Parameters;
306
307 QString peerVerifyName;
308 // If network status monitoring is enabled, we activate connectionMonitor
309 // as soons as one of channels managed to connect to host (and we
310 // have a pair of addresses (us,peer).
311 // NETMONTODO: consider activating a monitor on a change from
312 // HostLookUp state to ConnectingState (means we have both
313 // local/remote addresses known and can start monitoring this
314 // early).
315 QNetworkConnectionMonitor connectionMonitor;
316
317 friend class QHttpNetworkConnectionChannel;
318};
319
320
321
322QT_END_NAMESPACE
323
324#endif
325

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