void tst_WebSocketFrame::tst_copyConstructorAndAssignment() { FrameHelper frameHelper; frameHelper.setRsv1(0); frameHelper.setRsv2(0); frameHelper.setRsv3(0); frameHelper.setFinalFrame(true); frameHelper.setMask(1234u); frameHelper.setOpCode(QWebSocketProtocol::OpCodeBinary); frameHelper.setPayload(QByteArrayLiteral("12345")); QByteArray payload = frameHelper.wireRepresentation(); QBuffer buffer(&payload); buffer.open(QIODevice::ReadOnly); QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); buffer.close(); { QWebSocketFrame other(frame); QCOMPARE(other.closeCode(), frame.closeCode()); QCOMPARE(other.closeReason(), frame.closeReason()); QCOMPARE(other.hasMask(), frame.hasMask()); QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame()); QCOMPARE(other.isControlFrame(), frame.isControlFrame()); QCOMPARE(other.isDataFrame(), frame.isDataFrame()); QCOMPARE(other.isFinalFrame(), frame.isFinalFrame()); QCOMPARE(other.isValid(), frame.isValid()); QCOMPARE(other.mask(), frame.mask()); QCOMPARE(other.opCode(), frame.opCode()); QCOMPARE(other.payload(), frame.payload()); QCOMPARE(other.rsv1(), frame.rsv1()); QCOMPARE(other.rsv2(), frame.rsv2()); QCOMPARE(other.rsv3(), frame.rsv3()); } { QWebSocketFrame other; other = frame; QCOMPARE(other.closeCode(), frame.closeCode()); QCOMPARE(other.closeReason(), frame.closeReason()); QCOMPARE(other.hasMask(), frame.hasMask()); QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame()); QCOMPARE(other.isControlFrame(), frame.isControlFrame()); QCOMPARE(other.isDataFrame(), frame.isDataFrame()); QCOMPARE(other.isFinalFrame(), frame.isFinalFrame()); QCOMPARE(other.isValid(), frame.isValid()); QCOMPARE(other.mask(), frame.mask()); QCOMPARE(other.opCode(), frame.opCode()); QCOMPARE(other.payload(), frame.payload()); QCOMPARE(other.rsv1(), frame.rsv1()); QCOMPARE(other.rsv2(), frame.rsv2()); QCOMPARE(other.rsv3(), frame.rsv3()); } }
void tst_WebSocketFrame::tst_invalidFrames() { QFETCH(int, rsv1); QFETCH(int, rsv2); QFETCH(int, rsv3); QFETCH(quint32, mask); QFETCH(QWebSocketProtocol::OpCode, opCode); QFETCH(bool, isFinal); QFETCH(QByteArray, payload); QFETCH(QWebSocketProtocol::CloseCode, expectedError); FrameHelper helper; helper.setRsv1(rsv1); helper.setRsv2(rsv2); helper.setRsv3(rsv3); helper.setMask(mask); helper.setOpCode(opCode); helper.setFinalFrame(isFinal); helper.setPayload(payload); QByteArray wireRepresentation = helper.wireRepresentation(); QBuffer buffer; buffer.setData(wireRepresentation); buffer.open(QIODevice::ReadOnly); QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); buffer.close(); QVERIFY(!frame.isValid()); QCOMPARE(frame.closeCode(), expectedError); }
void tst_WebSocketFrame::tst_malformedFrames() { QFETCH(QByteArray, payload); QFETCH(QWebSocketProtocol::CloseCode, expectedError); QBuffer buffer; buffer.setData(payload); buffer.open(QIODevice::ReadOnly); QWebSocketFrame frame = QWebSocketFrame::readFrame(&buffer); buffer.close(); QVERIFY(!frame.isValid()); QCOMPARE(frame.closeCode(), expectedError); }
/*! \internal */ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) { bool isDone = false; while (!isDone) { QWebSocketFrame frame = QWebSocketFrame::readFrame(pIoDevice); if (Q_LIKELY(frame.isValid())) { if (frame.isControlFrame()) { isDone = processControlFrame(frame); } else { //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY if (Q_UNLIKELY(!m_isFragmented && frame.isContinuationFrame())) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError, tr("Received Continuation frame, while there is " \ "nothing to continue.")); return; } if (Q_UNLIKELY(m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame())) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError, tr("All data frames after the initial data frame " \ "must have opcode 0 (continuation).")); return; } if (!frame.isContinuationFrame()) { m_opCode = frame.opCode(); m_isFragmented = !frame.isFinalFrame(); } quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OpCodeText) ? m_textMessage.length() : m_binaryMessage.length(); if (Q_UNLIKELY((messageLength + quint64(frame.payload().length())) > MAX_MESSAGE_SIZE_IN_BYTES)) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeTooMuchData, tr("Received message is too big.")); return; } if (m_opCode == QWebSocketProtocol::OpCodeText) { QString frameTxt = m_pTextCodec->toUnicode(frame.payload().constData(), frame.payload().size(), m_pConverterState); bool failed = (m_pConverterState->invalidChars != 0) || (frame.isFinalFrame() && (m_pConverterState->remainingChars != 0)); if (Q_UNLIKELY(failed)) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeWrongDatatype, tr("Invalid UTF-8 code encountered.")); return; } else { m_textMessage.append(frameTxt); Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame()); } } else { m_binaryMessage.append(frame.payload()); Q_EMIT binaryFrameReceived(frame.payload(), frame.isFinalFrame()); } if (frame.isFinalFrame()) { if (m_opCode == QWebSocketProtocol::OpCodeText) Q_EMIT textMessageReceived(m_textMessage); else Q_EMIT binaryMessageReceived(m_binaryMessage); clear(); isDone = true; } } } else { Q_EMIT errorEncountered(frame.closeCode(), frame.closeReason()); clear(); isDone = true; } } }