31 #include "utf8/core.h" 32 #include "utf8/checked.h" 33 #include "utf8/unchecked.h" 41 case OpText:
return QStringLiteral(
"Text");
42 case OpBinary:
return QStringLiteral(
"Binary");
43 case OpClose:
return QStringLiteral(
"Close");
44 case OpPing:
return QStringLiteral(
"Ping");
45 case OpPong:
return QStringLiteral(
"Pong");
49 return QStringLiteral(
"Reserved");
73 return QStringLiteral(
"Unknown");
97 return list.join(
',');
113 QList<WSSubProtocol> results;
115 QStringList protocols = Protocols.split(
',');
116 for (
int i = 0; i < protocols.size(); ++i)
117 if (!QString::compare(protocols[i].trimmed(),
TORC_JSON_RPC.toLatin1(), Qt::CaseInsensitive))
123 m_serverSide(ServerSide),
125 m_closeReceived(false),
127 m_subProtocol(Protocol),
129 m_readState(ReadHeader),
131 m_frameFinalFragment(false),
132 m_frameMasked(false),
133 m_haveBufferedPayload(false),
136 m_framePayloadLength(0),
137 m_framePayloadReadPosition(0),
138 m_frameMask(QByteArray(4, 0)),
139 m_framePayload(QByteArray())
145 return m_haveBufferedPayload ? m_bufferedPayload : m_framePayload;
150 m_haveBufferedPayload =
false;
151 m_bufferedPayload = QByteArray();
152 m_readState = ReadHeader;
153 m_framePayload = QByteArray();
154 m_framePayloadReadPosition = 0;
155 m_framePayloadLength = 0;
170 m_subProtocol = Protocol;
179 payload.append((Close >> 8) & 0xff);
180 payload.append(Close & 0xff);
181 payload.append(Reason.toUtf8());
191 if (m_closeSent || (m_closeReceived && Code !=
OpClose))
199 frame.append(Code | 0x80);
206 for (
int i = 0; i < 4; ++i)
207 mask.append(qrand() % 0x100);
213 quint64 length = Payload.size();
219 else if (length <= 0xffff)
222 size.append((length >> 8) & 0xff);
223 size.append(length & 0xff);
225 else if (length <= 0x7fffffff)
228 size.append((length >> 56) & 0xff);
229 size.append((length >> 48) & 0xff);
230 size.append((length >> 40) & 0xff);
231 size.append((length >> 32) & 0xff);
232 size.append((length >> 24) & 0xff);
233 size.append((length >> 16) & 0xff);
234 size.append((length >> 8 ) & 0xff);
235 size.append((length ) & 0xff);
239 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Infeasibly large payload!"));
250 for (
int i = 0; i < Payload.size(); ++i)
251 Payload[i] = Payload[i] ^ mask[i % 4];
254 if (m_socket.write(frame) == frame.size())
256 if ((!Payload.isEmpty() && m_socket.write(Payload) == Payload.size()) || Payload.isEmpty())
258 LOG(VB_NETWORK, LOG_DEBUG, QStringLiteral(
"Sent frame (Final), OpCode: '%1' Masked: %2 Length: %3")
259 .arg(
OpCodeToString(Code)).arg(!m_serverSide).arg(Payload.size()));
268 void TorcWebSocketReader::HandlePing(QByteArray &Payload)
271 if (m_closeReceived || m_closeSent)
277 void TorcWebSocketReader::HandlePong(QByteArray &Payload)
287 void TorcWebSocketReader::HandleCloseRequest(QByteArray &Close)
293 if (Close.size() < 1)
295 QByteArray newpayload;
296 newpayload.append((closecode >> 8) & 0xff);
297 newpayload.append(closecode & 0xff);
301 else if (Close.size() == 1)
303 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid close payload size (<2)"));
307 else if (Close.size() > 1)
309 closecode = qFromBigEndian<quint16>(
reinterpret_cast<const uchar *
>(Close.data()));
311 if (closecode < CloseNormal || closecode > 4999 || closecode ==
CloseReserved1004 ||
314 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid close code"));
320 if (Close.size() > 2 && newclosecode ==
CloseNormal)
322 if (!utf8::is_valid(Close.data() + 2, Close.data() + Close.size()))
324 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid UTF8 in close payload"));
329 reason = QString::fromUtf8(Close.data() + 2, Close.size() -2);
335 QByteArray newpayload;
336 newpayload.append((newclosecode >> 8) & 0xff);
337 newpayload.append(newclosecode & 0xff);
345 m_closeReceived =
true;
357 if (m_socket.state() != QAbstractSocket::ConnectedState)
367 if (m_socket.bytesAvailable() < 2)
371 if (m_socket.read(header, 2) != 2)
377 m_frameFinalFragment = (header[0] & 0x80) != 0;
378 m_frameOpCode =
static_cast<OpCode>(header[0] & 0x0F);
379 m_frameMasked = (header[1] & 0x80) != 0;
380 quint8 length = (header[1] & 0x7F);
381 bool reservedbits = (header[0] & 0x70) != 0;
390 reason = QStringLiteral(
"Invalid use of reserved bits");
395 else if ((m_frameOpCode & 0x8) && length > 125)
397 reason = QStringLiteral(
"Control frame payload too large");
402 m_closeReceived =
true;
406 else if (m_serverSide != m_frameMasked)
408 reason = QStringLiteral(
"Masking error");
416 reason = QStringLiteral(
"Invalid use of reserved opcode");
421 else if (!m_frameFinalFragment && (m_frameOpCode ==
OpPing || m_frameOpCode ==
OpPong || m_frameOpCode ==
OpClose))
423 reason = QStringLiteral(
"Fragmented control frame");
428 else if (!m_haveBufferedPayload && m_frameOpCode ==
OpContinuation)
430 reason = QStringLiteral(
"Fragmentation error");
437 reason = QStringLiteral(
"Fragmentation error");
444 m_frameOpCode != m_subProtocolFrameFormat)
446 reason = QStringLiteral(
"Received incorrect frame type for subprotocol");
452 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Read error: %1 (%2)").arg(
CloseCodeToString(error), reason));
459 m_readState = Read16BitLength;
465 m_readState = Read64BitLength;
469 m_framePayloadLength = length;
470 m_readState = m_frameMasked ? ReadMask : ReadPayload;
474 case Read16BitLength:
476 if (m_socket.bytesAvailable() < 2)
481 if (m_socket.read(reinterpret_cast<char *>(length), 2) != 2)
487 m_framePayloadLength = qFromBigEndian<quint16>(
reinterpret_cast<const uchar *
>(length));
488 m_readState = m_frameMasked ? ReadMask : ReadPayload;
492 case Read64BitLength:
494 if (m_socket.bytesAvailable() < 8)
498 if (m_socket.read(reinterpret_cast<char *>(length), 8) != 8)
504 m_framePayloadLength = qFromBigEndian<quint64>(length) & ~(1LL << 63);
505 m_readState = m_frameMasked ? ReadMask : ReadPayload;
511 if (m_socket.bytesAvailable() < 4)
514 if (m_socket.read(const_cast<char *>(m_frameMask.constData()), 4) != 4)
520 m_readState = ReadPayload;
527 if (m_framePayloadReadPosition == 0)
528 m_framePayload = QByteArray(m_framePayloadLength, 0);
530 qint64 needed = m_framePayloadLength - m_framePayloadReadPosition;
535 qint64 red = qMin(m_socket.bytesAvailable(), needed);
537 if (m_socket.read(const_cast<char*>(m_framePayload.constData() + m_framePayloadReadPosition), red) != red)
543 m_framePayloadReadPosition += red;
547 if (m_framePayloadReadPosition == m_framePayloadLength)
549 LOG(VB_NETWORK, LOG_DEBUG, QStringLiteral(
"Frame, Final: %1 OpCode: '%2' Masked: %3 Length: %4")
550 .arg(m_frameFinalFragment).arg(
OpCodeToString(m_frameOpCode)).arg(m_frameMasked).arg(m_framePayloadLength));
554 for (
int i = 0; i < m_framePayload.size(); ++i)
555 m_framePayload[i] = (m_framePayload[i] ^ m_frameMask[i % 4]);
558 if (!m_frameFinalFragment && (m_frameOpCode ==
OpText || m_frameOpCode ==
OpBinary))
561 if (m_haveBufferedPayload)
563 m_bufferedPayload = QByteArray();
564 LOG(VB_GENERAL, LOG_WARNING, QStringLiteral(
"Already have payload buffer - clearing"));
567 m_haveBufferedPayload =
true;
568 m_bufferedPayload = QByteArray(m_framePayload);
569 m_bufferedPayloadOpCode = m_frameOpCode;
573 if (m_haveBufferedPayload)
574 m_bufferedPayload.append(m_framePayload);
576 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Continuation frame but no buffered payload"));
580 if (m_frameFinalFragment)
582 if (m_frameOpCode ==
OpPong)
584 HandlePong(m_framePayload);
586 else if (m_frameOpCode ==
OpPing)
588 HandlePing(m_framePayload);
590 else if (m_frameOpCode ==
OpClose)
592 HandleCloseRequest(m_framePayload);
596 bool invalidtext =
false;
599 if (!m_haveBufferedPayload && m_frameOpCode ==
OpText && !m_framePayload.isEmpty())
601 if (!utf8::is_valid(m_framePayload.data(), m_framePayload.data() + m_framePayload.size()))
603 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid UTF8"));
608 LOG(VB_NETWORK, LOG_DEBUG, QStringLiteral(
"'%1'").arg(QString::fromUtf8(m_framePayload)));
611 else if (m_haveBufferedPayload && m_bufferedPayloadOpCode ==
OpText)
613 if (!utf8::is_valid(m_bufferedPayload.data(), m_bufferedPayload.data() + m_bufferedPayload.size()))
615 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid UTF8"));
620 LOG(VB_NETWORK, LOG_DEBUG, QStringLiteral(
"'%1'").arg(QString::fromUtf8(m_bufferedPayload)));
634 SendFrame(m_haveBufferedPayload ? m_bufferedPayloadOpCode : m_frameOpCode,
635 m_haveBufferedPayload ? m_bufferedPayload : m_framePayload);
644 m_haveBufferedPayload =
false;
645 m_bufferedPayload = QByteArray();
650 m_readState = ReadHeader;
651 m_framePayload = QByteArray();
652 m_framePayloadReadPosition = 0;
653 m_framePayloadLength = 0;
655 else if (m_framePayload.size() > (qint64)m_framePayloadLength)
void SetSubProtocol(WSSubProtocol Protocol)
static QList< WSSubProtocol > SubProtocolsFromPrioritisedString(const QString &Protocols)
Parse a prioritised list of supported WebSocket sub-protocols.
const QByteArray & GetPayload(void)
static QString SubProtocolsToString(WSSubProtocols Protocols)
Convert SubProtocols to HTTP readable string.
void SendFrame(OpCode Code, QByteArray &Payload)
TorcWebSocketReader(QTcpSocket &Socket, WSSubProtocol Protocol, bool ServerSide)
static QString CloseCodeToString(CloseCode Code)
Convert CloseCode to human readable string.
static WSSubProtocols SubProtocolsFromString(const QString &Protocols)
Parse supported WSSubProtocols from Protocols.
#define LOG(_MASK_, _LEVEL_, _STRING_)
void InitiateClose(CloseCode Close, const QString &Reason)
static OpCode FormatForSubProtocol(WSSubProtocol Protocol)
static QString OpCodeToString(OpCode Code)
Convert OpCode to human readable string.