1// Copyright (C) 2019 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#include "qhttp2configuration.h"
5
6#include "private/http2protocol_p.h"
7#include "private/hpack_p.h"
8
9#include "qdebug.h"
10
11QT_BEGIN_NAMESPACE
12
13/*!
14 \class QHttp2Configuration
15 \brief The QHttp2Configuration class controls HTTP/2 parameters and settings.
16 \since 5.14
17
18 \reentrant
19 \inmodule QtNetwork
20 \ingroup network
21 \ingroup shared
22
23 QHttp2Configuration controls HTTP/2 parameters and settings that
24 QNetworkAccessManager will use to send requests and process responses
25 when the HTTP/2 protocol is enabled.
26
27 The HTTP/2 parameters that QHttp2Configuration currently supports include:
28
29 \list
30 \li The session window size for connection-level flow control.
31 Will be sent to a remote peer when needed as 'WINDOW_UPDATE'
32 frames on the stream with an identifier 0.
33 \li The stream receiving window size for stream-level flow control.
34 Sent as 'SETTINGS_INITIAL_WINDOW_SIZE' parameter in the initial
35 SETTINGS frame and, when needed, 'WINDOW_UPDATE' frames will be
36 sent on streams that QNetworkAccessManager opens.
37 \li The maximum frame size. This parameter limits the maximum payload
38 a frame coming from the remote peer can have. Sent by QNetworkAccessManager
39 as 'SETTINGS_MAX_FRAME_SIZE' parameter in the initial 'SETTINGS'
40 frame.
41 \li The server push. Allows to enable or disable server push. Sent
42 as 'SETTINGS_ENABLE_PUSH' parameter in the initial 'SETTINGS'
43 frame.
44 \endlist
45
46 The QHttp2Configuration class also controls if the header compression
47 algorithm (HPACK) is additionally using Huffman coding for string
48 compression.
49
50 \note The configuration must be set before the first request
51 was sent to a given host (and thus an HTTP/2 session established).
52
53 \note Details about flow control, server push and 'SETTINGS'
54 can be found in \l {https://httpwg.org/specs/rfc7540.html}{RFC 7540}.
55 Different modes and parameters of the HPACK compression algorithm
56 are described in \l {https://httpwg.org/specs/rfc7541.html}{RFC 7541}.
57
58 \sa QNetworkRequest::setHttp2Configuration(), QNetworkRequest::http2Configuration(), QNetworkAccessManager
59*/
60
61class QHttp2ConfigurationPrivate : public QSharedData
62{
63public:
64 unsigned sessionWindowSize = Http2::defaultSessionWindowSize;
65 unsigned streamWindowSize = Http2::defaultSessionWindowSize;
66
67 unsigned maxFrameSize = Http2::minPayloadLimit; // Initial (default) value of 16Kb.
68
69 bool pushEnabled = false;
70 // TODO: for now those two below are noop.
71 bool huffmanCompressionEnabled = true;
72};
73
74/*!
75 Default constructs a QHttp2Configuration object.
76
77 Such a configuration has the following values:
78 \list
79 \li Server push is disabled
80 \li Huffman string compression is enabled
81 \li Window size for connection-level flow control is 65535 octets
82 \li Window size for stream-level flow control is 65535 octets
83 \li Frame size is 16384 octets
84 \endlist
85*/
86QHttp2Configuration::QHttp2Configuration()
87 : d(new QHttp2ConfigurationPrivate)
88{
89}
90
91/*!
92 Copy-constructs this QHttp2Configuration.
93*/
94QHttp2Configuration::QHttp2Configuration(const QHttp2Configuration &) = default;
95
96/*!
97 Move-constructs this QHttp2Configuration from \a other
98*/
99QHttp2Configuration::QHttp2Configuration(QHttp2Configuration &&other) noexcept
100{
101 swap(other);
102}
103
104/*!
105 Copy-assigns \a other to this QHttp2Configuration.
106*/
107QHttp2Configuration &QHttp2Configuration::operator=(const QHttp2Configuration &) = default;
108
109/*!
110 Move-assigns \a other to this QHttp2Configuration.
111*/
112QHttp2Configuration &QHttp2Configuration::operator=(QHttp2Configuration &&) noexcept = default;
113
114/*!
115 Destructor.
116*/
117QHttp2Configuration::~QHttp2Configuration()
118{
119}
120
121/*!
122 If \a enable is \c true, a remote server can potentially
123 use server push to send responses in advance.
124
125 \sa serverPushEnabled
126*/
127void QHttp2Configuration::setServerPushEnabled(bool enable)
128{
129 d->pushEnabled = enable;
130}
131
132/*!
133 Returns true if server push was enabled.
134
135 \note By default, QNetworkAccessManager disables server
136 push via the 'SETTINGS' frame.
137
138 \sa setServerPushEnabled
139*/
140bool QHttp2Configuration::serverPushEnabled() const
141{
142 return d->pushEnabled;
143}
144
145/*!
146 If \a enable is \c true, HPACK compression will additionally
147 compress string using the Huffman coding. Enabled by default.
148
149 \note This parameter only affects 'HEADERS' frames that
150 QNetworkAccessManager is sending.
151
152 \sa huffmanCompressionEnabled
153*/
154void QHttp2Configuration::setHuffmanCompressionEnabled(bool enable)
155{
156 d->huffmanCompressionEnabled = enable;
157}
158
159/*!
160 Returns \c true if the Huffman coding in HPACK is enabled.
161
162 \sa setHuffmanCompressionEnabled
163*/
164bool QHttp2Configuration::huffmanCompressionEnabled() const
165{
166 return d->huffmanCompressionEnabled;
167}
168
169/*!
170 Sets the window size for connection-level flow control.
171 \a size cannot be 0 and must not exceed 2147483647 octets.
172
173 Returns \c true on success, \c false otherwise.
174
175 \sa sessionReceiveWindowSize
176*/
177bool QHttp2Configuration::setSessionReceiveWindowSize(unsigned size)
178{
179 if (!size || size > Http2::maxSessionReceiveWindowSize) { // RFC-7540, 6.9
180 qCWarning(QT_HTTP2) << "Invalid session window size";
181 return false;
182 }
183
184 d->sessionWindowSize = size;
185 return true;
186}
187
188/*!
189 Returns the window size for connection-level flow control.
190 The default value QNetworkAccessManager will be using is
191 2147483647 octets.
192*/
193unsigned QHttp2Configuration::sessionReceiveWindowSize() const
194{
195 return d->sessionWindowSize;
196}
197
198/*!
199 Sets the window size for stream-level flow control.
200 \a size cannot be 0 and must not exceed 2147483647 octets.
201
202 Returns \c true on success, \c false otherwise.
203
204 \sa streamReceiveWindowSize
205 */
206bool QHttp2Configuration::setStreamReceiveWindowSize(unsigned size)
207{
208 if (!size || size > Http2::maxSessionReceiveWindowSize) { // RFC-7540, 6.9
209 qCWarning(QT_HTTP2) << "Invalid stream window size";
210 return false;
211 }
212
213 d->streamWindowSize = size;
214 return true;
215}
216
217/*!
218 Returns the window size for stream-level flow control.
219 The default value QNetworkAccessManager will be using is
220 214748364 octets (see \l {https://httpwg.org/specs/rfc7540.html#SettingValues}{RFC 7540}).
221*/
222unsigned QHttp2Configuration::streamReceiveWindowSize() const
223{
224 return d->streamWindowSize;
225}
226
227/*!
228 Sets the maximum frame size that QNetworkAccessManager
229 will advertise to the server when sending its initial SETTINGS frame.
230 \note While this \a size is required to be within a range between
231 16384 and 16777215 inclusive, the actual payload size in frames
232 that carry payload maybe be less than 16384.
233
234 Returns \c true on success, \c false otherwise.
235*/
236bool QHttp2Configuration::setMaxFrameSize(unsigned size)
237{
238 if (size < Http2::minPayloadLimit || size > Http2::maxPayloadSize) {
239 qCWarning(QT_HTTP2) << "Maximum frame size to advertise is invalid";
240 return false;
241 }
242
243 d->maxFrameSize = size;
244 return true;
245}
246
247/*!
248 Returns the maximum payload size that HTTP/2 frames can
249 have. The default (initial) value is 16384 octets.
250*/
251unsigned QHttp2Configuration::maxFrameSize() const
252{
253 return d->maxFrameSize;
254}
255
256/*!
257 Swaps this configuration with the \a other configuration.
258*/
259void QHttp2Configuration::swap(QHttp2Configuration &other) noexcept
260{
261 d.swap(other&: other.d);
262}
263
264/*!
265 \fn bool QHttp2Configuration::operator==(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs) noexcept
266 Returns \c true if \a lhs and \a rhs have the same set of HTTP/2
267 parameters.
268*/
269
270/*!
271 \fn bool QHttp2Configuration::operator!=(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs) noexcept
272 Returns \c true if \a lhs and \a rhs do not have the same set of HTTP/2
273 parameters.
274*/
275
276/*!
277 \internal
278*/
279bool QHttp2Configuration::isEqual(const QHttp2Configuration &other) const noexcept
280{
281 if (d == other.d)
282 return true;
283
284 return d->pushEnabled == other.d->pushEnabled
285 && d->huffmanCompressionEnabled == other.d->huffmanCompressionEnabled
286 && d->sessionWindowSize == other.d->sessionWindowSize
287 && d->streamWindowSize == other.d->streamWindowSize;
288}
289
290QT_END_NAMESPACE
291

source code of qtbase/src/network/access/qhttp2configuration.cpp