Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qt6-websockets for openSUSE:Factory 
checked in at 2026-10-18 19:21:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qt6-websockets (Old)
 and      /work/SRC/openSUSE:Factory/.qt6-websockets.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qt6-websockets"

Sun Oct 18 19:21:46 2026 rev:37 rq:1384423 version:6.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/qt6-websockets/qt6-websockets.changes    
2026-08-21 16:52:51.959999577 +0200
+++ 
/work/SRC/openSUSE:Factory/.qt6-websockets.new.3698736/qt6-websockets.changes   
    2026-10-18 19:22:02.949589091 +0200
@@ -1,0 +2,6 @@
+Wed Sep 30 16:15:38 UTC 2026 - Christophe Marin <[email protected]>
+
+- Update to 6.12.0
+  https://www.qt.io/blog/qt-6.12-released
+
+-------------------------------------------------------------------

Old:
----
  qtwebsockets-everywhere-src-6.11.2.tar.xz

New:
----
  qtwebsockets-everywhere-src-6.12.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qt6-websockets.spec ++++++
--- /var/tmp/diff_new_pack.jJauIB/_old  2026-10-18 19:22:04.406649498 +0200
+++ /var/tmp/diff_new_pack.jJauIB/_new  2026-10-18 19:22:04.411649705 +0200
@@ -16,8 +16,8 @@
 #
 
 
-%define real_version 6.11.2
-%define short_version 6.11
+%define real_version 6.12.0
+%define short_version 6.12
 %define tar_name qtwebsockets-everywhere-src
 %define tar_suffix %{nil}
 #
@@ -27,7 +27,7 @@
 %endif
 #
 Name:           qt6-websockets%{?pkg_suffix}
-Version:        6.11.2
+Version:        6.12.0
 Release:        0
 Summary:        Qt 6 WebSockets library
 License:        GPL-2.0-only OR GPL-3.0-or-later OR LGPL-3.0-only

