Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit 157f424

Browse files
committed
code refactoring
1 parent 82029cd commit 157f424

File tree

2 files changed

+156
-107
lines changed

2 files changed

+156
-107
lines changed

libsrc/jsonserver/JsonClientConnection.cpp

Lines changed: 146 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ JsonClientConnection::JsonClientConnection(QTcpSocket *socket, Hyperion * hyperi
2727
_socket(socket),
2828
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
2929
_hyperion(hyperion),
30-
_receiveBuffer()
30+
_receiveBuffer(),
31+
_webSocketHandshakeDone(false)
3132
{
32-
_webSocketHandshakeDone = false;
3333
// connect internal signals and slots
3434
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
3535
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
@@ -45,106 +45,19 @@ void JsonClientConnection::readData()
4545
{
4646
_receiveBuffer += _socket->readAll();
4747

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
14861
int bytes = _receiveBuffer.indexOf('\n') + 1;
14962
while(bytes > 0)
15063
{
@@ -164,6 +77,128 @@ void JsonClientConnection::readData()
16477
}
16578
}
16679

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+
167202
void JsonClientConnection::socketClosed()
168203
{
169204
_webSocketHandshakeDone = false;
@@ -472,24 +507,28 @@ void JsonClientConnection::sendMessage(const Json::Value &message)
472507
Json::FastWriter writer;
473508
std::string serializedReply = writer.write(message);
474509

475-
if (!_webSocketHandshakeDone) { // raw tcp socket mode
510+
if (!_webSocketHandshakeDone)
511+
{
512+
// raw tcp socket mode
476513
_socket->write(serializedReply.data(), serializedReply.length());
477-
} else { // websocket mode
514+
} else
515+
{
516+
// websocket mode
478517
quint32 size = serializedReply.length();
479518

480519
// prepare data frame
481520
QByteArray response;
482521
response.append(0x81);
483-
if (size > 125) {
522+
if (size > 125)
523+
{
484524
response.append(0x7E);
485525
response.append((size >> 8) & 0xFF);
486526
response.append(size & 0xFF);
487527
} else {
488528
response.append(size);
489529
}
490530

491-
QByteArray data(serializedReply.c_str(), serializedReply.length());
492-
response.append(data);
531+
response.append(serializedReply.c_str(), serializedReply.length());
493532

494533
_socket->write(response.data(), response.length());
495534
}

libsrc/jsonserver/JsonClientConnection.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ private slots:
136136
/// @param error String describing the error
137137
///
138138
void sendErrorReply(const std::string & error);
139+
140+
///
141+
/// Do handshake for a websocket connection
142+
///
143+
void doWebSocketHandshake();
144+
145+
///
146+
/// Handle incoming websocket data frame
147+
///
148+
void handleWebSocketFrame();
139149

140150
private:
141151
///

0 commit comments

Comments
 (0)