diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-09-05 09:02:14 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-09-05 09:02:19 +0200 |
commit | 9f88317e29621451c18719abc5e22198b618471f (patch) | |
tree | 4259cf62f6b5343aeb1588ed19abeb7225dc8aee | |
parent | 034c5b8296119f6eb0046ae1276b7261872caa57 (diff) | |
parent | 36e4776fb5ac5506ab30cc96950aeb053c263ed2 (diff) |
Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
-rw-r--r-- | src/websockets/qwebsocket_p.cpp | 8 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.h | 4 | ||||
-rw-r--r-- | src/websockets/qwebsocketdataprocessor.cpp | 16 | ||||
-rw-r--r-- | src/websockets/qwebsocketdataprocessor_p.h | 2 | ||||
-rw-r--r-- | src/websockets/qwebsockethandshakeresponse.cpp | 9 | ||||
-rw-r--r-- | src/websockets/qwebsocketserver.cpp | 2 | ||||
-rw-r--r-- | tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp | 4 | ||||
-rw-r--r-- | tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp | 28 |
8 files changed, 56 insertions, 17 deletions
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index 9b94d04..36aefd9 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -113,6 +113,7 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol:: m_defaultMaskGenerator(), m_handshakeState(NothingDoneState) { + m_pingTimer.start(); } /*! @@ -144,6 +145,7 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol: m_defaultMaskGenerator(), m_handshakeState(NothingDoneState) { + m_pingTimer.start(); } /*! @@ -1173,13 +1175,13 @@ void QWebSocketPrivate::processData() { if (!m_pSocket) // disconnected with data still in-bound return; - if (m_pSocket->bytesAvailable()) { + while (m_pSocket->bytesAvailable()) { if (state() == QAbstractSocket::ConnectingState) { if (!m_pSocket->canReadLine()) return; processHandshake(m_pSocket); - } else { - m_dataProcessor.process(m_pSocket); + } else if (!m_dataProcessor.process(m_pSocket)) { + return; } } } diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index 4b39dfc..e72daa5 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -61,7 +61,7 @@ #include <QtNetwork/QSslError> #include <QtNetwork/QSslSocket> #endif -#include <QtCore/QTime> +#include <QtCore/QElapsedTimer> #include <private/qobject_p.h> #include "qwebsocket.h" @@ -229,7 +229,7 @@ private: QWebSocketProtocol::CloseCode m_closeCode; QString m_closeReason; - QTime m_pingTimer; + QElapsedTimer m_pingTimer; QWebSocketDataProcessor m_dataProcessor; QWebSocketConfiguration m_configuration; diff --git a/src/websockets/qwebsocketdataprocessor.cpp b/src/websockets/qwebsocketdataprocessor.cpp index 39287d4..191b992 100644 --- a/src/websockets/qwebsocketdataprocessor.cpp +++ b/src/websockets/qwebsocketdataprocessor.cpp @@ -123,8 +123,11 @@ quint64 QWebSocketDataProcessor::maxFrameSize() /*! \internal + + Returns \c true if a complete websocket frame has been processed; + otherwise returns \c false. */ -void QWebSocketDataProcessor::process(QIODevice *pIoDevice) +bool QWebSocketDataProcessor::process(QIODevice *pIoDevice) { bool isDone = false; @@ -135,7 +138,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) QObject::connect(pIoDevice, &QIODevice::readyRead, &waitTimer, &QTimer::stop, Qt::UniqueConnection); waitTimer.start(); - return; + return false; } else if (Q_LIKELY(frame.isValid())) { if (frame.isControlFrame()) { isDone = processControlFrame(frame); @@ -146,7 +149,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError, tr("Received Continuation frame, while there is " \ "nothing to continue.")); - return; + return true; } if (Q_UNLIKELY(m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame())) { @@ -154,7 +157,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeProtocolError, tr("All data frames after the initial data frame " \ "must have opcode 0 (continuation).")); - return; + return true; } if (!frame.isContinuationFrame()) { m_opCode = frame.opCode(); @@ -168,7 +171,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeTooMuchData, tr("Received message is too big.")); - return; + return true; } if (m_opCode == QWebSocketProtocol::OpCodeText) { @@ -181,7 +184,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeWrongDatatype, tr("Invalid UTF-8 code encountered.")); - return; + return true; } else { m_textMessage.append(frameTxt); Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame()); @@ -211,6 +214,7 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) } frame.clear(); } + return true; } /*! diff --git a/src/websockets/qwebsocketdataprocessor_p.h b/src/websockets/qwebsocketdataprocessor_p.h index 41226d6..03635b1 100644 --- a/src/websockets/qwebsocketdataprocessor_p.h +++ b/src/websockets/qwebsocketdataprocessor_p.h @@ -88,7 +88,7 @@ Q_SIGNALS: void errorEncountered(QWebSocketProtocol::CloseCode code, const QString &description); public Q_SLOTS: - void process(QIODevice *pIoDevice); + bool process(QIODevice *pIoDevice); void clear(); private: diff --git a/src/websockets/qwebsockethandshakeresponse.cpp b/src/websockets/qwebsockethandshakeresponse.cpp index 383f1bf..d3ef609 100644 --- a/src/websockets/qwebsockethandshakeresponse.cpp +++ b/src/websockets/qwebsockethandshakeresponse.cpp @@ -162,13 +162,16 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse( if (request.isValid()) { const QString acceptKey = calculateAcceptKey(request.key()); const QList<QString> matchingProtocols = - listIntersection(supportedProtocols, request.protocols(), std::less<>()); + listIntersection(supportedProtocols, request.protocols(), + std::less<QString>()); //TODO: extensions must be kept in the order in which they arrive //cannot use set.intersect() to get the supported extensions const QList<QString> matchingExtensions = - listIntersection(supportedExtensions, request.extensions(), std::less<>()); + listIntersection(supportedExtensions, request.extensions(), + std::less<QString>()); const QList<QWebSocketProtocol::Version> matchingVersions = - listIntersection(supportedVersions, request.versions(), std::greater<>()); //sort in descending order + listIntersection(supportedVersions, request.versions(), + std::greater<QWebSocketProtocol::Version>()); //sort in descending order if (Q_UNLIKELY(matchingVersions.isEmpty())) { m_error = QWebSocketProtocol::CloseCodeProtocolError; diff --git a/src/websockets/qwebsocketserver.cpp b/src/websockets/qwebsocketserver.cpp index 9717401..ecd9da8 100644 --- a/src/websockets/qwebsocketserver.cpp +++ b/src/websockets/qwebsocketserver.cpp @@ -359,6 +359,7 @@ int QWebSocketServer::maxPendingConnections() const handshake their connection is closed. \sa setHandshakeTimeout() + \since 5.14 */ int QWebSocketServer::handshakeTimeout() const { @@ -599,6 +600,7 @@ void QWebSocketServer::setMaxPendingConnections(int numConnections) negative value (e.g. -1) to disable the timeout. \sa handshakeTimeout() + \since 5.14 */ void QWebSocketServer::setHandshakeTimeout(int msec) { diff --git a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp index 19af815..71e1262 100644 --- a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp +++ b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp @@ -472,8 +472,8 @@ void tst_QWebSocket::tst_sendTextMessage() QCOMPARE(urlConnected, url); QCOMPARE(socket.bytesToWrite(), 0); - // transmit a long text message with 64 kb - QString longString(65536, 'a'); + // transmit a long text message with 1 MB + QString longString(0x100000, 'a'); socket.sendTextMessage(longString); QVERIFY(socket.bytesToWrite() > longString.length()); QVERIFY(textMessageReceived.wait()); diff --git a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp index 442196b..20d7060 100644 --- a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp +++ b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp @@ -116,6 +116,7 @@ private Q_SLOTS: void tst_scheme(); // qtbug-55927 void tst_handleConnection(); void tst_handshakeTimeout(); // qtbug-63312, qtbug-57026 + void multipleFrames(); private: bool m_shouldSkipUnsupportedIpv6Test; @@ -823,6 +824,33 @@ void tst_QWebSocketServer::tst_handshakeTimeout() } } +void tst_QWebSocketServer::multipleFrames() +{ + QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode); + QSignalSpy serverConnectionSpy(&server, &QWebSocketServer::newConnection); + QVERIFY(server.listen()); + + QWebSocket socket; + QSignalSpy socketConnectedSpy(&socket, &QWebSocket::connected); + QSignalSpy messageReceivedSpy(&socket, &QWebSocket::binaryMessageReceived); + socket.open(server.serverUrl().toString()); + + QVERIFY(serverConnectionSpy.wait()); + QVERIFY(socketConnectedSpy.wait()); + + auto serverSocket = std::unique_ptr<QWebSocket>(server.nextPendingConnection()); + QVERIFY(serverSocket); + for (int i = 0; i < 10; i++) + serverSocket->sendBinaryMessage(QByteArray("abc")); + if (serverSocket->bytesToWrite()) + QVERIFY(serverSocket->flush()); + + QVERIFY(messageReceivedSpy.wait()); + // Since there's no guarantee the operating system will fit all 10 websocket frames into 1 tcp + // frame, let's just assume it will do at least 2. EXCEPT_FAIL any which doesn't merge any. + QVERIFY2(messageReceivedSpy.count() > 1, "Received only 1 message in the TCP frame!"); +} + QTEST_MAIN(tst_QWebSocketServer) #include "tst_qwebsocketserver.moc" |