diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2022-03-29 17:03:05 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2022-04-01 09:50:22 +0000 |
commit | 631fb7665fb53521df2cedb186a8e1e370b2aaa4 (patch) | |
tree | 5db842459de6c442391f18bfc08470b636822f3c /tests | |
parent | a864f340543486e1962c72538b9e56e520f7cee4 (diff) | |
download | qtwebsockets-631fb7665fb53521df2cedb186a8e1e370b2aaa4.tar.gz |
Fix handshake looping infinitely making no progress
The processHandshake function may make no progress and return.
The loop calling processHandshake previously had no way of knowing this
and would happily loop forever despite the outcome being the same every
time.
This was particularly noticeable with any response that doesn't include
the \r\n\r\n sequence the first time we call processHandshake.
Since processHandshake either fails or succeeds, not performing any
partial-reads, we simply move it out of the loop and restructure some of
the code around it.
Pick-to: 6.3 6.3.0
Fixes: QTBUG-102111
Change-Id: I3955e4b90eb1be0a0ef5dfcf8a46921a086a8b49
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp index 1da7dc8..e5569fd 100644 --- a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp +++ b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp @@ -33,6 +33,8 @@ #include <QtWebSockets/QWebSocketServer> #include <QtWebSockets/qwebsocketprotocol.h> +#include <QtNetwork/qtcpserver.h> + QT_USE_NAMESPACE Q_DECLARE_METATYPE(QWebSocketProtocol::Version) @@ -162,6 +164,7 @@ private Q_SLOTS: void incomingMessageTooLong(); void incomingFrameTooLong(); void testingFrameAndMessageSizeApi(); + void customHeader(); }; tst_QWebSocket::tst_QWebSocket() @@ -949,6 +952,59 @@ void tst_QWebSocket::testingFrameAndMessageSizeApi() QTRY_COMPARE(maxAllowedIncomingMessageSize, socket.maxAllowedIncomingMessageSize()); } +void tst_QWebSocket::customHeader() +{ + QTcpServer server; + QSignalSpy serverSpy(&server, &QTcpServer::newConnection); + + server.listen(); + QUrl url = QUrl(QStringLiteral("ws://127.0.0.1")); + url.setPort(server.serverPort()); + + QNetworkRequest request(url); + request.setRawHeader("CustomHeader", "Example"); + QWebSocket socket; + socket.open(request); + + // Custom websocket server below (needed because a QWebSocketServer on + // localhost doesn't show the issue): + QVERIFY(serverSpy.wait()); + QTcpSocket *serverSocket = server.nextPendingConnection(); + QSignalSpy serverSocketSpy(serverSocket, &QTcpSocket::readyRead); + QByteArray data; + while (!data.contains("\r\n\r\n")) { + QVERIFY(serverSocketSpy.wait()); + data.append(serverSocket->readAll()); + } + QVERIFY(data.contains("CustomHeader: Example")); + const auto view = QLatin1String(data); + const auto keyHeader = QLatin1String("Sec-WebSocket-Key:"); + const qsizetype keyStart = view.indexOf(keyHeader, 0, Qt::CaseInsensitive) + keyHeader.length(); + QVERIFY(keyStart != -1); + const qsizetype keyEnd = view.indexOf(QLatin1String("\r\n"), keyStart); + QVERIFY(keyEnd != -1); + const QLatin1String keyView = view.sliced(keyStart, keyEnd - keyStart).trimmed(); + const QByteArray accept = + QByteArrayView(keyView) % QByteArrayLiteral("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + serverSocket->write( + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + % QCryptographicHash::hash(accept, QCryptographicHash::Sha1).toBase64() + ); // trailing \r\n\r\n intentionally left off to make the client wait for it + serverSocket->flush(); + // This would freeze prior to the fix for QTBUG-102111, because the client would loop forever. + // We use qWait to give the OS some time to move the bytes over to the client and push the event + // to our eventloop. + QTest::qWait(100); + serverSocket->write("\r\n\r\n"); + + // And check the client properly connects: + QSignalSpy connectedSpy(&socket, &QWebSocket::connected); + QVERIFY(connectedSpy.wait()); +} + QTEST_MAIN(tst_QWebSocket) #include "tst_qwebsocket.moc" |