summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf3
-rw-r--r--examples/websockets/echoserver/echoserver.cpp1
-rw-r--r--examples/websockets/simplechat/chatserver.cpp6
-rw-r--r--examples/websockets/sslechoclient/sslechoclient.cpp3
-rw-r--r--examples/websockets/sslechoserver/sslechoserver.cpp4
-rw-r--r--examples/websockets/websockets.pro3
-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/qmlwebsockets_plugin.h2
-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.cpp31
-rw-r--r--src/websockets/qwebsocket_p.h2
-rw-r--r--src/websockets/qwebsockethandshakeresponse.cpp2
-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--src/websockets/websockets.pro2
-rw-r--r--tests/auto/qml/qmlwebsockets/tst_qmlwebsockets.qml25
-rw-r--r--tests/auto/websockets/dataprocessor/dataprocessor.pro2
-rw-r--r--tests/auto/websockets/handshakerequest/handshakerequest.pro2
-rw-r--r--tests/auto/websockets/handshakeresponse/handshakeresponse.pro2
-rw-r--r--tests/auto/websockets/qdefaultmaskgenerator/qdefaultmaskgenerator.pro2
-rw-r--r--tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp127
-rw-r--r--tests/auto/websockets/websocketframe/websocketframe.pro2
-rw-r--r--tests/auto/websockets/websocketprotocol/websocketprotocol.pro2
-rw-r--r--tests/auto/websockets/websockets.pro2
-rw-r--r--tests/manual/websockets/tst_websockets.cpp5
34 files changed, 282 insertions, 51 deletions
diff --git a/.qmake.conf b/.qmake.conf
index f068d13..d1e1c4c 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,5 +1,6 @@
load(qt_build_config)
CONFIG += warning_clean
+DEFINES += QT_NO_FOREACH
-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..ae207f5 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,
@@ -94,8 +93,7 @@ void ChatServer::onNewConnection()
void ChatServer::processMessage(QString message)
{
QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
- Q_FOREACH (QWebSocket *pClient, m_clients)
- {
+ for (QWebSocket *pClient : qAsConst(m_clients)) {
if (pClient != pSender) //don't echo message back to sender
{
pClient->sendTextMessage(message);
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/examples/websockets/websockets.pro b/examples/websockets/websockets.pro
index e5eddf6..fa6c0c0 100644
--- a/examples/websockets/websockets.pro
+++ b/examples/websockets/websockets.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += network
SUBDIRS = echoclient \
echoserver \
@@ -9,7 +10,7 @@ SUBDIRS += qmlwebsocketclient \
qmlwebsocketserver
}
-contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
+qtConfig(ssl) {
SUBDIRS += \
sslechoserver \
sslechoclient
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/qmlwebsockets_plugin.h b/src/imports/qmlwebsockets/qmlwebsockets_plugin.h
index 318e0c7..749d830 100644
--- a/src/imports/qmlwebsockets/qmlwebsockets_plugin.h
+++ b/src/imports/qmlwebsockets/qmlwebsockets_plugin.h
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QtWebSocketsDeclarativeModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtWebSocketsDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
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..8f55e24 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>
@@ -304,11 +305,9 @@ QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket,
QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.acceptedVersion(), parent);
if (Q_LIKELY(pWebSocket)) {
QNetworkRequest netRequest(request.requestUrl());
- QMapIterator<QString, QString> headerIter(request.headers());
- while (headerIter.hasNext()) {
- headerIter.next();
- netRequest.setRawHeader(headerIter.key().toLatin1(), headerIter.value().toLatin1());
- }
+ const auto headers = request.headers();
+ for (auto it = headers.begin(), end = headers.end(); it != end; ++it)
+ netRequest.setRawHeader(it.key().toLatin1(), it.value().toLatin1());
#ifndef QT_NO_SSL
if (QSslSocket *sslSock = qobject_cast<QSslSocket *>(pTcpSocket))
pWebSocket->setSslConfiguration(sslSock->sslConfiguration());
@@ -592,6 +591,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 +709,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 +773,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 +788,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 +797,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 +879,7 @@ qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame)
/*!
\internal
*/
-QString readLine(QTcpSocket *pSocket)
+static QString readLine(QTcpSocket *pSocket)
{
Q_ASSERT(pSocket);
QString line;
@@ -1087,7 +1085,8 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
m_key = generateKey();
QList<QPair<QString, QString> > headers;
- foreach (const QByteArray &key, m_request.rawHeaderList())
+ const auto keys = m_request.rawHeaderList();
+ for (const QByteArray &key : keys)
headers << qMakePair(QString::fromLatin1(key),
QString::fromLatin1(m_request.rawHeader(key)));
@@ -1203,7 +1202,7 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
QString extensions,
QString protocols,
QByteArray key,
- QList<QPair<QString, QString> > headers)
+ const QList<QPair<QString, QString> > &headers)
{
QStringList handshakeRequest;
if (resourceName.contains(QStringLiteral("\r\n"))) {
@@ -1246,11 +1245,9 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
if (protocols.length() > 0)
handshakeRequest << QStringLiteral("Sec-WebSocket-Protocol: ") % protocols;
- QListIterator<QPair<QString, QString> > headerIter(headers);
- while (headerIter.hasNext()) {
- const QPair<QString,QString> &header = headerIter.next();
+ for (const auto &header : headers)
handshakeRequest << header.first % QStringLiteral(": ") % header.second;
- }
+
handshakeRequest << QStringLiteral("\r\n");
return handshakeRequest.join(QStringLiteral("\r\n"));
diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h
index 139c7ff..4863de7 100644
--- a/src/websockets/qwebsocket_p.h
+++ b/src/websockets/qwebsocket_p.h
@@ -193,7 +193,7 @@ private:
QString extensions,
QString protocols,
QByteArray key,
- QList<QPair<QString, QString> > headers);
+ const QList<QPair<QString, QString> > &headers);
static QWebSocket *upgradeFrom(QTcpSocket *tcpSocket,
const QWebSocketHandshakeRequest &request,
diff --git a/src/websockets/qwebsockethandshakeresponse.cpp b/src/websockets/qwebsockethandshakeresponse.cpp
index b5e1052..ee57d5c 100644
--- a/src/websockets/qwebsockethandshakeresponse.cpp
+++ b/src/websockets/qwebsockethandshakeresponse.cpp
@@ -207,7 +207,7 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(
if (Q_UNLIKELY(!m_canUpgrade)) {
response << QStringLiteral("HTTP/1.1 400 Bad Request");
QStringList versions;
- Q_FOREACH (QWebSocketProtocol::Version version, supportedVersions)
+ for (QWebSocketProtocol::Version version : supportedVersions)
versions << QString::number(static_cast<int>(version));
response << QStringLiteral("Sec-WebSocket-Version: ")
% versions.join(QStringLiteral(", "));
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/src/websockets/websockets.pro b/src/websockets/websockets.pro
index b9a513b..e4366ba 100644
--- a/src/websockets/websockets.pro
+++ b/src/websockets/websockets.pro
@@ -40,7 +40,7 @@ SOURCES += \
$$PWD/qmaskgenerator.cpp \
$$PWD/qdefaultmaskgenerator_p.cpp
-contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
+qtConfig(ssl) {
SOURCES += $$PWD/qsslserver.cpp
PRIVATE_HEADERS += $$PWD/qsslserver_p.h
}
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/dataprocessor/dataprocessor.pro b/tests/auto/websockets/dataprocessor/dataprocessor.pro
index 41fc91f..ad99900 100644
--- a/tests/auto/websockets/dataprocessor/dataprocessor.pro
+++ b/tests/auto/websockets/dataprocessor/dataprocessor.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_dataprocessor.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
diff --git a/tests/auto/websockets/handshakerequest/handshakerequest.pro b/tests/auto/websockets/handshakerequest/handshakerequest.pro
index 6a373b8..aa7779e 100644
--- a/tests/auto/websockets/handshakerequest/handshakerequest.pro
+++ b/tests/auto/websockets/handshakerequest/handshakerequest.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_handshakerequest.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
diff --git a/tests/auto/websockets/handshakeresponse/handshakeresponse.pro b/tests/auto/websockets/handshakeresponse/handshakeresponse.pro
index 9e23c46..ab6682b 100644
--- a/tests/auto/websockets/handshakeresponse/handshakeresponse.pro
+++ b/tests/auto/websockets/handshakeresponse/handshakeresponse.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_handshakeresponse.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
diff --git a/tests/auto/websockets/qdefaultmaskgenerator/qdefaultmaskgenerator.pro b/tests/auto/websockets/qdefaultmaskgenerator/qdefaultmaskgenerator.pro
index e284bc5..c3b1046 100644
--- a/tests/auto/websockets/qdefaultmaskgenerator/qdefaultmaskgenerator.pro
+++ b/tests/auto/websockets/qdefaultmaskgenerator/qdefaultmaskgenerator.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_defaultmaskgenerator.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
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
diff --git a/tests/auto/websockets/websocketframe/websocketframe.pro b/tests/auto/websockets/websocketframe/websocketframe.pro
index df9c910..8f58302 100644
--- a/tests/auto/websockets/websocketframe/websocketframe.pro
+++ b/tests/auto/websockets/websocketframe/websocketframe.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_websocketframe.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
diff --git a/tests/auto/websockets/websocketprotocol/websocketprotocol.pro b/tests/auto/websockets/websocketprotocol/websocketprotocol.pro
index 8ee7ff9..27748a9 100644
--- a/tests/auto/websockets/websocketprotocol/websocketprotocol.pro
+++ b/tests/auto/websockets/websocketprotocol/websocketprotocol.pro
@@ -10,4 +10,4 @@ QT = core testlib websockets websockets-private
SOURCES += tst_websocketprotocol.cpp
-requires(contains(QT_CONFIG, private_tests))
+requires(qtConfig(private_tests))
diff --git a/tests/auto/websockets/websockets.pro b/tests/auto/websockets/websockets.pro
index 4698cd0..b000229 100644
--- a/tests/auto/websockets/websockets.pro
+++ b/tests/auto/websockets/websockets.pro
@@ -3,7 +3,7 @@ TEMPLATE = subdirs
SUBDIRS = \
qwebsocketcorsauthenticator
-contains(QT_CONFIG, private_tests): SUBDIRS += \
+qtConfig(private_tests): SUBDIRS += \
websocketprotocol \
dataprocessor \
websocketframe \
diff --git a/tests/manual/websockets/tst_websockets.cpp b/tests/manual/websockets/tst_websockets.cpp
index 8568532..6b327aa 100644
--- a/tests/manual/websockets/tst_websockets.cpp
+++ b/tests/manual/websockets/tst_websockets.cpp
@@ -152,12 +152,11 @@ void tst_WebSocketsTest::testLocalAddress()
void tst_WebSocketsTest::testPeerAddress()
{
QHostInfo hostInfo = QHostInfo::fromName(m_url.host());
- QList<QHostAddress> addresses = hostInfo.addresses();
+ const QList<QHostAddress> addresses = hostInfo.addresses();
QVERIFY(addresses.length() > 0);
QHostAddress peer = m_pWebSocket->peerAddress();
bool found = false;
- Q_FOREACH (const QHostAddress &a, addresses)
- {
+ for (const QHostAddress &a : addresses) {
if (a == peer)
{
found = true;