Adapt copyright header
[contrib/qtwebsockets.git] / src / websockets / qwebsocketprotocol.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Kurt Pattyn <pattyn.kurt@gmail.com>.
4 ** Contact: http://www.qt-project.org/legal
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwebsocketprotocol_p.h"
43 #include <QtCore/QString>
44 #include <QtCore/QSet>
45 #include <QtCore/QtEndian>
46
47 QT_BEGIN_NAMESPACE
48
49 /*!
50   \namespace QWebSocketProtocol
51   \inmodule QtWebSockets
52   \brief Contains constants related to the WebSocket standard.
53 */
54
55 /*!
56     \enum QWebSocketProtocol::CloseCode
57
58     \inmodule QtWebSockets
59
60     The close codes supported by WebSockets V13
61
62     \value CloseCodeNormal                  Normal closure
63     \value CloseCodeGoingAway               Going away
64     \value CloseCodeProtocolError           Protocol error
65     \value CloseCodeDatatypeNotSupported    Unsupported data
66     \value CloseCodeReserved1004            Reserved
67     \value CloseCodeMissingStatusCode       No status received
68     \value CloseCodeAbnormalDisconnection   Abnormal closure
69     \value CloseCodeWrongDatatype           Invalid frame payload data
70     \value CloseCodePolicyViolated          Policy violation
71     \value CloseCodeTooMuchData             Message too big
72     \value CloseCodeMissingExtension        Mandatory extension missing
73     \value CloseCodeBadOperation            Internal server error
74     \value CloseCodeTlsHandshakeFailed      TLS handshake failed
75
76     \sa QWebSocket::close()
77 */
78 /*!
79     \enum QWebSocketProtocol::Version
80
81     \inmodule QtWebSockets
82
83     \brief The different defined versions of the Websocket protocol.
84
85     For an overview of the differences between the different protocols, see
86     <http://code.google.com/p/pywebsocket/wiki/WebSocketProtocolSpec>
87
88     \value VersionUnknown   Unknown or unspecified version.
89     \value Version0         hixie76:
90                             http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 &
91                             hybi-00:
92                             http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00.
93                             Works with key1, key2 and a key in the payload.
94                             Attribute: Sec-WebSocket-Draft value 0.
95                             Not supported by QtWebSockets.
96     \value Version4         hybi-04:
97                             http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-04.txt.
98                             Changed handshake: key1, key2, key3
99                             ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept
100                             Sec-WebSocket-Draft renamed to Sec-WebSocket-Version
101                             Sec-WebSocket-Version = 4.
102                             Not supported by QtWebSockets.
103     \value Version5         hybi-05:
104                             http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-05.txt.
105                             Sec-WebSocket-Version = 5
106                             Removed Sec-WebSocket-Nonce
107                             Added Sec-WebSocket-Accept.
108                             Not supported by QtWebSockets.
109     \value Version6         Sec-WebSocket-Version = 6.
110                             Not supported by QtWebSockets.
111     \value Version7         hybi-07:
112                             http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07.
113                             Sec-WebSocket-Version = 7.
114                             Not supported by QtWebSockets.
115     \value Version8         hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
116                             Status codes 1005 and 1006 are added and all codes are now unsigned
117                             Internal error results in 1006.
118                             Not supported by QtWebSockets.
119     \value Version13        hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and RFC 6455.
120                             Sec-WebSocket-Version = 13
121                             Status code 1004 is now reserved
122                             Added 1008, 1009 and 1010
123                             Must support TLS
124                             Clarify multiple version support.
125                             Supported by QtWebSockets.
126     \value VersionLatest    Refers to the latest known version to QtWebSockets.
127 */
128
129 /*!
130     \enum QWebSocketProtocol::OpCode
131
132     \inmodule QtWebSockets
133
134     The frame opcodes as defined by the WebSockets standard
135
136     \value OpCodeContinue     Continuation frame
137     \value OpCodeText         Text frame
138     \value OpCodeBinary       Binary frame
139     \value OpCodeReserved3    Reserved
140     \value OpCodeReserved4    Reserved
141     \value OpCodeReserved5    Reserved
142     \value OpCodeReserved6    Reserved
143     \value OpCodeReserved7    Reserved
144     \value OpCodeClose        Close frame
145     \value OpCodePing         Ping frame
146     \value OpCodePong         Pong frame
147     \value OpCodeReservedB    Reserved
148     \value OpCodeReservedC    Reserved
149     \value OpCodeReservedD    Reserved
150     \value OpCodeReservedE    Reserved
151     \value OpCodeReservedF    Reserved
152
153     \internal
154 */
155
156 /*!
157   \fn QWebSocketProtocol::isOpCodeReserved(OpCode code)
158   Checks if \a code is a valid OpCode
159
160   \internal
161 */
162
163 /*!
164   \fn QWebSocketProtocol::isCloseCodeValid(int closeCode)
165   Checks if \a closeCode is a valid web socket close code
166
167   \internal
168 */
169
170 /*!
171   \fn QWebSocketProtocol::currentVersion()
172   Returns the latest version that WebSocket is supporting
173
174   \internal
175 */
176
177 /*!
178     Parses the \a versionString and converts it to a Version value
179
180     \internal
181 */
182 QWebSocketProtocol::Version QWebSocketProtocol::versionFromString(const QString &versionString)
183 {
184     bool ok = false;
185     Version version = VersionUnknown;
186     const int ver = versionString.toInt(&ok);
187     QSet<Version> supportedVersions;
188     supportedVersions << Version0 << Version4 << Version5 << Version6 << Version7 << Version8
189                       << Version13;
190     if (Q_LIKELY(ok) && (supportedVersions.contains(static_cast<Version>(ver))))
191         version = static_cast<Version>(ver);
192     return version;
193 }
194
195 /*!
196     Mask the \a payload with the given \a maskingKey and stores the result back in \a payload.
197
198     \internal
199 */
200 void QWebSocketProtocol::mask(QByteArray *payload, quint32 maskingKey)
201 {
202     Q_ASSERT(payload);
203     mask(payload->data(), payload->size(), maskingKey);
204 }
205
206 /*!
207     Masks the \a payload of length \a size with the given \a maskingKey and
208     stores the result back in \a payload.
209
210     \internal
211 */
212 void QWebSocketProtocol::mask(char *payload, quint64 size, quint32 maskingKey)
213 {
214     Q_ASSERT(payload);
215     const quint8 mask[] = { quint8((maskingKey & 0xFF000000u) >> 24),
216                             quint8((maskingKey & 0x00FF0000u) >> 16),
217                             quint8((maskingKey & 0x0000FF00u) >> 8),
218                             quint8((maskingKey & 0x000000FFu))
219                           };
220     int i = 0;
221     while (size-- > 0)
222         *payload++ ^= mask[i++ % 4];
223 }
224
225 QT_END_NAMESPACE