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 | |
81 | QT_REQUIRE_CONFIG(http); |
82 | |
83 | QT_BEGIN_NAMESPACE |
84 | |
85 | class QHttpNetworkRequest; |
86 | class QHttpNetworkReply; |
87 | class QByteArray; |
88 | |
89 | #ifndef HttpMessagePair |
90 | typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair; |
91 | #endif |
92 | |
93 | class QHttpNetworkConnectionChannel : public QObject { |
94 | Q_OBJECT |
95 | public: |
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 | // SPDY or HTTP/2 requests; SPDY is TLS-only, but |
127 | // HTTP/2 can be cleartext also, that's why it's |
128 | // outside of QT_NO_SSL section. Sorted by priority: |
129 | QMultiMap<int, HttpMessagePair> spdyRequestsToSend; |
130 | bool switchedToHttp2 = false; |
131 | #ifndef QT_NO_SSL |
132 | bool ignoreAllSslErrors; |
133 | QList<QSslError> ignoreSslErrorsList; |
134 | QScopedPointer<QSslConfiguration> sslConfiguration; |
135 | void ignoreSslErrors(); |
136 | void ignoreSslErrors(const QList<QSslError> &errors); |
137 | void setSslConfiguration(const QSslConfiguration &config); |
138 | void requeueSpdyRequests(); // when we wanted SPDY but got HTTP |
139 | #endif |
140 | // to emit the signal for all in-flight replies: |
141 | void emitFinishedWithError(QNetworkReply::NetworkError error, const char *message); |
142 | #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section |
143 | QSharedPointer<QNetworkSession> networkSession; |
144 | #endif |
145 | |
146 | // HTTP pipelining -> http://en.wikipedia.org/wiki/Http_pipelining |
147 | enum PipeliningSupport { |
148 | PipeliningSupportUnknown, // default for a new connection |
149 | PipeliningProbablySupported, // after having received a server response that indicates support |
150 | PipeliningNotSupported // currently not used |
151 | }; |
152 | PipeliningSupport pipeliningSupported; |
153 | QList<HttpMessagePair> alreadyPipelinedRequests; |
154 | QByteArray pipeline; // temporary buffer that gets sent to socket in pipelineFlush |
155 | void pipelineInto(HttpMessagePair &pair); |
156 | void pipelineFlush(); |
157 | void requeueCurrentlyPipelinedRequests(); |
158 | void detectPipeliningSupport(); |
159 | |
160 | QHttpNetworkConnectionChannel(); |
161 | |
162 | QAbstractSocket::NetworkLayerProtocol networkLayerPreference; |
163 | |
164 | void setConnection(QHttpNetworkConnection *c); |
165 | QPointer<QHttpNetworkConnection> connection; |
166 | |
167 | #ifndef QT_NO_NETWORKPROXY |
168 | QNetworkProxy proxy; |
169 | void setProxy(const QNetworkProxy &networkProxy); |
170 | #endif |
171 | |
172 | void init(); |
173 | void close(); |
174 | void abort(); |
175 | |
176 | bool sendRequest(); |
177 | void sendRequestDelayed(); |
178 | |
179 | bool ensureConnection(); |
180 | |
181 | void allDone(); // reply header + body have been read |
182 | void handleStatus(); // called from allDone() |
183 | |
184 | bool resetUploadData(); // return true if resetting worked or there is no upload data |
185 | |
186 | void handleUnexpectedEOF(); |
187 | void closeAndResendCurrentRequest(); |
188 | void resendCurrentRequest(); |
189 | |
190 | bool isSocketBusy() const; |
191 | bool isSocketWriting() const; |
192 | bool isSocketWaiting() const; |
193 | bool isSocketReading() const; |
194 | |
195 | protected slots: |
196 | void _q_receiveReply(); |
197 | void _q_bytesWritten(qint64 bytes); // proceed sending |
198 | void _q_readyRead(); // pending data to read |
199 | void _q_disconnected(); // disconnected from host |
200 | void _q_connected(); // start sending request |
201 | void _q_error(QAbstractSocket::SocketError); // error from socket |
202 | #ifndef QT_NO_NETWORKPROXY |
203 | void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy |
204 | #endif |
205 | |
206 | void _q_uploadDataReadyRead(); |
207 | |
208 | #ifndef QT_NO_SSL |
209 | void _q_encrypted(); // start sending request (https) |
210 | void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket |
211 | void _q_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*); // tls-psk auth necessary |
212 | void _q_encryptedBytesWritten(qint64 bytes); // proceed sending |
213 | #endif |
214 | |
215 | friend class QHttpProtocolHandler; |
216 | }; |
217 | |
218 | QT_END_NAMESPACE |
219 | |
220 | #endif |
221 | |