++++++ qtwebsockets-everywhere-src-6.11.2.tar.xz -> 
qtwebsockets-everywhere-src-6.12.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/.cmake.conf 
new/qtwebsockets-everywhere-src-6.12.0/.cmake.conf
--- old/qtwebsockets-everywhere-src-6.11.2/.cmake.conf  2026-08-12 
03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/.cmake.conf  2026-09-27 
10:15:31.000000000 +0200
@@ -1,4 +1,4 @@
-set(QT_REPO_MODULE_VERSION "6.11.2")
+set(QT_REPO_MODULE_VERSION "6.12.0")
 set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
 set(QT_EXTRA_INTERNAL_TARGET_DEFINES
     "QT_NO_CONTEXTLESS_CONNECT=1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/.tag 
new/qtwebsockets-everywhere-src-6.12.0/.tag
--- old/qtwebsockets-everywhere-src-6.11.2/.tag 2026-08-12 03:33:36.000000000 
+0200
+++ new/qtwebsockets-everywhere-src-6.12.0/.tag 2026-09-27 10:15:31.000000000 
+0200
@@ -1 +1 @@
-3eab06de7076a83514e98c2403baa433d137b013
+6aedb199b5d8ee4afa4cfc956ded22bc0a2632e9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/CONTRIBUTING.md 
new/qtwebsockets-everywhere-src-6.12.0/CONTRIBUTING.md
--- old/qtwebsockets-everywhere-src-6.11.2/CONTRIBUTING.md      1970-01-01 
01:00:00.000000000 +0100
+++ new/qtwebsockets-everywhere-src-6.12.0/CONTRIBUTING.md      2026-09-27 
10:15:31.000000000 +0200
@@ -0,0 +1,11 @@
+## Qt contribution guidelines
+
+We welcome contributions to Qt!
+
+Note that we cannot accept pull requests on GitHub. All contributions
+to the Qt project are exclusively handled through the
+[Gerrit code review system](https://codereview.qt-project.org).
+
+See
+[contribute.qt-project.org](https://contribute.qt-project.org/) to learn
+more.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/REUSE.toml 
new/qtwebsockets-everywhere-src-6.12.0/REUSE.toml
--- old/qtwebsockets-everywhere-src-6.11.2/REUSE.toml   2026-08-12 
03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/REUSE.toml   2026-09-27 
10:15:31.000000000 +0200
@@ -36,7 +36,7 @@
 SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
 
 [[annotations]]
-path = ["**/doc/images/**", "**/README*", "**.qdocconf"]
+path = ["**/doc/images/**", "**/README*", "**.qdocconf", "CONTRIBUTING.md"]
 comment = "documentation"
 precedence = "closest"
 SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/dependencies.yaml 
new/qtwebsockets-everywhere-src-6.12.0/dependencies.yaml
--- old/qtwebsockets-everywhere-src-6.11.2/dependencies.yaml    2026-08-12 
03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/dependencies.yaml    2026-09-27 
10:15:31.000000000 +0200
@@ -1,7 +1,7 @@
 dependencies:
   ../qtbase:
-    ref: ef55f427f2c8b410d34f8a7681020a3000cf6866
+    ref: 025bdad181de241e81bf853c8a2d7bf3d19261a9
     required: true
   ../qtdeclarative:
-    ref: 4e3399c26ec57246c08de019cfcbda8d23604cfa
+    ref: 4332fbbb4c340463dc8cee36dda0c85d932122d8
     required: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qtwebsockets-everywhere-src-6.11.2/licenseRule.json 
new/qtwebsockets-everywhere-src-6.12.0/licenseRule.json
--- old/qtwebsockets-everywhere-src-6.11.2/licenseRule.json     2026-08-12 
03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/licenseRule.json     2026-09-27 
10:15:31.000000000 +0200
@@ -59,7 +59,7 @@
     {
         "comment": "Files with the following endings are Documentation 
licensed.",
         "file_pattern_ending": [".qdoc", ".qdocinc" , ".qdocconf", "README", 
"qt_attribution.json",
-                                 "README.md"],
+                                 "README.md", "CONTRIBUTING.md"],
         "location":{
             "": {
                 "comment": "",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qmaskgenerator.h 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qmaskgenerator.h
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qmaskgenerator.h      
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qmaskgenerator.h      
2026-09-27 10:15:31.000000000 +0200
@@ -6,7 +6,7 @@
 #define QMASKGENERATOR_H
 
 #include <QtCore/QObject>
-#include "QtWebSockets/qwebsockets_global.h"
+#include <QtWebSockets/qwebsockets_global.h>
 
 QT_BEGIN_NAMESPACE
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket.h 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket.h
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket.h  
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket.h  
2026-09-27 10:15:31.000000000 +0200
@@ -15,8 +15,8 @@
 #include <QtNetwork/QSslError>
 #include <QtNetwork/QSslConfiguration>
 #endif
-#include "QtWebSockets/qwebsockets_global.h"
-#include "QtWebSockets/qwebsocketprotocol.h"
+#include <QtWebSockets/qwebsockets_global.h>
+#include <QtWebSockets/qwebsocketprotocol.h>
 
 #include <QtCore/qobject.h>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket_p.cpp 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket_p.cpp
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket_p.cpp      
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket_p.cpp      
2026-09-27 10:15:31.000000000 +0200
@@ -389,54 +389,7 @@
  */
 void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString 
reason)
 {
-    if (Q_UNLIKELY(!m_pSocket))
-        return;
-    Q_Q(QWebSocket);
-    if (!m_isClosingHandshakeSent) {
-        m_closeCode = closeCode;
-        // 125 is the maximum length of a control frame, and 2 bytes are used 
for the close code:
-        const QByteArray reasonUtf8 = reason.toUtf8().left(123);
-        m_closeReason = QString::fromUtf8(reasonUtf8);
-        const quint16 code = qToBigEndian<quint16>(closeCode);
-        QByteArray payload;
-        payload.append(static_cast<const char *>(static_cast<const void 
*>(&code)), 2);
-        if (!reasonUtf8.isEmpty())
-            payload.append(reasonUtf8);
-        quint32 maskingKey = 0;
-        if (m_mustMask) {
-            maskingKey = generateMaskingKey();
-            QWebSocketProtocol::mask(payload.data(), quint64(payload.size()), 
maskingKey);
-        }
-        QByteArray frame = getFrameHeader(QWebSocketProtocol::OpCodeClose,
-                                          quint64(payload.size()), maskingKey, 
true);
-
-        Q_ASSERT(payload.size() <= 125);
-        frame.append(payload);
-        m_pSocket->write(frame);
-        m_pSocket->flush();
-
-        m_isClosingHandshakeSent = true;
-
-        Q_EMIT q->aboutToClose();
-    }
-    static constexpr auto closeTimerName = "_closeTimer"_L1;
-    if (!m_isClosingHandshakeReceived) {
-        QTimer *closeTimer = new QTimer(q);
-        closeTimer->setObjectName(closeTimerName);
-        closeTimer->setInterval(3000);
-        closeTimer->setSingleShot(true);
-        QObject::connect(q, &QWebSocket::disconnected, closeTimer, 
&QTimer::stop);
-        QObject::connect(q, &QWebSocket::disconnected, closeTimer, 
&QTimer::deleteLater);
-        QObject::connect(closeTimer, &QTimer::timeout, m_pSocket, 
&QTcpSocket::close);
-        QObject::connect(closeTimer, &QTimer::timeout, closeTimer, 
&QTimer::deleteLater);
-        closeTimer->start();
-    } else {
-        m_pSocket->close();
-        if (QTimer *closeTimer = q->findChild<QTimer *>(closeTimerName)) {
-            closeTimer->stop();
-            delete closeTimer;
-        }
-    }
+    doClose(closeCode, reason, false);
 }
 
 /*!
@@ -721,7 +674,7 @@
     QObject::connect(m_dataProcessor, 
&QWebSocketDataProcessor::textMessageReceived, q,
                      &QWebSocket::textMessageReceived);
     QObjectPrivate::connect(m_dataProcessor, 
&QWebSocketDataProcessor::errorEncountered, this,
-                            &QWebSocketPrivate::close);
+                            &QWebSocketPrivate::processError);
     QObjectPrivate::connect(m_dataProcessor, 
&QWebSocketDataProcessor::pingReceived, this,
                             &QWebSocketPrivate::processPing);
     QObjectPrivate::connect(m_dataProcessor, 
&QWebSocketDataProcessor::pongReceived, this,
@@ -1348,6 +1301,71 @@
     }
 }
 
+/*!
+    \internal
+
+    Sends the Close frame and then either closes the connection or waits for 
the
+    peer to do so. \a isFailed tells whether we are failing the connection as
+    described in RFC 6455 paragraph 7.1.7, in which case the transport is 
closed
+    right away instead.
+ */
+void QWebSocketPrivate::doClose(QWebSocketProtocol::CloseCode closeCode,
+                                QString reason, bool isFailed)
+{
+    if (Q_UNLIKELY(!m_pSocket))
+        return;
+    Q_Q(QWebSocket);
+    if (!m_isClosingHandshakeSent) {
+        m_closeCode = closeCode;
+        // 125 is the maximum length of a control frame, and 2 bytes are used 
for the close code:
+        const QByteArray reasonUtf8 = reason.toUtf8().left(123);
+        m_closeReason = QString::fromUtf8(reasonUtf8);
+        const quint16 code = qToBigEndian<quint16>(closeCode);
+        QByteArray payload;
+        payload.append(static_cast<const char *>(static_cast<const void 
*>(&code)), 2);
+        if (!reasonUtf8.isEmpty())
+            payload.append(reasonUtf8);
+        quint32 maskingKey = 0;
+        if (m_mustMask) {
+            maskingKey = generateMaskingKey();
+            QWebSocketProtocol::mask(payload.data(), quint64(payload.size()), 
maskingKey);
+        }
+        QByteArray frame = getFrameHeader(QWebSocketProtocol::OpCodeClose,
+                                          quint64(payload.size()), maskingKey, 
true);
+
+        Q_ASSERT(payload.size() <= 125);
+        frame.append(payload);
+        m_pSocket->write(frame);
+        m_pSocket->flush();
+
+        m_isClosingHandshakeSent = true;
+
+        Q_EMIT q->aboutToClose();
+    }
+
+    static constexpr auto closeTimerName = "_closeTimer"_L1;
+    const bool waitForPeer = !m_isClosingHandshakeReceived && !isFailed;
+    if (waitForPeer) {
+        if (q->findChild<QTimer *>(closeTimerName))
+            return;
+        QTimer *closeTimer = new QTimer(q);
+        closeTimer->setObjectName(closeTimerName);
+        closeTimer->setInterval(3000);
+        closeTimer->setSingleShot(true);
+        QObject::connect(q, &QWebSocket::disconnected, closeTimer, 
&QTimer::stop);
+        QObject::connect(q, &QWebSocket::disconnected, closeTimer, 
&QTimer::deleteLater);
+        QObject::connect(closeTimer, &QTimer::timeout, m_pSocket, 
&QTcpSocket::close);
+        QObject::connect(closeTimer, &QTimer::timeout, closeTimer, 
&QTimer::deleteLater);
+        closeTimer->start();
+    } else {
+        m_pSocket->close();
+        if (QTimer *closeTimer = q->findChild<QTimer *>(closeTimerName)) {
+            closeTimer->stop();
+            delete closeTimer;
+        }
+    }
+}
+
 void QWebSocketPrivate::socketDestroyed(QObject *socket)
 {
     Q_ASSERT(m_pSocket);
@@ -1418,6 +1436,18 @@
 }
 
 /*!
+    \internal
+
+    Fails the connection as described in RFC 6455 paragraph 7.1.7: send a Close
+    frame, then close the connection straight away. No reply can be processed
+    afterwards, so neither endpoint has anything to wait for.
+ */
+void QWebSocketPrivate::processError(QWebSocketProtocol::CloseCode closeCode, 
QString reason)
+{
+    doClose(closeCode, reason, true);
+}
+
+/*!
     \internal
  */
 QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket_p.h 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket_p.h
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocket_p.h        
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocket_p.h        
2026-09-27 10:15:31.000000000 +0200
@@ -167,9 +167,12 @@
     void processPing(const QByteArray &data);
     void processPong(const QByteArray &data);
     void processClose(QWebSocketProtocol::CloseCode closeCode, QString 
closeReason);
+    void processError(QWebSocketProtocol::CloseCode closeCode, QString reason);
     void processHandshake(QTcpSocket *pSocket);
     void processStateChanged(QAbstractSocket::SocketState socketState);
 
+    void doClose(QWebSocketProtocol::CloseCode closeCode, QString reason, bool 
isFailed);
+
     Q_REQUIRED_RESULT qint64 doWriteFrames(const QByteArray &data, bool 
isBinary);
 
     void makeConnections(QTcpSocket *pTcpSocket);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketcorsauthenticator.h
 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketcorsauthenticator.h
--- 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketcorsauthenticator.h
 2026-08-12 03:33:36.000000000 +0200
+++ 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketcorsauthenticator.h
 2026-09-27 10:15:31.000000000 +0200
@@ -4,7 +4,7 @@
 #ifndef QWEBSOCKETCORSAUTHENTICATOR_H
 #define QWEBSOCKETCORSAUTHENTICATOR_H
 
-#include "QtWebSockets/qwebsockets_global.h"
+#include <QtWebSockets/qwebsockets_global.h>
 #include <memory>
 
 QT_BEGIN_NAMESPACE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketdataprocessor.cpp
 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketdataprocessor.cpp
--- 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketdataprocessor.cpp
   2026-08-12 03:33:36.000000000 +0200
+++ 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketdataprocessor.cpp
   2026-09-27 10:15:31.000000000 +0200
@@ -134,6 +134,9 @@
  */
 bool QWebSocketDataProcessor::process(QIODevice *pIoDevice)
 {
+    if (Q_UNLIKELY(m_hasFailed))
+        return false;
+
     bool isDone = false;
 
     while (!isDone) {
@@ -150,19 +153,17 @@
             } else {
                 //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or 
OC_BINARY
                 if (Q_UNLIKELY(!m_isFragmented && 
frame.isContinuationFrame())) {
-                    clear();
-                    Q_EMIT 
errorEncountered(QWebSocketProtocol::CloseCodeProtocolError,
-                                            tr("Received Continuation frame, 
while there is " \
-                                               "nothing to continue."));
-                    return true;
+                    reportError(QWebSocketProtocol::CloseCodeProtocolError,
+                                tr("Received Continuation frame, while there 
is " \
+                                   "nothing to continue."));
+                    return false;
                 }
                 if (Q_UNLIKELY(m_isFragmented && frame.isDataFrame() &&
                                !frame.isContinuationFrame())) {
-                    clear();
-                    Q_EMIT 
errorEncountered(QWebSocketProtocol::CloseCodeProtocolError,
-                                            tr("All data frames after the 
initial data frame " \
-                                               "must have opcode 0 
(continuation)."));
-                    return true;
+                    reportError(QWebSocketProtocol::CloseCodeProtocolError,
+                                tr("All data frames after the initial data 
frame " \
+                                   "must have opcode 0 (continuation)."));
+                    return false;
                 }
                 if (!frame.isContinuationFrame()) {
                     m_opCode = frame.opCode();
@@ -173,10 +174,9 @@
                         : quint64(m_binaryMessage.size());
                 if (Q_UNLIKELY((messageLength + 
quint64(frame.payload().size())) >
                                maxAllowedMessageSize())) {
-                    clear();
-                    Q_EMIT 
errorEncountered(QWebSocketProtocol::CloseCodeTooMuchData,
-                                            tr("Received message is too 
big."));
-                    return true;
+                    reportError(QWebSocketProtocol::CloseCodeTooMuchData,
+                                tr("Received message is too big."));
+                    return false;
                 }
 
                 bool isFinalFrame = frame.isFinalFrame();
@@ -188,10 +188,9 @@
                         decoderHadError = r.error != 
QStringDecoder::FinalizeResult::Error::NoError;
                     }
                     if (Q_UNLIKELY(decoderHadError)) {
-                        clear();
-                        Q_EMIT 
errorEncountered(QWebSocketProtocol::CloseCodeWrongDatatype,
-                                                tr("Invalid UTF-8 code 
encountered."));
-                        return true;
+                        reportError(QWebSocketProtocol::CloseCodeWrongDatatype,
+                                    tr("Invalid UTF-8 code encountered."));
+                        return false;
                     } else {
                         m_textMessage.append(frameTxt);
                         frame.clear();
@@ -218,9 +217,8 @@
                 }
             }
         } else {
-            Q_EMIT errorEncountered(frame.closeCode(), frame.closeReason());
-            clear();
-            isDone = true;
+            reportError(frame.closeCode(), frame.closeReason());
+            return false;
         }
         frame.clear();
     }
@@ -242,11 +240,26 @@
     m_textMessage.clear();
     m_payloadLength = 0;
     m_decoder.resetState();
+    m_hasFailed = false;
     frame.clear();
 }
 
 /*!
     \internal
+
+    Reports a protocol violation and marks the connection as failed, so that no
+    further data is parsed after the error.
+ */
+void QWebSocketDataProcessor::reportError(QWebSocketProtocol::CloseCode code,
+                                          const QString &description)
+{
+    clear();
+    m_hasFailed = true;
+    Q_EMIT errorEncountered(code, description);
+}
+
+/*!
+    \internal
  */
 bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame)
 {
@@ -323,9 +336,8 @@
  */
 void QWebSocketDataProcessor::timeout()
 {
-    clear();
-    Q_EMIT errorEncountered(QWebSocketProtocol::CloseCodeGoingAway,
-                            tr("Timeout when reading data from socket."));
+    reportError(QWebSocketProtocol::CloseCodeGoingAway,
+                tr("Timeout when reading data from socket."));
 }
 
 QT_END_NAMESPACE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketdataprocessor_p.h
 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketdataprocessor_p.h
--- 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketdataprocessor_p.h
   2026-08-12 03:33:36.000000000 +0200
+++ 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketdataprocessor_p.h
   2026-09-27 10:15:31.000000000 +0200
@@ -89,8 +89,10 @@
     QWebSocketFrame frame;
     QChronoTimer *m_waitTimer;
     quint64 m_maxAllowedMessageSize = MAX_MESSAGE_SIZE_IN_BYTES;
+    bool m_hasFailed = false;
 
     bool processControlFrame(const QWebSocketFrame &frame);
+    void reportError(QWebSocketProtocol::CloseCode code, const QString 
&description);
     void timeout();
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsockethandshakeoptions.h
 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsockethandshakeoptions.h
--- 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsockethandshakeoptions.h
  2026-08-12 03:33:36.000000000 +0200
+++ 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsockethandshakeoptions.h
  2026-09-27 10:15:31.000000000 +0200
@@ -8,7 +8,7 @@
 #include <QtCore/QSharedDataPointer>
 #include <QtCore/QStringList>
 
-#include "QtWebSockets/qwebsockets_global.h"
+#include <QtWebSockets/qwebsockets_global.h>
 
 QT_BEGIN_NAMESPACE
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketprotocol.h 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketprotocol.h
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketprotocol.h  
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketprotocol.h  
2026-09-27 10:15:31.000000000 +0200
@@ -10,7 +10,7 @@
 #endif
 
 #include <QtCore/qglobal.h>
-#include "QtWebSockets/qwebsockets_global.h"
+#include <QtWebSockets/qwebsockets_global.h>
 
 QT_BEGIN_NAMESPACE
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketserver.h 
new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketserver.h
--- old/qtwebsockets-everywhere-src-6.11.2/src/websockets/qwebsocketserver.h    
2026-08-12 03:33:36.000000000 +0200
+++ new/qtwebsockets-everywhere-src-6.12.0/src/websockets/qwebsocketserver.h    
2026-09-27 10:15:31.000000000 +0200
@@ -5,8 +5,8 @@
 #ifndef QWEBSOCKETSERVER_H
 #define QWEBSOCKETSERVER_H
 
-#include "QtWebSockets/qwebsockets_global.h"
-#include "QtWebSockets/qwebsocketprotocol.h"
+#include <QtWebSockets/qwebsockets_global.h>
+#include <QtWebSockets/qwebsocketprotocol.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QString>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qtwebsockets-everywhere-src-6.11.2/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
 
new/qtwebsockets-everywhere-src-6.12.0/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
--- 
old/qtwebsockets-everywhere-src-6.11.2/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
    2026-08-12 03:33:36.000000000 +0200
+++ 
new/qtwebsockets-everywhere-src-6.12.0/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
    2026-09-27 10:15:31.000000000 +0200
@@ -13,7 +13,7 @@
 
 const quint8 FIN = 0x80;
 const quint8 RSV1 = 0x40;
-const quint8 RSV2 = 0x30;
+const quint8 RSV2 = 0x20;
 const quint8 RSV3 = 0x10;
 
 QT_USE_NAMESPACE
@@ -153,6 +153,19 @@
 
     void clearDataBuffers(); // qtbug-55506
 
+    /*!
+      Tests that QWebSocketDataProcessor stops handling a connection once it 
has
+      reported an error. RFC 6455 requires the connection to be failed on a
+      protocol violation (paragraphs 5.2 and 8.1) and forbids processing any
+      further data from the peer afterwards (paragraph 7.1.7), including bytes
+      already received (paragraph 7.1.1). The same handling is applied to frame
+      sequences that do not match the fragmentation rules of paragraph 5.4 and
+      to messages exceeding the configured limit.
+     */
+    void stopProcessingOnError();
+    void stopProcessingOnError_data();
+    void stopProcessingOnTimeout();
+
 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);
@@ -747,6 +760,7 @@
     binaryFrameSpy.clear();
     buffer.close();
     data.clear();
+    dataProcessor.clear();
 
     //only one byte; this is far too little;
     //should get a time out as well and the error should be CloseCodeGoingAway
@@ -780,6 +794,7 @@
     textFrameSpy.clear();
     binaryFrameSpy.clear();
     data.clear();
+    dataProcessor.clear();
 
 
     {
@@ -810,6 +825,7 @@
         binaryFrameSpy.clear();
         buffer.close();
         data.clear();
+        dataProcessor.clear();
 
         //with nothing in the buffer,
         //the dataProcessor should time out and the error should be 
CloseCodeGoingAway
@@ -841,6 +857,7 @@
         binaryFrameSpy.clear();
         buffer.close();
         data.clear();
+        dataProcessor.clear();
 
         //text frame with final bit not set
         data.append(char(QWebSocketProtocol::OpCodeText)).append(char(0x0));
@@ -860,6 +877,7 @@
 
         buffer.close();
         data.clear();
+        dataProcessor.clear();
 
         errorSpy.clear();
         closeSpy.clear();
@@ -1879,6 +1897,166 @@
     QTest::qWait(2000);
 }
 
+void tst_DataProcessor::stopProcessingOnError_data()
+{
+    QTest::addColumn<QByteArray>("data");
+    QTest::addColumn<QWebSocketProtocol::CloseCode>("expectedCloseCode");
+    // frames legitimately delivered before the violation is detected
+    QTest::addColumn<int>("expectedTextFrames");
+    // zero leaves the default limit in place
+    QTest::addColumn<quint64>("maxMessageSize");
+
+    // the well formed frame trailing most rows; it must never be delivered
+    QByteArray textFrame;
+    textFrame.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    textFrame.append(char(5));
+    textFrame.append("hello");
+
+    // Ensure a continuation frame that has no message to continue is rejected,
+    // and that the text frame behind it is not delivered.
+    QByteArray strayContinuation;
+    strayContinuation.append(char(FIN | QWebSocketProtocol::OpCodeContinue));
+    strayContinuation.append(char(0));
+    QTest::newRow("stray continuation frame")
+            << strayContinuation + textFrame << 
QWebSocketProtocol::CloseCodeProtocolError
+            << 0 << quint64(0);
+
+    // Ensure a frame rejected on its header does not leak the payload it
+    // announced.
+    QByteArray rsv1Frame;
+    rsv1Frame.append(char(FIN | RSV1 | QWebSocketProtocol::OpCodeText));
+    rsv1Frame.append(char(textFrame.size()));
+    QTest::newRow("rsv1 set, announced payload is a frame")
+            << rsv1Frame + textFrame << 
QWebSocketProtocol::CloseCodeProtocolError
+            << 0 << quint64(0);
+
+    // Ensure a payload that fails UTF-8 validation stops processing.
+    QByteArray invalidUtf8Frame;
+    invalidUtf8Frame.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    invalidUtf8Frame.append(char(1));
+    invalidUtf8Frame.append(char(0xFF));
+    QTest::newRow("invalid utf-8")
+            << invalidUtf8Frame + textFrame << 
QWebSocketProtocol::CloseCodeWrongDatatype
+            << 0 << quint64(0);
+
+    // Ensure a data frame arriving mid-fragmentation is rejected: once a 
message
+    // is fragmented, the frames that follow must use opcode 0.
+    QByteArray firstFragment;
+    firstFragment.append(char(QWebSocketProtocol::OpCodeText));
+    firstFragment.append(char(1));
+    firstFragment.append("a");
+    QByteArray secondDataFrame;
+    secondDataFrame.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    secondDataFrame.append(char(1));
+    secondDataFrame.append("b");
+    QTest::newRow("data frame during a fragmented message")
+            << firstFragment + secondDataFrame + textFrame
+            << QWebSocketProtocol::CloseCodeProtocolError << 1 << quint64(0);
+
+    // Ensure even the peer's Close frame is ignored after a failure.
+    QByteArray closeFrame;
+    closeFrame.append(char(FIN | QWebSocketProtocol::OpCodeClose));
+    closeFrame.append(char(2));
+    closeFrame.append(char(0x03));
+    closeFrame.append(char(0xE8));
+    QTest::newRow("close frame after the violation")
+            << strayContinuation + closeFrame << 
QWebSocketProtocol::CloseCodeProtocolError
+            << 0 << quint64(0);
+
+    // Ensure exceeding the configured message limit stops processing.
+    QTest::newRow("message too big")
+            << textFrame + textFrame << 
QWebSocketProtocol::CloseCodeTooMuchData
+            << 0 << quint64(4);
+}
+
+void tst_DataProcessor::stopProcessingOnError()
+{
+    QFETCH(QByteArray, data);
+    QFETCH(QWebSocketProtocol::CloseCode, expectedCloseCode);
+    QFETCH(int, expectedTextFrames);
+    QFETCH(quint64, maxMessageSize);
+
+    QWebSocketDataProcessor dataProcessor;
+    dataProcessor.setIdleTimeout(DefaultIdleTimeout);
+    if (maxMessageSize)
+        dataProcessor.setMaxAllowedMessageSize(maxMessageSize);
+
+    QSignalSpy errorSpy(&dataProcessor, 
&QWebSocketDataProcessor::errorEncountered);
+    QSignalSpy textFrameSpy(&dataProcessor, 
&QWebSocketDataProcessor::textFrameReceived);
+    QSignalSpy textMessageSpy(&dataProcessor, 
&QWebSocketDataProcessor::textMessageReceived);
+    QSignalSpy closeSpy(&dataProcessor, 
&QWebSocketDataProcessor::closeReceived);
+
+    QBuffer buffer;
+    buffer.setData(data);
+    buffer.open(QIODevice::ReadOnly);
+
+    // the violating frame is followed by a well-formed text frame in the same
+    // buffer; processing must stop at the violation
+    QVERIFY(!dataProcessor.process(&buffer));
+    QCOMPARE(errorSpy.size(), 1);
+    QCOMPARE(errorSpy.first().at(0).value<QWebSocketProtocol::CloseCode>(), 
expectedCloseCode);
+    QCOMPARE(textFrameSpy.size(), expectedTextFrames);
+    QCOMPARE(textMessageSpy.size(), 0);
+
+    // no further data is parsed for a connection that has failed
+    QVERIFY(!dataProcessor.process(&buffer));
+    QCOMPARE(errorSpy.size(), 1);
+    QCOMPARE(textFrameSpy.size(), expectedTextFrames);
+    QCOMPARE(textMessageSpy.size(), 0);
+    QCOMPARE(closeSpy.size(), 0);
+    buffer.close();
+
+    // ensure processor is usable again after clear()
+    dataProcessor.clear();
+    QByteArray goodFrame;
+    goodFrame.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    goodFrame.append(char(2));
+    goodFrame.append("ok");
+    QBuffer reopened;
+    reopened.setData(goodFrame);
+    reopened.open(QIODevice::ReadOnly);
+    QVERIFY(dataProcessor.process(&reopened));
+    QCOMPARE(textMessageSpy.size(), 1);
+    QCOMPARE(textMessageSpy.first().at(0).toString(), QStringLiteral("ok"));
+}
+
+void tst_DataProcessor::stopProcessingOnTimeout()
+{
+    QWebSocketDataProcessor dataProcessor;
+    dataProcessor.setIdleTimeout(DefaultIdleTimeout);
+
+    QSignalSpy errorSpy(&dataProcessor, 
&QWebSocketDataProcessor::errorEncountered);
+    QSignalSpy textMessageSpy(&dataProcessor, 
&QWebSocketDataProcessor::textMessageReceived);
+
+    // a header announcing a 7 byte payload, with no payload yet
+    QByteArray header;
+    header.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    header.append(char(7));
+
+    QBuffer buffer;
+    buffer.setData(header);
+    buffer.open(QIODevice::ReadOnly);
+    QVERIFY(!dataProcessor.process(&buffer));
+    buffer.close();
+
+    QTRY_VERIFY_WITH_TIMEOUT(errorSpy.size(), 7000);
+    QCOMPARE(errorSpy.size(), 1);
+    QCOMPARE(errorSpy.first().at(0).value<QWebSocketProtocol::CloseCode>(),
+             QWebSocketProtocol::CloseCodeGoingAway);
+
+    // the announced payload finally arrives; it must not be parsed as a frame
+    QByteArray payload;
+    payload.append(char(FIN | QWebSocketProtocol::OpCodeText));
+    payload.append(char(5));
+    payload.append("hello");
+
+    QBuffer resumed;
+    resumed.setData(payload);
+    resumed.open(QIODevice::ReadOnly);
+    QVERIFY(!dataProcessor.process(&resumed));
+    QCOMPARE(textMessageSpy.size(), 0);
+}
+
 QTEST_MAIN(tst_DataProcessor)
 
 #include "tst_dataprocessor.moc"

Reply via email to