MythTV master
websocket.h
Go to the documentation of this file.
1
2// Program Name: websocket.h
3// Created : 18 Jan 2015
4//
5// Purpose : Web Socket server
6//
7// Copyright (c) 2015 Stuart Morgan <smorgan@mythtv.org>
8//
9// Licensed under the GPL v2 or later, see LICENSE for details
10//
12
13#ifndef WEBSOCKET_H
14#define WEBSOCKET_H
15
18
19#include "upnpexp.h"
20
21#include <QRunnable>
22#include <QSslConfiguration>
23#include <QReadWriteLock>
24#include <QEvent>
25#include <QEventLoop>
26#include <QTimer>
27
28#include <cstdint>
29
39{
40 Q_OBJECT
41
42 public:
44 ~WebSocketServer() override;
45
46 bool IsRunning(void) const
47 {
48 m_rwlock.lockForRead();
49 bool tmp = m_running;
50 m_rwlock.unlock();
51 return tmp;
52 }
53
54 protected slots:
55 void newTcpConnection(qintptr socket) override; // QTcpServer
56
57 protected:
58 mutable QReadWriteLock m_rwlock;
60 bool m_running {true}; // protected by m_rwlock
61
62#ifndef QT_NO_OPENSSL
63 QSslConfiguration m_sslConfig;
64#endif
65
66 private:
67 //void LoadSSLConfig();
68};
69
70
77{
78 public:
80 {
81 m_mask.reserve(4);
82 }
83
85 {
86 m_payload.clear();
87 m_mask.clear();
88 }
89
90 void reset(void)
91 {
92 m_finalFrame = false;
93 m_payload.clear();
94 m_payload.resize(128);
95 m_payload.squeeze();
96 m_mask.clear();
97 m_payloadSize = 0;
99 m_fragmented = false;
100 }
101
102 enum OpCode : std::uint8_t
103 {
107 // Reserved
108 kOpClose = 0x8,
109 kOpPing = 0x9,
110 kOpPong = 0xA
111 // Reserved
112 };
113
114 bool m_finalFrame {false};
115 QByteArray m_payload;
116 uint64_t m_payloadSize {0};
118 bool m_isMasked {false};
119 QByteArray m_mask;
120 bool m_fragmented {false};
121};
122
123class WebSocketWorker;
124
137class WebSocketExtension : public QObject
138{
139 Q_OBJECT
140
141 public:
142 WebSocketExtension() = default;;
143 ~WebSocketExtension() override = default;
144
145 virtual bool HandleTextFrame(const WebSocketFrame &/*frame*/) { return false; }
146 virtual bool HandleBinaryFrame(const WebSocketFrame &/*frame*/) { return false; }
147
148 signals:
149 void SendTextMessage(const QString &);
150 void SendBinaryMessage(const QByteArray &);
151};
152
158class WebSocketWorkerThread : public QRunnable
159{
160 public:
161 WebSocketWorkerThread(WebSocketServer &webSocketServer, qintptr sock,
163#ifndef QT_NO_OPENSSL
164 , const QSslConfiguration& sslConfig
165#endif
166 );
167 ~WebSocketWorkerThread() override = default;
168
169 void run(void) override; // QRunnable
170
171 private:
173 qintptr m_socketFD;
175#ifndef QT_NO_OPENSSL
176 QSslConfiguration m_sslConfig;
177#endif
178};
179
198class WebSocketWorker : public QObject
199{
200 Q_OBJECT
201
202 public:
203
210 WebSocketWorker(WebSocketServer &webSocketServer, qintptr sock,
212#ifndef QT_NO_OPENSSL
213 , const QSslConfiguration& sslConfig
214#endif
215 );
216 ~WebSocketWorker() override;
217
218 void Exec();
219
221 {
226 // Reserved - 1004
227 // The following codes, 1005 and 1006 should not go over the wire,
228 // they are internal codes generated if the client has disconnected
229 // without sending a Close event or without indicating a reason for
230 // closure.
234 kClosePolicy = 1008, // Message violates server policy and 1003/1009 don't apply
235 kCloseTooLarge = 1009, // Message is larger than we support (32KB)
236 kCloseNoExtensions = 1010, // CLIENT ONLY
237 kCloseUnexpectedErr = 1011, // SERVER ONLY
238 // Reserved - 1012-1014
239 kCloseNoTLS = 1012 // Connection closed because it must use TLS
240 // Reserved
241 };
242
243 public slots:
244 void doRead();
245 void CloseConnection();
246
247 void SendHeartBeat();
248 bool SendText(const QString &message);
249 bool SendText(const QByteArray &message);
250 bool SendBinary(const QByteArray &data);
251
252 protected:
253 bool ProcessHandshake(QTcpSocket *socket);
254 void ProcessFrames(QTcpSocket *socket);
255
256 void HandleControlFrame(const WebSocketFrame &frame);
257 void HandleDataFrame(const WebSocketFrame &frame);
258
259 void HandleCloseConnection(const QByteArray &payload);
260
261 static QByteArray CreateFrame(WebSocketFrame::OpCode type, const QByteArray &payload);
262
263 bool SendFrame(const QByteArray &frame);
264 bool SendPing(const QByteArray &payload);
265 bool SendPong(const QByteArray &payload);
266 bool SendClose(ErrorCode errCode, const QString &message = QString());
267
268 void SetupSocket();
269 void CleanupSocket();
270
271 void RegisterExtension(WebSocketExtension *extension);
273
274 QEventLoop *m_eventLoop {nullptr};
276 qintptr m_socketFD;
277 QTcpSocket *m_socket {nullptr};
279
280 // True if we've successfully upgraded from HTTP
281 bool m_webSocketMode {false};
283
284 uint8_t m_errorCount {0};
285 bool m_isRunning {false};
286
287 QTimer *m_heartBeat {nullptr};
288
289#ifndef QT_NO_OPENSSL
290 QSslConfiguration m_sslConfig;
291#endif
292
293 bool m_fuzzTesting {false};
294
295 QList<WebSocketExtension *> m_extensions;
296};
297
298#endif // WEBSOCKET_H
Manages a collection of sockets listening on different ports.
Definition: serverpool.h:60
virtual void newTcpConnection(qintptr socket)
Definition: serverpool.cpp:678
Base class for extensions.
Definition: websocket.h:138
void SendTextMessage(const QString &)
virtual bool HandleTextFrame(const WebSocketFrame &)
Definition: websocket.h:145
~WebSocketExtension() override=default
virtual bool HandleBinaryFrame(const WebSocketFrame &)
Definition: websocket.h:146
WebSocketExtension()=default
void SendBinaryMessage(const QByteArray &)
A representation of a single WebSocket frame.
Definition: websocket.h:77
void reset(void)
Definition: websocket.h:90
bool m_fragmented
Definition: websocket.h:120
QByteArray m_mask
Definition: websocket.h:119
QByteArray m_payload
Definition: websocket.h:115
bool m_finalFrame
Definition: websocket.h:114
uint64_t m_payloadSize
Definition: websocket.h:116
OpCode m_opCode
Definition: websocket.h:117
The WebSocket server, which listens for connections.
Definition: websocket.h:39
QReadWriteLock m_rwlock
Definition: websocket.h:58
QSslConfiguration m_sslConfig
Definition: websocket.h:63
MThreadPool m_threadPool
Definition: websocket.h:59
bool IsRunning(void) const
Definition: websocket.h:46
The thread in which WebSocketWorker does it's thing.
Definition: websocket.h:159
WebSocketServer & m_webSocketServer
Definition: websocket.h:172
~WebSocketWorkerThread() override=default
PoolServerType m_connectionType
Definition: websocket.h:174
WebSocketWorkerThread(WebSocketServer &webSocketServer, qintptr sock, PoolServerType type, const QSslConfiguration &sslConfig)
Definition: websocket.cpp:73
QSslConfiguration m_sslConfig
Definition: websocket.h:176
void run(void) override
Definition: websocket.cpp:88
Performs all the protocol-level work for a single websocket connection.
Definition: websocket.h:199
void HandleCloseConnection(const QByteArray &payload)
Definition: websocket.cpp:719
void SendHeartBeat()
Definition: websocket.cpp:920
bool SendBinary(const QByteArray &data)
Definition: websocket.cpp:875
void HandleDataFrame(const WebSocketFrame &frame)
Definition: websocket.cpp:671
void ProcessFrames(QTcpSocket *socket)
Returns false if an error occurs.
Definition: websocket.cpp:478
bool m_webSocketMode
Definition: websocket.h:281
void CleanupSocket()
Definition: websocket.cpp:226
QSslConfiguration m_sslConfig
Definition: websocket.h:290
QList< WebSocketExtension * > m_extensions
Definition: websocket.h:295
QTimer * m_heartBeat
Definition: websocket.h:287
void CloseConnection()
Definition: websocket.cpp:155
static QByteArray CreateFrame(WebSocketFrame::OpCode type, const QByteArray &payload)
Definition: websocket.cpp:764
void RegisterExtension(WebSocketExtension *extension)
Definition: websocket.cpp:925
WebSocketServer & m_webSocketServer
Definition: websocket.h:275
qintptr m_socketFD
Definition: websocket.h:276
bool SendPong(const QByteArray &payload)
Definition: websocket.cpp:889
uint8_t m_errorCount
Definition: websocket.h:284
QTcpSocket * m_socket
Definition: websocket.h:277
WebSocketFrame m_readFrame
Definition: websocket.h:282
QEventLoop * m_eventLoop
Definition: websocket.h:274
bool SendClose(ErrorCode errCode, const QString &message=QString())
Definition: websocket.cpp:896
void HandleControlFrame(const WebSocketFrame &frame)
Returns false if an error occurs.
Definition: websocket.cpp:667
bool SendText(const QString &message)
Definition: websocket.cpp:855
WebSocketWorker(WebSocketServer &webSocketServer, qintptr sock, PoolServerType type, const QSslConfiguration &sslConfig)
Definition: websocket.cpp:105
void DeregisterExtension(WebSocketExtension *extension)
Definition: websocket.cpp:938
bool SendFrame(const QByteArray &frame)
Definition: websocket.cpp:840
bool m_fuzzTesting
Definition: websocket.h:293
void SetupSocket()
Definition: websocket.cpp:164
bool SendPing(const QByteArray &payload)
Definition: websocket.cpp:882
PoolServerType m_connectionType
Definition: websocket.h:278
bool ProcessHandshake(QTcpSocket *socket)
Definition: websocket.cpp:315
~WebSocketWorker() override
Definition: websocket.cpp:132
static guint32 * tmp
Definition: goom_core.cpp:26
unsigned short uint16_t
Definition: iso6937tables.h:3
PoolServerType
Definition: serverpool.h:30
#define UPNP_PUBLIC
Definition: upnpexp.h:9