@@ -27,9 +27,9 @@ JsonClientConnection::JsonClientConnection(QTcpSocket *socket, Hyperion * hyperi
27
27
_socket(socket),
28
28
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
29
29
_hyperion(hyperion),
30
- _receiveBuffer()
30
+ _receiveBuffer(),
31
+ _webSocketHandshakeDone(false )
31
32
{
32
- _webSocketHandshakeDone = false ;
33
33
// connect internal signals and slots
34
34
connect (_socket, SIGNAL (disconnected ()), this , SLOT (socketClosed ()));
35
35
connect (_socket, SIGNAL (readyRead ()), this , SLOT (readData ()));
@@ -45,106 +45,19 @@ void JsonClientConnection::readData()
45
45
{
46
46
_receiveBuffer += _socket->readAll ();
47
47
48
- if (_webSocketHandshakeDone) { // websocket mode, data frame
49
- quint8 opCode = 0 ;
50
- quint64 payloadLength = 0 ;
51
- bool isMasked = false ;
52
- quint32 index = 0 ;
53
- quint8 maskKey[4 ];
54
-
55
- if ((_receiveBuffer.at (0 ) & 0x80 ) == 0x80 ) { // final bit
56
- opCode = _receiveBuffer.at (0 ) & 0x0F ;
57
- isMasked = (_receiveBuffer.at (1 ) & 0x80 ) == 0x80 ;
58
- payloadLength = _receiveBuffer.at (1 ) & 0x7F ;
59
- index = 2 ;
60
-
61
- switch (payloadLength) {
62
- case 126 :
63
- payloadLength = ((_receiveBuffer.at (2 ) << 8 ) & 0xFF00 ) | (_receiveBuffer.at (3 ) & 0xFF );
64
- index += 2 ;
65
- break ;
66
- case 127 : {
67
- payloadLength = 0 ;
68
- for (uint i=0 ; i < 8 ; i++) {
69
- payloadLength |= ((quint64)(_receiveBuffer.at (index+i) & 0xFF )) << (8 *(7 -i));
70
- }
71
- index += 8 ;
72
- }
73
- break ;
74
- default :
75
- break ;
76
- }
77
-
78
- if (isMasked) { // if the data is masked we need to get the key for unmasking
79
- for (uint i=0 ; i < 4 ; i++) {
80
- maskKey[i] = _receiveBuffer.at (index + i);
81
- }
82
- index += 4 ;
83
- }
84
-
85
- // check the type of data frame
86
- switch (opCode) {
87
- case 0x01 : { // text
88
- QByteArray result = _receiveBuffer.mid (index, payloadLength);
89
- _receiveBuffer.clear ();
90
-
91
- // unmask data if necessary
92
- if (isMasked) {
93
- for (uint i=0 ; i < payloadLength; i++) {
94
- result[i] = (result[i] ^ maskKey[i % 4 ]);
95
- }
96
- }
97
-
98
- handleMessage (QString (result).toStdString ());
99
- }
100
- break ;
101
- case 0x08 : { // close
102
- quint8 close[]={0x88 , 0 };
103
- _socket->write ((const char *)close, 2 );
104
- _socket->flush ();
105
- _socket->close ();
106
- }
107
- break ;
108
- case 0x09 : { // ping, send pong
109
- quint8 close[]={0x0A , 0 };
110
- _socket->write ((const char *)close, 2 );
111
- _socket->flush ();
112
- }
113
- break ;
114
- }
115
- } else {
116
- std::cout << " Someone is sending very big messages over several frames... it's not supported yet" << std::endl;
117
- quint8 close[]={0x88 , 0 };
118
- _socket->write ((const char *)close, 2 );
119
- _socket->flush ();
120
- _socket->close ();
121
- }
122
- } else { // might be a handshake request or raw socket data
123
- if (_receiveBuffer.contains (" Upgrade: websocket" )){ // http header, might not be a very reliable check...
124
- std::cout << " Websocket handshake" << std::endl;
125
-
126
- // get the key to tprepare an answer
127
- int start = _receiveBuffer.indexOf (" Sec-WebSocket-Key" ) + 19 ;
128
- std::string value (_receiveBuffer.mid (start, _receiveBuffer.indexOf (" \r\n " , start) - start).data ());
129
- _receiveBuffer.clear ();
130
-
131
- // must be always appended
132
- value += " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ;
133
-
134
- // generate sha1 hash
135
- QByteArray hash = QCryptographicHash::hash (value.c_str (), QCryptographicHash::Sha1);
136
-
137
- // prepare an answer
138
- std::ostringstream h;
139
- h << " HTTP/1.1 101 Switching Protocols\r\n " <<
140
- " Upgrade: websocket\r\n " <<
141
- " Connection: Upgrade\r\n " <<
142
- " Sec-WebSocket-Accept: " << QString (hash.toBase64 ()).toStdString () << " \r\n\r\n " ;
143
-
144
- _socket->write (h.str ().c_str ());
145
- _socket->flush ();
146
- _webSocketHandshakeDone = true ; // we are in WebSocket mode, data frames should follow next
147
- } else { // raw socket data, handling as usual
48
+ if (_webSocketHandshakeDone)
49
+ {
50
+ // websocket mode, data frame
51
+ handleWebSocketFrame ();
52
+ } else
53
+ {
54
+ // might be a handshake request or raw socket data
55
+ if (_receiveBuffer.contains (" Upgrade: websocket" ))
56
+ {
57
+ doWebSocketHandshake ();
58
+ } else
59
+ {
60
+ // raw socket data, handling as usual
148
61
int bytes = _receiveBuffer.indexOf (' \n ' ) + 1 ;
149
62
while (bytes > 0 )
150
63
{
@@ -164,6 +77,128 @@ void JsonClientConnection::readData()
164
77
}
165
78
}
166
79
80
+ void JsonClientConnection::handleWebSocketFrame ()
81
+ {
82
+ if ((_receiveBuffer.at (0 ) & 0x80 ) == 0x80 )
83
+ {
84
+ // final bit found, frame complete
85
+ quint8 * maskKey = NULL ;
86
+ quint8 opCode = _receiveBuffer.at (0 ) & 0x0F ;
87
+ bool isMasked = (_receiveBuffer.at (1 ) & 0x80 ) == 0x80 ;
88
+ quint64 payloadLength = _receiveBuffer.at (1 ) & 0x7F ;
89
+ quint32 index = 2 ;
90
+
91
+ switch (payloadLength)
92
+ {
93
+ case 126 :
94
+ payloadLength = ((_receiveBuffer.at (2 ) << 8 ) & 0xFF00 ) | (_receiveBuffer.at (3 ) & 0xFF );
95
+ index += 2 ;
96
+ break ;
97
+ case 127 :
98
+ payloadLength = 0 ;
99
+ for (uint i=0 ; i < 8 ; i++) {
100
+ payloadLength |= ((quint64)(_receiveBuffer.at (index+i) & 0xFF )) << (8 *(7 -i));
101
+ }
102
+ index += 8 ;
103
+ break ;
104
+ default :
105
+ break ;
106
+ }
107
+
108
+ if (isMasked)
109
+ {
110
+ // if the data is masked we need to get the key for unmasking
111
+ maskKey = new quint8[4 ];
112
+ for (uint i=0 ; i < 4 ; i++)
113
+ {
114
+ maskKey[i] = _receiveBuffer.at (index + i);
115
+ }
116
+ index += 4 ;
117
+ }
118
+
119
+ // check the type of data frame
120
+ switch (opCode)
121
+ {
122
+ case 0x01 :
123
+ {
124
+ // frame contains text, extract it
125
+ QByteArray result = _receiveBuffer.mid (index, payloadLength);
126
+ _receiveBuffer.clear ();
127
+
128
+ // unmask data if necessary
129
+ if (isMasked)
130
+ {
131
+ for (uint i=0 ; i < payloadLength; i++)
132
+ {
133
+ result[i] = (result[i] ^ maskKey[i % 4 ]);
134
+ }
135
+ if (maskKey != NULL )
136
+ {
137
+ delete[] maskKey;
138
+ maskKey = NULL ;
139
+ }
140
+ }
141
+
142
+ handleMessage (QString (result).toStdString ());
143
+ }
144
+ break ;
145
+ case 0x08 :
146
+ {
147
+ // close request, confirm
148
+ quint8 close[] = {0x88 , 0 };
149
+ _socket->write ((const char *)close, 2 );
150
+ _socket->flush ();
151
+ _socket->close ();
152
+ }
153
+ break ;
154
+ case 0x09 :
155
+ {
156
+ // ping received, send pong
157
+ quint8 pong[] = {0x0A , 0 };
158
+ _socket->write ((const char *)pong, 2 );
159
+ _socket->flush ();
160
+ }
161
+ break ;
162
+ }
163
+ } else
164
+ {
165
+ std::cout << " Someone is sending very big messages over several frames... it's not supported yet" << std::endl;
166
+ quint8 close[] = {0x88 , 0 };
167
+ _socket->write ((const char *)close, 2 );
168
+ _socket->flush ();
169
+ _socket->close ();
170
+ }
171
+ }
172
+
173
+ void JsonClientConnection::doWebSocketHandshake ()
174
+ {
175
+ // http header, might not be a very reliable check...
176
+ std::cout << " Websocket handshake" << std::endl;
177
+
178
+ // get the key to prepare an answer
179
+ int start = _receiveBuffer.indexOf (" Sec-WebSocket-Key" ) + 19 ;
180
+ std::string value (_receiveBuffer.mid (start, _receiveBuffer.indexOf (" \r\n " , start) - start).data ());
181
+ _receiveBuffer.clear ();
182
+
183
+ // must be always appended
184
+ value += " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ;
185
+
186
+ // generate sha1 hash
187
+ QByteArray hash = QCryptographicHash::hash (value.c_str (), QCryptographicHash::Sha1);
188
+
189
+ // prepare an answer
190
+ std::ostringstream h;
191
+ h << " HTTP/1.1 101 Switching Protocols\r\n " <<
192
+ " Upgrade: websocket\r\n " <<
193
+ " Connection: Upgrade\r\n " <<
194
+ " Sec-WebSocket-Accept: " << QString (hash.toBase64 ()).toStdString () << " \r\n\r\n " ;
195
+
196
+ _socket->write (h.str ().c_str ());
197
+ _socket->flush ();
198
+ // we are in WebSocket mode, data frames should follow next
199
+ _webSocketHandshakeDone = true ;
200
+ }
201
+
167
202
void JsonClientConnection::socketClosed ()
168
203
{
169
204
_webSocketHandshakeDone = false ;
@@ -472,24 +507,28 @@ void JsonClientConnection::sendMessage(const Json::Value &message)
472
507
Json::FastWriter writer;
473
508
std::string serializedReply = writer.write (message);
474
509
475
- if (!_webSocketHandshakeDone) { // raw tcp socket mode
510
+ if (!_webSocketHandshakeDone)
511
+ {
512
+ // raw tcp socket mode
476
513
_socket->write (serializedReply.data (), serializedReply.length ());
477
- } else { // websocket mode
514
+ } else
515
+ {
516
+ // websocket mode
478
517
quint32 size = serializedReply.length ();
479
518
480
519
// prepare data frame
481
520
QByteArray response;
482
521
response.append (0x81 );
483
- if (size > 125 ) {
522
+ if (size > 125 )
523
+ {
484
524
response.append (0x7E );
485
525
response.append ((size >> 8 ) & 0xFF );
486
526
response.append (size & 0xFF );
487
527
} else {
488
528
response.append (size);
489
529
}
490
530
491
- QByteArray data (serializedReply.c_str (), serializedReply.length ());
492
- response.append (data);
531
+ response.append (serializedReply.c_str (), serializedReply.length ());
493
532
494
533
_socket->write (response.data (), response.length ());
495
534
}
0 commit comments