1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00

Compare commits

...

230 Commits

Author SHA1 Message Date
Topi Reinio
5238fdb1c3 Doc: Include namespaces in TOC
The QMqtt namespace was missing from the TOC as the .qhp subproject
selected only classes and headers.

Pick-to: 6.12
Change-Id: I5692ae2e77b80d9b3c4361945891e84c1ef4ccf7
Reviewed-by: Alexei Cazacov <alexei.cazacov@qt.io>
2026-10-25 15:09:56 +00:00
Tatiana Borisova
407ac111fd QMqttConnection: distinguish read errors from zero values
- The readBufferTyped<T>() method returns T{0} when it fails. But
in QtMqtt the value 0 is also used as "Success" return code.
In particular, src/mqtt/qmqttconnection.cpp
=> readBufferTyped<T>() returns 0 on failure, and finalize_connack()
reads the login result with it. src/mqtt/qmqttglobal.h =>
QMqtt::ReasonCode defines Success = 0.
So our failure value and the protocol's success value are the same
number.

- To fix this problem I make readBufferTyped<>() return std::nullopt
when the read fails, while using the returned value to represent
uccessfully read data. This allows callers to distinguish read errors
from valid zero values.

[ChangeLog][QMqttConnection][Important Behavior Changes] The Qt MQTT
client now stops parsing and closes the connection with the
ProtocolViolation error when a read error occurs while
parsing a packet.

Task-number: QTBUG-149867
Change-Id: I829a34cecfcb49ba330d5eb65aba755eee9326b0
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-10-23 10:09:58 +00:00
Qt Submodule Update Bot
d8fa0e633f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I628aa6161920a7d3fa21db807f594e4d25b58f61
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-10-22 17:20:29 +00:00
Tatiana Borisova
51fe8b4f2e Limit MQTT packet size for MQTT 3.x connections
- Enforce the configured packet size limit locally for MQTT 3.1/3.1.1.
- Close the connection if the broker sends a packet exceeding the limit.

MQTT 3.1 and 3.1.1 have no way to tell the broker the maximum packet
size the client accepts, so the limit can only be applied on the
client side. This is helpful for clients on embedded devices, where
memory is limited and a very large packet from the broker could
exhaust it.

[ChangeLog][QMqttClient] The maximumPacketSize connection property is
now also enforced for MQTT 3.1 and 3.1.1 connections. Previously it was
only honored for MQTT 5.0. The client now closes the connection if the
broker sends a packet larger than this limit. This helps clients on
embedded devices to protect their limited memory. The default behavior
is unchanged: if no limit is set, only the protocol maximum of 256 MB
applies.

Change-Id: I26625325f490e2396fa493005c1f322253007a33
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-10-20 11:48:44 +00:00
Qt Submodule Update Bot
457877b453 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ifba06f310ebdadd2fd94311e0f2c2d5c4085cc9c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-10-20 09:32:25 +00:00
Qt Submodule Update Bot
529a2ed7d9 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7f1d48e7c4a059139d53409bd77f61a5e3e5392b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-10-14 10:28:41 +00:00
Qt Submodule Update Bot
39f5d8bc63 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I4eda259e19bee548ad55c257ac4de89d6562e865
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-10-13 20:31:00 +00:00
Tatiana Borisova
a4ba93f3ca Add the readBufferSize property to limit the read buffer for clients
- this function should be used to protect your socket against receiving
too much data, which may eventually cause your application to run out
of memory.
- setSocketReadBufferSize(size) sets the size of internal read buffer
to be 'size' bytes.

[ChangeLog][QMqttClient] Added a readBufferSize property to limit
the transport buffer size.

Task-number: QTBUG-149866
Change-Id: I6ff843b66b50d019ecf620c25c47e0d779518113
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-10-09 15:34:07 +00:00
Tatiana Borisova
d24a6483d0 Document blocking I/O and threading considerations
- Document that disconnectFromHost() may block while waiting for pending
data to be written, with a timeout of up to 30 seconds.

- Recommend keeping QMqttClient and its transport outside the UI thread
because blocking I/O may occur and affect UI responsiveness.

Pick-to: 6.12
Task-number: QTBUG-150345
Change-Id: I27d300210750710c4a5138f8c3f97c7c929466af
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-10-08 09:42:57 +00:00
Qt Submodule Update Bot
e147dedea3 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I4d3b281b7ba556b9753806639db2b8f2a03db743
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-10-07 21:19:11 +00:00
Tatiana Borisova
1316c02fe7 MQTT 5: Add Maximum Packet Size check
Disconnect with reason code 0x95 (Packet too large) if a packet
exceeds the Maximum Packet Size limit, as required by section 3.1.2.11.4
of the MQTT 5 spec.

Note: This fix doesn't protect against memory exhaustion in user apps.
It just implements the spec requirement about message limit.

Pick-to: 6.12
Task-number: QTBUG-149866
Change-Id: I2baa8ceb95e4a045437e2caa51e5508b2fa8b2eb
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-10-06 13:05:52 +00:00
Qt Submodule Update Bot
ece01bf0ee Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iad96afcd2d25ef4c6d1f0b085f782d1b81089ff3
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-30 21:41:02 +00:00
Qt Submodule Update Bot
24678da81e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0c6fb192baf73ae18b8ced356af0890d1d402c57
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-22 13:35:15 +00:00
Tatiana Borisova
21b866609f The Qt app can freeze forever if the broker sends a bad message
- When QMqttConnection reads a message, it keeps a count of the bytes
left to read -> by the dataSize argument. If a read fails, the count
is never reduced.
- The fix cleaning up the count of the bytes left to read, since
the reading is not working anymore and parsing should be stopped.
It allows to get read of potential freezes.

The patch also updates the QByteArray specialization to return a
default-constructed QBA in case of an error. This is more in line
with the default implementation.

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149563
Change-Id: I8c8c5ef354103a996ac6e360fbc5c8f61d965f3d
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-09-15 09:06:31 +00:00
Qt Submodule Update Bot
6bdaef48c7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I23dabe0789f9adc00ba3ab1e9af553c6e2eb3c67
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-14 22:30:33 +00:00
Qt Submodule Update Bot
c58aedad7a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Id764db97c594b958cfc84a80ae85b6c5c0ad5574
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-10 00:05:42 +00:00
Qt Submodule Update Bot
dd767d7a57 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ic7d9314b90e2ff088c84f49acbc8a46f4258b1fb
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-02 05:07:22 +00:00
Tatiana Borisova
06d301aa50 Read the Remaining Length as a variable byte integer everywhere
- Every MQTT packet begins with a fixed header, whose second field is the
Remaining Length: the number of bytes that follow. It is not a byte. It
is spread over one to four bytes, seven value bits each, with the top
bit meaning "another byte follows". So values up to 127 take one byte,
and larger values take more.

Six packet types read it as a single quint8: SUBACK, UNSUBACK, PUBACK,
PUBREC, PUBREL and PUBCOMP. For most of them that used to be correct.
In MQTT 3.1.1 those packets contain nothing but a two byte identifier,
so the length was always exactly 2, which always fits in one byte. The
code did not even use the byte it read: it checked that the value was 2
and then hardcoded the length.

MQTT 5.0 support (ac66658) gave those packets an optional reason code
and properties, so the length can now be far above 127. That commit
switched off the "must be 2" check for MQTT 5.0 and began using the
byte as the real length, but kept reading only one byte. The check had
been the only thing making a one byte read safe, because a multi-byte
length always has its top bit set and so could never equal 2.

SUBACK never had a fixed length at all, since its payload carries one
reason code per subscribed topic filter. It has been misparsed for any
SUBACK above 127 bytes since the parser was written (d96011b).

Reading one byte of a two byte length consumes one byte too few, so the
remainder of the packet is then read as the next packet's header. The
client rejects a valid acknowledgement and stays out of step for the
rest of the connection. Brokers trigger this on ordinary traffic as
soon as they attach a reason string or user properties.

All six now use readVariableByteInteger(), and each rejects a length too
short to hold the fields the specification requires.

PUBREL also accepted a length of exactly 2 even for MQTT 5.0, which
rejected valid PUBREL packets carrying a reason code. It now accepts 2
or more there, and still requires exactly 2 for MQTT 3.1.1.

- Adds three regression tests driving the parser through the existing
FakeServer, so they need no broker.

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149569
Change-Id: Ib239d836556e0cc14e13c116dee757fdd1a7ae81
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-09-01 17:40:37 +00:00
Tatiana Borisova
33538c5143 PINGRESP from the network should not push the counter below zero
- finalize_pingresp() lowers m_pingTimeout every time, with no lower
limit. A broker can send a pile of unasked-for replies to push the
counter deep below zero, and then the client can spend some unexpected
amount of time to reach back the number that means:
"the broker has stopped answering, drop the link.”
- The fix prohibits pushing the counter below zero.

Task-number: QTBUG-149662
Pick-to: 6.11 6.12 6.8
Change-Id: I7b25e8ac3f83fa262a19010df9a91b2ee1c006fd
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-09-01 14:32:40 +00:00
Tatiana Borisova
9e0428b917 Skip remaining data for messages with unknown requests
- finalize_suback() and finalize_unsuback() read the 2-byte request ID.
If no matching request was found, they returned immediately.
However, m_missingData remained non-zero.
The leftover bytes are then incorrectly interpreted as the header of
the next message!

- This change fixes the issue universally for all handlers in the
processDataHelper().

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149570
Change-Id: I06c86414c3297caa386059a02fdec5c3765a0315
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-09-01 10:52:32 +00:00
Qt Submodule Update Bot
c7f7555d8e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ic8fadb4442f209a70a15a076d56b166f4d122f75
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-09-01 00:54:22 +00:00
Tatiana Borisova
011eb1e424 Fix topic alias bounds and storage sizes
- In the f8ecf4d56a we found that the
m_receiveAliases bounds check used a wrong property:
m_clientPrivate->m_serverConnectionProperties.maximumTopicAlias(),
but it must use instead:
m_clientPrivate->m_connectionProperties.maximumTopicAlias().

So, the idea is m_receiveAliases is sized according to the maximum
topic alias value declared by the client in CONNECT, while
m_publishAliases is sized according to the maximum value declared
by the server in CONNACK.

The previous fix did not update all related code.
1) The resize() calls for m_receiveAliases and m_publishAliases
still used the wrong properties.
2) The bounds check for m_publishAliases still used the client's
maximumTopicAlias() value instead of the server's.

- Update the resize() calls to use the appropriate connection
properties and fix the bounds check for m_publishAliases.

Amends f8ecf4d56a

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149564
Change-Id: I252c67966bf28c6994f34b19024d1b7894748473
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-08-28 17:36:29 +00:00
Qt Submodule Update Bot
ee16836877 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I13a69da7a50229cdfc602dda0edac4f2645da59e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-28 16:01:26 +00:00
Tatiana Borisova
c94175ff43 Stop parsing after closeConnection()
- Parsing continued after closeConnection(), leaving the client in the
"connected" state with a dead socket. This led to a permanent,
unrecoverable wedge in Release builds and a crash in Debug builds.

- Check whether the client is already disconnected before changing its
state to BrokerConnected.

Pick-to: 6.11 6.12 6.8
Task-number: QTBUG-149565
Change-Id: I13d45c24d24fe862d9aec6a7e421f5ef4d494db0
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-08-28 12:07:32 +00:00
Tatiana Borisova
13288574c1 Check readVariableByteInteger() return value
- On error, readVariableByteInteger() closes the connection and
returns-1. In this case, message handling should stop.

- Add checks for the return value to stop processing when -1 is returned.

Pick-to: 6.11 6.8 6.12
Task-number: QTBUG-149565
Change-Id: I8f6cc8d6f3011a89d3bd4033a3432f383e1e9164
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-08-28 12:07:30 +00:00
Tatiana Borisova
ecaf42152e Number overflow while rejecting a too-long length
- The length reader checked its 4-byte limit after doing the maths.
So, a 5th byte was multiplied in and overflows before the value
was thrown away. But it was not noticed, because we thrown it away
and returned -1.

- The fix moves iteration++ and if (iteration > 4) before the
calculation, preventing the overflow.

Pick-to: 6.11 6.8 6.12
Task-number: QTBUG-149571
Change-Id: I78c2063c7e01af3e8f196f824216d31de92fab48
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-08-28 12:07:28 +00:00
Qt Submodule Update Bot
ba2b82223a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie3ba332b167426218e86a904bc99a0bed0e4556c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-26 06:34:34 +00:00
Qt Submodule Update Bot
90f2efdd5d Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I45f8e4efaf7d02f0ef886257dd1ccaa1ad4f457e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-22 02:39:59 +00:00
Qt Submodule Update Bot
b73e4d4ffc Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I2751f6696663e560d274e1df7889943a578a6914
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-18 00:22:08 +00:00
Tatiana Borisova
96d602b65f Update to coin_module_test_template_v3.yaml
- The main differences between v2 and v3 are:
  * `coin_module_test_template_v2.yaml` ignores autotest return
    codes because the `COIN_CTEST_IGNORE_EXIT_CODE` flag is set.
  * The Axivion build was moved from coin_module_build_template_v2.yaml
    to coin_module_test_template_v3.yaml in commit
    c3ddec2f15a1cf806d8df444952cb2c2231ae4ad
- Switch the qtmqtt submodule to the newer v3 version to improve
the submodule CI experience for autotests and restore Axivion
checks.

Pick-to: 6.12 6.11
Change-Id: I1695c8ca1af616512dff437a0a4cdbd0491412d4
Reviewed-by: Toni Saario <toni.saario@qt.io>
2026-08-17 09:51:21 +00:00
Qt Submodule Update Bot
fe85eff00c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I49e7ca4073c1c483370a22ff51d8cde8d63345f4
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-14 10:49:39 +00:00
Qt Submodule Update Bot
16862e4fa7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I5706ec8cff106f1a19fcf9652ba06ae7a3076bab
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-08-04 15:26:25 +00:00
Qt Submodule Update Bot
2caa279c61 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I8126f0e67a0c58f8f671890050d3c13bf6e8e8d8
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-29 15:25:41 +00:00
Jani Heikkinen
ebd3d87293 Replace Q_ENUMS with Q_ENUM
Amends ea3dc64d3f,
7467bbdc84, and
ea0d792a44 (all before 6.0).

Fixes: QTBUG-148625
Pick-to: 6.12 6.11 6.8
Change-Id: I2f9b24f7e32d437cce258dfdce0d669c8d2638e1
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
2026-07-29 11:40:44 +00:00
Tatiana Borisova
14de26f60b Fix Qt-RangeLoopDetach Axivion warnings
- use std::as_const() where possible, and introduce an intermediate
  local const variable where it is not.

Axivion-Id: qt_Add-ons_qtmqtt_dev_linux:SV34
Axivion-Id: qt_Add-ons_qtmqtt_dev_linux:SV35
Axivion-Id: qt_Add-ons_qtmqtt_dev_linux:SV36
Axivion-Id: qt_Add-ons_qtmqtt_dev_linux:SV37
Pick-to: 6.12
Task-number: QTBUG-144762
Change-Id: I7b6d53116269007aca7d6f050b2abeb2515e9390
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2026-07-22 10:41:05 +00:00
Qt Submodule Update Bot
a85b5c3ecf Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I63842312d21575b3cb7f0722446ec14149aa2a5e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-18 21:34:00 +00:00
Qt Submodule Update Bot
2dc7e69f0e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I23bbd285e1aa00624ee2e21a65b54ec3693d416f
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-15 00:24:21 +00:00
Qt Submodule Update Bot
9cc2b3859d Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I8d5b1115587cdc9e4625785a23acba9cd770936a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-09 20:08:18 +00:00
Qt Submodule Update Bot
088b583810 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I92ec408cffa255a953e07fe93761fe9bf5fcc27b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-07 15:18:07 +00:00
Qt Submodule Update Bot
fa9b04ab15 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I2828b08e810e9fd3de8b3536472d21c17c67bf9f
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-07-01 17:52:59 +00:00
Qt Submodule Update Bot
53aba306b9 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7f19ead9837dcb5a80b0fabae0f3e2aae1562752
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-25 07:49:14 +00:00
Qt Submodule Update Bot
3b476b23eb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie71907f1afdf7b36ba1a363db0855716b731d96a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-18 21:00:58 +00:00
Qt Submodule Update Bot
cf66710eb6 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ibbf482f41eb56bea86a418094a81516fa913ae07
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-04 21:59:53 +00:00
Jani Heikkinen
5d592b2aa3 Bump version to 6.13.0
Change-Id: I63790a12e9734c478bb9f0bb86ff4527cd69b9e1
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-04 21:59:51 +00:00
Qt Submodule Update Bot
ae08a87fc4 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If9e34b78b899338e3bf3587caea8f5ef929fa39e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-03 01:35:30 +00:00
Qt Submodule Update Bot
1d7f954339 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I6b6c3fe3edd69ee2444bc7246d1c6916e3f8ba5d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-06-02 05:06:50 +00:00
Qt Submodule Update Bot
f7267c6452 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ieff8861b81fe08d9e05eae5343ad6716d7698383
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-31 15:44:17 +00:00
Qt Submodule Update Bot
cefbe34e78 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ieb10ad55da60b7ef62c9d84479fe98f5ea515209
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-29 01:11:37 +00:00
Qt Submodule Update Bot
b7d124d65f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I858f5ccddc5f368659f43646fa005537dce71a87
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-25 20:20:43 +00:00
Qt Submodule Update Bot
e7616f09c1 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I77d9159d75ac22b8fff8996dc4e403bc42421563
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-22 12:04:27 +00:00
Qt Submodule Update Bot
ba85d5db5c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I72a5e492509e54a18ee16a953e6a6c222a9aa124
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-15 12:13:24 +00:00
Qt Submodule Update Bot
396d0f90e7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iefedb03a0bf4aa12a5f13fd36d92a89d5631e685
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-08 05:41:49 +00:00
Qt Submodule Update Bot
468dfd5357 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Idcc316e0dea54aeb45941abebab5c4e28a55cd62
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-05-05 14:50:43 +00:00
Marc Mutz
24ec59ffbb Disable 1-to-2-arg qHash() adapter in qtmqtt
Pick-to: 6.11
Task-number: QTBUG-145851
Change-Id: Ic9f6a64b8aa99aad7682e5e6379d304bcff3a7d7
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2026-05-04 10:43:37 +00:00
Qt Submodule Update Bot
c0f5cee7eb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I421dcdadb5e23c65b453f555a25c3d0f9bba8dd1
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-04-30 13:10:00 +00:00
Kai Köhne
5287cf1442 Add CONTRIBUTING.md file
Point potential contributors to contribute.qt-project.org.

