1/****************************************************************************
2**
3** Copyright (C) 2016 Kurt Pattyn <pattyn.kurt@gmail.com>.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWebSockets 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#include "qwebsocketprotocol_p.h"
41#include <QtCore/QString>
42#include <QtCore/QSet>
43#include <QtCore/QtEndian>
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \namespace QWebSocketProtocol
49 \inmodule QtWebSockets
50 \brief Contains constants related to the WebSocket standard.
51 \since 5.3
52*/
53
54/*!
55 \enum QWebSocketProtocol::CloseCode
56
57 \inmodule QtWebSockets
58
59 The close codes supported by WebSockets V13
60
61 \value CloseCodeNormal Normal closure
62 \value CloseCodeGoingAway Going away
63 \value CloseCodeProtocolError Protocol error
64 \value CloseCodeDatatypeNotSupported Unsupported data
65 \value CloseCodeReserved1004 Reserved
66 \value CloseCodeMissingStatusCode No status received
67 \value CloseCodeAbnormalDisconnection Abnormal closure
68 \value CloseCodeWrongDatatype Invalid frame payload data
69 \value CloseCodePolicyViolated Policy violation
70 \value CloseCodeTooMuchData Message too big
71 \value CloseCodeMissingExtension Mandatory extension missing
72 \value CloseCodeBadOperation Internal server error
73 \value CloseCodeTlsHandshakeFailed TLS handshake failed
74
75 \sa QWebSocket::close()
76*/
77/*!
78 \enum QWebSocketProtocol::Version
79
80 \inmodule QtWebSockets
81
82 \brief The different defined versions of the WebSocket protocol.
83
84 For an overview of the differences between the different protocols, see
85 \l {pywebsocket's WebSocketProtocolSpec}.
86
87 \value VersionUnknown Unknown or unspecified version.
88 \value Version0 \l{hixie76} and \l{hybi-00}.
89 Works with key1, key2 and a key in the payload.
90 Attribute: Sec-WebSocket-Draft value 0.
91 Not supported by QtWebSockets.
92 \value Version4 \l{hybi-04}.
93 Changed handshake: key1, key2, key3
94 ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept
95 Sec-WebSocket-Draft renamed to Sec-WebSocket-Version
96 Sec-WebSocket-Version = 4.
97 Not supported by QtWebSockets.
98 \value Version5 \l{hybi-05}.
99 Sec-WebSocket-Version = 5
100 Removed Sec-WebSocket-Nonce
101 Added Sec-WebSocket-Accept.
102 Not supported by QtWebSockets.
103 \value Version6 Sec-WebSocket-Version = 6.
104 Not supported by QtWebSockets.
105 \value Version7 \l{hybi-07}.
106 Sec-WebSocket-Version = 7.
107 Not supported by QtWebSockets.
108 \value Version8 hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
109 Status codes 1005 and 1006 are added and all codes are now unsigned
110 Internal error results in 1006.
111 Not supported by QtWebSockets.
112 \value Version13 hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and \l{RFC 6455}.
113 Sec-WebSocket-Version = 13
114 Status code 1004 is now reserved
115 Added 1008, 1009 and 1010
116 Must support TLS
117 Clarify multiple version support.
118 Supported by QtWebSockets.
119 \value VersionLatest Refers to the latest known version to QtWebSockets.
120*/
121
122/*!
123 \enum QWebSocketProtocol::OpCode
124
125 \inmodule QtWebSockets
126
127 The frame opcodes as defined by the WebSockets standard
128
129 \value OpCodeContinue Continuation frame
130 \value OpCodeText Text frame
131 \value OpCodeBinary Binary frame
132 \value OpCodeReserved3 Reserved
133 \value OpCodeReserved4 Reserved
134 \value OpCodeReserved5 Reserved
135 \value OpCodeReserved6 Reserved
136 \value OpCodeReserved7 Reserved
137 \value OpCodeClose Close frame
138 \value OpCodePing Ping frame
139 \value OpCodePong Pong frame
140 \value OpCodeReservedB Reserved
141 \value OpCodeReservedC Reserved
142 \value OpCodeReservedD Reserved
143 \value OpCodeReservedE Reserved
144 \value OpCodeReservedF Reserved
145
146 \internal
147*/
148
149/*!
150 \fn QWebSocketProtocol::isOpCodeReserved(OpCode code)
151 Checks if \a code is a valid OpCode
152
153 \internal
154*/
155
156/*!
157 \fn QWebSocketProtocol::isCloseCodeValid(int closeCode)
158 Checks if \a closeCode is a valid WebSocket close code
159
160 \internal
161*/
162
163/*!
164 \fn QWebSocketProtocol::currentVersion()
165 Returns the latest version that WebSocket is supporting
166
167 \internal
168*/
169
170/*!
171 Parses the \a versionString and converts it to a Version value
172
173 \internal
174*/
175QWebSocketProtocol::Version QWebSocketProtocol::versionFromString(const QString &versionString)
176{
177 bool ok = false;
178 Version version = VersionUnknown;
179 const int ver = versionString.toInt(ok: &ok);
180 QSet<Version> supportedVersions;
181 supportedVersions << Version0 << Version4 << Version5 << Version6 << Version7 << Version8
182 << Version13;
183 if (Q_LIKELY(ok) && (supportedVersions.contains(value: static_cast<Version>(ver))))
184 version = static_cast<Version>(ver);
185 return version;
186}
187
188/*!
189 Mask the \a payload with the given \a maskingKey and stores the result back in \a payload.
190
191 \internal
192*/
193void QWebSocketProtocol::mask(QByteArray *payload, quint32 maskingKey)
194{
195 Q_ASSERT(payload);
196 mask(payload: payload->data(), size: quint64(payload->size()), maskingKey);
197}
198
199/*!
200 Masks the \a payload of length \a size with the given \a maskingKey and
201 stores the result back in \a payload.
202
203 \internal
204*/
205void QWebSocketProtocol::mask(char *payload, quint64 size, quint32 maskingKey)
206{
207 Q_ASSERT(payload);
208 const quint8 mask[] = { quint8((maskingKey & 0xFF000000u) >> 24),
209 quint8((maskingKey & 0x00FF0000u) >> 16),
210 quint8((maskingKey & 0x0000FF00u) >> 8),
211 quint8((maskingKey & 0x000000FFu))
212 };
213 quint64 i = 0;
214 while (size-- > 0)
215 *payload++ ^= mask[i++ % 4];
216}
217
218QT_END_NAMESPACE
219

source code of qtwebsockets/src/websockets/qwebsocketprotocol.cpp