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

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