From 6e82d0a793edc480d8b25fd5a0454f9ab999f762 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Fri, 14 Jun 2019 00:04:52 +0200 Subject: Divide QWebSocketFrame::readFrame into subroutines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To reduce the dependency of each state and remove local variables (bytesRead, hasMask, and payloadLength) from QWebSocketFrame::readFrame, this change breaks down the states of QWebSocketFrame::readFrame into subroutines. In this change, it uses a readFramePayloadLength function to handle PS_READ_PAYLOAD_LENGTH and PS_READ_BIG_PAYLOAD_LENGTH cases. In addition, a missing error-handling is added in the read-header case if the bytesAvailable is less than 2 bytes. The variable hasMask is replaced by transiently using m_mask to indicate whether to read a mask. After reading mask in readFrameMask, the transient value will be over-written and used in readFramePayload. To replace local variable payloadLength with QWebSocketFrame::m_length, m_length is expanded to hold the payload length. Change-Id: I1c2d197112cef5cea75215923fa28e6f2e6cbef8 Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- src/websockets/qwebsocketframe.cpp | 301 ++++++++++++++++++++----------------- src/websockets/qwebsocketframe_p.h | 8 +- 2 files changed, 167 insertions(+), 142 deletions(-) diff --git a/src/websockets/qwebsocketframe.cpp b/src/websockets/qwebsocketframe.cpp index 041302e..05c678d 100644 --- a/src/websockets/qwebsocketframe.cpp +++ b/src/websockets/qwebsocketframe.cpp @@ -296,14 +296,11 @@ bool QWebSocketFrame::isValid() const QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) { bool isDone = false; - qint64 bytesRead = 0; QWebSocketFrame frame; quint64 dataWaitSize = 0; Q_UNUSED(dataWaitSize); // value is used in MACRO, Q_UNUSED to avoid compiler warnings ProcessingState processingState = PS_READ_HEADER; ProcessingState returnState = PS_READ_HEADER; - bool hasMask = false; - quint64 payloadLength = 0; while (!isDone) { @@ -323,157 +320,35 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) break; case PS_READ_HEADER: - if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) { - //FIN, RSV1-3, Opcode - char header[2] = {0}; - bytesRead = pIoDevice->read(header, 2); - frame.m_isFinalFrame = (header[0] & 0x80) != 0; - frame.m_rsv1 = (header[0] & 0x40); - frame.m_rsv2 = (header[0] & 0x20); - frame.m_rsv3 = (header[0] & 0x10); - frame.m_opCode = static_cast(header[0] & 0x0F); - - //Mask, PayloadLength - hasMask = (header[1] & 0x80) != 0; - frame.m_length = (header[1] & 0x7F); - - switch (frame.m_length) - { - case 126: - { - processingState = PS_READ_PAYLOAD_LENGTH; - break; - } - case 127: - { - processingState = PS_READ_BIG_PAYLOAD_LENGTH; - break; - } - default: - { - payloadLength = frame.m_length; - processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; - break; - } - } - if (!frame.checkValidity()) - processingState = PS_DISPATCH_RESULT; - } else { + processingState = frame.readFrameHeader(pIoDevice); + if (processingState == PS_WAIT_FOR_MORE_DATA) { + processingState = PS_READ_HEADER; WAIT_FOR_MORE_DATA(2); } break; case PS_READ_PAYLOAD_LENGTH: - if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) { - uchar length[2] = {0}; - bytesRead = pIoDevice->read(reinterpret_cast(length), 2); - if (Q_UNLIKELY(bytesRead == -1)) { - frame.setError(QWebSocketProtocol::CloseCodeGoingAway, - tr("Error occurred while reading from the network: %1") - .arg(pIoDevice->errorString())); - processingState = PS_DISPATCH_RESULT; - } else { - payloadLength = qFromBigEndian(reinterpret_cast(length)); - if (Q_UNLIKELY(payloadLength < 126)) { - //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 - //"in all cases, the minimal number of bytes MUST be used to encode - //the length, for example, the length of a 124-byte-long string - //can't be encoded as the sequence 126, 0, 124" - frame.setError(QWebSocketProtocol::CloseCodeProtocolError, - tr("Lengths smaller than 126 " \ - "must be expressed as one byte.")); - processingState = PS_DISPATCH_RESULT; - } else { - processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; - } - } - } else { - WAIT_FOR_MORE_DATA(2); - } - break; - - case PS_READ_BIG_PAYLOAD_LENGTH: - if (Q_LIKELY(pIoDevice->bytesAvailable() >= 8)) { - uchar length[8] = {0}; - bytesRead = pIoDevice->read(reinterpret_cast(length), 8); - if (Q_UNLIKELY(bytesRead < 8)) { - frame.setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection, - tr("Something went wrong during "\ - "reading from the network.")); - processingState = PS_DISPATCH_RESULT; - } else { - //Most significant bit must be set to 0 as - //per http://tools.ietf.org/html/rfc6455#section-5.2 - payloadLength = qFromBigEndian(length); - if (Q_UNLIKELY(payloadLength & (quint64(1) << 63))) { - frame.setError(QWebSocketProtocol::CloseCodeProtocolError, - tr("Highest bit of payload length is not 0.")); - processingState = PS_DISPATCH_RESULT; - } else if (Q_UNLIKELY(payloadLength <= 0xFFFFu)) { - //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 - //"in all cases, the minimal number of bytes MUST be used to encode - //the length, for example, the length of a 124-byte-long string - //can't be encoded as the sequence 126, 0, 124" - frame.setError(QWebSocketProtocol::CloseCodeProtocolError, - tr("Lengths smaller than 65536 (2^16) " \ - "must be expressed as 2 bytes.")); - processingState = PS_DISPATCH_RESULT; - } else { - processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; - } - } - } else { - WAIT_FOR_MORE_DATA(8); + processingState = frame.readFramePayloadLength(pIoDevice); + if (processingState == PS_WAIT_FOR_MORE_DATA) { + processingState = PS_READ_PAYLOAD_LENGTH; + WAIT_FOR_MORE_DATA(frame.m_length == 126 ? 2 : 8); } - break; case PS_READ_MASK: - if (Q_LIKELY(pIoDevice->bytesAvailable() >= 4)) { - bytesRead = pIoDevice->read(reinterpret_cast(&frame.m_mask), - sizeof(frame.m_mask)); - if (bytesRead == -1) { - frame.setError(QWebSocketProtocol::CloseCodeGoingAway, - tr("Error while reading from the network: %1.") - .arg(pIoDevice->errorString())); - processingState = PS_DISPATCH_RESULT; - } else { - frame.m_mask = qFromBigEndian(frame.m_mask); - processingState = PS_READ_PAYLOAD; - } - } else { + processingState = frame.readFrameMask(pIoDevice); + if (processingState == PS_WAIT_FOR_MORE_DATA) { + processingState = PS_READ_MASK; WAIT_FOR_MORE_DATA(4); } break; case PS_READ_PAYLOAD: - if (!payloadLength) { - processingState = PS_DISPATCH_RESULT; - } else if (Q_UNLIKELY(payloadLength > MAX_FRAME_SIZE_IN_BYTES)) { - frame.setError(QWebSocketProtocol::CloseCodeTooMuchData, - tr("Maximum framesize exceeded.")); - processingState = PS_DISPATCH_RESULT; - } else { - quint64 bytesAvailable = quint64(pIoDevice->bytesAvailable()); - if (bytesAvailable >= payloadLength) { - frame.m_payload = pIoDevice->read(int(payloadLength)); - //payloadLength can be safely cast to an integer, - //because MAX_FRAME_SIZE_IN_BYTES = MAX_INT - if (Q_UNLIKELY(frame.m_payload.length() != int(payloadLength))) { - //some error occurred; refer to the Qt documentation of QIODevice::read() - frame.setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection, - tr("Some serious error occurred " \ - "while reading from the network.")); - processingState = PS_DISPATCH_RESULT; - } else { - if (hasMask) - QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask); - processingState = PS_DISPATCH_RESULT; - } - } else { - //if payload is too big, then this will timeout - WAIT_FOR_MORE_DATA(payloadLength); - } + processingState = frame.readFramePayload(pIoDevice); + if (processingState == PS_WAIT_FOR_MORE_DATA) { + processingState = PS_READ_PAYLOAD; + // if payload is too big, then this will timeout + WAIT_FOR_MORE_DATA(frame.m_length); } break; @@ -494,6 +369,152 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) return frame; } +/*! + \internal + */ +QWebSocketFrame::ProcessingState QWebSocketFrame::readFrameHeader(QIODevice *pIoDevice) +{ + if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) { + // FIN, RSV1-3, Opcode + char header[2] = {0}; + if (Q_UNLIKELY(pIoDevice->read(header, 2) < 2)) { + setError(QWebSocketProtocol::CloseCodeGoingAway, + tr("Error occurred while reading header from the network: %1") + .arg(pIoDevice->errorString())); + return PS_DISPATCH_RESULT; + } + m_isFinalFrame = (header[0] & 0x80) != 0; + m_rsv1 = (header[0] & 0x40); + m_rsv2 = (header[0] & 0x20); + m_rsv3 = (header[0] & 0x10); + m_opCode = static_cast(header[0] & 0x0F); + + // Mask + // Use zero as mask value to mean there's no mask to read. + // When the mask value is read, it over-writes this non-zero value. + m_mask = header[1] & 0x80; + // PayloadLength + m_length = (header[1] & 0x7F); + + if (!checkValidity()) + return PS_DISPATCH_RESULT; + + switch (m_length) { + case 126: + case 127: + return PS_READ_PAYLOAD_LENGTH; + default: + return hasMask() ? PS_READ_MASK : PS_READ_PAYLOAD; + } + } + return PS_WAIT_FOR_MORE_DATA; +} + +/*! + \internal + */ +QWebSocketFrame::ProcessingState QWebSocketFrame::readFramePayloadLength(QIODevice *pIoDevice) +{ + // see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 + // in all cases, the minimal number of bytes MUST be used to encode the length, + // for example, the length of a 124-byte-long string can't be encoded as the + // sequence 126, 0, 124" + switch (m_length) { + case 126: + if (Q_LIKELY(pIoDevice->bytesAvailable() >= 2)) { + uchar length[2] = {0}; + if (Q_UNLIKELY(pIoDevice->read(reinterpret_cast(length), 2) < 2)) { + setError(QWebSocketProtocol::CloseCodeGoingAway, + tr("Error occurred while reading from the network: %1") + .arg(pIoDevice->errorString())); + return PS_DISPATCH_RESULT; + } + m_length = qFromBigEndian(reinterpret_cast(length)); + if (Q_UNLIKELY(m_length < 126)) { + + setError(QWebSocketProtocol::CloseCodeProtocolError, + tr("Lengths smaller than 126 must be expressed as one byte.")); + return PS_DISPATCH_RESULT; + } + return hasMask() ? PS_READ_MASK : PS_READ_PAYLOAD; + } + break; + case 127: + if (Q_LIKELY(pIoDevice->bytesAvailable() >= 8)) { + uchar length[8] = {0}; + if (Q_UNLIKELY(pIoDevice->read(reinterpret_cast(length), 8) < 8)) { + setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection, + tr("Something went wrong during reading from the network.")); + return PS_DISPATCH_RESULT; + } + // Most significant bit must be set to 0 as + // per http://tools.ietf.org/html/rfc6455#section-5.2 + m_length = qFromBigEndian(length); + if (Q_UNLIKELY(m_length & (quint64(1) << 63))) { + setError(QWebSocketProtocol::CloseCodeProtocolError, + tr("Highest bit of payload length is not 0.")); + return PS_DISPATCH_RESULT; + } + if (Q_UNLIKELY(m_length <= 0xFFFFu)) { + setError(QWebSocketProtocol::CloseCodeProtocolError, + tr("Lengths smaller than 65536 (2^16) must be expressed as 2 bytes.")); + return PS_DISPATCH_RESULT; + } + return hasMask() ? PS_READ_MASK : PS_READ_PAYLOAD; + } + break; + default: + Q_UNREACHABLE(); + break; + } + return PS_WAIT_FOR_MORE_DATA; +} + +/*! + \internal + */ +QWebSocketFrame::ProcessingState QWebSocketFrame::readFrameMask(QIODevice *pIoDevice) +{ + if (Q_LIKELY(pIoDevice->bytesAvailable() >= 4)) { + if (Q_UNLIKELY(pIoDevice->read(reinterpret_cast(&m_mask), sizeof(m_mask)) < 4)) { + setError(QWebSocketProtocol::CloseCodeGoingAway, + tr("Error while reading from the network: %1.").arg(pIoDevice->errorString())); + return PS_DISPATCH_RESULT; + } + m_mask = qFromBigEndian(m_mask); + return PS_READ_PAYLOAD; + } + return PS_WAIT_FOR_MORE_DATA; +} + +/*! + \internal + */ +QWebSocketFrame::ProcessingState QWebSocketFrame::readFramePayload(QIODevice *pIoDevice) +{ + if (!m_length) + return PS_DISPATCH_RESULT; + + if (Q_UNLIKELY(m_length > MAX_FRAME_SIZE_IN_BYTES)) { + setError(QWebSocketProtocol::CloseCodeTooMuchData, tr("Maximum framesize exceeded.")); + return PS_DISPATCH_RESULT; + } + if (quint64(pIoDevice->bytesAvailable()) >= m_length) { + m_payload = pIoDevice->read(int(m_length)); + // m_length can be safely cast to an integer, + // because MAX_FRAME_SIZE_IN_BYTES = MAX_INT + if (Q_UNLIKELY(m_payload.length() != int(m_length))) { + // some error occurred; refer to the Qt documentation of QIODevice::read() + setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection, + tr("Some serious error occurred while reading from the network.")); + } else if (hasMask()) { + QWebSocketProtocol::mask(&m_payload, mask()); + } + return PS_DISPATCH_RESULT; + } + return PS_WAIT_FOR_MORE_DATA; +} + /*! \internal */ diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h index 5c3a7df..94677de 100644 --- a/src/websockets/qwebsocketframe_p.h +++ b/src/websockets/qwebsocketframe_p.h @@ -109,7 +109,7 @@ private: QString m_closeReason; quint32 m_mask; QWebSocketProtocol::OpCode m_opCode; - quint8 m_length; + quint64 m_length; QByteArray m_payload; bool m_isFinalFrame; @@ -122,13 +122,17 @@ private: { PS_READ_HEADER, PS_READ_PAYLOAD_LENGTH, - PS_READ_BIG_PAYLOAD_LENGTH, PS_READ_MASK, PS_READ_PAYLOAD, PS_DISPATCH_RESULT, PS_WAIT_FOR_MORE_DATA }; + ProcessingState readFrameHeader(QIODevice *pIoDevice); + ProcessingState readFramePayloadLength(QIODevice *pIoDevice); + ProcessingState readFrameMask(QIODevice *pIoDevice); + ProcessingState readFramePayload(QIODevice *pIoDevice); + void setError(QWebSocketProtocol::CloseCode code, const QString &closeReason); bool checkValidity(); }; -- cgit v1.2.1 From 140246105d3581ceb238134a02261d49417296c7 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Wed, 12 Jun 2019 16:41:35 +0200 Subject: Add an internal state to keep the processing state of frame reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macro 'WAIT_FOR_MORE_DATA' is revised because the processing state is kept by m_processingState. Remove the unused dataWaitSize and returnState local variables from QWebSocketFrame::readFrame. Change-Id: I8e270c5c7117b170159d4fb3b2bf1531a9cd5334 Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- src/websockets/qwebsocketframe.cpp | 91 +++++++++++++++++--------------------- src/websockets/qwebsocketframe_p.h | 2 +- 2 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/websockets/qwebsocketframe.cpp b/src/websockets/qwebsocketframe.cpp index 05c678d..fd814a4 100644 --- a/src/websockets/qwebsocketframe.cpp +++ b/src/websockets/qwebsocketframe.cpp @@ -93,7 +93,8 @@ QWebSocketFrame::QWebSocketFrame(const QWebSocketFrame &other) : m_rsv1(other.m_rsv1), m_rsv2(other.m_rsv2), m_rsv3(other.m_rsv3), - m_isValid(other.m_isValid) + m_isValid(other.m_isValid), + m_processingState(other.m_processingState) { } @@ -113,6 +114,7 @@ QWebSocketFrame &QWebSocketFrame::operator =(const QWebSocketFrame &other) m_length = other.m_length; m_payload = other.m_payload; m_isValid = other.m_isValid; + m_processingState = other.m_processingState; return *this; } @@ -132,7 +134,8 @@ QWebSocketFrame::QWebSocketFrame(QWebSocketFrame &&other) : m_rsv1(qMove(other.m_rsv1)), m_rsv2(qMove(other.m_rsv2)), m_rsv3(qMove(other.m_rsv3)), - m_isValid(qMove(other.m_isValid)) + m_isValid(qMove(other.m_isValid)), + m_processingState(qMove(other.m_processingState)) {} @@ -152,6 +155,7 @@ QWebSocketFrame &QWebSocketFrame::operator =(QWebSocketFrame &&other) qSwap(m_length, other.m_length); qSwap(m_payload, other.m_payload); qSwap(m_isValid, other.m_isValid); + qSwap(m_processingState, other.m_processingState); return *this; } @@ -175,6 +179,7 @@ void QWebSocketFrame::swap(QWebSocketFrame &other) qSwap(m_length, other.m_length); qSwap(m_payload, other.m_payload); qSwap(m_isValid, other.m_isValid); + qSwap(m_processingState, other.m_processingState); } } @@ -276,6 +281,7 @@ void QWebSocketFrame::clear() m_length = 0; m_payload.clear(); m_isValid = false; + m_processingState = PS_READ_HEADER; } /*! @@ -286,9 +292,9 @@ bool QWebSocketFrame::isValid() const return m_isValid; } -#define WAIT_FOR_MORE_DATA(dataSizeInBytes) \ - { returnState = processingState; \ - processingState = PS_WAIT_FOR_MORE_DATA; dataWaitSize = dataSizeInBytes; } +#define WAIT_FOR_MORE_DATA(returnState) \ + { needMoreData = true; \ + frame.m_processingState = (returnState); } /*! \internal @@ -297,73 +303,56 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) { bool isDone = false; QWebSocketFrame frame; - quint64 dataWaitSize = 0; - Q_UNUSED(dataWaitSize); // value is used in MACRO, Q_UNUSED to avoid compiler warnings - ProcessingState processingState = PS_READ_HEADER; - ProcessingState returnState = PS_READ_HEADER; while (!isDone) { - switch (processingState) { - case PS_WAIT_FOR_MORE_DATA: - //TODO: waitForReadyRead should really be changed - //now, when a WebSocket is used in a GUI thread - //the GUI will hang for at most 5 seconds - //maybe, a QStateMachine should be used - if (!pIoDevice->waitForReadyRead(5000)) { - frame.setError(QWebSocketProtocol::CloseCodeGoingAway, - tr("Timeout when reading data from socket.")); - processingState = PS_DISPATCH_RESULT; - } else { - processingState = returnState; - } - break; - + bool needMoreData = false; + switch (frame.m_processingState) { case PS_READ_HEADER: - processingState = frame.readFrameHeader(pIoDevice); - if (processingState == PS_WAIT_FOR_MORE_DATA) { - processingState = PS_READ_HEADER; - WAIT_FOR_MORE_DATA(2); - } + frame.m_processingState = frame.readFrameHeader(pIoDevice); + if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + WAIT_FOR_MORE_DATA(PS_READ_HEADER); break; case PS_READ_PAYLOAD_LENGTH: - processingState = frame.readFramePayloadLength(pIoDevice); - if (processingState == PS_WAIT_FOR_MORE_DATA) { - processingState = PS_READ_PAYLOAD_LENGTH; - WAIT_FOR_MORE_DATA(frame.m_length == 126 ? 2 : 8); - } + frame.m_processingState = frame.readFramePayloadLength(pIoDevice); + if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD_LENGTH); break; case PS_READ_MASK: - processingState = frame.readFrameMask(pIoDevice); - if (processingState == PS_WAIT_FOR_MORE_DATA) { - processingState = PS_READ_MASK; - WAIT_FOR_MORE_DATA(4); - } + frame.m_processingState = frame.readFrameMask(pIoDevice); + if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + WAIT_FOR_MORE_DATA(PS_READ_MASK); break; case PS_READ_PAYLOAD: - processingState = frame.readFramePayload(pIoDevice); - if (processingState == PS_WAIT_FOR_MORE_DATA) { - processingState = PS_READ_PAYLOAD; - // if payload is too big, then this will timeout - WAIT_FOR_MORE_DATA(frame.m_length); - } + frame.m_processingState = frame.readFramePayload(pIoDevice); + if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD); break; case PS_DISPATCH_RESULT: - processingState = PS_READ_HEADER; + frame.m_processingState = PS_DISPATCH_RESULT; isDone = true; break; default: - //should not come here - qWarning() << "DataProcessor::process: Found invalid state. This should not happen!"; - frame.clear(); - isDone = true; + Q_UNREACHABLE(); break; - } //end switch + } + + if (needMoreData) { + // TODO: waitForReadyRead should really be changed + // now, when a WebSocket is used in a GUI thread + // the GUI will hang for at most 5 seconds + // maybe, a QStateMachine should be used + if (!pIoDevice->waitForReadyRead(5000)) { + frame.setError(QWebSocketProtocol::CloseCodeGoingAway, + tr("Timeout when reading data from socket.")); + frame.m_processingState = PS_DISPATCH_RESULT; + } + } } return frame; diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h index 94677de..b442d01 100644 --- a/src/websockets/qwebsocketframe_p.h +++ b/src/websockets/qwebsocketframe_p.h @@ -126,7 +126,7 @@ private: PS_READ_PAYLOAD, PS_DISPATCH_RESULT, PS_WAIT_FOR_MORE_DATA - }; + } m_processingState{PS_READ_HEADER}; ProcessingState readFrameHeader(QIODevice *pIoDevice); ProcessingState readFramePayloadLength(QIODevice *pIoDevice); -- cgit v1.2.1 From 24894c032719157a2d738f03e0c70d3ff0cf1782 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Sun, 30 Jun 2019 13:56:25 +0200 Subject: Make QWebSocketFrame::readFrame as a non-static public function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The static function QWebSocketFrame::readFrame used to return a parsed QWebSocketFrame read from QIODevice. This change make QWebSocketFrame reusable. It will base on its internal state and keep processing the incoming data from QIODevice. Change-Id: Ic6dea59529fa935cdb8034519e633ea67e869674 Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- src/websockets/qwebsocketdataprocessor.cpp | 3 +- src/websockets/qwebsocketdataprocessor_p.h | 2 ++ src/websockets/qwebsocketframe.cpp | 34 ++++++++++------------ src/websockets/qwebsocketframe_p.h | 2 +- .../websocketframe/tst_websocketframe.cpp | 12 +++++--- 5 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/websockets/qwebsocketdataprocessor.cpp b/src/websockets/qwebsocketdataprocessor.cpp index 4f81222..ee28969 100644 --- a/src/websockets/qwebsocketdataprocessor.cpp +++ b/src/websockets/qwebsocketdataprocessor.cpp @@ -125,7 +125,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) bool isDone = false; while (!isDone) { - QWebSocketFrame frame = QWebSocketFrame::readFrame(pIoDevice); + frame.readFrame(pIoDevice); if (Q_LIKELY(frame.isValid())) { if (frame.isControlFrame()) { isDone = processControlFrame(frame); @@ -199,6 +199,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) clear(); isDone = true; } + frame.clear(); } } diff --git a/src/websockets/qwebsocketdataprocessor_p.h b/src/websockets/qwebsocketdataprocessor_p.h index e80a843..1d8024e 100644 --- a/src/websockets/qwebsocketdataprocessor_p.h +++ b/src/websockets/qwebsocketdataprocessor_p.h @@ -55,6 +55,7 @@ #include #include #include +#include "qwebsocketframe_p.h" #include "qwebsocketprotocol.h" #include "qwebsocketprotocol_p.h" @@ -111,6 +112,7 @@ private: quint64 m_payloadLength; QTextCodec::ConverterState *m_pConverterState; QTextCodec *m_pTextCodec; + QWebSocketFrame frame; bool processControlFrame(const QWebSocketFrame &frame); }; diff --git a/src/websockets/qwebsocketframe.cpp b/src/websockets/qwebsocketframe.cpp index fd814a4..5b10e02 100644 --- a/src/websockets/qwebsocketframe.cpp +++ b/src/websockets/qwebsocketframe.cpp @@ -294,46 +294,44 @@ bool QWebSocketFrame::isValid() const #define WAIT_FOR_MORE_DATA(returnState) \ { needMoreData = true; \ - frame.m_processingState = (returnState); } + m_processingState = (returnState); } /*! \internal */ -QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) +void QWebSocketFrame::readFrame(QIODevice *pIoDevice) { bool isDone = false; - QWebSocketFrame frame; - while (!isDone) { bool needMoreData = false; - switch (frame.m_processingState) { + switch (m_processingState) { case PS_READ_HEADER: - frame.m_processingState = frame.readFrameHeader(pIoDevice); - if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + m_processingState = readFrameHeader(pIoDevice); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) WAIT_FOR_MORE_DATA(PS_READ_HEADER); break; case PS_READ_PAYLOAD_LENGTH: - frame.m_processingState = frame.readFramePayloadLength(pIoDevice); - if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + m_processingState = readFramePayloadLength(pIoDevice); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD_LENGTH); break; case PS_READ_MASK: - frame.m_processingState = frame.readFrameMask(pIoDevice); - if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + m_processingState = readFrameMask(pIoDevice); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) WAIT_FOR_MORE_DATA(PS_READ_MASK); break; case PS_READ_PAYLOAD: - frame.m_processingState = frame.readFramePayload(pIoDevice); - if (frame.m_processingState == PS_WAIT_FOR_MORE_DATA) + m_processingState = readFramePayload(pIoDevice); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD); break; case PS_DISPATCH_RESULT: - frame.m_processingState = PS_DISPATCH_RESULT; + m_processingState = PS_DISPATCH_RESULT; isDone = true; break; @@ -348,14 +346,12 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) // the GUI will hang for at most 5 seconds // maybe, a QStateMachine should be used if (!pIoDevice->waitForReadyRead(5000)) { - frame.setError(QWebSocketProtocol::CloseCodeGoingAway, - tr("Timeout when reading data from socket.")); - frame.m_processingState = PS_DISPATCH_RESULT; + setError(QWebSocketProtocol::CloseCodeGoingAway, + tr("Timeout when reading data from socket.")); + m_processingState = PS_DISPATCH_RESULT; } } } - - return frame; } /*! diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h index b442d01..be79a6e 100644 --- a/src/websockets/qwebsocketframe_p.h +++ b/src/websockets/qwebsocketframe_p.h @@ -102,7 +102,7 @@ public: bool isValid() const; - static QWebSocketFrame readFrame(QIODevice *pIoDevice); + void readFrame(QIODevice *pIoDevice); private: QWebSocketProtocol::CloseCode m_closeCode; diff --git a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp index 5614df8..6b9aaaf 100644 --- a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp +++ b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp @@ -197,7 +197,8 @@ void tst_WebSocketFrame::tst_copyConstructorAndAssignment() QBuffer buffer(&payload); buffer.open(QIODevice::ReadOnly); - QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); + QWebSocketFrame frame; + frame.readFrame(&buffer); buffer.close(); { @@ -330,7 +331,8 @@ void tst_WebSocketFrame::tst_goodFrames() QBuffer buffer; buffer.setData(wireRepresentation); buffer.open(QIODevice::ReadOnly); - QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); + QWebSocketFrame frame; + frame.readFrame(&buffer); buffer.close(); QVERIFY(frame.isValid()); QCOMPARE(frame.rsv1(), rsv1); @@ -495,7 +497,8 @@ void tst_WebSocketFrame::tst_invalidFrames() QBuffer buffer; buffer.setData(wireRepresentation); buffer.open(QIODevice::ReadOnly); - QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); + QWebSocketFrame frame; + frame.readFrame(&buffer); buffer.close(); QVERIFY(!frame.isValid()); @@ -606,7 +609,8 @@ void tst_WebSocketFrame::tst_malformedFrames() QBuffer buffer; buffer.setData(payload); buffer.open(QIODevice::ReadOnly); - QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); + QWebSocketFrame frame; + frame.readFrame(&buffer); buffer.close(); QVERIFY(!frame.isValid()); -- cgit v1.2.1 From b14f5f59a3ae96949e6a33302385a751d6448182 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Fri, 28 Jun 2019 14:37:05 +0200 Subject: Remove waitForReadyRead from QWebSocketFrame::readFrame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asynchronously process socket frame in QWebSocketDataProcessor::process. If the processing of QWebSocketFrame is not done and waiting for more data, QWebSocketDataProcessor::process will return the control and wait for next readyRead signal to continue processing the unfinished socket frame. QWebSocketDataProcessor::process gets timeout after 5 seconds, and then an errorEncountered signal will be emitted. Fixes: QTBUG-74464 Change-Id: I03b7f874c1c266617e7eadf59c59ae43fa8540ce Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim --- src/websockets/qwebsocket_p.cpp | 4 +- src/websockets/qwebsocketdataprocessor.cpp | 22 +++++++- src/websockets/qwebsocketdataprocessor_p.h | 3 ++ src/websockets/qwebsocketframe.cpp | 62 ++++++++++------------ src/websockets/qwebsocketframe_p.h | 1 + .../websockets/dataprocessor/tst_dataprocessor.cpp | 16 ++++-- .../auto/websockets/qwebsocket/tst_qwebsocket.cpp | 36 ++++++++++++- 7 files changed, 103 insertions(+), 41 deletions(-) diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index 6965731..9b94d04 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -1173,10 +1173,10 @@ void QWebSocketPrivate::processData() { if (!m_pSocket) // disconnected with data still in-bound return; - while (m_pSocket->bytesAvailable()) { + if (m_pSocket->bytesAvailable()) { if (state() == QAbstractSocket::ConnectingState) { if (!m_pSocket->canReadLine()) - break; + return; processHandshake(m_pSocket); } else { m_dataProcessor.process(m_pSocket); diff --git a/src/websockets/qwebsocketdataprocessor.cpp b/src/websockets/qwebsocketdataprocessor.cpp index ee28969..39287d4 100644 --- a/src/websockets/qwebsocketdataprocessor.cpp +++ b/src/websockets/qwebsocketdataprocessor.cpp @@ -87,6 +87,10 @@ QWebSocketDataProcessor::QWebSocketDataProcessor(QObject *parent) : m_pTextCodec(QTextCodec::codecForName("UTF-8")) { clear(); + // initialize the internal timeout timer + waitTimer.setInterval(5000); + waitTimer.setSingleShot(true); + waitTimer.callOnTimeout(this, &QWebSocketDataProcessor::timeout); } /*! @@ -126,7 +130,13 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) while (!isDone) { frame.readFrame(pIoDevice); - if (Q_LIKELY(frame.isValid())) { + if (!frame.isDone()) { + // waiting for more data available + QObject::connect(pIoDevice, &QIODevice::readyRead, + &waitTimer, &QTimer::stop, Qt::UniqueConnection); + waitTimer.start(); + return; + } else if (Q_LIKELY(frame.isValid())) { if (frame.isControlFrame()) { isDone = processControlFrame(frame); } else { @@ -302,4 +312,14 @@ bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame) return mustStopProcessing; } +/*! + \internal + */ +void QWebSocketDataProcessor::timeout() +{ + clear(); + Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeGoingAway, + tr("Timeout when reading data from socket.")); +} + QT_END_NAMESPACE diff --git a/src/websockets/qwebsocketdataprocessor_p.h b/src/websockets/qwebsocketdataprocessor_p.h index 1d8024e..41226d6 100644 --- a/src/websockets/qwebsocketdataprocessor_p.h +++ b/src/websockets/qwebsocketdataprocessor_p.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "qwebsocketframe_p.h" #include "qwebsocketprotocol.h" #include "qwebsocketprotocol_p.h" @@ -113,8 +114,10 @@ private: QTextCodec::ConverterState *m_pConverterState; QTextCodec *m_pTextCodec; QWebSocketFrame frame; + QTimer waitTimer; bool processControlFrame(const QWebSocketFrame &frame); + void timeout(); }; QT_END_NAMESPACE diff --git a/src/websockets/qwebsocketframe.cpp b/src/websockets/qwebsocketframe.cpp index 5b10e02..11373a7 100644 --- a/src/websockets/qwebsocketframe.cpp +++ b/src/websockets/qwebsocketframe.cpp @@ -188,7 +188,7 @@ void QWebSocketFrame::swap(QWebSocketFrame &other) */ QWebSocketProtocol::CloseCode QWebSocketFrame::closeCode() const { - return m_closeCode; + return isDone() ? m_closeCode : QWebSocketProtocol::CloseCodeGoingAway; } /*! @@ -196,7 +196,7 @@ QWebSocketProtocol::CloseCode QWebSocketFrame::closeCode() const */ QString QWebSocketFrame::closeReason() const { - return m_closeReason; + return isDone() ? m_closeReason : tr("Waiting for more data from socket."); } /*! @@ -289,67 +289,63 @@ void QWebSocketFrame::clear() */ bool QWebSocketFrame::isValid() const { - return m_isValid; + return isDone() && m_isValid; } -#define WAIT_FOR_MORE_DATA(returnState) \ - { needMoreData = true; \ - m_processingState = (returnState); } +/*! + \internal + */ +bool QWebSocketFrame::isDone() const +{ + return m_processingState == PS_DISPATCH_RESULT; +} /*! \internal */ void QWebSocketFrame::readFrame(QIODevice *pIoDevice) { - bool isDone = false; - while (!isDone) + while (true) { - bool needMoreData = false; switch (m_processingState) { case PS_READ_HEADER: m_processingState = readFrameHeader(pIoDevice); - if (m_processingState == PS_WAIT_FOR_MORE_DATA) - WAIT_FOR_MORE_DATA(PS_READ_HEADER); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) { + m_processingState = PS_READ_HEADER; + return; + } break; case PS_READ_PAYLOAD_LENGTH: m_processingState = readFramePayloadLength(pIoDevice); - if (m_processingState == PS_WAIT_FOR_MORE_DATA) - WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD_LENGTH); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) { + m_processingState = PS_READ_PAYLOAD_LENGTH; + return; + } break; case PS_READ_MASK: m_processingState = readFrameMask(pIoDevice); - if (m_processingState == PS_WAIT_FOR_MORE_DATA) - WAIT_FOR_MORE_DATA(PS_READ_MASK); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) { + m_processingState = PS_READ_MASK; + return; + } break; case PS_READ_PAYLOAD: m_processingState = readFramePayload(pIoDevice); - if (m_processingState == PS_WAIT_FOR_MORE_DATA) - WAIT_FOR_MORE_DATA(PS_READ_PAYLOAD); + if (m_processingState == PS_WAIT_FOR_MORE_DATA) { + m_processingState = PS_READ_PAYLOAD; + return; + } break; case PS_DISPATCH_RESULT: - m_processingState = PS_DISPATCH_RESULT; - isDone = true; - break; + return; default: Q_UNREACHABLE(); - break; - } - - if (needMoreData) { - // TODO: waitForReadyRead should really be changed - // now, when a WebSocket is used in a GUI thread - // the GUI will hang for at most 5 seconds - // maybe, a QStateMachine should be used - if (!pIoDevice->waitForReadyRead(5000)) { - setError(QWebSocketProtocol::CloseCodeGoingAway, - tr("Timeout when reading data from socket.")); - m_processingState = PS_DISPATCH_RESULT; - } + return; } } } diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h index be79a6e..e2b4e9f 100644 --- a/src/websockets/qwebsocketframe_p.h +++ b/src/websockets/qwebsocketframe_p.h @@ -101,6 +101,7 @@ public: void clear(); bool isValid() const; + bool isDone() const; void readFrame(QIODevice *pIoDevice); diff --git a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp index f9a91d5..705ea39 100644 --- a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp +++ b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp @@ -193,7 +193,7 @@ private: //sequences void nonCharacterSequence(const char *sequence); - void doTest(); + void doTest(int timeout = 0); void doCloseFrameTest(); QString opCodeToString(quint8 opCode); @@ -744,6 +744,7 @@ void tst_DataProcessor::frameTooSmall() dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); QCOMPARE(errorSpy.count(), 1); QCOMPARE(closeSpy.count(), 0); QCOMPARE(pingMessageSpy.count(), 0); @@ -776,6 +777,7 @@ void tst_DataProcessor::frameTooSmall() dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); QCOMPARE(errorSpy.count(), 1); QCOMPARE(closeSpy.count(), 0); QCOMPARE(pingMessageSpy.count(), 0); @@ -808,6 +810,8 @@ void tst_DataProcessor::frameTooSmall() dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); + buffer.close(); data.clear(); @@ -820,6 +824,7 @@ void tst_DataProcessor::frameTooSmall() SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString))); dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); QCOMPARE(errorSpy.count(), 1); QCOMPARE(closeSpy.count(), 0); QCOMPARE(pingMessageSpy.count(), 0); @@ -849,6 +854,7 @@ void tst_DataProcessor::frameTooSmall() buffer.open(QIODevice::ReadOnly); dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); QCOMPARE(errorSpy.count(), 1); QCOMPARE(closeSpy.count(), 0); QCOMPARE(pingMessageSpy.count(), 0); @@ -877,6 +883,7 @@ void tst_DataProcessor::frameTooSmall() buffer.open(QIODevice::ReadOnly); dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); QCOMPARE(errorSpy.count(), 1); QCOMPARE(closeSpy.count(), 0); QCOMPARE(pingMessageSpy.count(), 0); @@ -1400,7 +1407,7 @@ void tst_DataProcessor::incompletePayload_data() void tst_DataProcessor::incompletePayload() { - doTest(); + doTest(7000); } void tst_DataProcessor::incompleteSizeField_data() @@ -1430,13 +1437,13 @@ void tst_DataProcessor::incompleteSizeField_data() void tst_DataProcessor::incompleteSizeField() { - doTest(); + doTest(7000); } ////////////////////////////////////////////////////////////////////////////////////////// /// HELPER FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////// -void tst_DataProcessor::doTest() +void tst_DataProcessor::doTest(int timeout) { QFETCH(quint8, firstByte); QFETCH(quint8, secondByte); @@ -1465,6 +1472,7 @@ void tst_DataProcessor::doTest() buffer.setData(data); buffer.open(QIODevice::ReadOnly); dataProcessor.process(&buffer); + QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), timeout); QCOMPARE(errorSpy.count(), 1); QCOMPARE(textMessageSpy.count(), 0); QCOMPARE(binaryMessageSpy.count(), 0); diff --git a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp index 2bb5d16..19af815 100644 --- a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp +++ b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp @@ -457,12 +457,46 @@ void tst_QWebSocket::tst_sendTextMessage() QVERIFY(isLastFrame); socket.close(); + socketConnectedSpy.clear(); + textMessageReceived.clear(); + textFrameReceived.clear(); - //QTBUG-36762: QWebSocket emits multiplied signals when socket was reopened + // QTBUG-74464 QWebsocket doesn't receive text (binary) message with size > 32 kb + socket.open(url); + + QTRY_COMPARE(socketConnectedSpy.count(), 1); + QCOMPARE(socketError.count(), 0); + QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); + arguments = serverConnectedSpy.takeFirst(); + urlConnected = arguments.at(0).toUrl(); + QCOMPARE(urlConnected, url); + QCOMPARE(socket.bytesToWrite(), 0); + + // transmit a long text message with 64 kb + QString longString(65536, 'a'); + socket.sendTextMessage(longString); + QVERIFY(socket.bytesToWrite() > longString.length()); + QVERIFY(textMessageReceived.wait()); + QCOMPARE(socket.bytesToWrite(), 0); + + QCOMPARE(textMessageReceived.count(), 1); + QCOMPARE(binaryMessageReceived.count(), 0); + QCOMPARE(binaryFrameReceived.count(), 0); + arguments = textMessageReceived.takeFirst(); + messageReceived = arguments.at(0).toString(); + QCOMPARE(messageReceived.length(), longString.length()); + QCOMPARE(messageReceived, longString); + + arguments = textFrameReceived.takeLast(); + isLastFrame = arguments.at(1).toBool(); + QVERIFY(isLastFrame); + + socket.close(); socketConnectedSpy.clear(); textMessageReceived.clear(); textFrameReceived.clear(); + //QTBUG-36762: QWebSocket emits multiplied signals when socket was reopened socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() + QStringLiteral(":") + QString::number(echoServer.port()))); -- cgit v1.2.1 From a302c6108d79b02a339b4ca93d2fce0b58386d51 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Sun, 30 Jun 2019 02:05:18 +0200 Subject: Add the missing tests in tst_DataProcessor::frameTooSmall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are missing tests of 'text frame with final bit not set'. After dataProcessor.process, the spied signals should be compared and cleared before processing next frame. Change-Id: I5737da9d57e0043cfedb400f4e0934c5ce7c4250 Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- .../websockets/dataprocessor/tst_dataprocessor.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp index 705ea39..5390ff0 100644 --- a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp +++ b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp @@ -811,7 +811,23 @@ void tst_DataProcessor::frameTooSmall() dataProcessor.process(&buffer); QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(closeSpy.count(), 0); + QCOMPARE(pingMessageSpy.count(), 0); + QCOMPARE(pongMessageSpy.count(), 0); + QCOMPARE(textMessageSpy.count(), 0); + QCOMPARE(binaryMessageSpy.count(), 0); + QCOMPARE(textFrameSpy.count(), 1); + QCOMPARE(binaryFrameSpy.count(), 0); + errorSpy.clear(); + closeSpy.clear(); + pingMessageSpy.clear(); + pongMessageSpy.clear(); + textMessageSpy.clear(); + binaryMessageSpy.clear(); + textFrameSpy.clear(); + binaryFrameSpy.clear(); buffer.close(); data.clear(); @@ -820,8 +836,6 @@ void tst_DataProcessor::frameTooSmall() //meaning the socket will be closed buffer.setData(data); buffer.open(QIODevice::ReadOnly); - QSignalSpy errorSpy(&dataProcessor, - SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString))); dataProcessor.process(&buffer); QTRY_VERIFY_WITH_TIMEOUT(errorSpy.count(), 7000); @@ -831,7 +845,7 @@ void tst_DataProcessor::frameTooSmall() QCOMPARE(pongMessageSpy.count(), 0); QCOMPARE(textMessageSpy.count(), 0); QCOMPARE(binaryMessageSpy.count(), 0); - QCOMPARE(textFrameSpy.count(), 1); + QCOMPARE(textFrameSpy.count(), 0); QCOMPARE(binaryFrameSpy.count(), 0); QList arguments = errorSpy.takeFirst(); -- cgit v1.2.1