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