summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--dist/changes-5.10.022
-rw-r--r--examples/websockets/simplechat/chatclient.html15
-rw-r--r--examples/websockets/simplechat/chatserver.cpp40
-rw-r--r--examples/websockets/simplechat/chatserver.h8
-rw-r--r--examples/websockets/simplechat/main.cpp1
-rw-r--r--src/imports/qmlwebsockets/qqmlwebsocket.h2
-rw-r--r--src/websockets/qdefaultmaskgenerator_p.cpp18
-rw-r--r--src/websockets/qmaskgenerator.cpp2
-rw-r--r--src/websockets/qwebsocket.cpp4
-rw-r--r--src/websockets/qwebsocket_p.cpp2
-rw-r--r--src/websockets/qwebsocketserver.h3
-rw-r--r--tests/auto/qml/qml.pro3
-rw-r--r--tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro1
-rw-r--r--tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp57
-rw-r--r--tests/auto/websockets/websockets.pro3
16 files changed, 136 insertions, 47 deletions
diff --git a/.qmake.conf b/.qmake.conf
index e795316..08b8470 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.9.3
+MODULE_VERSION = 5.10.0
diff --git a/dist/changes-5.10.0 b/dist/changes-5.10.0
new file mode 100644
index 0000000..9ad0d80
--- /dev/null
+++ b/dist/changes-5.10.0
@@ -0,0 +1,22 @@
+Qt 5.10 introduces many new features and improvements as well as bugfixes
+over the 5.9.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.10 series is binary compatible with the 5.9.x series.
+Applications compiled for 5.9 will continue to run with 5.10.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.10.0 Changes *
+****************************************************************************
+
+ - This release contains only minor code improvements.
diff --git a/examples/websockets/simplechat/chatclient.html b/examples/websockets/simplechat/chatclient.html
index 511d05b..d2dbf47 100644
--- a/examples/websockets/simplechat/chatclient.html
+++ b/examples/websockets/simplechat/chatclient.html
@@ -5,17 +5,20 @@
<body>
<h1>WebSocket Chat Client</h1>
<p>
+ Host: <input id="webSocketHost" type="text" value="localhost:1234"/>
+ </p>
+ <p>
<button onClick="initWebSocket();">Connect</button>
- <button onClick="stopWebSocket();">Disconnect</button>
+ <button id="disconnectButton" onClick="stopWebSocket();" disabled>Disconnect</button>
<button onClick="checkSocket();">State</button>
</p>
<p>
- <textarea id="debugTextArea" style="width:400px;height:200px;"></textarea>
+ <textarea id="debugTextArea" style="width:400px;height:200px;" readonly></textarea>
</p>
<p>
<input type="text" id="inputNick" value="nickname" />
<input type="text" id="inputText" onkeydown="if(event.keyCode==13)sendMessage();"/>
- <button onClick="sendMessage();">Send</button>
+ <button id="sendButton" onClick="sendMessage();" disabled>Send</button>
</p>
<script type="text/javascript">
@@ -38,7 +41,6 @@
}
}
- var wsUri = "ws://localhost:1234";
var websocket = null;
function initWebSocket() {
@@ -47,12 +49,17 @@
WebSocket = MozWebSocket;
if ( websocket && websocket.readyState == 1 )
websocket.close();
+ var wsUri = "ws://" + document.getElementById("webSocketHost").value;
websocket = new WebSocket( wsUri );
websocket.onopen = function (evt) {
debug("CONNECTED");
+ document.getElementById("disconnectButton").disabled = false;
+ document.getElementById("sendButton").disabled = false;
};
websocket.onclose = function (evt) {
debug("DISCONNECTED");
+ document.getElementById("disconnectButton").disabled = true;
+ document.getElementById("sendButton").disabled = true;
};
websocket.onmessage = function (evt) {
console.log( "Message received :", evt.data );
diff --git a/examples/websockets/simplechat/chatserver.cpp b/examples/websockets/simplechat/chatserver.cpp
index ae207f5..8885fe8 100644
--- a/examples/websockets/simplechat/chatserver.cpp
+++ b/examples/websockets/simplechat/chatserver.cpp
@@ -48,23 +48,31 @@
**
****************************************************************************/
#include "chatserver.h"
-#include "QtWebSockets/QWebSocketServer"
-#include "QtWebSockets/QWebSocket"
-#include <QtCore/QDebug>
+
+#include <QtWebSockets>
+#include <QtCore>
+
+#include <cstdio>
+using namespace std;
QT_USE_NAMESPACE
+static QString getIdentifier(QWebSocket *peer)
+{
+ return QStringLiteral("%1:%2").arg(peer->peerAddress().toString(),
+ QString::number(peer->peerPort()));
+}
+
//! [constructor]
ChatServer::ChatServer(quint16 port, QObject *parent) :
QObject(parent),
- m_pWebSocketServer(Q_NULLPTR)
+ m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Chat Server"),
+ QWebSocketServer::NonSecureMode,
+ this))
{
- m_pWebSocketServer = new QWebSocketServer(QStringLiteral("Chat Server"),
- QWebSocketServer::NonSecureMode,
- this);
if (m_pWebSocketServer->listen(QHostAddress::Any, port))
{
- qDebug() << "Chat Server listening on port" << port;
+ QTextStream(stdout) << "Chat Server listening on port " << port << '\n';
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &ChatServer::onNewConnection);
}
@@ -73,31 +81,32 @@ ChatServer::ChatServer(quint16 port, QObject *parent) :
ChatServer::~ChatServer()
{
m_pWebSocketServer->close();
- qDeleteAll(m_clients.begin(), m_clients.end());
}
//! [constructor]
//! [onNewConnection]
void ChatServer::onNewConnection()
{
- QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
+ auto pSocket = m_pWebSocketServer->nextPendingConnection();
+ QTextStream(stdout) << getIdentifier(pSocket) << " connected!\n";
+ pSocket->setParent(this);
- connect(pSocket, &QWebSocket::textMessageReceived, this, &ChatServer::processMessage);
- connect(pSocket, &QWebSocket::disconnected, this, &ChatServer::socketDisconnected);
+ connect(pSocket, &QWebSocket::textMessageReceived,
+ this, &ChatServer::processMessage);
+ connect(pSocket, &QWebSocket::disconnected,
+ this, &ChatServer::socketDisconnected);
m_clients << pSocket;
}
//! [onNewConnection]
//! [processMessage]
-void ChatServer::processMessage(QString message)
+void ChatServer::processMessage(const QString &message)
{
QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
for (QWebSocket *pClient : qAsConst(m_clients)) {
if (pClient != pSender) //don't echo message back to sender
- {
pClient->sendTextMessage(message);
- }
}
}
//! [processMessage]
@@ -106,6 +115,7 @@ void ChatServer::processMessage(QString message)
void ChatServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+ QTextStream(stdout) << getIdentifier(pClient) << " disconnected!\n";
if (pClient)
{
m_clients.removeAll(pClient);
diff --git a/examples/websockets/simplechat/chatserver.h b/examples/websockets/simplechat/chatserver.h
index 4c652a3..4a8285b 100644
--- a/examples/websockets/simplechat/chatserver.h
+++ b/examples/websockets/simplechat/chatserver.h
@@ -52,21 +52,21 @@
#include <QtCore/QObject>
#include <QtCore/QList>
-#include <QtCore/QByteArray>
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
+QT_FORWARD_DECLARE_CLASS(QString)
class ChatServer : public QObject
{
Q_OBJECT
public:
- explicit ChatServer(quint16 port, QObject *parent = Q_NULLPTR);
+ explicit ChatServer(quint16 port, QObject *parent = nullptr);
virtual ~ChatServer();
-private Q_SLOTS:
+private slots:
void onNewConnection();
- void processMessage(QString message);
+ void processMessage(const QString &message);
void socketDisconnected();
private:
diff --git a/examples/websockets/simplechat/main.cpp b/examples/websockets/simplechat/main.cpp
index 0b1c753..a1ffb49 100644
--- a/examples/websockets/simplechat/main.cpp
+++ b/examples/websockets/simplechat/main.cpp
@@ -48,6 +48,7 @@
**
****************************************************************************/
#include <QtCore/QCoreApplication>
+
#include "chatserver.h"
int main(int argc, char *argv[])
diff --git a/src/imports/qmlwebsockets/qqmlwebsocket.h b/src/imports/qmlwebsockets/qqmlwebsocket.h
index c3a808f..8db435d 100644
--- a/src/imports/qmlwebsockets/qqmlwebsocket.h
+++ b/src/imports/qmlwebsockets/qqmlwebsocket.h
@@ -54,7 +54,6 @@ class QQmlWebSocket : public QObject, public QQmlParserStatus
Q_DISABLE_COPY(QQmlWebSocket)
Q_INTERFACES(QQmlParserStatus)
- Q_ENUMS(Status)
Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
@@ -73,6 +72,7 @@ public:
Closed = 3,
Error = 4
};
+ Q_ENUM(Status)
QUrl url() const;
void setUrl(const QUrl &url);
diff --git a/src/websockets/qdefaultmaskgenerator_p.cpp b/src/websockets/qdefaultmaskgenerator_p.cpp
index 1035e8f..7763868 100644
--- a/src/websockets/qdefaultmaskgenerator_p.cpp
+++ b/src/websockets/qdefaultmaskgenerator_p.cpp
@@ -48,7 +48,7 @@
malicious scripts to attack bad behaving proxies.
For more information about the importance of good masking,
see \l {"Talking to Yourself for Fun and Profit" by Lin-Shung Huang et al}.
- The default mask generator uses the cryptographically insecure qrand() function.
+ The default mask generator uses the reasonably secure QRandomGenerator::global()->generate() function.
The best measure against attacks mentioned in the document above,
is to use QWebSocket over a secure connection (\e wss://).
In general, always be careful to not have 3rd party script access to
@@ -58,8 +58,7 @@
*/
#include "qdefaultmaskgenerator_p.h"
-#include <QDateTime>
-#include <limits>
+#include <QRandomGenerator>
QT_BEGIN_NAMESPACE
@@ -83,25 +82,26 @@ QDefaultMaskGenerator::~QDefaultMaskGenerator()
}
/*!
- Seeds the QDefaultMaskGenerator using qsrand().
- When seed() is not called, no seed is used at all.
-
\internal
*/
bool QDefaultMaskGenerator::seed() Q_DECL_NOEXCEPT
{
- qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
return true;
}
/*!
- Generates a new random mask using the insecure qrand() method.
+ Generates a new random mask using the insecure QRandomGenerator::global()->generate() method.
\internal
*/
quint32 QDefaultMaskGenerator::nextMask() Q_DECL_NOEXCEPT
{
- return quint32((double(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
+ quint32 value = QRandomGenerator::global()->generate();
+ while (Q_UNLIKELY(value == 0)) {
+ // a mask of zero has a special meaning
+ value = QRandomGenerator::global()->generate();
+ }
+ return value;
}
QT_END_NAMESPACE
diff --git a/src/websockets/qmaskgenerator.cpp b/src/websockets/qmaskgenerator.cpp
index 064ada2..40f8594 100644
--- a/src/websockets/qmaskgenerator.cpp
+++ b/src/websockets/qmaskgenerator.cpp
@@ -50,7 +50,7 @@
malicious scripts from attacking badly behaving proxies.
For more information about the importance of good masking,
see \l {"Talking to Yourself for Fun and Profit" by Lin-Shung Huang et al}.
- By default QWebSocket uses the cryptographically insecure qrand() function.
+ By default QWebSocket uses the reasonably secure QRandomGenerator::global()->generate() function.
The best measure against attacks mentioned in the document above,
is to use QWebSocket over a secure connection (\e wss://).
In general, always be careful to not have 3rd party script access to
diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp
index ba343e4..de5ac22 100644
--- a/src/websockets/qwebsocket.cpp
+++ b/src/websockets/qwebsocket.cpp
@@ -63,8 +63,8 @@
In that case, non-secure WebSocket connections fail. The best way to mitigate against
this problem is to use WebSocket over a secure connection.
- \warning To generate masks, this implementation of WebSockets uses the cryptographically
- insecure qrand() function.
+ \warning To generate masks, this implementation of WebSockets uses the reasonably
+ secure QRandomGenerator::global()->generate() function.
For more information about the importance of good masking,
see \l {"Talking to Yourself for Fun and Profit" by Lin-Shung Huang et al}.
The best measure against attacks mentioned in the document above,
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index bee2afa..1d23c84 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -1014,7 +1014,7 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
if (!ok)
errorDescription =
QWebSocket::tr("Accept-Key received from server %1 does not match the client key %2.")
- .arg(acceptKey).arg(accept);
+ .arg(acceptKey, accept);
} else {
errorDescription =
QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h
index f846290..9dc286b 100644
--- a/src/websockets/qwebsocketserver.h
+++ b/src/websockets/qwebsocketserver.h
@@ -65,8 +65,6 @@ class Q_WEBSOCKETS_EXPORT QWebSocketServer : public QObject
Q_DISABLE_COPY(QWebSocketServer)
Q_DECLARE_PRIVATE(QWebSocketServer)
- Q_ENUMS(SslMode)
-
public:
enum SslMode {
#ifndef QT_NO_SSL
@@ -74,6 +72,7 @@ public:
#endif
NonSecureMode = 1
};
+ Q_ENUM(SslMode)
explicit QWebSocketServer(const QString &serverName, SslMode secureMode,
QObject *parent = Q_NULLPTR);
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 2d2fde4..8951c55 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -1,6 +1,3 @@
TEMPLATE = subdirs
!uikit: SUBDIRS += qmlwebsockets qmlwebsockets_compat
-
-# QTBUG-60268
-boot2qt: SUBDIRS -= qmlwebsockets_compat
diff --git a/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro b/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
index e166f50..178fd88 100644
--- a/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
+++ b/tests/auto/websockets/qwebsocketserver/qwebsocketserver.pro
@@ -12,3 +12,4 @@ SOURCES += tst_qwebsocketserver.cpp
RESOURCES += $$PWD/../shared/qwebsocketshared.qrc
+boot2qt: DEFINES += SHOULD_CHECK_SYSCALL_SUPPORT
diff --git a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
index b7734a4..8a3760d 100644
--- a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
+++ b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
@@ -112,9 +112,15 @@ private Q_SLOTS:
void tst_serverDestroyedWhileSocketConnected();
void tst_scheme(); // qtbug-55927
void tst_handleConnection();
+
+private:
+ bool m_shouldSkipUnsupportedIpv6Test;
+#ifdef SHOULD_CHECK_SYSCALL_SUPPORT
+ bool ipv6GetsockoptionMissing(int level, int optname);
+#endif
};
-tst_QWebSocketServer::tst_QWebSocketServer()
+tst_QWebSocketServer::tst_QWebSocketServer() : m_shouldSkipUnsupportedIpv6Test(false)
{
}
@@ -132,8 +138,42 @@ void tst_QWebSocketServer::init()
#endif
}
+#ifdef SHOULD_CHECK_SYSCALL_SUPPORT
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+
+bool tst_QWebSocketServer::ipv6GetsockoptionMissing(int level, int optname)
+{
+ int testSocket;
+
+ testSocket = socket(PF_INET6, SOCK_STREAM, 0);
+
+ // If we can't test here, assume it's not missing
+ if (testSocket == -1)
+ return false;
+
+ bool result = false;
+ if (getsockopt(testSocket, level, optname, nullptr, 0) == -1) {
+ if (errno == EOPNOTSUPP) {
+ result = true;
+ }
+ }
+
+ close(testSocket);
+ return result;
+}
+
+#endif //SHOULD_CHECK_SYSCALL_SUPPORT
+
void tst_QWebSocketServer::initTestCase()
{
+#ifdef SHOULD_CHECK_SYSCALL_SUPPORT
+ // Qemu does not have required support for IPV6 socket options.
+ // If this is detected, skip the test
+ m_shouldSkipUnsupportedIpv6Test = ipv6GetsockoptionMissing(SOL_IPV6, IPV6_V6ONLY);
+#endif
}
void tst_QWebSocketServer::cleanupTestCase()
@@ -283,6 +323,9 @@ void tst_QWebSocketServer::tst_listening()
void tst_QWebSocketServer::tst_connectivity()
{
+ if (m_shouldSkipUnsupportedIpv6Test)
+ QSKIP("Syscalls needed for ipv6 sockoptions missing functionality");
+
QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
QSignalSpy serverConnectionSpy(&server, SIGNAL(newConnection()));
QSignalSpy serverErrorSpy(&server,
@@ -323,6 +366,9 @@ void tst_QWebSocketServer::tst_connectivity()
void tst_QWebSocketServer::tst_preSharedKey()
{
+ if (m_shouldSkipUnsupportedIpv6Test)
+ QSKIP("Syscalls needed for ipv6 sockoptions missing functionality");
+
#ifndef QT_NO_OPENSSL
QWebSocketServer server(QString(), QWebSocketServer::SecureMode);
@@ -399,6 +445,9 @@ void tst_QWebSocketServer::tst_preSharedKey()
void tst_QWebSocketServer::tst_maxPendingConnections()
{
+ if (m_shouldSkipUnsupportedIpv6Test)
+ QSKIP("Syscalls needed for ipv6 sockoptions missing functionality");
+
//tests if maximum connections are respected
//also checks if there are no side-effects like signals that are unexpectedly thrown
QWebSocketServer server(QString(), QWebSocketServer::NonSecureMode);
@@ -474,6 +523,9 @@ void tst_QWebSocketServer::tst_maxPendingConnections()
void tst_QWebSocketServer::tst_serverDestroyedWhileSocketConnected()
{
+ if (m_shouldSkipUnsupportedIpv6Test)
+ QSKIP("Syscalls needed for ipv6 sockoptions missing functionality");
+
QWebSocketServer * server = new QWebSocketServer(QString(), QWebSocketServer::NonSecureMode);
QSignalSpy serverConnectionSpy(server, SIGNAL(newConnection()));
QSignalSpy corsAuthenticationSpy(server,
@@ -505,6 +557,9 @@ void tst_QWebSocketServer::tst_serverDestroyedWhileSocketConnected()
void tst_QWebSocketServer::tst_scheme()
{
+ if (m_shouldSkipUnsupportedIpv6Test)
+ QSKIP("Syscalls needed for ipv6 sockoptions missing functionality");
+
QWebSocketServer plainServer(QString(), QWebSocketServer::NonSecureMode);
QSignalSpy plainServerConnectionSpy(&plainServer, SIGNAL(newConnection()));
diff --git a/tests/auto/websockets/websockets.pro b/tests/auto/websockets/websockets.pro
index 4b7ee4e..b000229 100644
--- a/tests/auto/websockets/websockets.pro
+++ b/tests/auto/websockets/websockets.pro
@@ -14,6 +14,3 @@ qtConfig(private_tests): SUBDIRS += \
SUBDIRS += \
qwebsocket \
qwebsocketserver
-
-# QTBUG-60268
-boot2qt: SUBDIRS -= qwebsocketserver