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 HTTP2PROTOCOL_P_H
41#define HTTP2PROTOCOL_P_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/qnetworkreply.h>
55#include <QtCore/qloggingcategory.h>
56#include <QtCore/qmetatype.h>
57#include <QtCore/qglobal.h>
58#include <QtCore/qmap.h>
59
60// Different HTTP/2 constants/values as defined by RFC 7540.
61
62QT_BEGIN_NAMESPACE
63
64class QHttpNetworkRequest;
65class QHttp2Configuration;
66class QHttpNetworkReply;
67class QByteArray;
68class QString;
69
70namespace Http2
71{
72
73enum class Settings : quint16
74{
75 HEADER_TABLE_SIZE_ID = 0x1,
76 ENABLE_PUSH_ID = 0x2,
77 MAX_CONCURRENT_STREAMS_ID = 0x3,
78 INITIAL_WINDOW_SIZE_ID = 0x4,
79 MAX_FRAME_SIZE_ID = 0x5,
80 MAX_HEADER_LIST_SIZE_ID = 0x6
81};
82
83enum class FrameType : uchar
84{
85 DATA = 0x0,
86 HEADERS = 0x1,
87 PRIORITY = 0x2,
88 RST_STREAM = 0x3,
89 SETTINGS = 0x4,
90 PUSH_PROMISE = 0x5,
91 PING = 0x6,
92 GOAWAY = 0x7,
93 WINDOW_UPDATE = 0x8,
94 CONTINUATION = 0x9,
95 // ATTENTION: enumerators must be sorted.
96 // We use LAST_FRAME_TYPE to check if
97 // frame type is known, if not - this frame
98 // must be ignored, HTTP/2 5.1).
99 LAST_FRAME_TYPE
100};
101
102enum class FrameFlag : uchar
103{
104 EMPTY = 0x0, // Valid for any frame type.
105 ACK = 0x1, // Valid for PING, SETTINGS
106 END_STREAM = 0x1, // Valid for HEADERS, DATA
107 END_HEADERS = 0x4, // Valid for PUSH_PROMISE, HEADERS,
108 PADDED = 0x8, // Valid for PUSH_PROMISE, HEADERS, DATA
109 PRIORITY = 0x20 // Valid for HEADERS,
110};
111
112Q_DECLARE_FLAGS(FrameFlags, FrameFlag)
113Q_DECLARE_OPERATORS_FOR_FLAGS(FrameFlags)
114
115enum Http2PredefinedParameters
116{
117 // Old-style enum, so we
118 // can use as Http2::frameHeaderSize for example.
119 clientPrefaceLength = 24, // HTTP/2, 3.5
120 connectionStreamID = 0, // HTTP/2, 5.1.1
121 frameHeaderSize = 9, // HTTP/2, 4.1
122
123 // The initial allowed payload size. We would use it as an
124 // upper limit for a frame payload we send, until our peer
125 // updates us with a larger SETTINGS_MAX_FRAME_SIZE.
126
127 // The initial maximum payload size that an HTTP/2 frame
128 // can contain is 16384. It's also the minimal size that
129 // can be advertised via 'SETTINGS' frames. A real frame
130 // can have a payload smaller than 16384.
131 minPayloadLimit = 16384, // HTTP/2 6.5.2
132 // The maximum allowed payload size.
133 maxPayloadSize = (1 << 24) - 1, // HTTP/2 6.5.2
134
135 defaultSessionWindowSize = 65535, // HTTP/2 6.5.2
136 // Using 1000 (rather arbitrarily), just to
137 // impose *some* upper limit:
138 maxPeerConcurrentStreams = 1000,
139 maxConcurrentStreams = 100 // HTTP/2, 6.5.2
140};
141
142// These are ints, const, they have internal linkage, it's ok to have them in
143// headers - no ODR violation.
144const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1
145
146// The default size of 64K is too small and limiting: if we use it, we end up
147// sending WINDOW_UPDATE frames on a stream/session all the time, for each
148// 2 DATE frames of size 16K (also default) we'll send a WINDOW_UPDATE frame
149// for a given stream and have a download speed order of magnitude lower than
150// our own HTTP/1.1 protocol handler. We choose a bigger window size: normally,
151// HTTP/2 servers are not afraid to immediately set it to the possible max,
152// we do the same and split this window size between our concurrent streams.
153const qint32 maxSessionReceiveWindowSize((quint32(1) << 31) - 1);
154const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / maxConcurrentStreams;
155
156struct Frame configurationToSettingsFrame(const QHttp2Configuration &configuration);
157QByteArray settingsFrameToBase64(const Frame &settingsFrame);
158void appendProtocolUpgradeHeaders(const QHttp2Configuration &configuration, QHttpNetworkRequest *request);
159
160extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength];
161
162enum class FrameStatus
163{
164 protocolError,
165 sizeError,
166 incompleteFrame,
167 goodFrame
168};
169
170enum Http2Error
171{
172 // Old-style enum to avoid excessive name
173 // qualification ...
174 // NB:
175 // I use the last enumerator to check
176 // that errorCode (quint32) is valid,
177 // so it needs to be the highest-numbered!
178 // HTTP/2 7:
179 HTTP2_NO_ERROR = 0x0,
180 PROTOCOL_ERROR = 0x1,
181 INTERNAL_ERROR = 0x2,
182 FLOW_CONTROL_ERROR = 0x3,
183 SETTINGS_TIMEOUT = 0x4,
184 STREAM_CLOSED = 0x5,
185 FRAME_SIZE_ERROR = 0x6,
186 REFUSE_STREAM = 0x7,
187 CANCEL = 0x8,
188 COMPRESSION_ERROR = 0x9,
189 CONNECT_ERROR = 0xa,
190 ENHANCE_YOUR_CALM = 0xb,
191 INADEQUATE_SECURITY = 0xc,
192 HTTP_1_1_REQUIRED = 0xd
193};
194
195void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error, QString &errorString);
196QString qt_error_string(quint32 errorCode);
197QNetworkReply::NetworkError qt_error(quint32 errorCode);
198bool is_protocol_upgraded(const QHttpNetworkReply &reply);
199
200} // namespace Http2
201
202Q_DECLARE_LOGGING_CATEGORY(QT_HTTP2)
203
204QT_END_NAMESPACE
205
206Q_DECLARE_METATYPE(Http2::Settings)
207
208#endif
209