summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--src/imports/qmlwebsockets/qqmlwebsocket.cpp10
-rw-r--r--src/websockets/qwebsocketdataprocessor.cpp14
-rw-r--r--src/websockets/qwebsockethandshakerequest.cpp16
-rw-r--r--src/websockets/qwebsocketserver.h4
-rw-r--r--src/websockets/qwebsocketserver_p.cpp8
-rw-r--r--src/websockets/qwebsocketserver_p.h2
-rw-r--r--tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp54
-rw-r--r--tests/auto/websockets/handshakerequest/tst_handshakerequest.cpp103
-rw-r--r--tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro2
-rw-r--r--tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp56
-rw-r--r--tests/auto/websockets/shared/localhost.cert18
-rw-r--r--tests/auto/websockets/shared/localhost.key27
-rw-r--r--tests/auto/websockets/shared/qwebsocketshared.qrc6
14 files changed, 287 insertions, 35 deletions
diff --git a/.qmake.conf b/.qmake.conf
index d1e1c4c..13d7a60 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -3,4 +3,4 @@ load(qt_build_config)
CONFIG += warning_clean
DEFINES += QT_NO_FOREACH
-MODULE_VERSION = 5.8.0
+MODULE_VERSION = 5.8.1
diff --git a/src/imports/qmlwebsockets/qqmlwebsocket.cpp b/src/imports/qmlwebsockets/qqmlwebsocket.cpp
index 9ff88d5..35f6259 100644
--- a/src/imports/qmlwebsockets/qqmlwebsocket.cpp
+++ b/src/imports/qmlwebsockets/qqmlwebsocket.cpp
@@ -63,11 +63,11 @@
The status can have the following values:
\list
- \li WebSockets.Connecting
- \li WebSockets.Open
- \li WebSockets.Closing
- \li WebSockets.Closed
- \li WebSockets.Error
+ \li WebSocket.Connecting
+ \li WebSocket.Open
+ \li WebSocket.Closing
+ \li WebSocket.Closed
+ \li WebSocket.Error
\endlist
*/
diff --git a/src/websockets/qwebsocketdataprocessor.cpp b/src/websockets/qwebsocketdataprocessor.cpp
index 520ecdc..d9fc550 100644
--- a/src/websockets/qwebsocketdataprocessor.cpp
+++ b/src/websockets/qwebsocketdataprocessor.cpp
@@ -182,12 +182,16 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice)
}
if (frame.isFinalFrame()) {
- if (m_opCode == QWebSocketProtocol::OpCodeText)
- Q_EMIT textMessageReceived(m_textMessage);
- else
- Q_EMIT binaryMessageReceived(m_binaryMessage);
- clear();
isDone = true;
+ if (m_opCode == QWebSocketProtocol::OpCodeText) {
+ const QString textMessage(m_textMessage);
+ clear();
+ Q_EMIT textMessageReceived(textMessage);
+ } else {
+ const QByteArray binaryMessage(m_binaryMessage);
+ clear();
+ Q_EMIT binaryMessageReceived(binaryMessage);
+ }
}
}
} else {
diff --git a/src/websockets/qwebsockethandshakerequest.cpp b/src/websockets/qwebsockethandshakerequest.cpp
index 81c5f97..ddeee2d 100644
--- a/src/websockets/qwebsockethandshakerequest.cpp
+++ b/src/websockets/qwebsockethandshakerequest.cpp
@@ -275,16 +275,12 @@ void QWebSocketHandshakeRequest::readHandshake(QTextStream &textStream, int maxH
if (m_requestUrl.isRelative()) {
// see http://tools.ietf.org/html/rfc6455#page-17
// No. 4 item in "The requirements for this handshake"
- int idx = host.indexOf(QStringLiteral(":"));
- bool ok = false;
- int port = 0;
- if (idx != -1) {
- port = host.rightRef(host.length() - idx - 1).toInt(&ok);
- host.truncate(idx);
+ m_requestUrl.setAuthority(host);
+ if (!m_requestUrl.userName().isNull()) { // If the username is null, the password must be too.
+ m_isValid = false;
+ clear();
+ return;
}
- m_requestUrl.setHost(host);
- if (ok)
- m_requestUrl.setPort(port);
}
if (m_requestUrl.scheme().isEmpty()) {
const QString scheme = isSecure() ? QStringLiteral("wss") : QStringLiteral("ws");
@@ -337,7 +333,7 @@ void QWebSocketHandshakeRequest::readHandshake(QTextStream &textStream, int maxH
//TODO: authentication field
- m_isValid = !(host.isEmpty() ||
+ m_isValid = !(m_requestUrl.host().isEmpty() ||
resourceName.isEmpty() ||
m_versions.isEmpty() ||
m_key.isEmpty() ||
diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h
index 47113e4..511a55b 100644
--- a/src/websockets/qwebsocketserver.h
+++ b/src/websockets/qwebsocketserver.h
@@ -69,9 +69,9 @@ class Q_WEBSOCKETS_EXPORT QWebSocketServer : public QObject
public:
enum SslMode {
#ifndef QT_NO_SSL
- SecureMode,
+ SecureMode = 0,
#endif
- NonSecureMode
+ NonSecureMode = 1
};
explicit QWebSocketServer(const QString &serverName, SslMode secureMode,
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 91bfafc..d675056 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -392,18 +392,20 @@ void QWebSocketServerPrivate::onNewConnection()
QObjectPrivate::connect(pTcpSocket, &QTcpSocket::readyRead,
this, &QWebSocketServerPrivate::handshakeReceived,
Qt::QueuedConnection);
+ QObjectPrivate::connect(pTcpSocket, &QTcpSocket::disconnected,
+ this, &QWebSocketServerPrivate::onSocketDisconnected);
}
}
/*!
\internal
*/
-void QWebSocketServerPrivate::onCloseConnection()
+void QWebSocketServerPrivate::onSocketDisconnected()
{
if (Q_LIKELY(currentSender)) {
QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(currentSender->sender);
if (Q_LIKELY(pTcpSocket))
- pTcpSocket->close();
+ pTcpSocket->deleteLater();
}
}
@@ -433,7 +435,7 @@ void QWebSocketServerPrivate::handshakeReceived()
this, &QWebSocketServerPrivate::handshakeReceived);
Q_Q(QWebSocketServer);
bool success = false;
- bool isSecure = false;
+ bool isSecure = (m_secureMode == SecureMode);
if (m_pendingConnections.length() >= maxPendingConnections()) {
pTcpSocket->close();
diff --git a/src/websockets/qwebsocketserver_p.h b/src/websockets/qwebsocketserver_p.h
index 46a2156..6aabebd 100644
--- a/src/websockets/qwebsocketserver_p.h
+++ b/src/websockets/qwebsocketserver_p.h
@@ -136,7 +136,7 @@ private:
const QString &errorDescription);
void onNewConnection();
- void onCloseConnection();
+ void onSocketDisconnected();
void handshakeReceived();
};
diff --git a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
index 55c27af..5f6cfba 100644
--- a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
+++ b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
@@ -173,6 +173,8 @@ private Q_SLOTS:
void minimumSizeRequirement();
void minimumSizeRequirement_data();
+ void clearDataBuffers(); // qtbug-55506
+
private:
//helper function that constructs a new row of test data for invalid UTF8 sequences
void invalidUTF8(const char *dataTag, const char *utf8Sequence, bool isCloseFrame);
@@ -243,7 +245,7 @@ void tst_DataProcessor::goodBinaryFrame()
QWebSocketDataProcessor dataProcessor;
QFETCH(QByteArray, payload);
- data.append((char)(FIN | QWebSocketProtocol::OpCodeBinary));
+ data.append(char(FIN | QWebSocketProtocol::OpCodeBinary));
if (payload.length() < 126)
{
@@ -337,7 +339,7 @@ void tst_DataProcessor::goodTextFrame()
QFETCH(QByteArray, payload);
QFETCH(int, size);
- data.append((char)(FIN | QWebSocketProtocol::OpCodeText));
+ data.append(char(FIN | QWebSocketProtocol::OpCodeText));
if (payload.length() < 126)
{
@@ -407,7 +409,7 @@ void tst_DataProcessor::goodControlFrame()
QSignalSpy pingReceivedSpy(&dataProcessor, SIGNAL(pingReceived(QByteArray)));
QSignalSpy pongReceivedSpy(&dataProcessor, SIGNAL(pongReceived(QByteArray)));
- data.append((char)(FIN | QWebSocketProtocol::OpCodePing));
+ data.append(char(FIN | QWebSocketProtocol::OpCodePing));
data.append(QChar::fromLatin1(0));
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
@@ -425,7 +427,7 @@ void tst_DataProcessor::goodControlFrame()
data.clear();
pingReceivedSpy.clear();
pongReceivedSpy.clear();
- data.append((char)(FIN | QWebSocketProtocol::OpCodePong));
+ data.append(char(FIN | QWebSocketProtocol::OpCodePong));
data.append(QChar::fromLatin1(0));
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
@@ -537,7 +539,7 @@ void tst_DataProcessor::goodOpcodes()
QWebSocketDataProcessor dataProcessor;
QFETCH(QWebSocketProtocol::OpCode, opCode);
- data.append((char)(FIN | opCode));
+ data.append(char(FIN | opCode));
data.append(char(0)); //zero length
buffer.setData(data);
@@ -584,7 +586,7 @@ void tst_DataProcessor::goodCloseFrame()
quint16 swapped = qToBigEndian<quint16>(closeCode);
const char *wireRepresentation = static_cast<const char *>(static_cast<const void *>(&swapped));
- data.append((char)(FIN | QWebSocketProtocol::OpCodeClose));
+ data.append(char(FIN | QWebSocketProtocol::OpCodeClose));
if (swapped != 0)
{
data.append(char(payload.length() + 2)).append(wireRepresentation, 2).append(payload);
@@ -800,7 +802,7 @@ void tst_DataProcessor::frameTooSmall()
{
//text frame with final bit not set
- data.append((char)(QWebSocketProtocol::OpCodeText)).append(char(0x0));
+ data.append(char(QWebSocketProtocol::OpCodeText)).append(char(0x0));
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
@@ -842,7 +844,7 @@ void tst_DataProcessor::frameTooSmall()
data.clear();
//text frame with final bit not set
- data.append((char)(QWebSocketProtocol::OpCodeText)).append(char(0x0));
+ data.append(char(QWebSocketProtocol::OpCodeText)).append(char(0x0));
buffer.setData(data);
buffer.open(QIODevice::ReadOnly);
dataProcessor.process(&buffer);
@@ -1832,6 +1834,42 @@ void tst_DataProcessor::insertIncompleteSizeFieldTest(quint8 payloadCode, quint8
<< QWebSocketProtocol::CloseCodeGoingAway;
}
+void tst_DataProcessor::clearDataBuffers()
+{
+ const QByteArray binaryData("Hello!");
+ QByteArray data;
+ data.append(char(FIN | QWebSocketProtocol::OpCodeBinary));
+ data.append(char(binaryData.length()));
+ data.append(binaryData);
+
+ QWebSocketDataProcessor dataProcessor;
+ connect(&dataProcessor, &QWebSocketDataProcessor::binaryMessageReceived,
+ [&binaryData](const QByteArray &message)
+ {
+ QCOMPARE(message, binaryData);
+ QEventLoop loop;
+ QTimer::singleShot(2000, &loop, SLOT(quit()));
+ loop.exec();
+ });
+
+ QBuffer buffer;
+ buffer.setData(data);
+ auto processData = [&dataProcessor, &buffer]()
+ {
+ buffer.open(QIODevice::ReadOnly);
+ dataProcessor.process(&buffer);
+ buffer.close();
+ };
+
+ QTimer timer;
+ timer.setSingleShot(true);
+ connect(&timer, &QTimer::timeout, processData);
+
+ timer.start(1000);
+ processData();
+ QTest::qWait(2000);
+}
+
QTEST_MAIN(tst_DataProcessor)
#include "tst_dataprocessor.moc"
diff --git a/tests/auto/websockets/handshakerequest/tst_handshakerequest.cpp b/tests/auto/websockets/handshakerequest/tst_handshakerequest.cpp
index 3419546..4a9603f 100644
--- a/tests/auto/websockets/handshakerequest/tst_handshakerequest.cpp
+++ b/tests/auto/websockets/handshakerequest/tst_handshakerequest.cpp
@@ -67,6 +67,9 @@ private Q_SLOTS:
void tst_qtbug_39355();
void tst_qtbug_48123_data();
void tst_qtbug_48123();
+
+ void tst_qtbug_57357_data();
+ void tst_qtbug_57357(); // ipv6 related
};
tst_HandshakeRequest::tst_HandshakeRequest()
@@ -375,6 +378,106 @@ void tst_HandshakeRequest::tst_qtbug_48123()
QCOMPARE(request.isValid(), shouldBeValid);
}
+void tst_HandshakeRequest::tst_qtbug_57357_data()
+{
+ QTest::addColumn<QString>("header");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<int>("port");
+
+ QString header = QLatin1String("GET /ABC/DEF/ HTTP/1.1\r\nHost: %1%2\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Sec-WebSocket-Key: 2Wg20829/4ziWlmsUAD8Dg==\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n\r\n");
+
+ QTest::newRow("ipv4-1") << header.arg(QStringLiteral("10.0.0.1")).arg(QStringLiteral(":1234")) << true
+ << QStringLiteral("10.0.0.1")
+ << 1234;
+ QTest::newRow("ipv4-2") << header.arg(QStringLiteral("127.0.0.1")).arg(QStringLiteral(":1111")) << true
+ << QStringLiteral("127.0.0.1")
+ << 1111;
+ QTest::newRow("ipv4-wo-port") << header.arg(QStringLiteral("10.0.0.1")).arg(QStringLiteral("")) << true
+ << QStringLiteral("10.0.0.1")
+ << 8080;
+
+ QTest::newRow("ipv6-1") << header.arg(QStringLiteral("[56:56:56:56:56:56:56:56]")).arg(QStringLiteral(":1234")) << true
+ << QStringLiteral("56:56:56:56:56:56:56:56")
+ << 1234;
+ QTest::newRow("ipv6-2") << header.arg(QStringLiteral("[::ffff:129.144.52.38]")).arg(QStringLiteral(":1111")) << true
+ << QStringLiteral("::ffff:129.144.52.38")
+ << 1111;
+ QTest::newRow("ipv6-wo-port") << header.arg(QStringLiteral("[56:56:56:56:56:56:56:56]")).arg(QStringLiteral("")) << true
+ << QStringLiteral("56:56:56:56:56:56:56:56")
+ << 8080;
+ QTest::newRow("ipv6-invalid-1") << header.arg(QStringLiteral("56:56:56:56:56:56:56:56]")).arg(QStringLiteral(":1234")) << false
+ << QStringLiteral("")
+ << 1234;
+
+ QTest::newRow("host-1") << header.arg(QStringLiteral("foo.com")).arg(QStringLiteral(":1234")) << true
+ << QStringLiteral("foo.com")
+ << 1234;
+ QTest::newRow("host-2") << header.arg(QStringLiteral("bar.net")).arg(QStringLiteral(":1111")) << true
+ << QStringLiteral("bar.net")
+ << 1111;
+ QTest::newRow("host-wo-port") << header.arg(QStringLiteral("foo.com")).arg(QStringLiteral("")) << true
+ << QStringLiteral("foo.com")
+ << 8080;
+
+ QTest::newRow("localhost-1") << header.arg(QStringLiteral("localhost")).arg(QStringLiteral(":1234")) << true
+ << QStringLiteral("localhost")
+ << 1234;
+ QTest::newRow("localhost-2") << header.arg(QStringLiteral("localhost")).arg(QStringLiteral(":1111")) << true
+ << QStringLiteral("localhost")
+ << 1111;
+ QTest::newRow("localhost-wo-port") << header.arg(QStringLiteral("localhost")).arg(QStringLiteral("")) << true
+ << QStringLiteral("localhost")
+ << 8080;
+
+ // reference: qtbase/tests/auto/corelib/io/qurl/tst_qurl.cpp: void tst_QUrl::ipvfuture_data()
+ QTest::newRow("ipvfuture-1") << header.arg(QStringLiteral("[v7.1234]")).arg(QStringLiteral(":1234")) << true
+ << QStringLiteral("v7.1234")
+ << 1234;
+
+ QTest::newRow("invalid-1") << header.arg(QStringLiteral("abc:def@foo.com")).arg(QStringLiteral("")) << false
+ << QStringLiteral("foo.com")
+ << 8080;
+ QTest::newRow("invalid-2") << header.arg(QStringLiteral(":def@foo.com")).arg(QStringLiteral("")) << false
+ << QStringLiteral("foo.com")
+ << 8080;
+ QTest::newRow("invalid-3") << header.arg(QStringLiteral("abc:@foo.com")).arg(QStringLiteral("")) << false
+ << QStringLiteral("foo.com")
+ << 8080;
+ QTest::newRow("invalid-4") << header.arg(QStringLiteral("@foo.com")).arg(QStringLiteral("")) << false
+ << QStringLiteral("foo.com")
+ << 8080;
+ QTest::newRow("invalid-5") << header.arg(QStringLiteral("foo.com/")).arg(QStringLiteral("")) << false
+ << QStringLiteral("foo.com")
+ << 8080;
+}
+
+void tst_HandshakeRequest::tst_qtbug_57357()
+{
+ QFETCH(QString, header);
+ QFETCH(bool, valid);
+ QFETCH(QString, host);
+ QFETCH(int, port);
+
+ QByteArray data;
+ QTextStream textStream(&data);
+ QWebSocketHandshakeRequest request(8080, false);
+
+ textStream << header;
+ textStream.seek(0);
+ request.readHandshake(textStream, MAX_HEADERLINE_LENGTH, MAX_HEADERS);
+
+ QCOMPARE(request.isValid(), valid);
+ if (valid) {
+ QCOMPARE(request.host(), host);
+ QCOMPARE(request.port(), port);
+ }
+}
+
QTEST_MAIN(tst_HandshakeRequest)
#include "tst_handshakerequest.moc"
diff --git a/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro b/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
index adba325..e166f50 100644
--- a/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
+++ b/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
@@ -10,3 +10,5 @@ TEMPLATE = app
SOURCES += tst_qwebsocketserver.cpp
+RESOURCES += $$PWD/../shared/qwebsocketshared.qrc
+
diff --git a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
index 699939f..7f2bfa4 100644
--- a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
+++ b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
@@ -32,6 +32,9 @@
#include <QtNetwork/qsslpresharedkeyauthenticator.h>
#include <QtNetwork/qsslcipher.h>
#endif
+#ifndef QT_NO_SSL
+#include <QtNetwork/qsslkey.h>
+#endif
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>
#include <QtWebSockets/QWebSocketCorsAuthenticator>
@@ -106,6 +109,7 @@ private Q_SLOTS:
void tst_preSharedKey();
void tst_maxPendingConnections();
void tst_serverDestroyedWhileSocketConnected();
+ void tst_scheme(); // qtbug-55927
};
tst_QWebSocketServer::tst_QWebSocketServer()
@@ -507,6 +511,58 @@ void tst_QWebSocketServer::tst_serverDestroyedWhileSocketConnected()
QCOMPARE(socketDisconnectedSpy.count(), 1);
}
+void tst_QWebSocketServer::tst_scheme()
+{
+ QWebSocketServer plainServer(QString(), QWebSocketServer::NonSecureMode);
+ QSignalSpy plainServerConnectionSpy(&plainServer, SIGNAL(newConnection()));
+
+ QVERIFY(plainServer.listen());
+
+ QWebSocket plainSocket;
+ plainSocket.open(plainServer.serverUrl().toString());
+
+ if (plainServerConnectionSpy.count() == 0)
+ QVERIFY(plainServerConnectionSpy.wait());
+ QScopedPointer<QWebSocket> plainServerSocket(plainServer.nextPendingConnection());
+ QVERIFY(!plainServerSocket.isNull());
+ QCOMPARE(plainServerSocket->requestUrl().scheme(), QStringLiteral("ws"));
+ plainServer.close();
+
+#ifndef QT_NO_SSL
+ QWebSocketServer secureServer(QString(), QWebSocketServer::SecureMode);
+ QSslConfiguration sslConfiguration;
+ QFile certFile(QStringLiteral(":/localhost.cert"));
+ QFile keyFile(QStringLiteral(":/localhost.key"));
+ QVERIFY(certFile.open(QIODevice::ReadOnly));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ QSslCertificate certificate(&certFile, QSsl::Pem);
+ QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);
+ certFile.close();
+ keyFile.close();
+ sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
+ sslConfiguration.setLocalCertificate(certificate);
+ sslConfiguration.setPrivateKey(sslKey);
+ sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
+ secureServer.setSslConfiguration(sslConfiguration);
+ QSignalSpy secureServerConnectionSpy(&secureServer, SIGNAL(newConnection()));
+
+ QVERIFY(secureServer.listen());
+
+ QWebSocket secureSocket;
+ typedef void (QWebSocket::* ignoreSslErrorsSlot)();
+ connect(&secureSocket, &QWebSocket::sslErrors,
+ &secureSocket, static_cast<ignoreSslErrorsSlot>(&QWebSocket::ignoreSslErrors));
+ secureSocket.open(secureServer.serverUrl().toString());
+
+ if (secureServerConnectionSpy.count() == 0)
+ QVERIFY(secureServerConnectionSpy.wait());
+ QScopedPointer<QWebSocket> secureServerSocket(secureServer.nextPendingConnection());
+ QVERIFY(!secureServerSocket.isNull());
+ QCOMPARE(secureServerSocket->requestUrl().scheme(), QStringLiteral("wss"));
+ secureServer.close();
+#endif
+}
+
QTEST_MAIN(tst_QWebSocketServer)
#include "tst_qwebsocketserver.moc"
diff --git a/tests/auto/websockets/shared/localhost.cert b/tests/auto/websockets/shared/localhost.cert
new file mode 100644
index 0000000..7aa33a1
--- /dev/null
+++ b/tests/auto/websockets/shared/localhost.cert
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIJAP26rumH9qOkMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMMCWxvY2FsaG9zdDAeFw0xMzExMDYxNjU4NTRaFw0yMzExMDQxNjU4NTRaMBQx
+EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALgagHqEqWr4WH+MFBQE+BWZri5UUn/QPORN2pUB1lWMzeDCM5YMc/D1dhUG
+7zg5I9QO5Ut1YcoVO25OAseddgVaIFXPNyEG2nUTz53xx3pyqp3WtQkYCRAQzI8K
+IFIzBSD+nJNl+8gBld7Fe+4d8bFCwfXspQBJ2RY8SQ6tjRFVKHN7haLsD+WV3AFg
+siWkCxeXxVLNI69cuLwV7bEsv6U1N1yNROvRpu4yJcaNnu36kJFbORPhNfy6qJGX
+i0A30dYdMoLhtCN3Qf/XwGyS84Rs2XXduNlBdUgbpluY2r2x3Gz32hIwsHHcPzX6
+O9nwVPQ8k29lfC8yPmAWA9vPiBUCAwEAAaNQME4wHQYDVR0OBBYEFJZESCN01tY3
+MgXxmqiUBNPxsgiKMB8GA1UdIwQYMBaAFJZESCN01tY3MgXxmqiUBNPxsgiKMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHylCJYED9PqLB9FE4A0CRfy
+BdxIqOK+UExxxkU1DeN7kM4U2+E0G85nqBLOL34BDj8LDKJH9WC7L9jMV8T3Upbg
++RrTGiIcyjsL18L2KWeOia1R6VVAQcZrqoWv+QXyVvIi8IpTOE074C6+Vzx6XYMe
+CpW4jcdfmn39oVeMXxz9+8wD7CWeCT+SMj8tt+OB1XjQwdEG03vb6ArtnuJT77VI
+3I090OtKksBE5hy1H9N2E3wxhFTxC+DI5sc7Bj87v3blL4Z3DvRUEHwQHcDccQ0D
+ERUEcSyn1YGSlDVbVf3CzH4WXxddUBmaSHf4JTuAMy0C0A6IWuMP+rVVvVMIXNM=
+-----END CERTIFICATE-----
diff --git a/tests/auto/websockets/shared/localhost.key b/tests/auto/websockets/shared/localhost.key
new file mode 100644
index 0000000..dcc262c
--- /dev/null
+++ b/tests/auto/websockets/shared/localhost.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuBqAeoSpavhYf4wUFAT4FZmuLlRSf9A85E3alQHWVYzN4MIz
+lgxz8PV2FQbvODkj1A7lS3VhyhU7bk4Cx512BVogVc83IQbadRPPnfHHenKqnda1
+CRgJEBDMjwogUjMFIP6ck2X7yAGV3sV77h3xsULB9eylAEnZFjxJDq2NEVUoc3uF
+ouwP5ZXcAWCyJaQLF5fFUs0jr1y4vBXtsSy/pTU3XI1E69Gm7jIlxo2e7fqQkVs5
+E+E1/LqokZeLQDfR1h0yguG0I3dB/9fAbJLzhGzZdd242UF1SBumW5javbHcbPfa
+EjCwcdw/Nfo72fBU9DyTb2V8LzI+YBYD28+IFQIDAQABAoIBADADmWZamuSvCEWb
+ftEJyrm3btneW/XBlV/lfhBGfmOpaTgo7dNARCyfl8A8Ir+DB3kSuXJIlsxhZTKL
+XeY5hsI2kyBN/o66ftbx57/FgsTIiv7HNEe+4P4zo2Xaujs12yyTuromatfqse97
+iaq8XIBibLt6kD3XBKrr5hHR6WyPW9F7sM91e/1OGTXBt9URvnnHqcimJ8Wvto5p
+SMFlud8JXMmARhWaIfqQIcNYmNEHea0LfOZVerTOPE7IZd5coM91mr71lzoxs9Ik
+bRMbqgyAMXEJV3ynEH2LjjJZo1bVb8Va45QqqOQ4FtL46n1Z+EVUXyhCHGepwyOv
+uAru0wECgYEA3CnM252417At+N9Zq4KtBJ8tIEXKqvK1Bl5aZSqaJClywjCttR2l
+lRAlIRAmqHCQuxLDDfLfiJh6xgZsjr4MhksuyKc7DKssfWW+XCd+5GaaMoMvJXhs
+caJdhNSHzpnLPi++tJBYHwHa354D5PJ3eItzLkmuVyhmc3plNbkBGLECgYEA1hIX
+mA9KadVG9VkaDci+xo1p0ACb5ccHAvmA8+fzb0H09yKw5bCSpNGeHj4Qv5ZFqsUm
+96NWYEB38ezupWqWMFd9zr1kD2s3r6Kpq1TS6xuDPapyiXaKpcH1ys7IWZkinCkN
+oxhPHcQbFu9/CN2zIVFKvF5P98Rh0+wO7fgL/qUCgYAyleAd7cVUuYQ2lIrz31iF
+oVUq/x4r3Qw+5Fr8t6cm++cEO08OODudXlJJoH5hYUu/z/XFNLKrne1Hpp42xe/2
+wzuCmvn0VTgpr8DnR6PeMrznMkEY6Oxxx46ZQIPbsnaCWVIGBsxYg4KYsqPObO+K
+YPAcCI3oNL4ldk/e4h0gYQKBgHm+4FxClfeKrEhs3DxqptUVJ9B8CC2t+3bdn1EX
+4YKs6DyFJkX7HetOq7ZXZf8P3583cOn1ovIquAyGy1KYQ8JKf+pMG9QJDip9QDGI
+lEvR4dn4ThuPp1qN7NPitl7+kIhvcKoI8TXkieOJYZ4ROAcCzJZErQYkUd7MqdD8
++RVhAoGAcWC9HRDhxjs4shaBlYi8Lfp3dV4f/4UgYosdFAZ26atwHz+sCLHwwg1j
+6t5Zxy9oEB89S5v5hkgO8//JmopvISSokdvocASMdKE+OmS3JfBmhQK9qVBW/vv/
+ut2bhPjEzIJyNFKX3xnGI8PREcR2eY+WLhIZ5KiR61tGpktJ4bg=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/websockets/shared/qwebsocketshared.qrc b/tests/auto/websockets/shared/qwebsocketshared.qrc
new file mode 100644
index 0000000..513a87f
--- /dev/null
+++ b/tests/auto/websockets/shared/qwebsocketshared.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>localhost.cert</file>
+ <file>localhost.key</file>
+ </qresource>
+</RCC>