summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/websockets/echoserver/echoserver.cpp1
-rw-r--r--examples/websockets/simplechat/chatserver.cpp3
-rw-r--r--examples/websockets/sslechoclient/sslechoclient.cpp3
-rw-r--r--examples/websockets/sslechoserver/sslechoserver.cpp4
-rw-r--r--src/imports/qmlwebsockets/plugins.qmltypes17
-rw-r--r--src/imports/qmlwebsockets/qmlwebsockets.pro2
-rw-r--r--src/imports/qmlwebsockets/qmlwebsockets_plugin.cpp1
-rw-r--r--src/imports/qmlwebsockets/qqmlwebsocket.cpp24
-rw-r--r--src/imports/qmlwebsockets/qqmlwebsocket.h3
-rw-r--r--src/websockets/doc/src/qtwebsockets-module.qdoc4
-rw-r--r--src/websockets/qsslserver.cpp1
-rw-r--r--src/websockets/qsslserver_p.h2
-rw-r--r--src/websockets/qwebsocket.cpp22
-rw-r--r--src/websockets/qwebsocket.h1
-rw-r--r--src/websockets/qwebsocket_p.cpp12
-rw-r--r--src/websockets/qwebsocketserver.cpp23
-rw-r--r--src/websockets/qwebsocketserver.h1
-rw-r--r--src/websockets/qwebsocketserver_p.cpp2
-rw-r--r--tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml25
-rw-r--r--tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp127
21 files changed, 257 insertions, 23 deletions
diff --git a/.qmake.conf b/.qmake.conf
index f068d13..69f27df 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += warning_clean
-MODULE_VERSION = 5.7.1
+MODULE_VERSION = 5.8.0
diff --git a/examples/websockets/echoserver/echoserver.cpp b/examples/websockets/echoserver/echoserver.cpp
index 013ddc2..d4e3b65 100644
--- a/examples/websockets/echoserver/echoserver.cpp
+++ b/examples/websockets/echoserver/echoserver.cpp
@@ -59,7 +59,6 @@ EchoServer::EchoServer(quint16 port, bool debug, QObject *parent) :
QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
QWebSocketServer::NonSecureMode, this)),
- m_clients(),
m_debug(debug)
{
if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
diff --git a/examples/websockets/simplechat/chatserver.cpp b/examples/websockets/simplechat/chatserver.cpp
index 33e5d8d..5a0c998 100644
--- a/examples/websockets/simplechat/chatserver.cpp
+++ b/examples/websockets/simplechat/chatserver.cpp
@@ -57,8 +57,7 @@ QT_USE_NAMESPACE
//! [constructor]
ChatServer::ChatServer(quint16 port, QObject *parent) :
QObject(parent),
- m_pWebSocketServer(Q_NULLPTR),
- m_clients()
+ m_pWebSocketServer(Q_NULLPTR)
{
m_pWebSocketServer = new QWebSocketServer(QStringLiteral("Chat Server"),
QWebSocketServer::NonSecureMode,
diff --git a/examples/websockets/sslechoclient/sslechoclient.cpp b/examples/websockets/sslechoclient/sslechoclient.cpp
index cb15e35..3de2fec 100644
--- a/examples/websockets/sslechoclient/sslechoclient.cpp
+++ b/examples/websockets/sslechoclient/sslechoclient.cpp
@@ -56,8 +56,7 @@ QT_USE_NAMESPACE
//! [constructor]
SslEchoClient::SslEchoClient(const QUrl &url, QObject *parent) :
- QObject(parent),
- m_webSocket()
+ QObject(parent)
{
connect(&m_webSocket, &QWebSocket::connected, this, &SslEchoClient::onConnected);
typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &);
diff --git a/examples/websockets/sslechoserver/sslechoserver.cpp b/examples/websockets/sslechoserver/sslechoserver.cpp
index 777d8dd..ae5d9ad 100644
--- a/examples/websockets/sslechoserver/sslechoserver.cpp
+++ b/examples/websockets/sslechoserver/sslechoserver.cpp
@@ -60,8 +60,7 @@ QT_USE_NAMESPACE
//! [constructor]
SslEchoServer::SslEchoServer(quint16 port, QObject *parent) :
QObject(parent),
- m_pWebSocketServer(Q_NULLPTR),
- m_clients()
+ m_pWebSocketServer(Q_NULLPTR)
{
m_pWebSocketServer = new QWebSocketServer(QStringLiteral("SSL Echo Server"),
QWebSocketServer::SecureMode,
@@ -109,7 +108,6 @@ void SslEchoServer::onNewConnection()
connect(pSocket, &QWebSocket::binaryMessageReceived,
this, &SslEchoServer::processBinaryMessage);
connect(pSocket, &QWebSocket::disconnected, this, &SslEchoServer::socketDisconnected);
- //connect(pSocket, &QWebSocket::pong, this, &SslEchoServer::processPong);
m_clients << pSocket;
}
diff --git a/src/imports/qmlwebsockets/plugins.qmltypes b/src/imports/qmlwebsockets/plugins.qmltypes
index b79da44..cbbb628 100644
--- a/src/imports/qmlwebsockets/plugins.qmltypes
+++ b/src/imports/qmlwebsockets/plugins.qmltypes
@@ -4,15 +4,15 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtWebSockets 1.0'
+// 'qmlplugindump -nonrelocatable QtWebSockets 1.1'
Module {
dependencies: []
Component {
name: "QQmlWebSocket"
prototype: "QObject"
- exports: ["QtWebSockets/WebSocket 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtWebSockets/WebSocket 1.0", "QtWebSockets/WebSocket 1.1"]
+ exportMetaObjectRevisions: [0, 1]
Enum {
name: "Status"
values: {
@@ -32,6 +32,11 @@ Module {
Parameter { name: "message"; type: "string" }
}
Signal {
+ name: "binaryMessageReceived"
+ revision: 1
+ Parameter { name: "message"; type: "QByteArray" }
+ }
+ Signal {
name: "statusChanged"
Parameter { name: "status"; type: "Status" }
}
@@ -48,6 +53,12 @@ Module {
type: "qlonglong"
Parameter { name: "message"; type: "string" }
}
+ Method {
+ name: "sendBinaryMessage"
+ revision: 1
+ type: "qlonglong"
+ Parameter { name: "message"; type: "QByteArray" }
+ }
}
Component {
name: "QQmlWebSocketServer"
diff --git a/src/imports/qmlwebsockets/qmlwebsockets.pro b/src/imports/qmlwebsockets/qmlwebsockets.pro
index dea84a8..fef47f4 100644
--- a/src/imports/qmlwebsockets/qmlwebsockets.pro
+++ b/src/imports/qmlwebsockets/qmlwebsockets.pro
@@ -1,4 +1,4 @@
-QT = core websockets qml
+QT = core websockets qml qml-private core-private
TARGETPATH = QtWebSockets
diff --git a/src/imports/qmlwebsockets/qmlwebsockets_plugin.cpp b/src/imports/qmlwebsockets/qmlwebsockets_plugin.cpp
index 11c9dec..24fe34a 100644
--- a/src/imports/qmlwebsockets/qmlwebsockets_plugin.cpp
+++ b/src/imports/qmlwebsockets/qmlwebsockets_plugin.cpp
@@ -53,6 +53,7 @@ void QtWebSocketsDeclarativeModule::registerTypes(const char *uri)
// @uri QtWebSockets
qmlRegisterType<QQmlWebSocket>(uri, 1 /*major*/, 0 /*minor*/, "WebSocket");
+ qmlRegisterType<QQmlWebSocket, 1>(uri, 1 /*major*/, 1 /*minor*/, "WebSocket");
qmlRegisterType<QQmlWebSocketServer>(uri, 1 /*major*/, 0 /*minor*/, "WebSocketServer");
}
diff --git a/src/imports/qmlwebsockets/qqmlwebsocket.cpp b/src/imports/qmlwebsockets/qqmlwebsocket.cpp
index aea2c82..9ff88d5 100644
--- a/src/imports/qmlwebsockets/qqmlwebsocket.cpp
+++ b/src/imports/qmlwebsockets/qqmlwebsocket.cpp
@@ -90,6 +90,12 @@
*/
/*!
+ \qmlsignal WebSocket::binaryMessageReceived(QString message)
+ \since 5.8
+ This signal is emitted when a binary message is received.
+ */
+
+/*!
\qmlsignal WebSocket::statusChanged(Status status)
This signal is emitted when the status of the WebSocket changes.
the \l [QML]{WebSocket::status}{status} argument provides the current status.
@@ -102,6 +108,12 @@
Sends \c message to the server.
*/
+/*!
+ \qmlmethod void WebSocket::sendBinaryMessage(ArrayBuffer message)
+ \since 5.8
+ Sends \c message to the server.
+ */
+
#include "qqmlwebsocket.h"
#include <QtWebSockets/QWebSocket>
@@ -144,6 +156,16 @@ qint64 QQmlWebSocket::sendTextMessage(const QString &message)
return m_webSocket->sendTextMessage(message);
}
+qint64 QQmlWebSocket::sendBinaryMessage(const QByteArray &message)
+{
+ if (m_status != Open) {
+ setErrorString(tr("Messages can only be sent when the socket is open."));
+ setStatus(Error);
+ return 0;
+ }
+ return m_webSocket->sendBinaryMessage(message);
+}
+
QUrl QQmlWebSocket::url() const
{
return m_url;
@@ -198,6 +220,8 @@ void QQmlWebSocket::setSocket(QWebSocket *socket)
m_webSocket->setParent(Q_NULLPTR);
connect(m_webSocket.data(), &QWebSocket::textMessageReceived,
this, &QQmlWebSocket::textMessageReceived);
+ connect(m_webSocket.data(), &QWebSocket::binaryMessageReceived,
+ this, &QQmlWebSocket::binaryMessageReceived);
typedef void (QWebSocket::* ErrorSignal)(QAbstractSocket::SocketError);
connect(m_webSocket.data(), static_cast<ErrorSignal>(&QWebSocket::error),
this, &QQmlWebSocket::onError);
diff --git a/src/imports/qmlwebsockets/qqmlwebsocket.h b/src/imports/qmlwebsockets/qqmlwebsocket.h
index c5682ed..c3a808f 100644
--- a/src/imports/qmlwebsockets/qqmlwebsocket.h
+++ b/src/imports/qmlwebsockets/qqmlwebsocket.h
@@ -83,10 +83,11 @@ public:
bool isActive() const;
Q_INVOKABLE qint64 sendTextMessage(const QString &message);
-
+ Q_REVISION(1) Q_INVOKABLE qint64 sendBinaryMessage(const QByteArray &message);
Q_SIGNALS:
void textMessageReceived(QString message);
+ Q_REVISION(1) void binaryMessageReceived(QByteArray message);
void statusChanged(Status status);
void activeChanged(bool isActive);
void errorStringChanged(QString errorString);
diff --git a/src/websockets/doc/src/qtwebsockets-module.qdoc b/src/websockets/doc/src/qtwebsockets-module.qdoc
index 6c717f4..971e22c 100644
--- a/src/websockets/doc/src/qtwebsockets-module.qdoc
+++ b/src/websockets/doc/src/qtwebsockets-module.qdoc
@@ -48,7 +48,7 @@
*/
/*!
- \qmlmodule QtWebSockets 1.0
+ \qmlmodule QtWebSockets 1.1
\title Qt WebSockets QML Types
\ingroup qmlmodules
\brief Provides QML types for WebSocket-based communication.
@@ -56,7 +56,7 @@
The QML types are accessed by using:
\code
- import QtWebSockets 1.0
+ import QtWebSockets 1.1
\endcode
\note Prior to Qt 5.5, the import statement was \c{import Qt.WebSockets 1.0}
diff --git a/src/websockets/qsslserver.cpp b/src/websockets/qsslserver.cpp
index 41db66a..5df59f7 100644
--- a/src/websockets/qsslserver.cpp
+++ b/src/websockets/qsslserver.cpp
@@ -119,6 +119,7 @@ void QSslServer::incomingConnection(qintptr socket)
connect(pSslSocket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors),
this, &QSslServer::sslErrors);
connect(pSslSocket, &QSslSocket::encrypted, this, &QSslServer::newEncryptedConnection);
+ connect(pSslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, this, &QSslServer::preSharedKeyAuthenticationRequired);
addPendingConnection(pSslSocket);
diff --git a/src/websockets/qsslserver_p.h b/src/websockets/qsslserver_p.h
index 538e3b5..d5e581a 100644
--- a/src/websockets/qsslserver_p.h
+++ b/src/websockets/qsslserver_p.h
@@ -54,6 +54,7 @@
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QSslError>
#include <QtNetwork/QSslConfiguration>
+#include <QtNetwork/QSslPreSharedKeyAuthenticator>
#include <QtCore/QList>
QT_BEGIN_NAMESPACE
@@ -74,6 +75,7 @@ Q_SIGNALS:
void sslErrors(const QList<QSslError> &errors);
void peerVerifyError(const QSslError &error);
void newEncryptedConnection();
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
protected:
virtual void incomingConnection(qintptr socket);
diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp
index 90973d6..ba343e4 100644
--- a/src/websockets/qwebsocket.cpp
+++ b/src/websockets/qwebsocket.cpp
@@ -239,6 +239,28 @@ not been filled in with new information when the signal returns.
QWebSocket::ignoreSslErrors() will have no effect.
*/
/*!
+ \fn void QWebSocket::preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
+ \since 5.8
+
+ This signal is emitted if the SSL/TLS handshake negotiates a PSK
+ ciphersuite, and therefore a PSK authentication is then required.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the SSL handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by the websocket and must not be
+ deleted by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+ \sa QSslSocket::preSharedKeyAuthenticationRequired()
+*/
+/*!
\fn void QWebSocket::pong(quint64 elapsedTime, const QByteArray &payload)
Emitted when a pong message is received in reply to a previous ping.
diff --git a/src/websockets/qwebsocket.h b/src/websockets/qwebsocket.h
index e6c2473..cbe53ca 100644
--- a/src/websockets/qwebsocket.h
+++ b/src/websockets/qwebsocket.h
@@ -142,6 +142,7 @@ Q_SIGNALS:
#ifndef QT_NO_SSL
void sslErrors(const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
#endif
private:
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index be8cb88..3a20b09 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -60,6 +60,7 @@
#ifndef QT_NO_SSL
#include <QtNetwork/QSslConfiguration>
#include <QtNetwork/QSslError>
+#include <QtNetwork/QSslPreSharedKeyAuthenticator>
#endif
#include <QtCore/QDebug>
@@ -592,6 +593,8 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
#ifndef QT_NO_SSL
const QSslSocket * const sslSocket = qobject_cast<const QSslSocket *>(pTcpSocket);
if (sslSocket) {
+ QObject::connect(sslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, q,
+ &QWebSocket::preSharedKeyAuthenticationRequired);
QObject::connect(sslSocket, &QSslSocket::encryptedBytesWritten, q,
&QWebSocket::bytesWritten);
typedef void (QSslSocket:: *sslErrorSignalType)(const QList<QSslError> &);
@@ -708,12 +711,11 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
bool lastFrame)
{
QByteArray header;
- quint8 byte = 0x00;
bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
if (Q_LIKELY(ok)) {
//FIN, RSV1-3, opcode (RSV-1, RSV-2 and RSV-3 are zero)
- byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00));
+ quint8 byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00));
header.append(static_cast<char>(byte));
byte = 0x00;
@@ -773,7 +775,6 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
if (Q_UNLIKELY(numFrames == 0))
numFrames = 1;
quint64 currentPosition = 0;
- qint64 bytesWritten = 0;
quint64 bytesLeft = data.size();
for (int i = 0; i < numFrames; ++i) {
@@ -789,7 +790,7 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
: QWebSocketProtocol::OpCodeContinue;
//write header
- bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
+ m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
//write payload
if (Q_LIKELY(size > 0)) {
@@ -798,7 +799,6 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
QWebSocketProtocol::mask(currentData, size, maskingKey);
qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
if (Q_LIKELY(written > 0)) {
- bytesWritten += written;
payloadWritten += written;
} else {
m_pSocket->flush();
@@ -881,7 +881,7 @@ qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame)
/*!
\internal
*/
-QString readLine(QTcpSocket *pSocket)
+static QString readLine(QTcpSocket *pSocket)
{
Q_ASSERT(pSocket);
QString line;
diff --git a/src/websockets/qwebsocketserver.cpp b/src/websockets/qwebsocketserver.cpp
index ab5da31..f8ecdf2 100644
--- a/src/websockets/qwebsocketserver.cpp
+++ b/src/websockets/qwebsocketserver.cpp
@@ -193,6 +193,29 @@
*/
/*!
+ \fn void QWebSocketServer::preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
+ \since 5.8
+
+ QWebSocketServer emits this signal when it negotiates a PSK ciphersuite, and
+ therefore a PSK authentication is then required.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the SSL handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by the socket and must not be
+ deleted by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+ \sa QSslSocket::preSharedKeyAuthenticationRequired()
+*/
+
+/*!
\enum QWebSocketServer::SslMode
Indicates whether the server operates over wss (SecureMode) or ws (NonSecureMode)
diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h
index 58a3d54..47113e4 100644
--- a/src/websockets/qwebsocketserver.h
+++ b/src/websockets/qwebsocketserver.h
@@ -128,6 +128,7 @@ Q_SIGNALS:
#ifndef QT_NO_SSL
void peerVerifyError(const QSslError &error);
void sslErrors(const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
#endif
void closed();
};
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 288c05b..91bfafc 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -104,6 +104,8 @@ void QWebSocketServerPrivate::init()
q_ptr, &QWebSocketServer::peerVerifyError);
QObject::connect(pSslServer, &QSslServer::sslErrors,
q_ptr, &QWebSocketServer::sslErrors);
+ QObject::connect(pSslServer, &QSslServer::preSharedKeyAuthenticationRequired,
+ q_ptr, &QWebSocketServer::preSharedKeyAuthenticationRequired);
}
#else
qFatal("SSL not supported on this platform.");
diff --git a/tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml b/tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml
index a8d3225..d0f19f6 100644
--- a/tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml
+++ b/tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml
@@ -27,7 +27,7 @@
****************************************************************************/
import QtQuick 2.5
-import QtWebSockets 1.0
+import QtWebSockets 1.1
import QtTest 1.1
Rectangle {
@@ -84,5 +84,28 @@ Rectangle {
socket.sendTextMessage('hello');
tryCompare(socket, 'status', WebSocket.Error);
}
+
+ function test_send_receive_binary() {
+ ensureConnected();
+
+ var o = {};
+ var sending = new Uint8Array([42, 43]);
+ server.currentSocket.binaryMessageReceived.connect(function(received) {
+ var view = new DataView(received);
+ compare(received.byteLength, sending.length);
+ compare(view.getUInt8(0), sending[0]);
+ compare(view.getUInt8(1), sending[1]);
+ o.called = true;
+ });
+
+ socket.sendBinaryMessage(sending.buffer);
+ tryCompare(o, 'called', true);
+ }
+
+ function test_send_binary_error_closed() {
+ ensureDisconnected();
+ socket.sendBinaryMessage('hello');
+ tryCompare(socket, 'status', WebSocket.Error);
+ }
}
}
diff --git a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
index fb3d5b8..699939f 100644
--- a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
+++ b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
@@ -28,6 +28,10 @@
#include <QString>
#include <QtTest>
#include <QNetworkProxy>
+#ifndef QT_NO_OPENSSL
+#include <QtNetwork/qsslpresharedkeyauthenticator.h>
+#include <QtNetwork/qsslcipher.h>
+#endif
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>
#include <QtWebSockets/QWebSocketCorsAuthenticator>
@@ -43,6 +47,47 @@ Q_DECLARE_METATYPE(QWebSocketCorsAuthenticator *)
Q_DECLARE_METATYPE(QSslError)
#endif
+#ifndef QT_NO_OPENSSL
+// Use this cipher to force PSK key sharing.
+static const QString PSK_CIPHER_WITHOUT_AUTH = QStringLiteral("PSK-AES256-CBC-SHA");
+static const QByteArray PSK_CLIENT_PRESHAREDKEY = QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f");
+static const QByteArray PSK_SERVER_IDENTITY_HINT = QByteArrayLiteral("QtTestServerHint");
+static const QByteArray PSK_CLIENT_IDENTITY = QByteArrayLiteral("Client_identity");
+
+class PskProvider : public QObject
+{
+ Q_OBJECT
+
+public:
+ bool m_server = false;
+ QByteArray m_identity;
+ QByteArray m_psk;
+
+public slots:
+ void providePsk(QSslPreSharedKeyAuthenticator *authenticator)
+ {
+ QVERIFY(authenticator);
+ QCOMPARE(authenticator->identityHint(), PSK_SERVER_IDENTITY_HINT);
+ if (m_server)
+ QCOMPARE(authenticator->maximumIdentityLength(), 0);
+ else
+ QVERIFY(authenticator->maximumIdentityLength() > 0);
+
+ QVERIFY(authenticator->maximumPreSharedKeyLength() > 0);
+
+ if (!m_identity.isEmpty()) {
+ authenticator->setIdentity(m_identity);
+ QCOMPARE(authenticator->identity(), m_identity);
+ }
+
+ if (!m_psk.isEmpty()) {
+ authenticator->setPreSharedKey(m_psk);
+ QCOMPARE(authenticator->preSharedKey(), m_psk);
+ }
+ }
+};
+#endif
+
class tst_QWebSocketServer : public QObject
{
Q_OBJECT
@@ -58,6 +103,7 @@ private Q_SLOTS:
void tst_settersAndGetters();
void tst_listening();
void tst_connectivity();
+ void tst_preSharedKey();
void tst_maxPendingConnections();
void tst_serverDestroyedWhileSocketConnected();
};
@@ -74,6 +120,9 @@ void tst_QWebSocketServer::init()
qRegisterMetaType<QWebSocketCorsAuthenticator *>("QWebSocketCorsAuthenticator *");
#ifndef QT_NO_SSL
qRegisterMetaType<QSslError>("QSslError");
+#ifndef QT_NO_OPENSSL
+ qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
+#endif
#endif
}
@@ -268,6 +317,84 @@ void tst_QWebSocketServer::tst_connectivity()
QCOMPARE(serverErrorSpy.count(), 0);
}
+void tst_QWebSocketServer::tst_preSharedKey()
+{
+#ifndef QT_NO_OPENSSL
+ QWebSocketServer server(QString(), QWebSocketServer::SecureMode);
+
+ bool cipherFound = false;
+ const QList<QSslCipher> supportedCiphers = QSslSocket::supportedCiphers();
+ for (const QSslCipher &cipher : supportedCiphers) {
+ if (cipher.name() == PSK_CIPHER_WITHOUT_AUTH) {
+ cipherFound = true;
+ break;
+ }
+ }
+
+ if (!cipherFound)
+ QSKIP("SSL implementation does not support the necessary cipher");
+
+ QSslCipher cipher(PSK_CIPHER_WITHOUT_AUTH);
+ QList<QSslCipher> list;
+ list << cipher;
+
+ QSslConfiguration config = QSslConfiguration::defaultConfiguration();
+ config.setCiphers(list);
+ config.setPeerVerifyMode(QSslSocket::VerifyNone);
+ config.setPreSharedKeyIdentityHint(PSK_SERVER_IDENTITY_HINT);
+ server.setSslConfiguration(config);
+
+ PskProvider providerServer;
+ providerServer.m_server = true;
+ providerServer.m_identity = PSK_CLIENT_IDENTITY;
+ providerServer.m_psk = PSK_CLIENT_PRESHAREDKEY;
+ connect(&server, &QWebSocketServer::preSharedKeyAuthenticationRequired, &providerServer, &PskProvider::providePsk);
+
+ QSignalSpy serverPskRequiredSpy(&server, &QWebSocketServer::preSharedKeyAuthenticationRequired);
+ QSignalSpy serverConnectionSpy(&server, &QWebSocketServer::newConnection);
+ QSignalSpy serverErrorSpy(&server,
+ SIGNAL(serverError(QWebSocketProtocol::CloseCode)));
+ QSignalSpy serverClosedSpy(&server, &QWebSocketServer::closed);
+ QSignalSpy sslErrorsSpy(&server, SIGNAL(sslErrors(QList<QSslError>)));
+
+ QWebSocket socket;
+ QSslConfiguration socketConfig = QSslConfiguration::defaultConfiguration();
+ socketConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ socketConfig.setCiphers(list);
+ socket.setSslConfiguration(socketConfig);
+
+ PskProvider providerClient;
+ providerClient.m_identity = PSK_CLIENT_IDENTITY;
+ providerClient.m_psk = PSK_CLIENT_PRESHAREDKEY;
+ connect(&socket, &QWebSocket::preSharedKeyAuthenticationRequired, &providerClient, &PskProvider::providePsk);
+ QSignalSpy socketPskRequiredSpy(&socket, &QWebSocket::preSharedKeyAuthenticationRequired);
+ QSignalSpy socketConnectedSpy(&socket, &QWebSocket::connected);
+
+ QVERIFY(server.listen());
+ QCOMPARE(server.serverAddress(), QHostAddress(QHostAddress::Any));
+ QCOMPARE(server.serverUrl(), QUrl(QString::asprintf("wss://%ls:%d",
+ qUtf16Printable(QHostAddress(QHostAddress::LocalHost).toString()), server.serverPort())));
+
+ socket.open(server.serverUrl().toString());
+
+ if (socketConnectedSpy.count() == 0)
+ QVERIFY(socketConnectedSpy.wait());
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(serverConnectionSpy.count(), 1);
+ QCOMPARE(serverPskRequiredSpy.count(), 1);
+ QCOMPARE(socketPskRequiredSpy.count(), 1);
+
+ QCOMPARE(serverClosedSpy.count(), 0);
+
+ server.close();
+
+ QVERIFY(serverClosedSpy.wait());
+ QCOMPARE(serverClosedSpy.count(), 1);
+ QCOMPARE(sslErrorsSpy.count(), 0);
+ QCOMPARE(serverErrorSpy.count(), 0);
+#endif
+}
+
void tst_QWebSocketServer::tst_maxPendingConnections()
{
//tests if maximum connections are respected