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 
61 QT_REQUIRE_CONFIG(http);
62 
63 #if !defined(QT_NO_SSL)
64 
65 QT_BEGIN_NAMESPACE
66 
67 class QHttpNetworkRequest;
68 
69 #ifndef HttpMessagePair
70 typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
71 #endif
72 
73 class QSpdyProtocolHandler : public QObject, public QAbstractProtocolHandler {
74     Q_OBJECT
75 public:
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 
110 private slots:
111     void _q_uploadDataReadyRead();
112     void _q_replyDestroyed(QObject*);
113     void _q_uploadDataDestroyed(QObject *);
114 
115 private:
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 
223 Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags)
224 Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::ControlFrameFlags)
225 Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_Flags)
226 Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_ID_Flags)
227 
228 QT_END_NAMESPACE
229 
230 #endif // !defined(QT_NO_SSL)
231 
232 #endif // QSPDYPROTOCOLHANDLER_H
233