1/****************************************************************************
2**
3** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
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 QSPDYPROTOCOLHANDLER_H
41#define QSPDYPROTOCOLHANDLER_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 <private/qabstractprotocolhandler_p.h>
56#include <QtNetwork/qnetworkreply.h>
57#include <private/qbytedata_p.h>
58
59#include <zlib.h>
60
61QT_REQUIRE_CONFIG(http);
62
63#if !defined(QT_NO_SSL)
64
65QT_BEGIN_NAMESPACE
66
67class QHttpNetworkRequest;
68
69#ifndef HttpMessagePair
70typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
71#endif
72
73class QSpdyProtocolHandler : public QObject, public QAbstractProtocolHandler {
74 Q_OBJECT
75public:
76 QSpdyProtocolHandler(QHttpNetworkConnectionChannel *channel);
77 ~QSpdyProtocolHandler();
78
79 enum DataFrameFlag {
80 DataFrame_FLAG_FIN = 0x01,
81 DataFrame_FLAG_COMPRESS = 0x02
82 };
83
84 Q_DECLARE_FLAGS(DataFrameFlags, DataFrameFlag)
85
86 enum ControlFrameFlag {
87 ControlFrame_FLAG_FIN = 0x01,
88 ControlFrame_FLAG_UNIDIRECTIONAL = 0x02
89 };
90
91 Q_DECLARE_FLAGS(ControlFrameFlags, ControlFrameFlag)
92
93 enum SETTINGS_Flag {
94 FLAG_SETTINGS_CLEAR_SETTINGS = 0x01
95 };
96
97 Q_DECLARE_FLAGS(SETTINGS_Flags, SETTINGS_Flag)
98
99 enum SETTINGS_ID_Flag {
100 FLAG_SETTINGS_PERSIST_VALUE = 0x01,
101 FLAG_SETTINGS_PERSISTED = 0x02
102 };
103
104 Q_DECLARE_FLAGS(SETTINGS_ID_Flags, SETTINGS_ID_Flag)
105
106 virtual void _q_receiveReply() override;
107 virtual void _q_readyRead() override;
108 virtual bool sendRequest() override;
109
110private slots:
111 void _q_uploadDataReadyRead();
112 void _q_replyDestroyed(QObject*);
113 void _q_uploadDataDestroyed(QObject *);
114
115private:
116
117 enum FrameType {
118 FrameType_SYN_STREAM = 1,
119 FrameType_SYN_REPLY = 2,
120 FrameType_RST_STREAM = 3,
121 FrameType_SETTINGS = 4,
122 FrameType_PING = 6,
123 FrameType_GOAWAY = 7,
124 FrameType_HEADERS = 8,
125 FrameType_WINDOW_UPDATE = 9,
126 FrameType_CREDENTIAL // has a special type
127 };
128
129 enum StatusCode {
130 StatusCode_PROTOCOL_ERROR = 1,
131 StatusCode_INVALID_STREAM = 2,
132 StatusCode_REFUSED_STREAM = 3,
133 StatusCode_UNSUPPORTED_VERSION = 4,
134 StatusCode_CANCEL = 5,
135 StatusCode_INTERNAL_ERROR = 6,
136 StatusCode_FLOW_CONTROL_ERROR = 7,
137 StatusCode_STREAM_IN_USE = 8,
138 StatusCode_STREAM_ALREADY_CLOSED = 9,
139 StatusCode_INVALID_CREDENTIALS = 10,
140 StatusCode_FRAME_TOO_LARGE = 11
141 };
142
143 enum SETTINGS_ID {
144 SETTINGS_UPLOAD_BANDWIDTH = 1,
145 SETTINGS_DOWNLOAD_BANDWIDTH = 2,
146 SETTINGS_ROUND_TRIP_TIME = 3,
147 SETTINGS_MAX_CONCURRENT_STREAMS = 4,
148 SETTINGS_CURRENT_CWND = 5,
149 SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
150 SETTINGS_INITIAL_WINDOW_SIZE = 7,
151 SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
152 };
153
154 enum GOAWAY_STATUS {
155 GOAWAY_OK = 0,
156 GOAWAY_PROTOCOL_ERROR = 1,
157 GOAWAY_INTERNAL_ERROR = 11
158 };
159
160 enum RST_STREAM_STATUS_CODE {
161 RST_STREAM_PROTOCOL_ERROR = 1,
162 RST_STREAM_INVALID_STREAM = 2,
163 RST_STREAM_REFUSED_STREAM = 3,
164 RST_STREAM_UNSUPPORTED_VERSION = 4,
165 RST_STREAM_CANCEL = 5,
166 RST_STREAM_INTERNAL_ERROR = 6,
167 RST_STREAM_FLOW_CONTROL_ERROR = 7,
168 RST_STREAM_STREAM_IN_USE = 8,
169 RST_STREAM_STREAM_ALREADY_CLOSED = 9,
170 RST_STREAM_INVALID_CREDENTIALS = 10,
171 RST_STREAM_FRAME_TOO_LARGE = 11
172 };
173
174 quint64 bytesAvailable() const;
175 bool readNextChunk(qint64 length, char *sink);
176
177 void sendControlFrame(FrameType type, ControlFrameFlags flags, const char *data, quint32 length);
178
179 void sendSYN_STREAM(const HttpMessagePair &pair, qint32 streamID,
180 qint32 associatedToStreamID);
181 void sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode);
182 void sendPING(quint32 pingID);
183
184 bool uploadData(qint32 streamID);
185 Q_INVOKABLE void sendWINDOW_UPDATE(qint32 streamID, quint32 deltaWindowSize);
186
187 qint64 sendDataFrame(qint32 streamID, DataFrameFlags flags, quint32 length,
188 const char *data);
189
190 QByteArray composeHeader(const QHttpNetworkRequest &request);
191 bool uncompressHeader(const QByteArray &input, QByteArray *output);
192
193 void handleControlFrame(const QByteArray &frameHeaders);
194 void handleDataFrame(const QByteArray &frameHeaders);
195
196 void handleSYN_STREAM(char, quint32, const QByteArray &frameData);
197 void handleSYN_REPLY(char flags, quint32, const QByteArray &frameData);
198 void handleRST_STREAM(char flags, quint32 length, const QByteArray &frameData);
199 void handleSETTINGS(char flags, quint32 length, const QByteArray &frameData);
200 void handlePING(char, quint32 length, const QByteArray &frameData);
201 void handleGOAWAY(char flags, quint32, const QByteArray &frameData);
202 void handleHEADERS(char flags, quint32, const QByteArray &frameData);
203 void handleWINDOW_UPDATE(char, quint32, const QByteArray &frameData);
204
205 qint32 generateNextStreamID();
206 void parseHttpHeaders(char flags, const QByteArray &frameData);
207
208 void replyFinished(QHttpNetworkReply *httpReply, qint32 streamID);
209 void replyFinishedWithError(QHttpNetworkReply *httpReply, qint32 streamID,
210 QNetworkReply::NetworkError errorCode, const char *errorMessage);
211
212 qint32 m_nextStreamID;
213 QHash<quint32, HttpMessagePair> m_inFlightStreams;
214 qint32 m_maxConcurrentStreams;
215 quint32 m_initialWindowSize;
216 QByteDataBuffer m_spdyBuffer;
217 bool m_waitingForCompleteStream;
218 z_stream m_deflateStream;
219 z_stream m_inflateStream;
220 QHash<QObject *, qint32> m_streamIDs;
221};
222
223Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags)
224Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::ControlFrameFlags)
225Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_Flags)
226Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_ID_Flags)
227
228QT_END_NAMESPACE
229
230#endif // !defined(QT_NO_SSL)
231
232#endif // QSPDYPROTOCOLHANDLER_H
233

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