Change-Id: Id4dbc0dda57fe316f5d338dd0ef407b278287671
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
2026-04-21 07:22:04 +00:00
Qt Submodule Update Bot
778fa2d33c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I40d407b8b63b744c47ba731c02e72c66529bb241
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-04-20 19:01:00 +00:00
Qt Submodule Update Bot
92c214f82a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ibfb2ad9bb0924abb7a074358c4ba1f877c81c489
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-04-17 18:55:29 +00:00
Qt Submodule Update Bot
ed2aeb5392 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7483d2540c6338db7b3f8b444cbf05daf07564a8
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-04-16 07:38:06 +00:00
Qt Submodule Update Bot
fe7422c165 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I5dfd827abd2d9fe68403371fd40659ea2e9c459e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-30 09:25:50 +00:00
Qt Submodule Update Bot
8c32cf60c0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I9110839ce13a2e73145908973465dd8024d2594c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-27 08:24:11 +00:00
Qt Submodule Update Bot
92de735434 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0fdb37e81eea6ed61cd084b60b6c772d851acc90
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-26 08:20:47 +00:00
Marc Mutz
a3c58404a4 Tst_QMqttSubscription: fix -Wunused-lambda-capture
Says Clang:

  tst_qmqttsubscription.cpp:515:92: warning: lambda capture 'client' is not used [-Wunused-lambda-capture]
    515 |         connect(subscriptions[i], &QMqttSubscription::messageReceived, subscriptions[i], [&client, topic, &received](QMqttMessage msg) {
        |                                                                                           ~^~~~~~~
  tst_qmqttsubscription.cpp:545:92: warning: lambda capture 'client' is not used [-Wunused-lambda-capture]
    545 |         connect(subscriptions[i], &QMqttSubscription::messageReceived, subscriptions[i], [&client, topic, &received](QMqttMessage msg) {
        |                                                                                           ~^~~~~~~
  tst_qmqttsubscription.cpp:576:92: warning: lambda capture 'client' is not used [-Wunused-lambda-capture]
    576 |         connect(subscriptions[i], &QMqttSubscription::messageReceived, subscriptions[i], [&client, topic, &received](QMqttMessage msg) {
        |                                                                                           ~^~~~~~~

Fix by removing the problematic capture. I don't know why it doesn't
complain about `topic`, which also looks unused.

Amends c383083270 (picked to 6.8).

Pick-to: 6.11 6.10 6.8
Change-Id: I52850ae4ff9b5e2faee86cd8252d78ce5f0908ff
Reviewed-by: Even Oscar Andersen <even.oscar.andersen@qt.io>
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2026-03-24 08:50:18 +01:00
Qt Submodule Update Bot
3e904a3eb4 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I63b95f05c9dde6633111f63b6008920cec54da21
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-23 23:46:51 +00:00
Qt Submodule Update Bot
8931b61d89 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I11332b97298dde75f48ae3cfb5eb1b9452447a94
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-18 17:43:38 +00:00
Qt Submodule Update Bot
0ec04b89e2 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I08c40165efeebfb2df661bdac17e8ad2db48fb49
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-17 14:05:05 +00:00
Qt Submodule Update Bot
6d7b27ab94 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0d18827d5f92c8ba488a7ccac5a7550444e7400b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-13 15:47:14 +00:00
Qt Submodule Update Bot
00a8eb7b67 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie1d5820003ae40418f00ae2c3d67c2891068c92c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-11 19:11:40 +00:00
Jerome Pasion
34656ac5ba Doc: Add alt text for \image tags for qtmqtt
Alternate text (alt text) improves the documentation experience for
screen readers and for other accessibility tools.

Task-number: QTBUG-135098
Pick-to: 6.11
Change-Id: Ia1793ff3e0bacd8cfdad2e8c04725a5093ed30aa
Reviewed-by: David Boddie <david.boddie@qt.io>
2026-03-11 14:32:53 +01:00
Qt Submodule Update Bot
39260ae2da Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I546348735b48a645c452395b24393c6989299e33
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-10 06:57:24 +00:00
Qt Submodule Update Bot
b29077d7a8 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib2e0d05e73020cc2e1215e76841417b5b8d3e76c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-09 10:06:28 +00:00
Qt Submodule Update Bot
3f7a78ee7a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib0d6c76b924a6615c804c25113d663cb94bdaea3
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-03-05 10:31:13 +00:00
Qt Submodule Update Bot
e67dafc7f0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I1fcbfb7adb0b827e6335765762b8fdc93818af8f
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-02-17 16:00:25 +00:00
Qt Submodule Update Bot
d29b14762a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If1bf7c2f766842b21393cee6e5ae3d1d8eca172c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-02-11 01:32:08 +00:00
Qt Submodule Update Bot
9b6034ed76 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ibce7dde41a8136a6986c9fabac8ad7c48f06e336
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-02-09 00:06:17 +00:00
Qt Submodule Update Bot
3ba3066570 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I1f069b0755e58e6f1f049c6b0194e043b768ff21
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-02-03 12:02:40 +00:00
Qt Submodule Update Bot
66508a4eb9 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I151ad0cb4c1667d46b199a065ab8903fda2ac063
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-29 15:14:14 +00:00
Qt Submodule Update Bot
a7e5abab46 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If85193ce60865df2fb92425715bb187c5e8f225d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-25 16:52:48 +00:00
Qt Submodule Update Bot
b4bcd45be0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7b92d3d4456e78d32af59118422bffcc1a37bfcc
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-20 00:10:09 +00:00
Qt Submodule Update Bot
2bc0a35600 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I4b7e6ac674561afb0df13d537fd5332a6105bf13
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-17 02:14:55 +00:00
Qt Submodule Update Bot
9713f3ce3c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I32610627abd76b060c7adea079d67e0970586957
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-14 14:43:57 +00:00
Ivan Solovev
e2ae1fc992 Fix docs for new items of QMqttClient::TransportType
Mention that the transport uses QWebSocket, not QIODevice.

Technically, the implementation is still based on QIODevice, but that
is not what we want to highlight in the docs.

Amends dec643fc61.

Pick-to: 6.11 6.10
Change-Id: If561b3828cf8ffce4f245f7b4688a168a2ae3857
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
Reviewed-by: Even Oscar Andersen <even.oscar.andersen@qt.io>
2026-01-14 09:24:32 +00:00
Qt Submodule Update Bot
8e5acbae56 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib20ce2a7150e5de68de88bfc6fd6795939c7b828
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2026-01-05 13:57:08 +00:00
Qt Submodule Update Bot
c588c20e66 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I255f088dfb1a6623b9847b977d3d9158d2a25b7e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-20 00:59:24 +00:00
Jani Heikkinen
f86a1256ea Bump version to 6.12.0
Change-Id: I60f51632b5e24ba98afe6d9d1bb156bf08989b82
Reviewed-by: Akseli Salovaara <akseli.salovaara@qt.io>
2025-12-16 22:38:11 +00:00
Qt Submodule Update Bot
cf63fbc069 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7578986ec8bac24afdc5cfe7a325fa3ded0ba340
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-16 22:38:10 +00:00
Qt Submodule Update Bot
18f56919ea Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I27aaf4c2d2ef97d7f3978e47acbe952bc3939ea0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-12 17:56:25 +00:00
Qt Submodule Update Bot
4f6e8dd0f1 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7ee826f2a6539fe2fe764f1e6df6ad17de721bac
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-05 12:44:08 +00:00
Qt Submodule Update Bot
10b203bfa2 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I51c421442b87aacc46e628661319e3e1983dffae
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-05 03:01:55 +00:00
Qt Submodule Update Bot
b50be0baf7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I3ee675366b1355cfa625f18803d3874a47065214
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-02 10:46:02 +00:00
Eren Bursali
1189064b88 QT_NO_AS_CONST: rename "QT_NO_AS_CONST" to "QT_NO_QASCONST"
QT_NO_AS_CONST got renamed in qtbase.git in commit
03baf08d2bb9

Task-number: QTBUG-141558
Change-Id: Iadf4ab8b56ae714cccee2e6093009555c710c41b
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2025-12-02 09:39:22 +01:00
Qt Submodule Update Bot
977115a9cb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iec832909c05cb475a08eb71f86349c551a81c5a1
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-12-01 10:01:53 +00:00
Qt Submodule Update Bot
db2c48bf61 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I30a8b40542a8badb8272ec30ed4bcabb6d9e605d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-28 11:03:30 +00:00
Qt Submodule Update Bot
c4be55826e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I009322caf810db5402f98788ef63886ef712213b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-26 11:25:09 +00:00
Qt Submodule Update Bot
c6ea0e6059 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I74249232f221b19d0568210eb8039caf1b97e98c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-25 05:49:34 +00:00
Qt Submodule Update Bot
00190db47e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I444bf8b12e27a117d534a8a1ef03362ed5508e68
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-20 19:24:30 +00:00
Qt Submodule Update Bot
f6a803d24c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I917bda3b42bd8be0f0d5624501ac9a0edc6f0fd2
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-19 12:08:30 +00:00
Qt Submodule Update Bot
6372682e14 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7159d919f11488a9d5edefdb619dd3af3aeea42d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-18 16:43:07 +00:00
Qt Submodule Update Bot
2b011198f1 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iafffb7c835835bcf57de5e2653cc88c563a5891a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-15 00:54:26 +00:00
Qt Submodule Update Bot
f18faa609a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I43e38acf9b1fc30ab43f0143391b5fac8fa7eb84
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-14 01:30:50 +00:00
Qt Submodule Update Bot
f1cee95bbd Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ifb01c321e1c15f74ccb87a67fef782511a250902
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-12 13:28:58 +00:00
Qt Submodule Update Bot
0d21bdef58 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib5b9196a1eb9bf856c06c24fd0547f8a273b8f21
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-11 21:44:14 +00:00
Qt Submodule Update Bot
ad34c67816 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ia883cd3b309fa9ce3424e0b2ec051207ecde375f
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-10 23:04:08 +00:00
Qt Submodule Update Bot
7bf74eac1d Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I4f439ced40d37d13cf09f008f8efa9de37d570d9
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-07 13:36:33 +00:00
Qt Submodule Update Bot
44c50b2b66 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I3d21a10d68e7fba47f1c24738f0d09e286eb3a77
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-06 01:13:17 +00:00
Qt Submodule Update Bot
6e29d031b5 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If5ae9b44030e08f90b776cf9d47481117c2a3eb9
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-11-01 18:34:55 +00:00
Qt Submodule Update Bot
bd81918910 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I1ac66064a7f6aa9782979bbd35ce10694ebac8df
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-10-30 23:06:19 +00:00
Qt Submodule Update Bot
32f954d6c2 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Idd4bfa5846ee2cddbc25e12d8aa99bf9c3e50eb4
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-10-27 20:02:37 +00:00
Qt Submodule Update Bot
467f31cc1b Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Icc8643527c208d6df601d2a9e0254de0ce1e0818
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-10-24 02:32:26 +00:00
Ivan Solovev
b5c1e3aeb6 Mark more files as security-critical
The qmqttclient.cpp file contains parts of the MQTT protocol
implementation, and hence marked as security-critical.

The qmqtttopicname.cpp file contains the code that validates the topic
name and also parses the levels -> it is a data-parser, so should be
security-critical as well.

Amends 18548033e1, which incorrectly
marked these files as significant.

Not picking to 6.9 anymore, because that branch is already closed.

Task-number: QTBUG-135764
Pick-to: 6.10 6.8
Change-Id: I0e8b72fb1d24b7bbf6ac5edab63e137f9d36dd30
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-10-15 10:17:04 +02:00
Qt Submodule Update Bot
6740c49752 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I98731db56278fdcfec8432b6021a434946b04333
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-10-09 12:01:52 +00:00
Qt Submodule Update Bot
d2118973e7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Icb670b8c44894305bd5d818fc3a8aeb737f406c0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-10-03 11:28:27 +00:00
Qt Submodule Update Bot
9f1c2af872 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ia42e0000115cc06ef2d76bced89ac5df3a7f3027
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-30 23:15:30 +00:00
Qt Submodule Update Bot
13b1e8f4db Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If877ba8189738ea27003a9e3dee1237ad8ed5f01
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-29 11:25:32 +00:00
Qt Submodule Update Bot
ccb2349722 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I3db6f7d4eca7ba5e3fe54dbf6433cce04c47d105
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-26 18:49:50 +00:00
Qt Submodule Update Bot
6624b461eb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I34f9de26d6e05f500604f11264716160034ac989
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-20 15:03:54 +00:00
Qt Submodule Update Bot
7cd379444a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie9d561227fe3154099c38cbdae9818f9e708cc36
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-18 13:42:52 +00:00
Even Oscar Andersen
635ae612f1 Implement waitForBytesWritten for the websockets case
Not implementing this function causes a lot if Invalid Socket
Specified in the tests.

Also fixed a problem with broker_connection.h where
DefaultVersionTestData did not evaluate to version(0)
if MQTT_TEST_PROTOCOL was defined.

Fixes: QTBUG-137305
Pick-to: 6.10
Change-Id: I4b825196548a3f5bf07c3bb4203a0b46033004ba
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-09-10 11:39:48 +02:00
Qt Submodule Update Bot
2c9be38a7c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0e8d9b044a8a2cf8a1940fcd54a381cd469d4fc0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-05 14:35:58 +00:00
Qt Submodule Update Bot
d5c3a3334c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I4fb85f3bf08501514df0adefe1dc31fab56bc705
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-09-01 22:01:06 +00:00
Qt Submodule Update Bot
fae7ba0455 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0876db987f0144f03beb88d17020798dbb0228a8
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-08-08 23:06:26 +00:00
Topi Reinio
1cc23b20ef Doc: Fix incorrect usage of \generatelist
The \generatelist command takes an optional argument
that affect how the members are listed, for example,
`classesbymodule` which creates an annotated list of
the classes in a named C++ module.

`groupsbymodule` is not recognized or documented. QDoc
falls back to generating a list of all members of a
group in this case. While the end result is correct,
this relies on an undocumented feature that is likely
to change and break.

Replace these instances with an explicit \annotatedlist
command that produces the same output.

Pick-to: 6.10
Task-number: QTBUG-138901
Change-Id: I4c36087ff39efc740bc938888aa2531f635d9b67
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
2025-08-06 09:16:23 +00:00
Qt Submodule Update Bot
96ec1750fe Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Icda5f2dddf8307463100183c8be1740f217d9b7f
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-08-05 11:16:37 +00:00
Ivan Solovev
111328866c QMqttClient: optimize client id generation
Use the QUuid::Id128 format when converting a QUuid to string.
This format does not use curly braces and dashes, so we do not need
to remove them later.

Change-Id: I9b76c4eea03a4ba150e2a95ed8d108a6b1d9b8e6
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
2025-07-29 15:11:27 +02:00
Ivan Solovev
18548033e1 Mark the rest of sources as security-significant
This is the default level. All critical parts were identified in the
previous commits.

Fixes: QTBUG-135764
Pick-to: 6.10 6.9 6.8
Change-Id: Ib9df3db37e3efe3074f0fbc99eb60d31281d5a5a
Reviewed-by: Matthias Rauter <matthias.rauter@qt.io>
2025-07-29 14:06:19 +02:00
Ivan Solovev
7674ec983f Mark qmqtttopicfilter.cpp as security-critical
The QMqttTopicFilter::isValid() method parses the user-provided
string and validates it according to the MQTT protocol.

Task-number: QTBUG-135764
Pick-to: 6.10 6.9 6.8
Change-Id: I841bf83bbf29a2cdf4cf3faec93615a33f597241
Reviewed-by: Matthias Rauter <matthias.rauter@qt.io>
2025-07-29 14:06:17 +02:00
Ivan Solovev
13a98e39e7 Mark files that implement MQTT protocol as security-critical
The qmqttconnection.cpp file implements parts of the MQTT protocol,
including proper packet generation
(e.g. in QMqttConnection::sendControlConnect()) and parsing
(e.g. in QMqttConnection::processDataHelper()).

The qmqttcontrolpacket.cpp file implements payload serialization
in QMqttControlPacket::serializePayload().

Task-number: QTBUG-135764
Pick-to: 6.10 6.9 6.8
Change-Id: I5b398c8739e549ba849fcc31f25cd05ca3384f30
Reviewed-by: Matthias Rauter <matthias.rauter@qt.io>
2025-07-29 14:06:14 +02:00
Qt Submodule Update Bot
0342578df5 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I13d5a5e3ea13b2cf9e31ca22748b12f50cee48e5
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-07-18 14:16:23 +00:00
Qt Submodule Update Bot
7a968c89c9 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I64fe155aec3684907356e7b21dcd33cf5eda5774
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-07-15 09:36:36 +00:00
Lucie Gérard
0cd68dbd7b Remove year from Qt Copyright in REUSE.toml
Change-Id: I52b3893620e9b027db6ba7da7dcb38780b085e6e
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2025-07-09 11:01:49 +02:00
Qt Submodule Update Bot
06c368d44f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I3bd4366c6510c2e610fa684e9ab6db1cf504ab6d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-07-07 11:01:40 +00:00
Qt Submodule Update Bot
f4398ac583 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0d8c1a212a44147d69ec92c5ff97257d533636fe
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-07-03 17:47:37 +00:00
Qt Submodule Update Bot
8141fbbb6c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I745c707bea84130fa451c8178f9ad0f5d46f2e45
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-07-02 00:01:47 +00:00
Qt Submodule Update Bot
3f99de6d17 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I2c7f6a2c5622c60af230dac827f144ffa81bb531
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-30 15:55:49 +00:00
Qt Submodule Update Bot
7cbde7dc91 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I9ba15372af59a99a409d7aeb3556f5aa8d1ad6fe
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-27 16:23:42 +00:00
Qt Submodule Update Bot
f2c7593a55 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I8f2203f45802b9dc7bd8c19835bb22ad97bfb28c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-25 23:28:27 +00:00
Even Oscar Andersen
c383083270 Make sure unsubscribe followed by subscribe returns new subscription
Since we could only have one subscription for each topic it was
not possible to return a new subscription when a subscription
request comes in on a topic that is scheduled for destruction.

We solve this by switching to a QMultiHash for the active
subscriptions, allowing more then one subscription for a
given topic. However, at most one of these subscriptions
are not present in the list of subscriptions scheduled to
be unsubscribed

This patch also changes multiple unsubscribes to the
same topic. Earlier all would return true, and
m_pendingUnsubscriptions would be updated for all
requests.
The new behavior is that only the first unsubscribe
is acted upon. Furthere requests will return false.

Fixes: QTBUG-135653
Pick-to: 6.8 6.9 6.10
Change-Id: I5a79efb68b3191e185325a89cc2042c773bb5c12
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-06-24 13:14:36 +02:00
Cristian Le
a0a4633308 Move qt_internal_project_setup as early as possible
The earliest we can move this is right after `BuildInternals`. This
allows us to add function calls before navigating the `find_package`
tree of the dependents.

Task-number: QTBUG-135233
Change-Id: I2ee7bb0cb5addc422405768ba5706607a7257d6f
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2025-06-20 15:33:39 +02:00
Qt Submodule Update Bot
b47cff69bf Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Idaf84020852076585ef93858717f5a752a0b3a19
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-18 01:10:05 +00:00
Qt Submodule Update Bot
9c0cef3350 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iaa91353a84251a60f0e01dd2db6a611684c1320c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-14 05:35:06 +00:00
Jani Heikkinen
ae33492ca8 Bump version to 6.11.0
Change-Id: I086e87ea2dcc44e5acd11d298cf893dd26dba16b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-06-14 06:35:05 +01:00
Even Oscar Andersen
6eb01cac46 Mention in websockets subscription example that websockets are builtin
Added a \note, but keeping the example to show how to create custom
transports.

Pick-to: 6.10
Change-Id: Idf3b22532f6e0b94a0113cea6152a36e81398ea9
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
2025-06-12 13:40:32 +02:00
Even Oscar Andersen
2978075162 Add missing trailing comma for enums
Found in api-review.

Task-number: QTBUG-137478
Pick-to: 6.10
Change-Id: I73984caae5714c0f3cddd0f1770ddf19fd6fcd49
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-06-12 09:32:21 +02:00
Even Oscar Andersen
951ea815b8 cosmetic fix in qmqttclient.h after API review
Moved declaration of the new connectToHostWebSocket[Secure]
afer connectToHostEncrypted

Task-number: QTBUG-137478
Pick-to: 6.10
Change-Id: I58ef8da23bf9759a1744908e02c6b9ef5db405f1
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-06-12 08:23:11 +02:00
Qt Submodule Update Bot
27a5c3ce6b Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I1de43ec97d385dfb22be3908444106d911b0dfc6
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-24 01:05:08 +00:00
Qt Submodule Update Bot
d09d1fbf67 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I5856f01258f66531f630498d347d9e7b4abc1841
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-21 11:10:34 +00:00
Qt Submodule Update Bot
f542cfa1a4 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0684185387dd54082efc089b588d10aec101a8a6
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-18 11:34:05 +00:00
Qt Submodule Update Bot
22b5735162 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I178cf8b191d92ccd0b5eff57b07f70ee25f09c63
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-13 21:31:06 +00:00
Qt Submodule Update Bot
5b5dee5f74 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib21e6cac99074663dc91eee737af41225a3aa7e0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-08 16:39:13 +00:00
Qt Submodule Update Bot
9c04ffb5c3 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib2312b9c2a8a2f5d61b56bfa405d259cc7cb3dda
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-03 03:37:03 +00:00
Qt Submodule Update Bot
7ce0033a38 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I6308729917e195f4a8aec5328285f00fff913410
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-05-01 09:33:52 +00:00
Qt Submodule Update Bot
ec49cefbaf Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib0f38c485af7f093122f5a2739ee90f365103ada
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-04-29 15:16:48 +00:00
Qt Submodule Update Bot
11172cfa34 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Idaac3051ff5ff6656e43f0327cc8d9c4da0946cb
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-04-24 10:35:47 +00:00
Michal Klocek
9929b7c148 Band-aid patch for overriding mosquitto installation detection
Currently installation is detected by looking for 'mqtt.conf' files,
which are set during provisioning in install-mosquitto-mqtt.sh
and install-mosquitto.ps1. However, this only reflects installation on
the build machine and not on test node. Therefore, add a way to disable
it on WOA also when cross compiled despite of existence of
'mqtt.conf' files on build node.

This is just barely a band aid patch as handling should be really done
during provisioning by Set-EnvironmentVariable, which than could be
read directly by test node as {{.Env.XXX}. However, it would also require the test to detect the setting during runtime and not during compile time.

Note the native arm64 windows setup has no mosquitto installation,
therefore this patch does not change anything for current native windows
arm setup, it only overrides setup for cross compilation node.

Task-number: COIN-1211
Change-Id: Ie6e84b6b04da48c1df284a388022f31ba1eea93e
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2025-04-11 08:01:20 +00:00
Qt Submodule Update Bot
97fd1f585f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Id96ae45b056d46ea5bf62bc0c89eb4b92f65e0ed
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-04-03 16:38:58 +00:00
Qt Submodule Update Bot
2465b63c36 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I3f33036115fd78c2bb44973ead264a0bed78bd07
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-04-01 13:26:22 +00:00
Qt Submodule Update Bot
c04fcebf93 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I573c1e68a9c5d65c57eca4b56a214b8cfa65c6ea
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-03-29 16:47:26 +00:00
Paul Wicking
2cfbbfd24e Add .gitreview file
`git-review` is a command line tool for interacting with Gerrit.
Some IDEs offer support for this tool, either natively or through
plugins. The tool relies on a configuration file, .gitreview. Adding
this configuration file to our repositories simplifies initial setup
for contributors that use the tool directly or through their IDE of
choice.

The configuration file adds a remote called 'gerrit'. This is the
default for the tool, and also the name set for
codereview.qt-project.org by Qt's `init-repository` script. Thus,
the configuration should work seamlessly alongside other repository
helpers.

Task-number: QTBUG-132604
Pick-to: 6.9 6.8
Change-Id: I5b2f0c79f58d97fcc9cb339d663d9cb15cd09c57
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
2025-03-24 15:22:02 +01:00
Qt Submodule Update Bot
b5bd818d22 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Id6dfed84e1357377c11ab0171d3b615cbbf879d2
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-03-19 18:31:03 +00:00
Lucie Gérard
0c91902e7e Update licensing of files with infrastructure type
A QUIP 18[1] update sets git files, REUSE.toml and licenseRule.json
as infrastructure type files. They are licensed with:
LicenseRef-Qt-Commercial OR BSD-3-Clause

[1]: https://contribute.qt-project.org/quips/18

Pick-to: 6.9 6.8
Change-Id: I03d77977a9ee6e41d0a7b45dbe9dc3006c2cce83
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2025-03-14 13:37:56 +01:00
Lucie Gérard
609f3fe7eb Remove unnecessary comment
Pick-to: 6.9 6.8
Change-Id: Ib2c53483e2fe011c239df0918663a75e98641e0e
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-03-05 09:37:10 +01:00
Qt Submodule Update Bot
9048f80e3a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ia06b68d234528992174e8ba1f1b25b0a0752dd33
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-02-28 09:13:41 +00:00
Lucie Gérard
6b9b462bb5 Make module ready for source SBOM checking
This includes:
- turning VERIFY_SOURCE_SBOM ON
- adding exception to the licenseRule.json files
- correcting the licensing given via REUSE.toml files

A lot of files are skipped during the license test,
but all are present in the source SBOM.
This is why  correction are needed before turning the
source SBOM check on.

Task-number: QTBUG-131434
Pick-to: 6.9
Change-Id: I5398523eafdae59a234bc2ed5ddd229c0aa923df
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2025-02-21 07:45:57 +00:00
Qt Submodule Update Bot
d0ee0581d0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ic6437947f3193cb5b8566d6e8094781925184503
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-02-20 11:57:14 +00:00
Qt Submodule Update Bot
af0893b8bb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I10122a727ab1fb3273aa3d5a9c2996bba8e0c135
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-02-19 17:58:37 +00:00
Qt Submodule Update Bot
0473d461f5 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I93c88e4acbc28f9976e99a6512fddfd50641aa0a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-02-19 05:29:38 +00:00
Qt Submodule Update Bot
5d29379dfb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I64add92d00913c692797554b5154ea2220f66055
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-02-18 15:51:34 +00:00
Even Oscar Andersen
f9305b56d9 Add websockets as an optional dependency on qtmqtt
Change-Id: I82e1e809adef35d1d09ec248c69f4f49eca8b0f2
Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
2025-01-30 09:11:48 +01:00
Even Oscar Andersen
8316766cec Add tests for websocket support for mqtt
For at least one platform run the twelve combinations of:
 Transport: [Tcp,Ssl,Ws,Wss]
 Protocol: [3.1, 3.1.1, 5.0]

This happens if the following defines are present:
  MQTT_TEST_BROKER
  MQTT_TEST_TYPE
  MQTT_TEST_PROTOCOL

If these are not defined, the old test behavior is kept

The logic is that we are replacing the type of VersionClient
to homegrown logic that replaces connectToHost with the
correct function:
  connectToHost
  connectToHostEncrypted,
  connectToHostWebSocket
  connectToHostWebSocketEncrypted

For this to work it is important that the VersionClient
macro is used everywhere.

Also, DefaultVersionTestData has been changed to
return version(0) if MQTT_TEST_PROTOCOL is defined,
we will now run one protocol at the time instead.

This is Change Request 2 of 2 wrt testing.

Task-number: QTBUG-129171
Change-Id: I4f68d7c2ea226a1107f009c80f87f8b749d9f120
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
2025-01-29 15:54:55 +01:00
Even Oscar Andersen
967c70f1d5 Use VersionClient macro everywhere
We want to use the VersionClient macro to iterate over
version,connectiontype. To do this (in a later patch)
it is necessary that VersionClient is used everywhere.

This is change request 1 of 2 wrt mqtt tests.

Task-number: QTBUG-129171
Change-Id: Ica2f97bc2fd130cc49191d7381d49e88e8dc4a0c
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
2025-01-29 12:40:15 +01:00
Even Oscar Andersen
dec643fc61 Add websocket support for mqtt
Move the example IODevices to be used with websockets
under the mqtt umbrella.

Two (private) devices are created; QMqttSecureWebSocketIO
and QMqttWebSocketIO

Fixes: QTBUG-129171
Change-Id: Ib7d37150c3a229e882a0c04a32cdd8b7929baf3b
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
2025-01-29 07:42:34 +01:00
Even Oscar Andersen
24f5eceea2 Replace raw m_transport pointer with std::shared_ptr
Preparing for the add websocket change request.

Using shared_ptr gives automatic lifetime management
and is needed when adding more transport types.

Task-number: QTBUG-129171
Change-Id: I347175c018963130f403f8e9fe764e77203383a9
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
2025-01-27 06:42:47 +01:00
Qt Submodule Update Bot
aa2fb73ac4 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I7cd9aed27c00b0470c2d336156cc581a00597480
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-01-23 19:56:18 +00:00
Qt Submodule Update Bot
3543195ee0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Icf63208ccf188653718b210a0d6ae529424d7a01
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-01-20 13:32:20 +00:00
Qt Submodule Update Bot
937974f18c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ibbc37bab74636877240d7af614765127a3d144e0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-01-14 18:18:02 +00:00
Qt Submodule Update Bot
ceeb04c46f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I81b0d58559b4eec930a43c470696233a0998b1fb
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-01-03 14:15:01 +00:00
Jani Heikkinen
d1f445af72 Bump version to 6.10.0
Change-Id: I95e2cd231e584635b5a1efddc04192a45c274378
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2025-01-03 14:15:00 +00:00
Volker Hilsheimer
7130aadcea Move logging category into new private global header
Addresses header review comemnts, amends
18bed862b2.

Task-number: QTBUG-132090
Fixes: QTBUG-132164
Pick-to: 6.9
Change-Id: I7d8f2b048482e18112b02374fe53f2bbed52021e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
2024-12-17 13:48:37 +01:00
Qt Submodule Update Bot
b118aafb0b Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I610c91b8895a9466575dec1e2a47feb784783bb0
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-12-08 17:02:31 +00:00
Qt Submodule Update Bot
9aec010a74 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I11b6c11833d5f35a8bef63ed8dbe0175482de226
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-12-08 03:30:11 +00:00
Qt Submodule Update Bot
aeac9f7e17 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ic9cea01fc588b15225e9245d83231ec09c535325
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-12-03 13:50:10 +00:00
Qt Submodule Update Bot
5a0b137e9e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0716289397822076834c4ec245cdc5920cc21729
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-12-02 13:50:33 +00:00
Jøger Hansegård
f6f8bc0fe4 Add CMakeUserPresets.json to .gitignore
The CMakeUserPresets.json file can be used to simplify configuring Qt,
particularly with tools such as Visual Studio and Visual Studio Code.

As opposed to the CMakePresets.json, the CMakeUserPresets.json should
only contain user specific configurations, and should never be checked
into source code management system.

This file is already ignored in the top level Qt super-project, but to
facilitate working with each individual submodule, we should also have
this .gitignore in each submodule.

Pick-to: 6.8
Change-Id: Ic12b3cce1b1082f206d076532f5d68452805ed08
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Even Oscar Andersen <even.oscar.andersen@qt.io>
2024-11-28 18:02:47 +01:00
Jøger Hansegård
45ab6b8cd2 Only call find_package when building tests as standalone
This allows us to build manual tests together with Qt by specifying
QT_BUILD_MANUAL_TESTS and QT_BUILD_TESTS. A benefit of doing this, is
that the manual tests show up as debuggable targets with IDEs such as
Visual Studio Code, while keeping full code navigation capabilities into
the Qt code.

Pick-to: 6.8
Change-Id: Idd309c06fb2586fd634386951a3345aa40bc093a
Reviewed-by: Even Oscar Andersen <even.oscar.andersen@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2024-11-28 18:02:17 +01:00
Qt Submodule Update Bot
8452101eca Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I5a9a7ec519bf43dd2833271c5ae0e2e56020f42a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-28 12:18:13 +00:00
Qt Submodule Update Bot
1de96c8ec1 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I48ae9d954bb377a8ab7c71b84ebbcd025ce2e1f8
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-26 15:29:21 +00:00
Qt Submodule Update Bot
048d6bebbb Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0fff0ee90623922bcaddc6bee4199e492c1ca812
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-25 22:12:51 +00:00
Even Oscar Andersen
b539b0c38b Fix signal/slot problem with quicksubscription example
The example does not build with latest changes.

As it turns out there is a mismatch between the topic property
and the connected signal. Since the signal is not used, it is
removed in the hope that it will then build.

The error message from the build is:

Failure Summary:
The build failed due to a compilation error in 'qmlmqttclient.cpp'.
The function 'QmlMqttSubscription::topicChanged()' was called without
the required 'QString' argument.

Log snippet:
error: no matching function for call to ‘QmlMqttSubscription::topicChanged()’
note: candidate: ‘void QmlMqttSubscription::topicChanged(QString)’
note: candidate expects 1 argument, 0 provided

Change-Id: Ia8cedda578e2f2c082354892bd00cb9fd25b5652
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-11-20 17:36:32 +01:00
Qt Submodule Update Bot
83db4482e7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I319161c12707baa74acb06a988b34d6170baa6ae
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-20 16:36:28 +00:00
Lucie Gérard
cb00ee0cff Add REUSE.toml files and missing licenses
REUSE.toml files are read by reuse to complement or override the
copyright and licensing information found in file.

The use of REUSE.toml files was introduced in REUSE version 3.1.0a1.
This reuse version is compatible with reuse specification
version 3.2 [1].
With this commit's files,
* The SPDX document generated by reuse spdx conforms to SPDX 2.3,
* The reuse lint command reports that the Qt project is reuse compliant.

In order to be reuse compliant all the licenses present in the
LICENSES directory must be used. License files not used are removed.

[1]: https://reuse.software/spec-3.2/

Task-number: QTBUG-124453
Task-number: QTBUG-125211
Pick-to: 6.8
Change-Id: If5891d7b09a559e55081ef4e9111d91eb49a6b14
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2024-11-14 12:24:58 +00:00
Qt Submodule Update Bot
264ce67ade Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I0eedefc1a3ee5119970cc3c858e1f2369474e031
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-07 05:22:55 +00:00
Qt Submodule Update Bot
f17511d6f5 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I043938cf3dd509f5e28cb4b8fdf62f43d535f834
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-06 11:58:18 +00:00
Topi Reinio
5400305ccf Doc: Enable documentation testing in the CI
Include documentation testing steps in coin/module_config.yaml and
set the warning limit to zero.

Task-number: QTBUG-130559
Change-Id: I00593599b978406ec2fe166273be479d29f3a8e5
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
2024-11-04 11:24:39 +00:00
Qt Submodule Update Bot
2bf9713ece Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iff52463fb25dbda8fdbba6af713ec99a6cea4806
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-11-01 18:10:00 +00:00
Qt Submodule Update Bot
5f8de4a443 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ifdd09fab0f59f5f3fc5aefbfc3f63d2811a205c6
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-10-30 20:14:55 +00:00
Qt Submodule Update Bot
fd2a5b9d4e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib5946e102f2d7f59a9d8e0e64bd7f81390229bcc
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-10-23 03:22:15 +00:00
Qt Submodule Update Bot
e321f4663b Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I079d8af75b2929fee57fb625d92741918d460705
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-27 06:59:33 +00:00
Qt Submodule Update Bot
f1b13c908a Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ieec8f837a1902f929d9bacddccd54ae6cc1c1597
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-25 04:24:27 +00:00
Qt Submodule Update Bot
ba488ed615 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iba24b0f940d43fceba2fc4d4b99c9af2cbf55e8b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-23 18:09:28 +00:00
Qt Submodule Update Bot
06f07a00a8 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I6ab3b0900bd92e9fe66d74a56ef96a1384fd0b1d
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-20 16:57:40 +00:00
Qt Submodule Update Bot
50677c5da2 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie914acb8f8718fa8465a03aee87a11c076f4411a
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-11 07:09:17 +00:00
Qt Submodule Update Bot
cec66481b3 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ib10adc31ce68dc076afaeda8daf22dfa99625758
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-05 05:14:16 +00:00
Qt Submodule Update Bot
575e141bb0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I45d14154ce8830934a5a11102ee64977213c0508
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-09-03 18:42:42 +00:00
Qt Submodule Update Bot
84888e818e Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I9073c080ab86a24281bb9bfa33b4751915fc3cad
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-31 07:01:24 +00:00
Qt Submodule Update Bot
fefcebc0f3 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I2452d0f49d0765dab5c729c2a6593d79f708a544
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-29 07:11:20 +00:00
Qt Submodule Update Bot
8dc327b4ba Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I48a5e0e0ab862f6250092df36047104cfe7d1d99
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-28 01:39:07 +00:00
Qt Submodule Update Bot
c15616b0a7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I9bedf4a768bf77236570023fef1b1926d97ee3fc
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-24 05:54:12 +00:00
Qt Submodule Update Bot
334f06a95f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I17def9c64152d66a7e77cee345c03d030b53e8f4
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-21 21:14:12 +00:00
Qt Submodule Update Bot
240875588c Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I669882ed4f72ffa329239a574d9d50f186ea832e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-19 11:36:18 +00:00
Qt Submodule Update Bot
0eee872326 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I2bd212ad4d12f40487c9299ea9abf8e867eb53c3
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-14 21:27:03 +00:00
Qt Submodule Update Bot
6490484c9d Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I8da68d76d458a7d8578f238260a492102030b842
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-09 12:41:23 +00:00
Alexei Cazacov
5fcdb78b9c Docs: Organize topics in the qtmqtt repo
This commit organizes the articles, so they:
- have a reasonable tree structure
- can be navigated through the topic tree in the Qt Creator help viewer

Task-number: QTBUG-127289
Change-Id: I877bf1c62485161177ebe78f8326a4f979886cc5
Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
2024-08-07 08:20:14 +00:00
Qt Submodule Update Bot
3a7f631998 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I12fa23e0df7292e3c448e7afe6b1b56c28ccaec3
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-06 22:39:14 +00:00
Qt Submodule Update Bot
87d82a895f Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I36a06d6ee579ac1d0013b730b4b09c7eb9407240
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-08-01 11:11:38 +00:00
Volker Hilsheimer
18bed862b2 Clean up logging categories
Declare them in a suitable header if they are used across multiple
unrelated files, otherwise use Q_STATIC_LOGGING_CATEGORY.

Unbreaks -Werror built.

Change-Id: Ic0759a2185be4288e8c7791c3a9cf22371d2d477
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
2024-07-31 11:40:25 +02:00
Qt Submodule Update Bot
314a9bd0f6 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ide41d158581a7fe535f1ac25f6a6b07e396d5ee2
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-07-30 15:09:07 +00:00
Qt Submodule Update Bot
a87700e0d0 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I5e2899978b80ed0c4733940c15ece1eb0aa7789b
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-07-26 16:10:28 +00:00
Qt Submodule Update Bot
386ca7d5b8 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I62492ac5cc1ed55f518ca6d9ddf1e0f62f223e8c
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-07-21 23:40:08 +00:00
Qt Submodule Update Bot
362b9a9e08 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I831b3c834a1044684ad934afa3edc60daee4217e
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-07-17 23:49:10 +00:00
Qt Submodule Update Bot
3813cf3bdd Update dependencies on 'dev' in qt/qtmqtt
Change-Id: If98e6cb3093a6bf27b5a1b4b2f23d3ba0e756d76
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-07-11 14:09:12 +00:00
Alexandru Croitor
45a786170c CMake: Annotate some targets with SBOM information
Pick-to: 6.8
Task-number: QTBUG-122899
Change-Id: I7034d7a15f378b935624b1f957fb251c5cd16ad9
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2024-07-11 12:02:38 +02:00
Qt Submodule Update Bot
3f24adc297 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I26b774832e3cdf2ae021d304eb1865f51230a000
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-28 23:44:19 +00:00
Qt Submodule Update Bot
a8125e63e4 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I55110f65c422af76131371168ebbe5450417a1c8
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-25 20:06:49 +00:00
Qt Submodule Update Bot
5c5c9c44d7 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ic1c26194b6f2d52761b8e4300aa056b81f2a4485
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-20 08:30:09 +00:00
Qt Submodule Update Bot
dd6bf765ed Update dependencies on 'dev' in qt/qtmqtt
Change-Id: I522b1d4dbc31f94ab626e51cc4f66a18dd7c3919
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-18 23:28:04 +00:00
Qt Submodule Update Bot
a66f4ab2aa Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ie6fb0cbffaeb52055b45d9cd5f40ddf6d9b3e535
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-14 14:08:15 +00:00
Qt Submodule Update Bot
06e4c4e9b5 Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Ia35e9b08f1ed40250067a3517c0bed32f475e6a3
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-11 03:13:55 +00:00
Jani Heikkinen
b1317fcbfe Bump version to 6.9.0
Change-Id: Icbf5bb9d13324cb692464a96fd7b5cbca89961ab
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-06 03:49:39 +01:00
Qt Submodule Update Bot
5ce02acf9b Update dependencies on 'dev' in qt/qtmqtt
Change-Id: Iead1bfbbb6f46429cb53abc20bd789dfa2871ddd
Reviewed-by: Qt Submodule Update Bot <qt_submodule_update_bot@qt-project.org>
2024-06-06 02:49:38 +00:00
Alexey Edelev
613fbbab5c Remove the use of GENERATE_CPP_EXPORTS argument
The behavior that argument was enabling is the default one now.

Pick-to: 6.8
Task-number: QTBUG-90492
Change-Id: I4e59f9ce590f76fd077cf1dafa7a423e6f958b5a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2024-06-05 12:09:25 +00:00
87 changed files with 2858 additions and 537 deletions

View File

@ -1,4 +1,5 @@
set(QT_REPO_MODULE_VERSION "6.8.0")
set(QT_REPO_MODULE_VERSION "6.13.0")
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_QASCONST=1")
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_FOREACH=1")
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_SINGLE_ARGUMENT_QHASH_OVERLOAD=1")

1
.gitignore vendored
View File

@ -68,6 +68,7 @@ Makefile*
# QtCtreator CMake
CMakeLists.txt.user*
CMakeUserPresets.json
## Visual Studio
# User-specific files

4
.gitreview Normal file
View File

@ -0,0 +1,4 @@
[gerrit]
host=codereview.qt-project.org
project=qt/qtmqtt
defaultbranch=dev

View File

@ -11,9 +11,14 @@ project(QtMqtt
LANGUAGES CXX C
)
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core Network)
find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS Quick WebSockets # For tests
Gui Widgets) # For examples
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals)
# This should be called as early as possible, just after find_package(BuildInternals) where it is
# defined.
qt_internal_project_setup()
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core Network)
find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS Quick # For tests
Gui Widgets WebSockets) # For examples
qt_build_repo()

11
CONTRIBUTING.md Normal file
View File

@ -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.

View File

@ -1,22 +0,0 @@
The Qt Company GPL Exception 1.0
Exception 1:
As a special exception you may create a larger work which contains the
output of this application and distribute that work under terms of your
choice, so long as the work is not otherwise derived from or based on
this application and so long as the work does not in itself generate
output that contains the output from this application in its original
or modified form.
Exception 2:
As a special exception, you have permission to combine this application
with Plugins licensed under the terms of your choice, to produce an
executable, and to copy and distribute the resulting executable under
the terms of your choice. However, the executable must be accompanied
by a prominent notice offering all users of the executable the entire
source code to this application, excluding the source code of the
independent modules, but including any changes you have made to this
application, under the terms of this license.

44
REUSE.toml Normal file
View File

@ -0,0 +1,44 @@
version = 1
[[annotations]]
path = [".cmake.conf", "**.yaml", "**/ci_config_linux.json", "**.pro", ".tag"]
precedence = "closest"
comment = "build system"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "BSD-3-Clause"
[[annotations]]
path = ["**/.gitattributes", "**.gitignore", "**.gitreview"]
precedence = "closest"
comment = "version control system. Infrastructure"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
[[annotations]]
path = ["**/doc/images/**", "examples/**"]
comment = "this must be after the build system table because example and snippets take precedence over build system"
precedence = "closest"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
[[annotations]]
path = ["**.qdocconf", "src/mqtt/doc/style/style.css",
"tests/README.txt", "CONTRIBUTING.md"]
comment = "documentation"
precedence = "closest"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"
[[annotations]]
path = ["**.toml", "licenseRule.json"]
comment = "infrastructure"
precedence = "override"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause"
[[annotations]]
path = ["**/qt_attribution.json"]
comment = "currently not needed, but ready if such file is added. documentation."
precedence = "override"
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"

View File

@ -6,7 +6,23 @@ accept_configuration:
instructions:
Build:
- type: EnvironmentVariable
variableName: VERIFY_SOURCE_SBOM
variableValue: "ON"
- type: EnvironmentVariable
variableName: COIN_NO_MOSQUITTO
variableValue: "1"
enable_if:
condition: and
conditions:
- condition: property
property: host.os
equals_value: Windows
- condition: property
property: target.arch
in_values: ["AARCH64", "ARM64"]
- !include "{{qt/qtbase}}/coin_module_build_template_v2.yaml"
Test:
- !include "{{qt/qtbase}}/coin_module_test_template_v2.yaml"
- !include "{{qt/qtbase}}/coin_module_test_template_v3.yaml"
- !include "{{qt/qtbase}}/coin_module_test_docs.yaml"

View File

@ -1,7 +1,10 @@
dependencies:
../qtbase:
ref: 244964d06a3ffcfea922f79c726ba9182149e2c7
ref: 537c0040b0c1a1b3bae99e9edca827c9e3a16ee7
required: true
../qtdeclarative:
ref: 4ad3d0c6096e6caefec74681eed86c2fa92149fd
ref: 3c20488ac4a676c612cef9539144194a4fb86801
required: true
../qtwebsockets:
ref: 217120e4e991ed2de51cac910cccfbf51f912e65
required: false

8
dist/REUSE.toml vendored Normal file
View File

@ -0,0 +1,8 @@
version = 1
[[annotations]]
path = ["*"]
precedence = "override"
comment = "Licensed as documentation."
SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd."
SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -10,6 +10,8 @@
topics.
\image quickpublication.png
{MQTT publishing interface with Hostname, Port, Topic, Message, QoS,
and Retain fields}
\e {Qt Quick Publication} demonstrates how to register QMqttClient as a QML type and
use it in a Qt Quick application.

View File

@ -10,6 +10,8 @@
topics.
\image quicksubscription.png
{MQTT subscription interface with Hostname, Port, Topic fields, Connect
and Subscribe buttons}
\e {Qt Quick Subscription} demonstrates how to register QMqttClient as a QML type and
use it in a Qt Quick application.

View File

@ -9,18 +9,61 @@
\brief Creating a minimalistic telemetry application.
\image simpleclient.png
{MQTT client with Host, Port, Protocol fields, WebSockets and Secure
options, Topic and Message inputs, and log showing state changes}
\e {Simple MQTT Client} demonstrates how to create a minimalistic client
application.
To use the application, you first specify a broker, such as
\e test.mosquitto.org or \e broker.hivemq.com and the port number 1883, and
connect to it. You can then subscribe to a topic and send a message, which
you will also receive.
To use the application, you first specify a Host, a Port, Secure on/off,
WebSockets on/off, and Protocol. Then click on connect. Afterward you can
subscribe to a topic and send a message, which you will also receive.
You may also run the application twice. Publish in one and Subscribe in
the other, and the messages shall be transmitted.
\note Port number 1883 is not encrypted, and therefore it is suitable only
for development and testing purposes. In production, always use encrypted
connections.
\section1 simpleclient Options
\list
\li Host - you may use test.mosquitto.org or broker.hivemq.com
\li Port - port to connect to, will depend on WebSockets selection and Secure selection
\li WebSockets - you may specify: selected (enabled) or not selected (disabled)
\li Secure - you may specify: selected (enabled) or not selected (disabled)
\li Protocol - you may specify
\list
\li mqtt 3.1
\li mqtt 3.1.1
\li mqtt 5.0
\endlist
\li Topic - A topic to publish or subscribe to
\li Message - A message to send on the topic if you are publishing
\endlist
\section1 Connection Settings
These are the usual combinations, and will work with test.mosquitto.org.
For broker.hivemq.com check the information in the links. Note that if
Secure is enabled it might be necessary to install certificates on the
computer. It might also be necessary to add the certificate to the mqtt
client in code.
\section1
\list
\li Port 1883, Secure=disabled, WebSockets=disabled - mqtt over tcp
\li Port 8883, Secure=enabled, WebSockets=disabled - mqtt over ssl
\li Port 8080, Secure=disabled, WebSockets=enabled - mqtt over websockets
\li Port 8081, Secure=enabled, WebSockets=enabled - mqtt over secure websockets
\endlist
For more information about the brokers see:
\list
\li \l {https://test.mosquitto.org}
\li \l {https://broker.hivemq.com}
\li \l {https://www.hivemq.com/mqtt/public-mqtt-broker}
\endlist
\note Port numbers 1883 and 8080 are not encrypted, and therefore they are
suitable only for development and testing purposes. In production, always
use encrypted connections.
\note WebAssembly only supports WebSockets enabled.
\section1 Creating a Client

View File

@ -9,6 +9,8 @@
\brief Creating a application that communicates with an MQTT broker.
\image subscriptions.png
{Main window with connection and publishing controls, and two
subscription windows showing received messages on qtmqtt/topic1}
\e {MQTT Subscriptions} shows how to create an application that communicates
with an MQTT broker. A new dialog opens for each subscription, where you can

View File

@ -12,6 +12,9 @@
QIODevice to combine a \l {Qt WebSockets}{web socket} connection with
QMqttClient.
\note Since Qt 6.10, WebSockets are supported natively by Qt MQTT.
This example is retained to demonstrate how to implement a custom transport.
\section1 Creating a Custom QIODevice
The new custom device, \c WebSocketIODevice, has to be a subclass of

View File

@ -9,7 +9,6 @@ QmlMqttSubscription::QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c)
, client(c)
{
connect(sub, &QMqttSubscription::messageReceived, this, &QmlMqttSubscription::handleMessage);
m_topic = sub->topic();
}
QmlMqttSubscription::~QmlMqttSubscription()

View File

@ -15,14 +15,12 @@ class QmlMqttClient;
class QmlMqttSubscription : public QObject
{
Q_OBJECT
Q_PROPERTY(QMqttTopicFilter topic MEMBER m_topic NOTIFY topicChanged)
QML_UNCREATABLE("Not intended to be creatable")
public:
QmlMqttSubscription(QMqttSubscription *s, QmlMqttClient *c);
~QmlMqttSubscription();
Q_SIGNALS:
void topicChanged(QString);
void messageReceived(const QString &msg);
public slots:
@ -32,7 +30,6 @@ private:
Q_DISABLE_COPY(QmlMqttSubscription)
QMqttSubscription *sub;
QmlMqttClient *client;
QMqttTopicFilter m_topic;
};
class QmlMqttClient : public QObject

View File

@ -41,6 +41,9 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->lineEditHost, &QLineEdit::textChanged, m_client, &QMqttClient::setHostname);
connect(ui->spinBoxPort, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::setClientPort);
connect(ui->checkBoxWebSockets, &QCheckBox::checkStateChanged, this, [this](int ws) { setWebSockets(ws != 0); });
connect(ui->checkBoxSecure, &QCheckBox::checkStateChanged, this, [this](int s) { setSecure(s != 0); } );
connect(ui->comboBoxProtocol, &QComboBox::currentIndexChanged, this, [this](int p) { setProtocol(static_cast<QMqttClient::ProtocolVersion>(p + 3)); });
updateLogStateChange();
}
@ -55,7 +58,27 @@ void MainWindow::on_buttonConnect_clicked()
ui->lineEditHost->setEnabled(false);
ui->spinBoxPort->setEnabled(false);
ui->buttonConnect->setText(tr("Disconnect"));
m_client->connectToHost();
m_client->setProtocolVersion(m_protocol);
if (m_secure && m_webSockets)
m_client->connectToHostWebSocketEncrypted();
#if !defined(QT_NO_SSL) && !defined(Q_OS_WASM)
if (m_secure && !m_webSockets)
m_client->connectToHostEncrypted({});
#endif
if (!m_secure && m_webSockets)
m_client->connectToHostWebSocket();
#if !defined(Q_OS_WASM)
if (!m_secure && !m_webSockets)
m_client->connectToHost();
#endif
if (m_client->state() == QMqttClient::Disconnected) {
ui->lineEditHost->setEnabled(true);
ui->spinBoxPort->setEnabled(true);
ui->buttonConnect->setText(tr("Connect"));
m_client->disconnectFromHost();
}
} else {
ui->lineEditHost->setEnabled(true);
ui->spinBoxPort->setEnabled(true);
@ -90,6 +113,21 @@ void MainWindow::setClientPort(int p)
m_client->setPort(static_cast<quint16>(p));
}
void MainWindow::setSecure(bool s)
{
m_secure = s;
}
void MainWindow::setWebSockets(bool ws)
{
m_webSockets = ws;
}
void MainWindow::setProtocol(QMqttClient::ProtocolVersion p)
{
m_protocol = p;
}
void MainWindow::on_buttonPublish_clicked()
{
if (m_client->publish(ui->lineEditTopic->text(), ui->lineEditMessage->text().toUtf8()) == -1)

View File

@ -23,7 +23,9 @@ public:
public slots:
void setClientPort(int p);
void setSecure(bool s);
void setWebSockets(bool ws);
void setProtocol(QMqttClient::ProtocolVersion p);
private slots:
void on_buttonConnect_clicked();
void on_buttonQuit_clicked();
@ -36,8 +38,11 @@ private slots:
void on_buttonSubscribe_clicked();
private:
Ui::MainWindow *ui;
QMqttClient *m_client;
Ui::MainWindow *ui = nullptr;
QMqttClient *m_client = nullptr;
bool m_secure = false;
bool m_webSockets = false;
QMqttClient::ProtocolVersion m_protocol = QMqttClient::ProtocolVersion::MQTT_3_1_1;
};
#endif // MAINWINDOW_H

View File

@ -18,9 +18,9 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<widget class="QLabel" name="labelHost">
<property name="text">
<string>Host:</string>
</property>
@ -33,8 +33,15 @@
</property>
</widget>
</item>
<item row="0" column="2" rowspan="3">
<widget class="QPushButton" name="buttonConnect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="labelPort">
<property name="text">
<string>Port:</string>
</property>
@ -43,51 +50,69 @@
<item row="2" column="1">
<widget class="QSpinBox" name="spinBoxPort">
<property name="maximum">
<number>99999</number>
<number>65535</number>
</property>
<property name="value">
<number>1883</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelWebSockets">
<property name="text">
<string>WebSockets:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="checkBoxWebSockets" />
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelSecure">
<property name="text">
<string>Secure:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="checkBoxSecure" />
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelProtocol">
<property name="text">
<string>Protocol:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="comboBoxProtocol">
<item>
<property name="text">
<string>mqtt 3.1</string>
</property>
</item>
<item>
<property name="text">
<string>mqtt 3.1.1</string>
</property>
</item>
<item>
<property name="text">
<string>mqtt 5.0</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="buttonConnect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditMessage">
<layout class="QGridLayout" name="gridLayout2">
<item row="0" column="0">
<widget class="QLabel" name="labelTopic">
<property name="text">
<string>This is a test message</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="buttonSubscribe">
<property name="text">
<string>Subscribe</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="buttonPublish">
<property name="text">
<string>Publish</string>
<string>Topic:</string>
</property>
</widget>
</item>
@ -98,10 +123,31 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<item row="0" column="2">
<widget class="QPushButton" name="buttonSubscribe">
<property name="text">
<string>Topic:</string>
<string>Subscribe</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelMessage">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditMessage">
<property name="text">
<string>This is a test message</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="buttonPublish">
<property name="text">
<string>Publish</string>
</property>
</widget>
</item>
@ -114,7 +160,11 @@
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPlainTextEdit" name="editLog"/>
<widget class="QPlainTextEdit" name="editLog">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
@ -145,37 +195,6 @@
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionQuit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>

View File

@ -1,6 +1,6 @@
[
{
"comment" : ["file_pattern_ending: strings matched against the end of a file name.",
"comment": ["file_pattern_ending: strings matched against the end of a file name.",
"location keys: regular expression matched against the beginning of",
"the file path (relative to the git submodule root).",
"spdx: list of SPDX-License-Expression's allowed in the matching files.",
@ -9,75 +9,100 @@
"unless they are examples",
"Files with other endings can also be build system files"
],
"file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf",
"configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in"],
"location" : {
"" : {
"comment" : "Default",
"file type" : "build system",
"spdx" : ["BSD-3-Clause"]
"file_pattern_ending": ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf",
"configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in",
".cmake.conf", ".tag", "ci_config_linux.json", ".yaml"],
"location": {
"": {
"comment": "Default",
"file type": "build system",
"spdx": ["BSD-3-Clause"]
},
"(.*)(examples/|snippets/)" : {
"comment" : "Example takes precedence",
"file type" : "examples and snippets",
"spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
"(.*)(examples/|snippets/)": {
"comment": "Example takes precedence",
"file type": "examples and snippets",
"spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
}
}
},
{
"comments" : ["Files with the following endings are Tool licensed,",
"comments": ["Files with the following endings are infrastructure licensed"],
"file_pattern_ending": [".gitattributes", ".gitignore", ".gitmodules", ".gitreview",
"_clang-format", "licenseRule.json", "REUSE.toml"],
"location":{
"": {
"comment": "Default",
"file type": "infrastructure",
"spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
}
}
},
{
"comments": ["Files with the following endings are Tool licensed,",
"unless they are examples.",
"Files with other endings can also be tool files."],
"file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"],
"location" :{
"" : {
"comment" : "Default",
"file type" : "tools and utils",
"spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"]
"file_pattern_ending": [".sh", ".py", ".pl", ".bat", ".ps1"],
"location":{
"": {
"comment": "Default",
"file type": "tools and utils",
"spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"]
},
"(.*)(examples/|snippets/)" : {
"comment" : "Example takes precedence",
"file type" : "examples and snippets",
"spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
"(.*)(examples/|snippets/)": {
"comment": "Example takes precedence",
"file type": "examples and snippets",
"spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
}
}
},
{
"comment" : "Files with the following endings are Documentation licensed.",
"file_pattern_ending" : [".qdoc", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"],
"location" :{
"" : {
"comment" : "",
"file type" : "documentation",
"spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
"comment": "Files with the following endings are documentation licensed.",
"file_pattern_ending": [".qdoc", ".qdocinc" , ".qdocconf", ".css",
"README.txt", "CONTRIBUTING.md",
"qt_attribution.json"],
"location":{
"": {
"comment": "",
"file type": "documentation",
"spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
}
}
},
{
"comment" : ["All other files",
"comment": ["All other files",
"The licensing is defined only by the file location in the Qt module repository.",
"NO <file_pattern_ending> key for this case!",
"This needs to be the last entry of the file."],
"location" : {
"" : {
"comment" : "Default",
"file type" : "module and plugin",
"spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
"location": {
"": {
"comment": "Default",
"file type": "module and plugin",
"spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
},
"src/" : {
"comment" : "Default",
"file type" : "module and plugin",
"spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
"dist/": {
"comment": "Default",
"file type": "documentation",
"spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"]
},
"tests/" : {
"comment" : "Default",
"file type" : "test",
"spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
"src/": {
"comment": "Default",
"file type": "module and plugin",
"spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
},
"(.*)(examples/|snippets/)" : {
"comment" : "Default",
"file type" : "examples and snippets",
"spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
"tests/": {
"comment": "Default",
"file type": "test",
"spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"]
},
"(.*)(examples/|snippets/)": {
"comment": "Default",
"file type": "examples and snippets",
"spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
},
".*/doc/images": {
"comment": "Default",
"file type": "examples and snippets",
"spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"]
}
}
}

View File

@ -1,4 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
set(QT_SBOM_DEFAULT_QT_LICENSE_ID_LIBRARIES "QT_COMMERCIAL_OR_GPL3")
add_subdirectory(mqtt)

View File

@ -12,7 +12,7 @@ qt_internal_add_module(Mqtt
qmqttconnection.cpp qmqttconnection_p.h
qmqttconnectionproperties.cpp qmqttconnectionproperties.h qmqttconnectionproperties_p.h
qmqttcontrolpacket.cpp qmqttcontrolpacket_p.h
qmqttglobal.h
qmqttglobal.h qmqttglobal_p.h
qmqttmessage.cpp qmqttmessage.h qmqttmessage_p.h
qmqttpublishproperties.cpp qmqttpublishproperties.h qmqttpublishproperties_p.h
qmqttsubscription.cpp qmqttsubscription.h qmqttsubscription_p.h
@ -27,8 +27,24 @@ qt_internal_add_module(Mqtt
Qt::Network
PRIVATE_MODULE_INTERFACE
Qt::CorePrivate
GENERATE_CPP_EXPORTS
)
qt_internal_extend_target(Mqtt
CONDITION
TARGET Qt::WebSockets
DEFINES
QT_MQTT_WITH_WEBSOCKETS
PUBLIC_LIBRARIES
Qt::WebSockets
SOURCES
transportLayers/mqtt_websocket_io_base.cpp
transportLayers/mqtt_websocket_io_base_p.h
transportLayers/mqtt_websocket_io.cpp
transportLayers/mqtt_websocket_io_p.h
transportLayers/mqtt_secure_websocket_io.cpp
transportLayers/mqtt_secure_websocket_io_p.h
)
qt_internal_add_docs(Mqtt
doc/qtmqtt.qdocconf
)

View File

@ -14,15 +14,20 @@ qhp.QtMqtt.virtualFolder = qtmqtt
qhp.QtMqtt.indexTitle = Qt MQTT
qhp.QtMqtt.indexRoot =
qhp.QtMqtt.subprojects = classes examples
qhp.QtMqtt.subprojects = overview classes examples
qhp.QtMqtt.subprojects.overview.title = Overview
qhp.QtMqtt.subprojects.overview.indexTitle = Qt MQTT Overview
qhp.QtMqtt.subprojects.overview.selectors = group:none
qhp.QtMqtt.subprojects.classes.title = C++ Classes
qhp.QtMqtt.subprojects.classes.indexTitle = Qt MQTT C++ Classes
qhp.QtMqtt.subprojects.classes.selectors = class fake:headerfile
qhp.QtMqtt.subprojects.classes.selectors = class namespace headerfile
qhp.QtMqtt.subprojects.classes.sortPages = true
qhp.QtMqtt.subprojects.examples.title = Examples
qhp.QtMqtt.subprojects.examples.indexTitle = Qt MQTT Examples
qhp.QtMqtt.subprojects.examples.selectors = fake:example
qhp.QtMqtt.subprojects.examples.selectors = example
qhp.QtMqtt.subprojects.examples.sortPages = true
headerdirs += ..
@ -40,3 +45,6 @@ manifestmeta.thumbnail.names += "QtMqtt/WebSockets MQTT Subscription*"
navigation.landingpage = "Qt MQTT"
navigation.cppclassespage = "Qt MQTT C++ Classes"
# Allow zero warnings when testing documentation in CI
warninglimit = 0

View File

@ -59,5 +59,5 @@
In addition, it is available under the
\l{GNU General Public License, version 3}.
\generatelist{groupsbymodule attributions-qtmqtt}
\annotatedlist attributions-qtmqtt
*/

View File

@ -21,7 +21,8 @@
broker. The other clients can subscribe to notifications on particular
topics sent by the client.
\image mqtt.png
\image mqtt.png {Broker distributing messages from Client 1 to Client 2
(Topic A) and Client 3 (Topics A and B)}
For example, if \e {Client 2} subscribes to messages on \e {Topic A}, it
receives a notification when \e {Client 1} sends a message on that topic.
@ -178,4 +179,18 @@
discarded. The broker \e{should} store the last message, but \e{may}
also discard it. This depends on the implementation of the broker.
\section1 Threading and Blocking Operations
Consider running \l QMqttClient and its related classes in a thread
separate from the UI thread.\l QMqttClient uses a \l QIODevice as
its transport, and some transport operations may block. For example,
QMqttClient::disconnectFromHost() may wait synchronously for pending
data to be written, with a timeout of up to 30 seconds. Calling it from
the UI thread can therefore block the UI event loop and make the
application unresponsive. Keeping the MQTT client and its transport in
a dedicated thread helps prevent potentially blocking I/O from affecting
UI responsiveness. Use signals and slots or other mechanisms that queue
work to the target thread to communicate between the MQTT thread and
the UI thread.
*/

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttauthenticationproperties.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTAUTHENTICATIONPROPERTIES_H
#define QMQTTAUTHENTICATIONPROPERTIES_H

View File

@ -1,9 +1,15 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:critical reason:network-protocol
#include "qmqttclient.h"
#include "qmqttclient_p.h"
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include "transportLayers/mqtt_websocket_io_p.h"
#include "transportLayers/mqtt_secure_websocket_io_p.h"
#endif // QT_MQTT_WITH_WEBSOCKETS
#include <QtCore/QLoggingCategory>
#include <QtCore/QUuid>
#include <QtCore/QtEndian>
@ -151,6 +157,21 @@ Q_LOGGING_CATEGORY(lcMqttClient, "qt.mqtt.client")
\sa keepAlive(), requestPing(), serverConnectionProperties(), pingResponseReceived()
*/
/*!
\property QMqttClient::readBufferSize
\since 6.13
\brief This property holds the size of the internal read buffer.
The property limits the amount of data that the client can receive
before you call read() or readAll().
A read buffer size of 0 (the default) means that the buffer has no size
limit, ensuring that no data is lost.
\note The limit is not applicable for a plain \c TransportType::IODevice
transport type.
*/
/*!
\enum QMqttClient::TransportType
@ -163,6 +184,12 @@ Q_LOGGING_CATEGORY(lcMqttClient, "qt.mqtt.client")
The transport uses a class based on a QAbstractSocket.
\value SecureSocket
The transport uses a class based on a QSslSocket.
\value [since 6.10] WebSocket
The transport uses a class based on a QIODevice,
which uses a QWebSocket internally.
\value [since 6.10] SecureWebSocket
The transport uses a class based on a QIODevice,
which uses a secure QWebSocket internally.
*/
/*!
@ -312,6 +339,15 @@ Q_LOGGING_CATEGORY(lcMqttClient, "qt.mqtt.client")
\sa authenticationRequested(), authenticate()
*/
/*!
\since 6.13
\fn QMqttClient::readBufferSizeChanged(qint64 size)
This signal is emitted when the \a size of internal read buffer is changed.
\sa readBufferSize()
*/
/*!
Creates a new MQTT client instance with the specified \a parent.
*/
@ -324,6 +360,7 @@ QMqttClient::QMqttClient(QObject *parent) : QObject(*(new QMqttClientPrivate(thi
/*!
Deletes a MQTT client. If the MQTT client was not already disconnected from the MQTT broker,
it will be disconnected from automatically.
\note If a transport is specified with setTransport it must be valid at this point
*/
QMqttClient::~QMqttClient()
{
@ -332,6 +369,7 @@ QMqttClient::~QMqttClient()
d->m_connection.setClientDestruction();
disconnectFromHost();
}
d->m_connection.disconnectAndResetTransport();
}
/*!
@ -342,7 +380,7 @@ QMqttClient::~QMqttClient()
\l Disconnected state.
\note Setting a custom transport for a client does not pass over responsibility
on connection management. The transport has to be opened for QIODevice based
on connection management or ownership. The transport has to be opened for QIODevice based
transports or connected for socket type transports before calling QMqttClient::connectToHost().
*/
void QMqttClient::setTransport(QIODevice *device, QMqttClient::TransportType transport)
@ -354,6 +392,8 @@ void QMqttClient::setTransport(QIODevice *device, QMqttClient::TransportType tra
return;
}
d->m_connection.setTransport(device, transport);
// Set the currently active buffer size for a new transport.
d->m_connection.setReadBufferSize(d->m_readBufferSize);
}
/*!
@ -365,6 +405,74 @@ QIODevice *QMqttClient::transport() const
return d->m_connection.transport();
}
/*!
\since 6.13
Limits the read buffer of the transport used by this client to
\a size bytes. Triggers warning message if the limit could not
be applied.
The transport does not buffer more than \a size bytes: it stops
reading from the network until the client has taken the data out of
the buffer. Use this function to protect the application against a
broker that sends more data than the application can handle, which
could make it run out of memory. A size of \c 0 means that the buffer
has no size limit, which is the default of the underlying transport.
\code
QMqttClient client;
client.setHostname(QStringLiteral("broker.example.com"));
client.setPort(1883);
client.setReadBufferSize(64 * 1024);
client.connectToHost();
\endcode
The size can be set before connecting. It is applied to the transport
when connectToHost() creates it, or when setTransport() sets it. The size
has no effect if the transport is a plain \l QMqttClient::IODevice.
Before Qt 6.13, the \c QMqttClient class provided no way to limit the
amount of incoming data. However, applications using older versions of
\c QMqttClient with certain types of transport, such as transports derived
from \c AbstractSocket, can protect themselves against memory exhaustion
caused by a broker, as shown in the example below:
\code
QMqttClient client;
client.setHostname(QStringLiteral("broker.example.com"));
client.setPort(1883);
QObject::connect(&client, &QMqttClient::connected, &client, [&client]() {
QAbstractSocket *socket = dynamic_cast<QAbstractSocket *>(client.transport());
if (socket)
socket->setReadBufferSize(64 * 1024);
});
client.connectToHost();
\endcode
\note If you use a custom QIODevice-based transport, implement
support for a read buffer limit in the device and configure it
before calling setTransport(). Some devices already support it.
For example, \l QSerialPort provides QSerialPort::setReadBufferSize().
\note This limit and the MQTT 5 maximum packet size protect against
different things. The maximum packet size limits the size of an
individual packet, not the total size of a buffer.
\sa setTransport(), QMqttConnectionProperties::setMaximumPacketSize()
*/
void QMqttClient::setReadBufferSize(qint64 size)
{
Q_D(QMqttClient);
if (d->m_readBufferSize == size)
return;
// Store the size even if there is no transport yet. setTransport() and
// connectToHost() apply it to the transport they set or create.
d->m_readBufferSize = size;
d->m_connection.setReadBufferSize(size);
emit readBufferSizeChanged(d->m_readBufferSize);
}
/*!
Adds a new subscription to receive notifications on \a topic. The parameter
\a qos specifies the level at which security messages are received. For more
@ -512,6 +620,56 @@ quint16 QMqttClient::port() const
return d->m_port;
}
/*!
\since 6.10
Set a web socket transport type and initiates a connection to the MQTT broker.
Earlier transport type is replaced.
If \a webSocket is given, hostname and port is ignored, and connection is done
with that websocket. webSocket is owned by the calling code, and must be valid
for the lifetime of the QMqttClient object.
*/
void QMqttClient::connectToHostWebSocket(QWebSocket *webSocket)
{
#ifndef QT_MQTT_WITH_WEBSOCKETS
Q_UNUSED(webSocket);
qWarning() << " Qt built without websocket support, connect skipped";
#else
Q_D(QMqttClient);
d->m_connection.connectTransport(
TransportType::WebSocket,
std::make_shared<QMqttWebSocketIO>(nullptr, webSocket));
connectToHost();
d->m_connection.m_transportIsSet = false;
#endif // QT_MQTT_WITH_WEBSOCKETS
}
/*!
\since 6.10
Set a secure websocket transport type and initiates a connection to the MQTT broker.
Earlier transport type is replaced.
If \a webSocket is given, hostname and port is ignored, and connection is done
with that websocket. webSocket is owned by the calling code, and must be valid
for the lifetime of the QMqttClient object.
*/
void QMqttClient::connectToHostWebSocketEncrypted(QWebSocket *webSocket)
{
#ifndef QT_MQTT_WITH_WEBSOCKETS
Q_UNUSED(webSocket);
qWarning() << " Qt built without websocket support, connect skipped";
#else
Q_D(QMqttClient);
d->m_connection.connectTransport(
TransportType::SecureWebSocket,
std::make_shared<QMqttSecureWebSocketIO>(nullptr, webSocket));
connectToHost();
d->m_connection.m_transportIsSet = false;
#endif // QT_MQTT_WITH_WEBSOCKETS
}
/*!
Initiates a connection to the MQTT broker.
*/
@ -566,6 +724,11 @@ void QMqttClient::connectToHost(bool encrypted, const QString &sslPeerName)
return;
}
// We can safely set the active buffer size for the new transport here,
// as the transport type has been determined by ensureTransport() or
// connectToHostWebSocket()/connectToHostWebSocketEncrypted() at this point.
d->m_connection.setReadBufferSize(d->m_readBufferSize);
// Once transport has connected, it will invoke
// QMqttConnection::sendControlConnect to
// handshake with the broker
@ -573,6 +736,11 @@ void QMqttClient::connectToHost(bool encrypted, const QString &sslPeerName)
/*!
Disconnects from the MQTT broker.
\note This function may block while waiting for pending data
to be written to the transport.
See \l {Threading and Blocking Operations} for recommended approaches
on handling it.
*/
void QMqttClient::disconnectFromHost()
{
@ -646,6 +814,12 @@ bool QMqttClient::autoKeepAlive() const
return d->m_autoKeepAlive;
}
qint64 QMqttClient::readBufferSize() const
{
Q_D(const QMqttClient);
return d->m_readBufferSize;
}
/*!
\since 5.12
@ -1019,10 +1193,7 @@ QMqttClientPrivate::QMqttClientPrivate(QMqttClient *c)
: QObjectPrivate()
{
m_client = c;
m_clientId = QUuid::createUuid().toString();
m_clientId.remove(QLatin1Char('{'));
m_clientId.remove(QLatin1Char('}'));
m_clientId.remove(QLatin1Char('-'));
m_clientId = QUuid::createUuid().toString(QUuid::Id128);
m_clientId.resize(23);
#ifdef QT_BUILD_INTERNAL
// Some test servers require a username token

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTMQTTCLIENT_H
#define QTMQTTCLIENT_H
@ -22,6 +23,7 @@
QT_BEGIN_NAMESPACE
class QWebSocket;
class QMqttClientPrivate;
class Q_MQTT_EXPORT QMqttClient : public QObject
@ -30,13 +32,15 @@ public:
enum TransportType {
IODevice = 0,
AbstractSocket,
SecureSocket
SecureSocket,
WebSocket,
SecureWebSocket,
};
enum ClientState {
Disconnected = 0,
Connecting,
Connected
Connected,
};
Q_ENUM(ClientState)
@ -52,22 +56,19 @@ public:
TransportInvalid = 256,
ProtocolViolation,
UnknownError,
Mqtt5SpecificError
Mqtt5SpecificError,
};
Q_ENUM(ClientError)
enum ProtocolVersion {
MQTT_3_1 = 3,
MQTT_3_1_1 = 4,
MQTT_5_0 = 5
MQTT_5_0 = 5,
};
Q_ENUM(ProtocolVersion)
private:
Q_OBJECT
Q_ENUMS(ClientState)
Q_ENUMS(ClientError)
Q_ENUMS(ProtocolVersion)
Q_PROPERTY(QString clientId READ clientId WRITE setClientId NOTIFY clientIdChanged)
Q_PROPERTY(QString hostname READ hostname WRITE setHostname NOTIFY hostnameChanged)
Q_PROPERTY(quint16 port READ port WRITE setPort NOTIFY portChanged)
@ -83,12 +84,15 @@ private:
Q_PROPERTY(quint8 willQoS READ willQoS WRITE setWillQoS NOTIFY willQoSChanged)
Q_PROPERTY(bool willRetain READ willRetain WRITE setWillRetain NOTIFY willRetainChanged)
Q_PROPERTY(bool autoKeepAlive READ autoKeepAlive WRITE setAutoKeepAlive NOTIFY autoKeepAliveChanged)
Q_PROPERTY(qint64 readBufferSize READ readBufferSize WRITE setReadBufferSize NOTIFY readBufferSizeChanged)
public:
explicit QMqttClient(QObject *parent = nullptr);
~QMqttClient() override;
void setTransport(QIODevice *device, TransportType transport);
QIODevice *transport() const;
void setReadBufferSize(qint64 size);
QMqttSubscription *subscribe(const QMqttTopicFilter &topic, quint8 qos = 0);
QMqttSubscription *subscribe(const QMqttTopicFilter &topic,
@ -115,6 +119,8 @@ public:
#ifndef QT_NO_SSL
void connectToHostEncrypted(const QSslConfiguration &conf);
#endif
Q_INVOKABLE void connectToHostWebSocket(QWebSocket *webSocket = nullptr);
Q_INVOKABLE void connectToHostWebSocketEncrypted(QWebSocket *webSocket = nullptr);
Q_INVOKABLE void disconnectFromHost();
ClientState state() const;
@ -129,6 +135,7 @@ public:
QByteArray willMessage() const;
bool willRetain() const;
bool autoKeepAlive() const;
qint64 readBufferSize() const;
void setConnectionProperties(const QMqttConnectionProperties &prop);
QMqttConnectionProperties connectionProperties() const;
@ -164,6 +171,7 @@ Q_SIGNALS:
void willMessageChanged(QByteArray willMessage);
void willRetainChanged(bool willRetain);
void autoKeepAliveChanged(bool autoKeepAlive);
void readBufferSizeChanged(qint64 size);
void authenticationRequested(const QMqttAuthenticationProperties &p);
void authenticationFinished(const QMqttAuthenticationProperties &p);

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTCLIENT_P_H
#define QMQTTCLIENT_P_H
@ -15,6 +16,7 @@
// We mean it.
//
#include "qmqttglobal_p.h"
#include "qmqttclient.h"
#include "qmqttconnection_p.h"
@ -46,6 +48,7 @@ public:
quint8 m_willQoS{0};
bool m_willRetain{false};
bool m_autoKeepAlive{true};
qint64 m_readBufferSize{0};
QString m_username;
QString m_password;
bool m_cleanSession{true};

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTCONNECTION_P_H
#define QMQTTCONNECTION_P_H
@ -26,6 +27,9 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QtEndian>
#include <memory>
#include <optional>
QT_BEGIN_NAMESPACE
class QMqttClientPrivate;
@ -45,7 +49,9 @@ public:
explicit QMqttConnection(QObject *parent = nullptr);
~QMqttConnection() override;
void disconnectAndResetTransport();
void setTransport(QIODevice *device, QMqttClient::TransportType transport);
void connectTransport(QMqttClient::TransportType transport, const std::shared_ptr<QIODevice> &device);
QIODevice *transport() const;
bool ensureTransport(bool createSecureIfNeeded = false);
@ -62,8 +68,8 @@ public:
QMqttSubscription *sendControlSubscribe(const QMqttTopicFilter &topic, quint8 qos, const QMqttSubscriptionProperties &properties);
bool sendControlUnsubscribe(const QMqttTopicFilter &topic, const QMqttUnsubscriptionProperties &properties);
bool sendControlPingRequest(bool isAuto = true);
bool sendControlDisconnect();
bool sendControlDisconnect(std::optional<QMqtt::ReasonCode> reasonCode = std::nullopt);
void setReadBufferSize(qint64 size);
void setClientPrivate(QMqttClientPrivate *clientPrivate);
inline quint16 unusedPacketIdentifier() const;
@ -82,9 +88,10 @@ protected:
void timerEvent(QTimerEvent *event) override;
public:
QIODevice *m_transport{nullptr};
std::shared_ptr<QIODevice> m_transport;
QMqttClient::TransportType m_transportType{QMqttClient::IODevice};
bool m_ownTransport{false};
bool m_transportIsSet{false}; // connectTo* does not reset m_transport;
bool m_connectedTransport{false}; // We have connected the signals for m_transport if true
QMqttClientPrivate *m_clientPrivate{nullptr};
#ifndef QT_NO_SSL
QSslConfiguration m_sslConfiguration;
@ -102,11 +109,11 @@ private:
bool processDataHelper();
bool readBuffer(char *data, quint64 size);
qint32 readVariableByteInteger(qint64 *dataSize = nullptr);
void readAuthProperties(QMqttAuthenticationProperties &properties);
void readConnackProperties(QMqttServerConnectionProperties &properties);
void readMessageStatusProperties(QMqttMessageStatusProperties &properties);
void readPublishProperties(QMqttPublishProperties &properties);
void readSubscriptionProperties(QMqttSubscription *sub);
bool readAuthProperties(QMqttAuthenticationProperties &properties);
bool readConnackProperties(QMqttServerConnectionProperties &properties);
bool readMessageStatusProperties(QMqttMessageStatusProperties &properties);
bool readPublishProperties(QMqttPublishProperties &properties);
bool readSubscriptionProperties(QMqttSubscription *sub);
QByteArray writeConnectProperties();
QByteArray writeLastWillProperties() const;
QByteArray writePublishProperties(const QMqttPublishProperties &properties);
@ -114,8 +121,18 @@ private:
QByteArray writeUnsubscriptionProperties(const QMqttUnsubscriptionProperties &properties);
QByteArray writeAuthenticationProperties(const QMqttAuthenticationProperties &properties);
void closeConnection(QMqttClient::ClientError error);
void closeOnMalformedPacket();
QByteArray readBuffer(quint64 size);
template<typename T> T readBufferTyped(qint64 *dataSize = nullptr);
template<typename T> std::optional<T> readBufferTyped(qint64 *dataSize = nullptr);
bool isPendingUnsubscribe(QMqttSubscription *) const;
QMqttSubscription *findActiveSubscription(const QMqttTopicFilter &topic) const;
template <typename T>
void setSocketBufferSize(qint64 size) {
auto *socket = qobject_cast<T *>(m_transport.get());
Q_ASSERT(socket);
socket->setReadBufferSize(size);
}
QByteArray m_readBuffer;
int m_readPosition{0};
qint64 m_missingData{0};
@ -128,9 +145,13 @@ private:
QMqttControlPacket::PacketType m_currentPacket{QMqttControlPacket::UNKNOWN};
bool writePacketToTransport(const QMqttControlPacket &p);
// I: There can be many occurences of different QMqttSubscription * with
// the same QMqttTopicFilter, but only one that is not in
// m_pendingUnsubscriptions.
QHash<quint16, QMqttSubscription *> m_pendingSubscriptionAck;
QHash<quint16, QMqttSubscription *> m_pendingUnsubscriptions;
QHash<QMqttTopicFilter, QMqttSubscription *> m_activeSubscriptions;
QMultiHash<QMqttTopicFilter, QMqttSubscription *> m_activeSubscriptions;
QHash<quint16, QSharedPointer<QMqttControlPacket>> m_pendingMessages;
QHash<quint16, QSharedPointer<QMqttControlPacket>> m_pendingReleaseMessages;
InternalConnectionState m_internalState{BrokerDisconnected};

View File

@ -1,18 +1,15 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttconnectionproperties.h"
#include "qmqttconnectionproperties_p.h"
#include <QtCore/QLoggingCategory>
#include <limits>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMqttConnection)
/*!
\class QMqttConnectionProperties
@ -307,6 +304,11 @@ void QMqttConnectionProperties::setMaximumReceive(quint16 maximumReceive)
If no maximum packet size is specified, no limit is imposed beyond the
limitations of the protocol itself.
\note Since Qt 6.13, this limit can be applied to incoming packets
when using MQTT 3.1 or MQTT 3.1.1. These protocol versions cannot announce
the limit to the broker, but the client closes the connection with
\l QMqttClient::ProtocolViolation when it receives a larger packet.
*/
void QMqttConnectionProperties::setMaximumPacketSize(quint32 packetSize)
{

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTCONNECTIONPROPERTIES_H
#define QMQTTCONNECTIONPROPERTIES_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTCONNECTIONPROPERTIES_P_H
#define QMQTTCONNECTIONPROPERTIES_P_H
@ -18,8 +19,12 @@
#include "qmqttconnectionproperties.h"
#include "private/qglobal_p.h"
#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMqttConnection)
class QMqttLastWillPropertiesData : public QSharedData
{
public:

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:critical reason:network-protocol
#include "qmqttcontrolpacket_p.h"
@ -8,8 +9,6 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMqttClient)
QMqttControlPacket::QMqttControlPacket()
{

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTCONTROLPACKET_P_H
#define QMQTTCONTROLPACKET_P_H
@ -14,7 +15,7 @@
//
// We mean it.
//
#include "qmqttglobal.h"
#include "qmqttglobal_p.h"
#include <QtCore/QByteArray>
#include <QtCore/QtGlobal>

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTQMQTTGLOBAL_H
#define QTQMQTTGLOBAL_H

28
src/mqtt/qmqttglobal_p.h Normal file
View File

@ -0,0 +1,28 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTQMQTTGLOBAL_P_H
#define QTQMQTTGLOBAL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtMqtt/qmqttglobal.h>
#include <QtCore/qloggingcategory.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMqttClient)
QT_END_NAMESPACE
#endif // QTQMQTTGLOBAL_P_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttmessage.h"
#include "qmqttmessage_p.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTMESSAGE_H
#define QMQTTMESSAGE_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTMESSAGE_P_H
#define QMQTTMESSAGE_P_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttpublishproperties.h"
#include "qmqttpublishproperties_p.h"
@ -9,8 +10,6 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMqttClient)
/*!
\class QMqttPublishProperties

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTPUBLISHPROPERTIES_H
#define QMQTTPUBLISHPROPERTIES_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTPUBLISHPROPERTIES_P_H
#define QMQTTPUBLISHPROPERTIES_P_H
@ -15,7 +16,7 @@
// We mean it.
//
#include "qmqttglobal.h"
#include "qmqttglobal_p.h"
#include "qmqttpublishproperties.h"
#include <QtCore/QSharedData>

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttsubscription.h"
#include "qmqttsubscription_p.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTSUBSCRIPTION_H
#define QMQTTSUBSCRIPTION_H
@ -18,7 +19,6 @@ class QMqttSubscriptionPrivate;
class Q_MQTT_EXPORT QMqttSubscription : public QObject
{
Q_OBJECT
Q_ENUMS(SubscriptionState)
Q_PROPERTY(SubscriptionState state READ state NOTIFY stateChanged)
Q_PROPERTY(quint8 qos READ qos NOTIFY qosChanged)
Q_PROPERTY(QMqttTopicFilter topic READ topic)
@ -35,6 +35,7 @@ public:
UnsubscriptionPending,
Error
};
Q_ENUM(SubscriptionState)
SubscriptionState state() const;
QMqttTopicFilter topic() const;

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTSUBSCRIPTION_P_H
#define QMQTTSUBSCRIPTION_P_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqttsubscriptionproperties.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTSUBSCRIPTIONPROPERTIES_H
#define QMQTTSUBSCRIPTIONPROPERTIES_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 Lorenz Haas
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
#include "qmqtttopicfilter.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 Lorenz Haas
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTTOPICFILTER_H
#define QMQTTTOPICFILTER_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 Lorenz Haas
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
#include "qmqtttopicname.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2017 Lorenz Haas
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTTOPICNAME_H
#define QMQTTTOPICNAME_H

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qmqtttype.h"

View File

@ -1,5 +1,6 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QMQTTTYPE_H
#define QMQTTTYPE_H

View File

@ -0,0 +1,45 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "mqtt_secure_websocket_io_p.h"
#ifdef QT_MQTT_WITH_WEBSOCKETS
QMqttSecureWebSocketIO::~QMqttSecureWebSocketIO()
{
disconnect(m_socket.get(), &QWebSocket::connected, this, &QMqttSecureWebSocketIO::doSocketEncrypted);
}
QMqttSecureWebSocketIO::QMqttSecureWebSocketIO(QObject *parent, QWebSocket *webSocket)
:
QMqttWebSocketIOBase(parent, webSocket)
{
connect(m_socket.get(), &QWebSocket::connected, this, &QMqttSecureWebSocketIO::doSocketEncrypted);
}
void QMqttSecureWebSocketIO::connectToHostEncrypted(const QString &hostname, quint16 port, QMqttClient::ProtocolVersion version)
{
setProtocol(version);
if (!isExternalSocket()) {
QUrl url(QString(u"wss://") + hostname + u":" + QString().setNum(port));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8(m_protocol) });
m_socket->open(url, options);
}
open(QIODevice::ReadWrite);
}
void QMqttSecureWebSocketIO::close()
{
m_socket->close();
QMqttWebSocketIOBase::close();
}
void QMqttSecureWebSocketIO::doSocketEncrypted()
{
emit encrypted();
}
#include "moc_mqtt_secure_websocket_io_p.cpp"
#endif /* QT_MQTT_WITH_WEBSOCKETS */

View File

@ -0,0 +1,53 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTMQTTCLIENT_SECURE_WEBSOCKET_IODEVICE_H
#define QTMQTTCLIENT_SECURE_WEBSOCKET_IODEVICE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include <QtWebSockets/QWebSocketHandshakeOptions>
#include <QtWebSockets/QWebSocket>
#include <QtCore/QIODevice>
#include "transportLayers/mqtt_websocket_io_base_p.h"
#include "qmqttclient.h"
QT_BEGIN_NAMESPACE
class QMqttSecureWebSocketIO : public QMqttWebSocketIOBase
{
Q_OBJECT
public:
Q_DISABLE_COPY_MOVE(QMqttSecureWebSocketIO)
~QMqttSecureWebSocketIO() override;
QMqttSecureWebSocketIO(QObject *parent = nullptr, QWebSocket *webSocket = nullptr);
void close() override;
void connectToHostEncrypted(const QString &hostname, quint16 port, QMqttClient::ProtocolVersion version);
Q_SIGNALS:
void encrypted();
public slots:
void doSocketEncrypted();
};
QT_END_NAMESPACE
#endif /* QT_MQTT_WITH_WEBSOCKETS */
#endif /* QTMQTTCLIENT_SECURE_WEBSOCKET_IODEVICE_H */

View File

@ -0,0 +1,45 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "mqtt_websocket_io_p.h"
#ifdef QT_MQTT_WITH_WEBSOCKETS
QMqttWebSocketIO::~QMqttWebSocketIO()
{
disconnect(m_socket.get(), &QWebSocket::connected, this, &QMqttWebSocketIO::doSocketConnected);
}
QMqttWebSocketIO::QMqttWebSocketIO(QObject *parent, QWebSocket *webSocket)
:
QMqttWebSocketIOBase(parent, webSocket)
{
connect(m_socket.get(), &QWebSocket::connected, this, &QMqttWebSocketIO::doSocketConnected);
}
void QMqttWebSocketIO::connectToHost(const QString &hostname, quint16 port, QMqttClient::ProtocolVersion version)
{
setProtocol(version);
if (!isExternalSocket()) {
QUrl url(QString(u"ws://") + hostname + u":" + QString().setNum(port));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8(m_protocol) });
m_socket->open(url, options);
}
open(QIODevice::ReadWrite);
}
void QMqttWebSocketIO::close()
{
m_socket->close();
QMqttWebSocketIOBase::close();
}
void QMqttWebSocketIO::doSocketConnected()
{
emit connected();
}
#include "moc_mqtt_websocket_io_p.cpp"
#endif /* QT_MQTT_WITH_WEBSOCKETS */

View File

@ -0,0 +1,103 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "mqtt_websocket_io_base_p.h"
#ifdef QT_MQTT_WITH_WEBSOCKETS
QMqttWebSocketIOBase::~QMqttWebSocketIOBase()
{
disconnect(m_socket.get(), &QWebSocket::disconnected, this, &QMqttWebSocketIOBase::doSocketDisconnected);
disconnect(m_socket.get(), &QWebSocket::errorOccurred, this, &QMqttWebSocketIOBase::doSocketErrorOccured);
disconnect(m_socket.get(), &QWebSocket::binaryMessageReceived, this, &QMqttWebSocketIOBase::doSocketHandleBinaryMessage);
}
QMqttWebSocketIOBase::QMqttWebSocketIOBase(QObject *parent, QWebSocket *webSocket)
:
QIODevice(parent)
{
m_externalSocket = (webSocket != nullptr);
if (webSocket)
m_socket = std::shared_ptr<QWebSocket>(webSocket, [](QWebSocket *) { ; }); // skip deleter
else
m_socket = std::make_shared<QWebSocket>();
connect(m_socket.get(), &QWebSocket::disconnected, this, &QMqttWebSocketIOBase::doSocketDisconnected);
connect(m_socket.get(), &QWebSocket::errorOccurred, this, &QMqttWebSocketIOBase::doSocketErrorOccured);
connect(m_socket.get(), &QWebSocket::binaryMessageReceived, this, &QMqttWebSocketIOBase::doSocketHandleBinaryMessage);
setProtocol(QMqttClient::ProtocolVersion::MQTT_3_1);
}
bool QMqttWebSocketIOBase::open(QIODevice::OpenMode mode)
{
if (!QIODevice::open(mode))
{
close();
emit errorOccurred(QAbstractSocket::SocketResourceError);
}
// Will emit onConnectionEstablished or onConnectionError
return false;
}
void QMqttWebSocketIOBase::close()
{
QIODevice::close();
}
qint64 QMqttWebSocketIOBase::readData(char *data, qint64 maxlen)
{
qint64 bytesToRead = qMin(maxlen, (qint64)m_buffer.size());
memcpy(data, m_buffer.constData(), bytesToRead);
m_buffer = m_buffer.right(m_buffer.size() - bytesToRead);
return bytesToRead;
}
qint64 QMqttWebSocketIOBase::writeData(const char *data, qint64 len)
{
QByteArray msg(data, len);
const int length = m_socket->sendBinaryMessage(msg);
emit bytesWritten(length);
return length;
}
void QMqttWebSocketIOBase::setProtocol(QMqttClient::ProtocolVersion version)
{
switch (version) {
case QMqttClient::ProtocolVersion::MQTT_3_1:
setProtocol("mqttv3.1");
break;
case QMqttClient::ProtocolVersion::MQTT_3_1_1:
setProtocol("mqtt");
break;
case QMqttClient::ProtocolVersion::MQTT_5_0:
setProtocol("mqtt");
break;
} /* end-switch */
}
void QMqttWebSocketIOBase::setProtocol(const QByteArray &data)
{
m_protocol = data;
}
void QMqttWebSocketIOBase::doSocketHandleBinaryMessage(const QByteArray &msg)
{
m_buffer.append(msg);
emit readyRead();
}
void QMqttWebSocketIOBase::doSocketDisconnected()
{
emit disconnected();
}
void QMqttWebSocketIOBase::doSocketErrorOccured(QAbstractSocket::SocketError error)
{
emit errorOccurred(error);
}
#include "moc_mqtt_websocket_io_base_p.cpp"
#endif /* QT_MQTT_WITH_WEBSOCKETS */

View File

@ -0,0 +1,105 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTMQTTCLIENT_WEBSOCKET_IODEVICE_BASE_H
#define QTMQTTCLIENT_WEBSOCKET_IODEVICE_BASE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include <QtWebSockets/QWebSocketHandshakeOptions>
#include <QtWebSockets/QWebSocket>
#include <QtCore/QIODevice>
#include "qmqttclient.h"
QT_BEGIN_NAMESPACE
class QMqttWebSocketIOBase : public QIODevice
{
Q_OBJECT
protected:
QMqttWebSocketIOBase(QObject *parent = nullptr, QWebSocket *webSocket = nullptr);
public:
Q_DISABLE_COPY_MOVE(QMqttWebSocketIOBase)
~QMqttWebSocketIOBase() override;
bool open(OpenMode mode) override;
void close() override;
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
void setProtocol(QMqttClient::ProtocolVersion version);
void setProtocol(const QByteArray &data);
bool isSequential() const override
{
return true;
}
qint64 bytesAvailable() const override
{
return static_cast<qint64>(m_buffer.size()) + QIODevice::bytesAvailable();
}
bool waitForBytesWritten(int msecs) override
{
Q_UNUSED(msecs);
m_socket->flush();
return true;
}
bool isConnected() const
{
return (m_socket->state() == QAbstractSocket::ConnectedState);
}
QAbstractSocket::SocketState state() const
{
return m_socket->state();
}
bool isExternalSocket() const
{
return m_externalSocket;
}
void setReadBufferSize(qint64 size)
{
m_socket->setReadBufferSize(size);
}
Q_SIGNALS:
void disconnected();
void errorOccurred(QAbstractSocket::SocketError error);
public slots:
void doSocketHandleBinaryMessage(const QByteArray &msg);
void doSocketDisconnected();
void doSocketErrorOccured(QAbstractSocket::SocketError error);
protected:
std::shared_ptr<QWebSocket> m_socket;
bool m_externalSocket = false;
QByteArray m_protocol;
QByteArray m_buffer;
};
QT_END_NAMESPACE
#endif /* QT_MQTT_WITH_WEBSOCKETS */
#endif /* QTMQTTCLIENT_WEBSOCKET_IODEVICE_BASE_H */

View File

@ -0,0 +1,54 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QTMQTTCLIENT_WEBSOCKET_IODEVICE_H
#define QTMQTTCLIENT_WEBSOCKET_IODEVICE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include <QtWebSockets/QWebSocketHandshakeOptions>
#include <QtWebSockets/QWebSocket>
#include <QtCore/QIODevice>
#include "transportLayers/mqtt_websocket_io_base_p.h"
#include "qmqttclient.h"
QT_BEGIN_NAMESPACE
class QMqttWebSocketIO : public QMqttWebSocketIOBase
{
Q_OBJECT
public:
Q_DISABLE_COPY_MOVE(QMqttWebSocketIO)
~QMqttWebSocketIO() override;
QMqttWebSocketIO(QObject *parent = nullptr, QWebSocket *webSocket = nullptr);
void close() override;
void connectToHost(const QString &hostname, quint16 port, QMqttClient::ProtocolVersion version);
Q_SIGNALS:
void connected();
public slots:
void doSocketConnected();
};
QT_END_NAMESPACE
#endif /* QT_MQTT_WITH_WEBSOCKETS */
#endif /* QTMQTTCLIENT_WEBSOCKET_IODEVICE_H */

View File

@ -1,6 +1,122 @@
# Copyright (C) 2022 The Qt Company Ltd.
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# This function adds the test 12 times if run on a computer where the
# mosquitto broker has been provisioned by running the corresponding
# script located qt6/coin/provisioning/*/*mosquitto*
#
# The script adds the file /etc/mosquitto/conf.d/mqtt.conf on unix-like
# systems, and the file C:\\Program Files\\mosquitto\\conf.d\\mqtt.conf
# on windows like systems. So this is what we test for.
#
# If we are on a provisioned system as detected by the two files above
# we define these variables which the test use
# MQTT_TEST_TYPE= selection from; 3, 4, 5
# 3 -> Vers 3.1
# 4 -> Vers 3.1.1
# 5 -> Vers 5.0
# MQTT_TEST_PROTOCOL= selection from; Tcp,Ssl,Ws,Wss
# MQTT_TEST_BROKER="localhost"
#
# If neither of these files are present, we use the existing
# design which is to run for tcp,3.1.1 by default.
# In this case set the environment variable MQTT_TEST_BROKER
# to localhost
#
# Finally, we allow the test to override for individual test
# cases, if wanted. This is mostly used for MQTT_TEST_TYPE
#
function(qtmqtt_is_mosquitto_installed result)
set(skip $ENV{COIN_NO_MOSQUITTO})
if(skip)
set(${result} FALSE PARENT_SCOPE)
elseif(EXISTS "/etc/mosquitto/conf.d/mqtt.conf" OR
EXISTS "C:\\Program Files\\mosquitto\\conf.d\\mqtt.conf")
set(${result} ON PARENT_SCOPE)
else()
set(${result} FALSE PARENT_SCOPE)
endif()
endfunction()
function(qtmqtt_add_test)
set(options)
set(oneValueArgs TARGET)
set(multiValueArgs SOURCES DEFINES INCLUDE_DIRECTORIES LIBRARIES)
cmake_parse_arguments(
arg_mqtt
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
set(TYPES)
set(PROTOCOLS)
qtmqtt_is_mosquitto_installed(is_installed)
if(${is_installed})
if(WASM)
if(TARGET Qt::WebSockets)
set(TYPES Ws Wss)
set(PROTOCOLS 3 4 5)
endif()
elseif(QT_FEATURE_ssl)
if(TARGET Qt::WebSockets)
set(TYPES Tcp Ssl Ws Wss)
else()
set(TYPES Tcp Ssl)
endif()
set(PROTOCOLS 3 4 5)
else()
if(TARGET Qt::WebSockets)
set(TYPES Tcp Ws)
else()
set(TYPES Tcp)
endif()
set(PROTOCOLS 3 4 5)
endif()
elseif(NOT WASM)
set(TYPES Tcp)
set(PROTOCOLS 4)
endif()
foreach(TYPE ${TYPES})
foreach(PROTOCOL ${PROTOCOLS})
set(EXTRA_DEFINES)
set(EXTRA_LIBS)
if(${is_installed})
set(EXTRA_DEFINES MQTT_TEST_TYPE="${TYPE}" MQTT_TEST_PROTOCOL=${PROTOCOL} MQTT_TEST_BROKER="localhost")
endif()
if(TARGET Qt::WebSockets)
set(EXTRA_DEFINES ${EXTRA_DEFINES} QT_MQTT_WITH_WEBSOCKETS)
set(EXTRA_LIBS Qt::WebSockets)
endif()
qt_internal_add_test(
${arg_mqtt_TARGET}_${TYPE}_${PROTOCOL}
SOURCES
${arg_mqtt_SOURCES}
DEFINES
${arg_mqtt_DEFINES} ${EXTRA_DEFINES}
INCLUDE_DIRECTORIES
${arg_mqtt_INCLUDE_DIRECTORIES}
LIBRARIES
${arg_mqtt_LIBRARIES} ${EXTRA_LIBS}
TESTDATA
"../../certificate/cert.crt"
"../../certificate/cert.key"
BUILTIN_TESTDATA
)
endforeach()
endforeach()
endfunction()
if(QT_BUILD_STANDALONE_TESTS)
# Add qt_find_package calls for extra dependencies that need to be found when building
# the standalone tests here.

View File

@ -5,7 +5,9 @@
## tst_conformance Test:
#####################################################################
qt_internal_add_test(tst_conformance
qtmqtt_add_test(
TARGET
tst_conformance
SOURCES
../../common/broker_connection.h
tst_conformance.cpp

View File

@ -42,7 +42,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_MqttConformance::Tst_MqttConformance()

View File

@ -5,7 +5,9 @@
## tst_qmqttclient Test:
#####################################################################
qt_internal_add_test(tst_qmqttclient
qtmqtt_add_test(
TARGET
tst_qmqttclient
SOURCES
../../common/broker_connection.h
tst_qmqttclient.cpp

View File

@ -41,6 +41,11 @@ private Q_SLOTS:
void reconnect_QTBUG65726();
void openIODevice_QTBUG66955_data();
void openIODevice_QTBUG66955();
void subackLongRemainingLength();
void pubackLongRemainingLength();
void pubrelWithReasonCode();
void shortRemainingLength_data();
void shortRemainingLength();
void staticProperties_QTBUG_67176_data();
void staticProperties_QTBUG_67176();
void authentication();
@ -51,10 +56,11 @@ private Q_SLOTS:
void subscriptionIdsOverlap();
void keepAlive_data();
void keepAlive();
void reconnect();
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttClient::Tst_QMqttClient()
@ -173,7 +179,7 @@ void Tst_QMqttClient::sendReceive()
bool verified = false;
auto sub = subscriber.subscribe(testTopic, 1);
QVERIFY(sub);
connect(sub, &QMqttSubscription::messageReceived, [&](QMqttMessage msg) {
connect(sub, &QMqttSubscription::messageReceived, sub, [&](QMqttMessage msg) {
verified = msg.payload() == data;
received = true;
});
@ -185,7 +191,7 @@ void Tst_QMqttClient::sendReceive()
QSKIP("The MQTT 5 test broker does not support huge packages.", SkipOnce);
publisher.publish(testTopic, data, 1);
QTRY_VERIFY2(received, "Subscriber did not receive message");
QTRY_VERIFY2_WITH_TIMEOUT(received, "Subscriber did not receive message", std::chrono::seconds(180));
QVERIFY2(verified, "Subscriber received different message");
}
@ -226,7 +232,8 @@ void Tst_QMqttClient::retainMessage()
sub.setClientId(QLatin1String("SubA"));
sub.setHostname(m_testBroker);
sub.setPort(m_port);
connect(&sub, &QMqttClient::messageReceived, [&msgCount, testMessage](const QByteArray &msg) {
connect(&sub, &QMqttClient::messageReceived, &sub,
[&msgCount, testMessage](const QByteArray &msg) {
if (msg == testMessage)
msgCount++;
});
@ -270,8 +277,12 @@ void Tst_QMqttClient::willMessage()
client1.connectToHost();
QTRY_COMPARE(client1.state(), QMqttClient::Connected);
if (!client1.isTcp())
QSKIP("This test is only for tcp");
auto client1Sub = client1.subscribe(willTopic, 1);
connect(client1Sub, &QMqttSubscription::messageReceived, [=](QMqttMessage message) {
connect(client1Sub, &QMqttSubscription::messageReceived,
client1Sub, [=](QMqttMessage message) {
Q_UNUSED(message);
// Just debug purposes
//qDebug() << "Got something:" << message;
@ -282,7 +293,7 @@ void Tst_QMqttClient::willMessage()
// Client B connects (via TcpSocket)
QTcpSocket sock;
sock.connectToHost(m_testBroker, m_port);
sock.connectToHost(client1.hostname(), client1.port());
QVERIFY(sock.waitForConnected());
for (int i = 1; i > 0; --i) {
@ -336,10 +347,12 @@ void Tst_QMqttClient::compliantTopic_data()
void Tst_QMqttClient::compliantTopic()
{
QFETCH(QString, topic);
QFETCH(QMqttClient::ProtocolVersion, mqttVersion);
QString truncTopic = topic;
truncTopic.truncate(std::numeric_limits<std::uint16_t>::max());
QMqttClient publisher;
VersionClient(mqttVersion, publisher);
publisher.setClientId(QLatin1String("publisher"));
publisher.setHostname(m_testBroker);
publisher.setPort(m_port);
@ -347,7 +360,7 @@ void Tst_QMqttClient::compliantTopic()
publisher.connectToHost();
QTRY_COMPARE(publisher.state(), QMqttClient::Connected);
QMqttClient subscriber;
VersionClient(mqttVersion, subscriber);
subscriber.setClientId(QLatin1String("subscriber"));
subscriber.setHostname(m_testBroker);
subscriber.setPort(m_port);
@ -357,7 +370,8 @@ void Tst_QMqttClient::compliantTopic()
bool received = false;
bool verified = false;
connect(&subscriber, &QMqttClient::messageReceived, [&](const QByteArray &, const QMqttTopicName &t) {
connect(&subscriber, &QMqttClient::messageReceived,
&subscriber, [&](const QByteArray &, const QMqttTopicName &t) {
received = true;
verified = t == truncTopic;
});
@ -415,7 +429,8 @@ void Tst_QMqttClient::dataIncludingZero()
const QString testTopic(QLatin1String("Qt/QMqttClient/some/topic"));
auto sub = client.subscribe(testTopic, 1);
QVERIFY(sub);
connect(sub, &QMqttSubscription::messageReceived, [&](QMqttMessage msg) {
connect(sub, &QMqttSubscription::messageReceived,
sub, [&](QMqttMessage msg) {
verified = msg.payload() == data;
correctSize = msg.payload().size() == dataSize;
received = true;
@ -459,14 +474,25 @@ public:
connect(server, &QTcpServer::newConnection, this, &FakeServer::createSocket);
server->listen(QHostAddress::Any, 5726);
}
// Sends raw bytes to the client, so a test can drive the parser with an exact
// byte sequence.
void send(const QByteArray &data) { socket->write(data); }
public slots:
void createSocket() {
socket = server->nextPendingConnection();
connectionAcknowledged = false;
lastRequest.clear();
connect(socket, &QTcpSocket::readyRead, this, &FakeServer::connectionRequested);
}
void connectionRequested() {
// We assume it is always a connect statement, so no verification is done
// We assume the first packet is always a connect statement, so no verification
// is done. Everything after that is recorded for the test to answer itself.
if (connectionAcknowledged) {
lastRequest.append(socket->readAll());
return;
}
connectionAcknowledged = true;
socket->readAll();
QByteArray response;
response += 0x20;
@ -490,6 +516,8 @@ public:
QTcpSocket *socket;
QMqttClient::ProtocolVersion version{QMqttClient::MQTT_3_1_1};
bool connectionSuccess{false};
bool connectionAcknowledged{false};
QByteArray lastRequest;
};
DefaultVersionTestData(Tst_QMqttClient::reconnect_QTBUG65726_data)
@ -505,6 +533,9 @@ void Tst_QMqttClient::reconnect_QTBUG65726()
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
if (!client.isTcp())
QSKIP("This test is only for tcp");
server.version = client.protocolVersion();
client.connectToHost();
@ -557,6 +588,220 @@ void Tst_QMqttClient::openIODevice_QTBUG66955()
QTRY_COMPARE(trans.written, 1);
}
// A reason string property (0x1f) of the requested content length.
static QByteArray reasonStringProperty(quint16 length)
{
QByteArray property;
property.append(char(0x1f));
property.append(char(length >> 8));
property.append(char(length & 0xff));
property.append(QByteArray(length, 'r'));
return property;
}
// The packet identifier of a packet the client wrote, skipping the packet type and
// its variable byte remaining length.
static quint16 packetIdentifier(const QByteArray &packet)
{
qsizetype pos = 1;
while (pos < packet.size() && (packet.at(pos) & 128) != 0)
++pos;
Q_ASSERT(pos < packet.size() - 2);
++pos;
return quint16(quint8(packet.at(pos)) << 8 | quint8(packet.at(pos + 1)));
}
static void appendPacketIdentifier(QByteArray *payload, quint16 id)
{
payload->append(char(id >> 8));
payload->append(char(id & 0xff));
}
// MQTT-2.2.3 (3.1.1) / MQTT-2.1.4 (5.0) The remaining length is a variable byte
// integer, so a packet longer than 127 bytes carries a two byte length whose first
// byte has the continuation bit set. Reading only that first byte consumes one byte
// too few and leaves the rest of the payload to be parsed as the next packet's
// fixed header.
void Tst_QMqttClient::subackLongRemainingLength()
{
FakeServer server;
server.version = QMqttClient::MQTT_5_0;
server.connectionSuccess = true;
VersionClient(QMqttClient::MQTT_5_0, client);
if (!client.isTcp())
QSKIP("This test is only for tcp");
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
auto sub = client.subscribe(QMqttTopicFilter(QLatin1String("a/b")), 1);
QVERIFY(sub);
QTRY_VERIFY(server.lastRequest.size() >= 4); // The SUBSCRIBE arrived
// SUBACK with a reason string, which pushes the remaining length past 127.
QByteArray payload;
appendPacketIdentifier(&payload, packetIdentifier(server.lastRequest));
const QByteArray properties = reasonStringProperty(123);
payload.append(char(properties.size())); // Property length, 126
payload.append(properties);
payload.append(char(0x01)); // Reason code: maximum QoS 1
QCOMPARE(payload.size(), 130);
QByteArray packet;
packet.append(char(0x90));
packet.append(char(0x82)); // Remaining length 130, low seven bits plus continuation
packet.append(char(0x01)); // Remaining length 130, remaining bits
packet.append(payload);
server.send(packet);
QTRY_COMPARE(sub->state(), QMqttSubscription::Subscribed);
QCOMPARE(client.state(), QMqttClient::Connected);
QCOMPARE(client.error(), QMqttClient::NoError);
}
void Tst_QMqttClient::pubackLongRemainingLength()
{
FakeServer server;
server.version = QMqttClient::MQTT_5_0;
server.connectionSuccess = true;
VersionClient(QMqttClient::MQTT_5_0, client);
if (!client.isTcp())
QSKIP("This test is only for tcp");
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
const qint32 id = client.publish(QMqttTopicName(QLatin1String("a/b")), QByteArray("x"), 1);
QVERIFY(id > 0);
QTRY_VERIFY(server.lastRequest.size() >= 4); // The PUBLISH arrived
QSignalSpy sentSpy(&client, &QMqttClient::messageSent);
// PUBACK with a reason string, which pushes the remaining length past 127.
QByteArray payload;
appendPacketIdentifier(&payload, quint16(id));
payload.append(char(0x00)); // Reason code: Success
const QByteArray properties = reasonStringProperty(123);
payload.append(char(properties.size())); // Property length, 126
payload.append(properties);
QCOMPARE(payload.size(), 130);
QByteArray packet;
packet.append(char(0x40));
packet.append(char(0x82)); // Remaining length 130, low seven bits plus continuation
packet.append(char(0x01)); // Remaining length 130, remaining bits
packet.append(payload);
server.send(packet);
QTRY_COMPARE(sentSpy.count(), 1);
QCOMPARE(sentSpy.at(0).at(0).toInt(), id);
QCOMPARE(client.state(), QMqttClient::Connected);
QCOMPARE(client.error(), QMqttClient::NoError);
}
// MQTT-3.6.2, MQTT-3.6.2.1 In MQTT 5.0 the PUBREL variable header holds a reason
// code and properties in addition to the packet identifier. A remaining length of 2
// only occurs when both are omitted, so a longer PUBREL must be accepted.
void Tst_QMqttClient::pubrelWithReasonCode()
{
FakeServer server;
server.version = QMqttClient::MQTT_5_0;
server.connectionSuccess = true;
VersionClient(QMqttClient::MQTT_5_0, client);
if (!client.isTcp())
QSKIP("This test is only for tcp");
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
QMqtt::MessageStatus status = QMqtt::MessageStatus::Unknown;
QString reasonString;
connect(&client, &QMqttClient::messageStatusChanged, &client,
[&](qint32, QMqtt::MessageStatus s, const QMqttMessageStatusProperties &properties)
{
status = s;
reasonString = properties.reason();
});
// PUBLISH, QoS 2, topic "a/b", packet identifier 7, no properties, payload "x".
// The client answers with a PUBREC, which puts it in the middle of the QoS 2
// exchange and makes it expect a PUBREL.
server.send(QByteArray::fromHex("34090003612f6200070078"));
QTRY_VERIFY(server.lastRequest.size() >= 4); // The PUBREC arrived
// PUBREL, packet identifier 7, reason code Success, and a reason string. Remaining
// length 12: 2 identifier + 1 reason code + 1 property length + 8 property bytes.
server.send(QByteArray::fromHex("620c000700081f000568656c6c6f"));
QTRY_COMPARE(status, QMqtt::MessageStatus::Released);
QCOMPARE(reasonString, QLatin1String("hello"));
QCOMPARE(client.state(), QMqttClient::Connected);
QCOMPARE(client.error(), QMqttClient::NoError);
}
// The remaining length counts the bytes that follow the fixed header, so a packet
// declaring less than the fields the specification requires is malformed. Accepting
// one leaves the parser reading past the end of the packet: the reason code loops in
// finalize_suback() and finalize_unsuback() read at least once regardless of what is
// left, and finalize_pubAckRecRelComp() always reads a packet identifier. Each of
// these packets must be rejected as a protocol violation instead.
void Tst_QMqttClient::shortRemainingLength_data()
{
QTest::addColumn<QMqttClient::ProtocolVersion>("mqttVersion");
QTest::addColumn<QByteArray>("packet");
// SUBACK, packet identifier 7, and nothing else. MQTT-3.9.3 requires at least one
// reason code, so the shortest legal remaining length is 3.
QTest::newRow("SUBACK 3.1.1, no reason code")
<< QMqttClient::MQTT_3_1_1 << QByteArray::fromHex("90020007");
// The same, plus an empty property block. MQTT-3.9.2.1 makes the property length
// mandatory in MQTT 5.0, so the shortest legal remaining length is 4.
QTest::newRow("SUBACK 5.0, no reason code")
<< QMqttClient::MQTT_5_0 << QByteArray::fromHex("9003000700");
// UNSUBACK, packet identifier 7, empty property block, no reason code. The
// property length is mandatory (MQTT-3.11.2.1) and at least one reason code is
// required (MQTT-3.11.3), so the shortest legal remaining length is 4.
QTest::newRow("UNSUBACK 5.0, no reason code")
<< QMqttClient::MQTT_5_0 << QByteArray::fromHex("b003000700");
// PUBACK with half a packet identifier. The reason code and the property length may
// both be omitted (MQTT-3.4.2.1), but the identifier may not, so the shortest legal
// remaining length is 2.
QTest::newRow("PUBACK 5.0, truncated packet identifier")
<< QMqttClient::MQTT_5_0 << QByteArray::fromHex("400100");
// The same for PUBREL, MQTT-3.6.2.1.
QTest::newRow("PUBREL 5.0, truncated packet identifier")
<< QMqttClient::MQTT_5_0 << QByteArray::fromHex("620100");
}
void Tst_QMqttClient::shortRemainingLength()
{
QFETCH(QMqttClient::ProtocolVersion, mqttVersion);
QFETCH(QByteArray, packet);
FakeServer server;
server.version = mqttVersion;
server.connectionSuccess = true;
VersionClient(mqttVersion, client);
if (!client.isTcp())
QSKIP("This test is only for tcp");
client.setHostname(QLatin1String("localhost"));
client.setPort(5726);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
server.send(packet);
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
QCOMPARE(client.error(), QMqttClient::ProtocolViolation);
}
DefaultVersionTestData(Tst_QMqttClient::staticProperties_QTBUG_67176_data)
void Tst_QMqttClient::staticProperties_QTBUG_67176()
@ -567,6 +812,9 @@ void Tst_QMqttClient::staticProperties_QTBUG_67176()
client.setHostname(m_testBroker);
client.setPort(m_port);
auto clientVersion = client.protocolVersion();
const QString hostname = client.hostname();
const int port = client.port();
const QString clientId = client.clientId();
const quint16 keepAlive = client.keepAlive();
const bool clean = client.cleanSession();
@ -578,16 +826,16 @@ void Tst_QMqttClient::staticProperties_QTBUG_67176()
QCOMPARE(client.clientId(), clientId);
client.setHostname(QLatin1String("some.domain.foo"));
QCOMPARE(client.hostname(), m_testBroker);
QCOMPARE(client.hostname(), hostname);
client.setPort(1234);
QCOMPARE(client.port(), m_port);
QCOMPARE(client.port(), port);
client.setKeepAlive(keepAlive + 10);
QCOMPARE(client.keepAlive(), keepAlive);
client.setProtocolVersion(QMqttClient::MQTT_3_1);
QCOMPARE(client.protocolVersion(), mqttVersion);
QCOMPARE(client.protocolVersion(), clientVersion);
client.setUsername(QLatin1String("someUser"));
QCOMPARE(client.username(), QLatin1String());
@ -601,8 +849,7 @@ void Tst_QMqttClient::staticProperties_QTBUG_67176()
void Tst_QMqttClient::authentication()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -610,12 +857,14 @@ void Tst_QMqttClient::authentication()
connectionProperties.setAuthenticationMethod(QLatin1String("SCRAM-SHA-1"));
client.setConnectionProperties(connectionProperties);
connect(&client, &QMqttClient::authenticationRequested, [](const QMqttAuthenticationProperties &prop)
connect(&client, &QMqttClient::authenticationRequested, &client,
[](const QMqttAuthenticationProperties &prop)
{
qDebug() << "Authentication requested:" << prop.authenticationMethod();
});
connect(&client, &QMqttClient::authenticationFinished, [](const QMqttAuthenticationProperties &prop)
connect(&client, &QMqttClient::authenticationFinished, &client,
[](const QMqttAuthenticationProperties &prop)
{
qDebug() << "Authentication finished:" << prop.authenticationMethod();
});
@ -645,17 +894,18 @@ void Tst_QMqttClient::messageStatus()
QFETCH(int, qos);
QFETCH(QList<QMqtt::MessageStatus>, expectedStatus);
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
const QString topic = QLatin1String("Qt/client/statusCheck");
connect(&client, &QMqttClient::messageStatusChanged, [&expectedStatus](qint32,
connect(&client, &QMqttClient::messageStatusChanged,
&client, [&expectedStatus](qint32,
QMqtt::MessageStatus s,
const QMqttMessageStatusProperties &)
{
@ -684,16 +934,14 @@ void Tst_QMqttClient::messageStatusReceive()
QFETCH(int, qos);
QFETCH(QList<QMqtt::MessageStatus>, expectedStatus);
QMqttClient publisher;
publisher.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, publisher);
publisher.setHostname(m_testBroker);
publisher.setPort(m_port);
publisher.connectToHost();
QTRY_VERIFY2(publisher.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttClient subscriber;
subscriber.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, subscriber);
subscriber.setHostname(m_testBroker);
subscriber.setPort(m_port);
@ -706,9 +954,8 @@ void Tst_QMqttClient::messageStatusReceive()
QTRY_VERIFY2(subscription->state() == QMqttSubscription::Subscribed, "Could not subscribe to topic");
QVERIFY(subscription->qos() >= qos);
connect(&subscriber, &QMqttClient::messageStatusChanged, [&expectedStatus](qint32,
QMqtt::MessageStatus s,
const QMqttMessageStatusProperties &)
connect(&subscriber, &QMqttClient::messageStatusChanged, &subscriber,
[&expectedStatus](qint32, QMqtt::MessageStatus s, const QMqttMessageStatusProperties &)
{
QCOMPARE(s, expectedStatus.first());
expectedStatus.takeFirst();
@ -737,8 +984,7 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
const QString topic = QLatin1String("Qt/client/idcheck");
// Connect publisher
QMqttClient pub;
pub.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, pub);
pub.setHostname(m_testBroker);
pub.setPort(m_port);
@ -746,8 +992,7 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
QTRY_VERIFY2(pub.state() == QMqttClient::Connected, "Could not connect publisher.");
// Connect subA
QMqttClient subClientA;
subClientA.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, subClientA);
subClientA.setHostname(m_testBroker);
subClientA.setPort(m_port);
@ -760,7 +1005,8 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
QTRY_VERIFY2(subA->state() == QMqttSubscription::Subscribed, "Could not subscibe A.");
int receiveACounter = 0;
connect(subA, &QMqttSubscription::messageReceived, [&receiveACounter](QMqttMessage msg) {
connect(subA, &QMqttSubscription::messageReceived, subA,
[&receiveACounter](QMqttMessage msg) {
qDebug() << "Sub A received:" << msg.publishProperties().subscriptionIdentifiers();
// ### TODO: Wait for fix at https://github.com/eclipse/paho.mqtt.testing/issues/56
//QVERIFY(msg.publishProperties().subscriptionIdentifiers().size() == 1);
@ -769,8 +1015,7 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
});
// Connect subB
QMqttClient subClientB;
subClientB.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, subClientB);
subClientB.setHostname(m_testBroker);
subClientB.setPort(m_port);
@ -783,7 +1028,8 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
QTRY_VERIFY2(subB->state() == QMqttSubscription::Subscribed, "Could not subscibe A.");
int receiveBCounter = 2;
connect(subB, &QMqttSubscription::messageReceived, [&receiveBCounter](QMqttMessage msg) {
connect(subB, &QMqttSubscription::messageReceived,
subB, [&receiveBCounter](QMqttMessage msg) {
qDebug() << "Sub B received:" << msg.publishProperties().subscriptionIdentifiers();
QVERIFY(msg.publishProperties().subscriptionIdentifiers().size() > 0);
receiveBCounter -= msg.publishProperties().subscriptionIdentifiers().size();
@ -795,7 +1041,8 @@ void Tst_QMqttClient::subscriptionIdsOverlap()
QTRY_VERIFY2(subB2->state() == QMqttSubscription::Subscribed, "Could not subscibe A.");
int receiveB2Counter = 2;
connect(subB2, &QMqttSubscription::messageReceived, [&receiveB2Counter](QMqttMessage msg) {
connect(subB2, &QMqttSubscription::messageReceived,
subB2, [&receiveB2Counter](QMqttMessage msg) {
qDebug() << "Sub B2 received:" << msg.publishProperties().subscriptionIdentifiers();
QVERIFY(msg.publishProperties().subscriptionIdentifiers().size() > 0);
receiveB2Counter -= msg.publishProperties().subscriptionIdentifiers().size();
@ -869,11 +1116,11 @@ void Tst_QMqttClient::keepAlive()
QTimer t;
t.setInterval(keepAlive * 1000);
t.setSingleShot(false);
t.connect(&t, &QTimer::timeout, [&client]() {
t.connect(&t, &QTimer::timeout, &client, [&client]() {
client.requestPing();
});
connect(&client, &QMqttClient::connected, [&t]() {
connect(&client, &QMqttClient::connected, &t, [&t]() {
t.start();
});
@ -886,6 +1133,76 @@ void Tst_QMqttClient::keepAlive()
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
}
void Tst_QMqttClient::reconnect()
{
VersionClient(QMqttClient::ProtocolVersion(0), client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
client.disconnectFromHost();
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
/* The rest requires a mosquitto installation that runs
on multiple ports.
*/
#if defined(MQTT_TEST_BROKER)
client.setPort(client.port() + 1000);
client.connectToHost();
QTRY_COMPARE(client.state(), QMqttClient::Connected);
client.disconnectFromHost();
QTRY_COMPARE(client.state(), QMqttClient::Disconnected);
QMqttClient client2;
client2.setHostname(client.hostname());
for (int i = 0; i < 2; ++i) {
#if defined(QT_MQTT_WITH_WEBSOCKETS)
client2.setPort(9080);
client2.connectToHostWebSocket();
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
#if defined(QT_MQTT_WITH_WEBSOCKETS) && !defined(QT_NO_SSL)
client2.setPort(9081);
QUrl url(QString(u"wss://") + client2.hostname() + QString(u":") + QString::number(client2.port()));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8("mqttv3.1") });
QWebSocket socket;
socket.setSslConfiguration(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
socket.open(url, options);
client2.connectToHostWebSocketEncrypted(&socket);
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
#if !defined(QT_NO_SSL)
client2.setPort(9883);
client2.connectToHostEncrypted(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
#endif
client2.setPort(2883);
client2.connectToHost();
QTRY_COMPARE(client2.state(), QMqttClient::Connected);
client2.disconnectFromHost();
QTRY_COMPARE(client2.state(), QMqttClient::Disconnected);
}
#endif
}
QTEST_MAIN(Tst_QMqttClient)
#include "tst_qmqttclient.moc"

View File

@ -5,7 +5,9 @@
## tst_qmqttconnectionproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttconnectionproperties
qtmqtt_add_test(
TARGET
tst_qmqttconnectionproperties
SOURCES
../../common/broker_connection.h
tst_qmqttconnectionproperties.cpp

View File

@ -31,7 +31,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttConnectionProperties::tst_QMqttConnectionProperties()
@ -100,8 +100,7 @@ void tst_QMqttConnectionProperties::getSet()
void tst_QMqttConnectionProperties::receiveServerProperties()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
QMqttServerConnectionProperties server = client.serverConnectionProperties();
QCOMPARE(server.isValid(), false);
@ -156,8 +155,7 @@ void tst_QMqttConnectionProperties::receiveServerProperties()
void tst_QMqttConnectionProperties::maximumPacketSize()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -205,8 +203,7 @@ void tst_QMqttConnectionProperties::maximumPacketSize()
void tst_QMqttConnectionProperties::maximumTopicAlias()
{
const QByteArray msgContent("SomeContent");
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -242,7 +239,7 @@ void tst_QMqttConnectionProperties::maximumTopicAlias()
client.publish(topic, msgContent, 1);
QTRY_VERIFY(publishSpy.size() == 1);
QVERIFY(transportSpy.size() == 1);
QTRY_VERIFY(transportSpy.size() == 1);
const int dataSize = transportSpy.at(0).at(0).toInt();
if (publishTransportSize == 0) {
publishTransportSize = dataSize;
@ -291,7 +288,8 @@ void tst_QMqttConnectionProperties::maximumTopicAlias()
QVERIFY(usageSize < overwriteSize);
}
void createTopicAliasClient(QMqttClient &client, const QString &hostname, quint16 port)
template<typename Client>
void createTopicAliasClient(Client &client, const QString &hostname, quint16 port)
{
client.setProtocolVersion(QMqttClient::MQTT_5_0);
client.setHostname(hostname);
@ -308,13 +306,13 @@ void tst_QMqttConnectionProperties::maximumTopicAliasReceive()
const QByteArray msgContent("SomeContent");
const QString topic("Qt/connprop/receive/alias");
QMqttClient client;
VersionClient(QMqttClient::MQTT_5_0, client);
createTopicAliasClient(client, m_testBroker, m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttClient subscriber;
VersionClient(QMqttClient::MQTT_5_0, subscriber);
createTopicAliasClient(subscriber, m_testBroker, m_port);
subscriber.connectToHost();
@ -344,8 +342,7 @@ void tst_QMqttConnectionProperties::maximumTopicAliasReceive()
void tst_QMqttConnectionProperties::assignedClientId()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.setClientId(QLatin1String(""));
@ -361,8 +358,7 @@ void tst_QMqttConnectionProperties::assignedClientId()
void tst_QMqttConnectionProperties::userProperties()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
QMqttConnectionProperties p;

View File

@ -5,7 +5,9 @@
## tst_qmqttcontrolpacket Test:
#####################################################################
qt_internal_add_test(tst_qmqttcontrolpacket
qtmqtt_add_test(
TARGET
tst_qmqttcontrolpacket
SOURCES
tst_qmqttcontrolpacket.cpp
DEFINES

View File

@ -5,7 +5,9 @@
## tst_qmqttlastwillproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttlastwillproperties
qtmqtt_add_test(
TARGET
tst_qmqttlastwillproperties
SOURCES
../../common/broker_connection.h
tst_qmqttlastwillproperties.cpp

View File

@ -27,7 +27,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttLastWillProperties::tst_QMqttLastWillProperties()
@ -87,8 +87,7 @@ void tst_QMqttLastWillProperties::getSet()
void tst_QMqttLastWillProperties::payloadFormat()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -119,8 +118,7 @@ void tst_QMqttLastWillProperties::willDelay()
QFETCH(int, delay);
QFETCH(int, expiry);
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -145,8 +143,7 @@ void tst_QMqttLastWillProperties::willDelay()
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker");
QMqttClient recipient;
recipient.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, recipient);
recipient.setHostname(m_testBroker);
recipient.setPort(m_port);
recipient.connectToHost();

View File

@ -5,7 +5,9 @@
## tst_qmqttpublishproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttpublishproperties
qtmqtt_add_test(
TARGET
tst_qmqttpublishproperties
SOURCES
../../common/broker_connection.h
tst_qmqttpublishproperties.cpp

View File

@ -26,7 +26,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttPublishProperties::tst_QMqttPublishProperties()
@ -112,17 +112,14 @@ void tst_QMqttPublishProperties::getSet()
void tst_QMqttPublishProperties::propertyConsistency()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttClient client2;
client2.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client2);
client2.setHostname(m_testBroker);
client2.setPort(m_port);

View File

@ -5,7 +5,9 @@
## tst_qmqttsubscription Test:
#####################################################################
qt_internal_add_test(tst_qmqttsubscription
qtmqtt_add_test(
TARGET
tst_qmqttsubscription
SOURCES
../../common/broker_connection.h
tst_qmqttsubscription.cpp

View File

@ -31,11 +31,15 @@ private Q_SLOTS:
void noLocal();
void qtbug_106203();
void qtbug_104478();
void qtbug_135653_connected();
void qtbug_135653_not_connected();
void qtbug_135653_not_unsubscribed();
private:
void createAndSubscribe(QMqttClient *c, QMqttSubscription **sub, const QString &topic);
template<typename Client>
void createAndSubscribe(Client *c, QMqttSubscription **sub, const QString &topic);
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttSubscription::Tst_QMqttSubscription()
@ -148,6 +152,9 @@ void Tst_QMqttSubscription::reconnect()
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
if (!client.isTcp() && !client.isSsl())
QSKIP("This test only runs for tcp and ssl");
// - Subscribe to topic A
const QString subscription("Qt/subscription/topics/resub");
auto sub = client.subscribe(subscription, 1);
@ -211,7 +218,8 @@ void Tst_QMqttSubscription::reconnect()
QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect.");
}
void Tst_QMqttSubscription::createAndSubscribe(QMqttClient *c, QMqttSubscription **sub, const QString &topic)
template<typename Client>
void Tst_QMqttSubscription::createAndSubscribe(Client *c, QMqttSubscription **sub, const QString &topic)
{
c->setProtocolVersion(QMqttClient::MQTT_5_0);
c->setHostname(m_testBroker);
@ -227,8 +235,7 @@ void Tst_QMqttSubscription::createAndSubscribe(QMqttClient *c, QMqttSubscription
void Tst_QMqttSubscription::sharedConnection()
{
// Create / Connect publisher
QMqttClient sender;
sender.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, sender);
sender.setHostname(m_testBroker);
sender.setPort(m_port);
sender.connectToHost();
@ -237,13 +244,16 @@ void Tst_QMqttSubscription::sharedConnection()
// Create GroupA
const int groupSizeA = 2;
const QString groupTopicA{QLatin1String("$share/groupA/shared/sub")};
QMqttClient listenersA[groupSizeA];
VersionClient(QMqttClient::MQTT_5_0, listenersA0);
VersionClient(QMqttClient::MQTT_5_0, listenersA1);
std::vector listenersA = {&listenersA0, &listenersA1};
QMqttSubscription *subsA[groupSizeA];
int messageCounterA[groupSizeA] = {0};
int messageSumA = 0;
// listenerAx: $share/groupA/Qt/Subscription/shared_check/#
for (int i = 0; i < groupSizeA; ++i) {
createAndSubscribe(&listenersA[i], &subsA[i], groupTopicA);
createAndSubscribe(listenersA[i], &subsA[i], groupTopicA);
QCOMPARE(subsA[i]->isSharedSubscription(), true);
QCOMPARE(subsA[i]->sharedSubscriptionName(), QLatin1String("groupA"));
connect(subsA[i], &QMqttSubscription::messageReceived, [i, &messageCounterA, &messageSumA]() {
@ -256,13 +266,18 @@ void Tst_QMqttSubscription::sharedConnection()
// Create GroupB
const int groupSizeB = 5;
const QString groupTopicB{QLatin1String("$share/groupB/shared/#")};
QMqttClient listenersB[groupSizeB];
VersionClient(QMqttClient::MQTT_5_0, listenersB0);
VersionClient(QMqttClient::MQTT_5_0, listenersB1);
VersionClient(QMqttClient::MQTT_5_0, listenersB2);
VersionClient(QMqttClient::MQTT_5_0, listenersB3);
VersionClient(QMqttClient::MQTT_5_0, listenersB4);
std::vector listenersB ={&listenersB0, &listenersB1, &listenersB2, &listenersB3, &listenersB4};
QMqttSubscription *subsB[groupSizeB];
int messageCounterB[groupSizeB] = {0};
int messageSumB = 0;
// listenerBx: $share/groupB/Qt/Subscription/shared_check/#
for (int i = 0; i < groupSizeB; ++i) {
createAndSubscribe(&listenersB[i], &subsB[i], groupTopicB);
createAndSubscribe(listenersB[i], &subsB[i], groupTopicB);
QCOMPARE(subsB[i]->isSharedSubscription(), true);
QCOMPARE(subsB[i]->sharedSubscriptionName(), QLatin1String("groupB"));
connect(subsB[i], &QMqttSubscription::messageReceived, [i, &messageCounterB, &messageSumB]() {
@ -322,8 +337,7 @@ void Tst_QMqttSubscription::sharedNonShared()
QFETCH(bool, expected);
// Create / Connect publisher
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
@ -371,11 +385,13 @@ void Tst_QMqttSubscription::noLocal()
QFETCH(QMqttClient::ProtocolVersion, version);
QFETCH(bool, non);
QMqttClient client;
client.setProtocolVersion(version);
VersionClient(version, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
const auto clientVersion = client.protocolVersion();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
QMqttSubscriptionProperties subProps;
@ -392,7 +408,7 @@ void Tst_QMqttSubscription::noLocal()
client.publish(topic, "content", 1);
QTRY_VERIFY(publishSpy.size() == 1);
if (version == QMqttClient::MQTT_3_1_1 || !non) { // 3.1.1 does not know NoLocal and sends to subscription
if (clientVersion == QMqttClient::MQTT_3_1_1 || !non) { // 3.1.1 does not know NoLocal and sends to subscription
QTRY_VERIFY(receivalSpy.size() == 1);
} else {
QTest::qWait(3000);
@ -405,7 +421,7 @@ void Tst_QMqttSubscription::qtbug_106203()
const QString topic(QLatin1String("Qt/qtbug106203/Identity"));
// Fill up sub-Topics with retained messages (ie connection state of devices)
QMqttClient retainer;
VersionClient(QMqttClient::MQTT_3_1_1, retainer);
retainer.setHostname(m_testBroker);
retainer.setPort(m_port);
retainer.connectToHost();
@ -422,7 +438,7 @@ void Tst_QMqttSubscription::qtbug_106203()
retainer.disconnectFromHost();
QTRY_VERIFY2(retainer.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");
QMqttClient client;
VersionClient(QMqttClient::MQTT_3_1_1, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -453,7 +469,7 @@ void Tst_QMqttSubscription::qtbug_106203()
void Tst_QMqttSubscription::qtbug_104478()
{
QMqttClient client;
VersionClient(QMqttClient::MQTT_3_1_1, client);
client.setHostname(m_testBroker);
client.setPort(m_port);
@ -475,13 +491,99 @@ void Tst_QMqttSubscription::qtbug_104478()
client.publish(topic, "Wildcard checks", 1);
QTRY_VERIFY2(pubSpy.size() == 1, "Could not publish message.");
QTRY_VERIFY2(singleSpy.count() == 1, "Did not receive message");
QTRY_VERIFY2(mixedSpy.count() == 1, "Did not receive message");
QTRY_VERIFY2(singleSpy.count() >= 1, "Did not receive message");
QTRY_VERIFY2(mixedSpy.count() >= 1, "Did not receive message");
client.disconnectFromHost();
QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");
}
void Tst_QMqttSubscription::qtbug_135653_connected()
{
VersionClient(QMqttClient::ProtocolVersion(0), client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
const QString topic(QLatin1String("test/foo/bar/test3"));
QMqttSubscription *subscriptions[10] = { 0 };
for (int i = 0; i < 10; ++i) {
bool received = false;
subscriptions[i] = client.subscribe(topic);
connect(subscriptions[i], &QMqttSubscription::messageReceived, subscriptions[i],
[topic, &received](QMqttMessage msg) {
received = (msg.payload() == "Hello World");
});
client.publish(topic, QString(QLatin1String("Hello World")).toLocal8Bit(), 1, true);
QTRY_VERIFY2(received, "Could not receive message.");
client.unsubscribe(topic);
client.unsubscribe(topic);
}
for (int i = 0; i < 10; ++i) {
QVERIFY(subscriptions[i]);
for (int j = i + 1; j < 10; ++j)
QVERIFY(subscriptions[i] != subscriptions[j]);
}
}
void Tst_QMqttSubscription::qtbug_135653_not_connected()
{
VersionClient(QMqttClient::ProtocolVersion(0), client);
client.setHostname(m_testBroker);
client.setPort(m_port);
const QString topic(QLatin1String("test/foo/bar/test4"));
QMqttSubscription *subscriptions[10] = { 0 };
for (int i = 0; i < 10; ++i) {
bool received = false;
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
subscriptions[i] = client.subscribe(topic);
connect(subscriptions[i], &QMqttSubscription::messageReceived,
subscriptions[i], [topic, &received](QMqttMessage msg) {
received = (msg.payload() == "Hello World");
});
client.publish(topic, QString(QLatin1String("Hello World")).toLocal8Bit(), 1, true);
QTRY_VERIFY2(received, "Could not receive message.");
client.disconnectFromHost();
QTRY_VERIFY2(client.state() == QMqttClient::Disconnected, "Could not disconnect from broker.");
client.unsubscribe(topic);
client.unsubscribe(topic);
}
for (int i = 0; i < 10; ++i) {
QVERIFY(subscriptions[i]);
for (int j = i + 1; j < 10; ++j)
QVERIFY(subscriptions[i] != subscriptions[j]);
}
}
void Tst_QMqttSubscription::qtbug_135653_not_unsubscribed()
{
const QString topic(QLatin1String("test/foo/bar/test5"));
QMqttSubscription *subscriptions[10] = { 0 };
for (int i = 0; i < 10; ++i) {
bool received = false;
VersionClient(QMqttClient::ProtocolVersion(0), client);
client.setHostname(m_testBroker);
client.setPort(m_port);
client.connectToHost();
QTRY_VERIFY2(client.state() == QMqttClient::Connected, "Could not connect to broker.");
subscriptions[i] = client.subscribe(topic);
connect(subscriptions[i], &QMqttSubscription::messageReceived,
subscriptions[i], [topic, &received](QMqttMessage msg) {
received = (msg.payload() == "Hello World");
});
client.publish(topic, QString(QLatin1String("Hello World")).toLocal8Bit(), 1, true);
QTRY_VERIFY2(received, "Could not receive message.");
}
}
QTEST_MAIN(Tst_QMqttSubscription)
#include "tst_qmqttsubscription.moc"

View File

@ -5,7 +5,9 @@
## tst_qmqttsubscriptionproperties Test:
#####################################################################
qt_internal_add_test(tst_qmqttsubscriptionproperties
qtmqtt_add_test(
TARGET
tst_qmqttsubscriptionproperties
SOURCES
../../common/broker_connection.h
tst_qmqttsubscriptionproperties.cpp

View File

@ -26,7 +26,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
tst_QMqttSubscriptionProperties::tst_QMqttSubscriptionProperties()
@ -70,8 +70,7 @@ void tst_QMqttSubscriptionProperties::getSet()
void tst_QMqttSubscriptionProperties::subscribe()
{
QMqttClient client;
client.setProtocolVersion(QMqttClient::MQTT_5_0);
VersionClient(QMqttClient::MQTT_5_0, client);
client.setHostname(m_testBroker);
client.setPort(m_port);

View File

@ -5,7 +5,9 @@
## tst_qmqtttopicfilter Test:
#####################################################################
qt_internal_add_test(tst_qmqtttopicfilter
qtmqtt_add_test(
TARGET
tst_qmqtttopicfilter
SOURCES
tst_qmqtttopicfilter.cpp
DEFINES

View File

@ -5,7 +5,9 @@
## tst_qmqtttopicname Test:
#####################################################################
qt_internal_add_test(tst_qmqtttopicname
qtmqtt_add_test(
TARGET
tst_qmqtttopicname
SOURCES
tst_qmqtttopicname.cpp
DEFINES

View File

@ -25,7 +25,7 @@ private Q_SLOTS:
private:
QProcess m_brokerProcess;
QString m_testBroker;
quint16 m_port{1883};
quint16 m_port{0};
};
Tst_QMqttClient::Tst_QMqttClient()
@ -54,9 +54,8 @@ void Tst_QMqttClient::stressTest_data()
void Tst_QMqttClient::stressTest()
{
QFETCH(int, qos);
QMqttClient subscriber;
QMqttClient publisher;
VersionClient(0, subscriber);
VersionClient(0, publisher);
subscriber.setHostname(m_testBroker);
subscriber.setPort(m_port);
@ -110,7 +109,7 @@ void Tst_QMqttClient::stressTest2()
QSet<qint32> msgIds;
msgIds.reserve(msgCount);
QMqttClient publisher;
VersionClient(0, publisher);
publisher.setHostname(m_testBroker);
publisher.setPort(m_port);

View File

@ -0,0 +1,27 @@
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-----BEGIN CERTIFICATE-----
MIID6zCCAtOgAwIBAgIUbbY+pKEPOOytRZ3RujmmdriEAKcwDQYJKoZIhvcNAQEL
BQAwgYMxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARPc2xvMQ0wCwYDVQQHDARPc2xv
MQswCQYDVQQKDAJRdDELMAkGA1UECwwCUXQxEjAQBgNVBAMMCWxvY2FsaG9zdDEo
MCYGCSqGSIb3DQEJARYZZXZlbi5vc2Nhci5hbmRlcnNlbkBxdC5pbzAgFw0yNDEw
MzExMTMyNDdaGA8yMTI0MTAwNzExMzI0N1owgYMxCzAJBgNVBAYTAk5PMQ0wCwYD
VQQIDARPc2xvMQ0wCwYDVQQHDARPc2xvMQswCQYDVQQKDAJRdDELMAkGA1UECwwC
UXQxEjAQBgNVBAMMCWxvY2FsaG9zdDEoMCYGCSqGSIb3DQEJARYZZXZlbi5vc2Nh
ci5hbmRlcnNlbkBxdC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AJzWmpWU9f/baRi/Fhn362W488HzC2/MUdbTZGIQUqt1TwTLyYMEqkr6WMy/NdYL
8X5oXW0uz8LttbFp98wJTkNirYBMxowxwWWePnqbK0iKaZTBvBzUh0vWvmtFzHUW
E93K1NtKyL76Zj/EZv0I0CpkWMobpzEW/zquPj83Wxki0xp2rr/HHynqFv8KFMoJ
pR1A6uWtly12V1aQyXZIyMoIUPgDPmsHtNZKBCcz7IsAYHjjfvEIJ+r4lOOsgTXj
cdMU+0hHfyNCy1/6xmBwnchSqDZf3bTyFRu6GK+zzFKBSyt4MB7zQ2P29qYwoNJO
buJkPRfqiQJJRLkwyu59TB0CAwEAAaNTMFEwHQYDVR0OBBYEFGGxHowwihBbJlM5
2wzicQa2sCfwMB8GA1UdIwQYMBaAFGGxHowwihBbJlM52wzicQa2sCfwMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACf4lUaBpw65tOZk32EpMD0D
M0ilx1AwfUqliKdhVvkFJ6jN5h17YhVjFoGtSzE7ry5Rg5J07tUK5Xkjcfk39UWV
RofVnRhrtiticXs0eXQkDXqao0aMjUjsWiokr4/cTNT5R3h9jmjzyjA6pWf2oSjT
GTzZAHdcuBTUfvPy/Ff4M5AVNsI6geUqrUd6XzFwQsDWTT86sdWQIC8j+FMghhss
9XRNOmhWtWGSRbP0HqlWOz5hFRPP/faI/FGTknzkkVYoWaB1CR+ThFK9jYi0FnFL
2fIcJPt+6g6d01Ws5cb9HpL9joUloCjsZ+w6PXYNVyHTaG3Lg5o4nT1Oizvrq1k=
-----END CERTIFICATE-----

View File

@ -0,0 +1,32 @@
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCc1pqVlPX/22kY
vxYZ9+tluPPB8wtvzFHW02RiEFKrdU8Ey8mDBKpK+ljMvzXWC/F+aF1tLs/C7bWx
affMCU5DYq2ATMaMMcFlnj56mytIimmUwbwc1IdL1r5rRcx1FhPdytTbSsi++mY/
xGb9CNAqZFjKG6cxFv86rj4/N1sZItMadq6/xx8p6hb/ChTKCaUdQOrlrZctdldW
kMl2SMjKCFD4Az5rB7TWSgQnM+yLAGB4437xCCfq+JTjrIE143HTFPtIR38jQstf
+sZgcJ3IUqg2X9208hUbuhivs8xSgUsreDAe80Nj9vamMKDSTm7iZD0X6okCSUS5
MMrufUwdAgMBAAECggEAKs2u9q/my2M4NZbBE2lEB0kIzZ/lOSfMFhMvTEwkI8Mq
Q6bSYj19tGTKo2Zz7OzphZQ6GzgxX4O8mKTRChBoGZ/uths9/Lj/jRo49wEuOOf9
lKmjC0M9gYckBObRvArAdUGMAiVQ0D5KdZDGgrxLA6bLTK1rXcxm777qIhqbdCpN
i9RwW9wp9rMV53J8mmWWUDVpfbIKHAmp50JknXj07onPEqN6IKdZY7sYACfYiz/8
l31rKfR/P5j/aRBOFwBnq7Z3JGfOEQPmE8bxQ2Vt3ZXPK2ekreDx4j2Tz+gSZmF3
Ee8DonQtA1DTOlhMyb6FhJrEFmDr38jGQqDK4qV8iQKBgQDLoOSYzX0xcyK2dPMD
woPGcKymI+XYx0Q6cVZo1GttNarhBN0w0ms9a4SYoTMhAI9tzjJw/sU5t9kLan6n
m11PqQVK+Vbh1v2YICJW89LcOFYwyO6IAiMN1LUdy8las4GwcXRwBWWnXAnE+YJK
AiXcmB1ZX3j8pgStCF9VApC50wKBgQDFLP87pGtWW3nvkxoDpgVb1CwpO1T1EsFF
Yzv7eIkFQGUkqF7OlslhMCOERE8pj4dr4CoTIvVsYW+lYfBnFPpQ0pQ+BZ2meZ0u
GfWBDYpNGTGrxEDBc923glb2oegQQirHpiWtlinp5nciOn/rqpUwJR3b46drFlNy
26CTKA+8TwKBgQDKv8qdMo2i/QblMRD+/2CB55KgYkHrVI1ku5DUFB1awgMAxf0P
LZRFtZZy+p6UD6DALn0e8S2jSKE9sq2laRbByINSoW2WtKAQJn7KoT+kshtvu8F1
fts0XERyBITaYL2S14SePWF4ADZiACVwVy8ns/YVFPC8bvlc6Gczl7hOrQKBgQCP
BUmJSIT3GdlDlq7q8JS4fBkgO0IvldAM9aL/j/nLjl8PDPXf4e3mihVpDmdhXRO8
gtfiE5xzZeWmz3iiPMworeYLauVkaJhDZV73ogusStcFoY/bAqFTR76unNgIWwZO
1MxFskNqvtmxQT+igJRAXNvgsKuyeHpFONurggaP7wKBgCj25sAxVcOuOcANQGcO
wCNvt1pHDJengrzaKooCJqm5YxNhrcKlJsdQcQ1Mu+KyhcMY/WF/0UaJZytlHMWf
aDlF7zKqhQFqFY7nk/C7+fED7Kg3XJR54qtweVNzD6k4yTeSsvBeTd2aaepzZvJI
IOQ3RPVQNsdgjn3VTGs/rmrR
-----END PRIVATE KEY-----

View File

@ -8,8 +8,16 @@
#include <QtNetwork/QTcpSocket>
#include <QtTest/QTest>
#ifdef QT_MQTT_WITH_WEBSOCKETS
#include <QWebSocket>
#include <QWebSocketHandshakeOptions>
#endif
QString invokeOrInitializeBroker(QProcess *gBrokerProcess)
{
#if defined(MQTT_TEST_BROKER)
return QString::fromLatin1(MQTT_TEST_BROKER);
#endif
const QString broker = qgetenv("MQTT_TEST_BROKER");
if (broker.size()) {
qDebug("Overwriting default test broker");
@ -65,13 +73,264 @@ QString invokeOrInitializeBroker(QProcess *gBrokerProcess)
return QString();
}
Q_DECLARE_METATYPE(QMqttClient::ProtocolVersion)
#define VersionClient(MQTTVERSION, CLIENTNAME) QMqttClient CLIENTNAME; CLIENTNAME.setProtocolVersion(MQTTVERSION)
#if !defined(QT_NO_SSL)
QSslConfiguration makeConfig(QString certificateFile)
{
if (certificateFile.isEmpty())
certificateFile=QString(u":/certificate/cert.crt");
QSslConfiguration config;
QFile file(certificateFile);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << " Could not open certificate file " << certificateFile;
} else {
const auto bytes = file.readAll();
const QSslCertificate certificate(bytes);
config.addCaCertificate(certificate);
}
return config;
}
#endif /* !QT_NO_SSL */
int getBrokerPort(int defaultPort)
{
if (getenv("MQTT_TEST_BROKER_PORT"))
return atoi(getenv("MQTT_TEST_BROKER_PORT"));
#if defined (MQTT_TEST_PROTOCOL)
return defaultPort;
#else
return defaultPort - 1000; /* evaluates to 1883 for the old system */
#endif
}
QMqttClient::ProtocolVersion getProtocolVersion(int version)
{
#if defined (MQTT_TEST_PROTOCOL)
if (version == 0)
version=MQTT_TEST_PROTOCOL;
#else
if ((version == 0) && getenv("MQTT_TEST_PROTOCOL_VERSION")) {
switch (atoi(getenv("MQTT_TEST_PROTOCOL_VERSION"))) {
case 3: version = QMqttClient::MQTT_3_1; break;
case 4: version = QMqttClient::MQTT_3_1_1; break;
case 5: version = QMqttClient::MQTT_5_0; break;
}
}
if (version == 0)
version = QMqttClient::MQTT_5_0;
#endif
return (QMqttClient::ProtocolVersion)version;
}
class MqTTTestClientBase : public QMqttClient
{
public:
virtual bool isTcp() const { return false; }
virtual bool isSsl() const { return false; }
virtual bool isWs() const { return false; }
virtual bool isWss() const { return false; }
public:
virtual void setPort(quint16 port) = 0;
virtual void connectToHost() = 0;
void setTransport(QIODevice *device, TransportType transport)
{
m_transportSet = true;
QMqttClient::setTransport(device, transport);
}
void disconnectFromHost()
{
m_transportSet = false;
QMqttClient::disconnectFromHost();
}
protected:
bool m_transportSet = false;
};
class MqTTClientTcp : public MqTTTestClientBase
{
public:
MqTTClientTcp() = default;
virtual bool isTcp() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(2883);
QMqttClient::setPort(port);
}
void connectToHost() override
{
QMqttClient::connectToHost();
}
};
#ifdef QT_MQTT_WITH_WEBSOCKETS
class MqTTClientWs : public MqTTTestClientBase
{
public:
MqTTClientWs() = default;
virtual bool isWs() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9080);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else
QMqttClient::connectToHostWebSocket();
}
};
#endif
#ifdef QT_MQTT_WITH_WEBSOCKETS
class MqTTClientWss : public MqTTTestClientBase
{
public:
MqTTClientWss()
{
#ifndef QT_NO_SSL
const QString origin;
const QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest;
socket = new QWebSocket(origin, version, this);
#endif
}
virtual bool isWss() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9081);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else {
#ifndef QT_NO_SSL
QUrl url(QString(u"wss://") + QMqttClient::hostname() + QString(u":") + QString::number(QMqttClient::port()));
QWebSocketHandshakeOptions options;
options.setSubprotocols(QStringList{ QString::fromUtf8("mqttv3.1") });
socket->setSslConfiguration(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
socket->open(url, options);
#endif
QMqttClient::connectToHostWebSocketEncrypted(socket);
}
}
private:
QWebSocket *socket = nullptr;
};
#endif
#ifndef QT_NO_SSL
class MqTTClientSsl : public MqTTTestClientBase
{
public:
MqTTClientSsl() = default;
virtual bool isSsl() const override { return true; }
void setPort(quint16 port) override
{
if (port == 0)
port = getBrokerPort(9883);
QMqttClient::setPort(port);
}
void connectToHost() override
{
if (m_transportSet)
QMqttClient::connectToHost();
else {
QMqttClient::connectToHostEncrypted(makeConfig(QString::fromUtf8(getenv("MQTT_TEST_BROKER_CERTIFICATE"))));
}
}
};
#endif /* !QT_NO_SSL */
Q_DECLARE_METATYPE(QMqttClient::ProtocolVersion)
#if !defined(QT_NO_SSL) && defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ws")) p##CLIENTNAME = std::make_shared<MqTTClientWs>(); \
if (TestType == QString(u"Wss")) p##CLIENTNAME = std::make_shared<MqTTClientWss>(); \
if (TestType == QString(u"Ssl")) p##CLIENTNAME = std::make_shared<MqTTClientSsl>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(QT_NO_SSL) && defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ws")) p##CLIENTNAME = std::make_shared<MqTTClientWs>(); \
if (TestType == QString(u"Wss")) p##CLIENTNAME = std::make_shared<MqTTClientWss>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if !defined(QT_NO_SSL) && !defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (TestType == QString(u"Ssl")) p##CLIENTNAME = std::make_shared<MqTTClientSsl>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(QT_NO_SSL) && !defined(QT_MQTT_WITH_WEBSOCKETS)
#define VersionClientBase(MQTTVERSION, CLIENTNAME, TestType) \
std::shared_ptr<MqTTTestClientBase> p##CLIENTNAME; \
if (TestType == QString(u"Tcp")) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
if (!p##CLIENTNAME) p##CLIENTNAME = std::make_shared<MqTTClientTcp>(); \
MqTTTestClientBase &CLIENTNAME = *p##CLIENTNAME; \
CLIENTNAME.setProtocolVersion(getProtocolVersion(MQTTVERSION))
#endif
#if defined(MQTT_TEST_TYPE)
#define VersionClient(MQTTVERSION, CLIENTNAME) \
VersionClientBase(MQTTVERSION, CLIENTNAME, MQTT_TEST_TYPE)
#else
#define VersionClient(MQTTVERSION, CLIENTNAME) \
VersionClientBase(MQTTVERSION, CLIENTNAME, qgetenv("MQTT_TEST_BROKER_TYPE"))
#endif
#ifdef MQTT_TEST_PROTOCOL
#define DefaultVersionTestData(FUNCTION) \
void FUNCTION() \
{ \
QTest::addColumn<QMqttClient::ProtocolVersion>("mqttVersion"); \
QTest::newRow("V3.1.1") << QMqttClient::MQTT_3_1_1; \
QTest::newRow("V5.0.0") << QMqttClient::MQTT_5_0; \
QTest::newRow("V0") << QMqttClient::ProtocolVersion(0); \
}
#else
#define DefaultVersionTestData(FUNCTION) \
void FUNCTION() \
{ \
QTest::addColumn<QMqttClient::ProtocolVersion>("mqttVersion"); \
if (getenv("MQTT_TEST_PROTOCOL_VERSION"))\
QTest::newRow("V0") << QMqttClient::ProtocolVersion(0); \
else { \
QTest::newRow("V3.1.1") << QMqttClient::MQTT_3_1_1; \
QTest::newRow("V5.0.0") << QMqttClient::MQTT_5_0; \
} \
}
#endif

View File

@ -16,7 +16,9 @@ endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/mqtt/consolepubsub")
find_package(Qt6 REQUIRED COMPONENTS Mqtt)
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
find_package(Qt6 REQUIRED COMPONENTS Mqtt)
end()
#
# Pub