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 QHTTPNETWORKCONNECTIONCHANNEL_H
41#define QHTTPNETWORKCONNECTIONCHANNEL_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
59#include <private/qobject_p.h>
60#include <qauthenticator.h>
61#include <qnetworkproxy.h>
62#include <qbuffer.h>
63
64#include <private/qhttpnetworkheader_p.h>
65#include <private/qhttpnetworkrequest_p.h>
66#include <private/qhttpnetworkreply_p.h>
67
68#include <private/qhttpnetworkconnection_p.h>
69#include <private/qabstractprotocolhandler_p.h>
70
71#ifndef QT_NO_SSL
72# include <QtNetwork/qsslsocket.h>
73# include <QtNetwork/qsslerror.h>
74# include <QtNetwork/qsslconfiguration.h>
75#else
76# include <QtNetwork/qtcpsocket.h>
77#endif
78
79#include <QtCore/qscopedpointer.h>
80
81QT_REQUIRE_CONFIG(http);
82
83QT_BEGIN_NAMESPACE
84
85class QHttpNetworkRequest;
86class QHttpNetworkReply;
87class QByteArray;
88
89#ifndef HttpMessagePair
90typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
91#endif
92
93class QHttpNetworkConnectionChannel : public QObject {
94 Q_OBJECT
95public:
96 // TODO: Refactor this to add an EncryptingState (and remove pendingEncrypt).
97 // Also add an Unconnected state so IdleState does not have double meaning.
98 enum ChannelState {
99 IdleState = 0, // ready to send request
100 ConnectingState = 1, // connecting to host
101 WritingState = 2, // writing the data
102 WaitingState = 4, // waiting for reply
103 ReadingState = 8, // reading the reply
104 ClosingState = 16,
105 BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|ClosingState)
106 };
107 QAbstractSocket *socket;
108 bool ssl;
109 bool isInitialized;
110 ChannelState state;
111 QHttpNetworkRequest request; // current request, only used for HTTP
112 QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
113 qint64 written;
114 qint64 bytesTotal;
115 bool resendCurrent;
116 int lastStatus; // last status received on this channel
117 bool pendingEncrypt; // for https (send after encrypted)
118 int reconnectAttempts; // maximum 2 reconnection attempts
119 QAuthenticatorPrivate::Method authMethod;
120 QAuthenticatorPrivate::Method proxyAuthMethod;
121 QAuthenticator authenticator;
122 QAuthenticator proxyAuthenticator;
123 bool authenticationCredentialsSent;
124 bool proxyCredentialsSent;
125 QScopedPointer<QAbstractProtocolHandler> protocolHandler;
126 QMultiMap<int, HttpMessagePair> h2RequestsToSend;
127 bool switchedToHttp2 = false;
128#ifndef QT_NO_SSL
129 bool ignoreAllSslErrors;
130 QList<QSslError> ignoreSslErrorsList;
131 QScopedPointer<QSslConfiguration> sslConfiguration;
132 void ignoreSslErrors();
133 void ignoreSslErrors(const QList<QSslError> &errors);
134 void setSslConfiguration(const QSslConfiguration &config);
135 void requeueHttp2Requests(); // when we wanted HTTP/2 but got HTTP/1.1
136#endif
137 // to emit the signal for all in-flight replies:
138 void emitFinishedWithError(QNetworkReply::NetworkError error, const char *message);
139
140 // HTTP pipelining -> http://en.wikipedia.org/wiki/Http_pipelining
141 enum PipeliningSupport {
142 PipeliningSupportUnknown, // default for a new connection
143 PipeliningProbablySupported, // after having received a server response that indicates support
144 PipeliningNotSupported // currently not used
145 };
146 PipeliningSupport pipeliningSupported;
147 QList<HttpMessagePair> alreadyPipelinedRequests;
148 QByteArray pipeline; // temporary buffer that gets sent to socket in pipelineFlush
149 void pipelineInto(HttpMessagePair &pair);
150 void pipelineFlush();
151 void requeueCurrentlyPipelinedRequests();
152 void detectPipeliningSupport();
153
154 QHttpNetworkConnectionChannel();
155
156 QAbstractSocket::NetworkLayerProtocol networkLayerPreference;
157
158 void setConnection(QHttpNetworkConnection *c);
159 QPointer<QHttpNetworkConnection> connection;
160
161#ifndef QT_NO_NETWORKPROXY
162 QNetworkProxy proxy;
163 void setProxy(const QNetworkProxy &networkProxy);
164#endif
165
166 void init();
167 void close();
168 void abort();
169
170 bool sendRequest();
171 void sendRequestDelayed();
172
173 bool ensureConnection();
174
175 void allDone(); // reply header + body have been read
176 void handleStatus(); // called from allDone()
177
178 bool resetUploadData(); // return true if resetting worked or there is no upload data
179
180 void handleUnexpectedEOF();
181 void closeAndResendCurrentRequest();
182 void resendCurrentRequest();
183
184 bool isSocketBusy() const;
185 bool isSocketWriting() const;
186 bool isSocketWaiting() const;
187 bool isSocketReading() const;
188
189 protected slots:
190 void _q_receiveReply();
191 void _q_bytesWritten(qint64 bytes); // proceed sending
192 void _q_readyRead(); // pending data to read
193 void _q_disconnected(); // disconnected from host
194 void _q_connected(); // start sending request
195 void _q_error(QAbstractSocket::SocketError); // error from socket
196#ifndef QT_NO_NETWORKPROXY
197 void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy
198#endif
199
200 void _q_uploadDataReadyRead();
201
202#ifndef QT_NO_SSL
203 void _q_encrypted(); // start sending request (https)
204 void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket
205 void _q_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*); // tls-psk auth necessary
206 void _q_encryptedBytesWritten(qint64 bytes); // proceed sending
207#endif
208
209 friend class QHttpProtocolHandler;
210};
211
212QT_END_NAMESPACE
213
214#endif
215