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

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>
This commit is contained in:
Tatiana Borisova 2026-10-08 15:04:05 +02:00
parent 457877b453
commit 51fe8b4f2e
2 changed files with 22 additions and 10 deletions

View File

@ -1970,18 +1970,25 @@ bool QMqttConnection::processDataHelper()
if (m_missingData > 0) {
// MQTT-2.1.4 The remaining length in the fixed header says where the message ends.
const qint64 packetEnd = qint64(m_readPosition) + m_missingData;
// 3.1.2.11.4 Maximum Packet Size
// If client receives a packet whose size exceeds this limit,
// this is a Protocol Error, the Client uses DISCONNECT with
// Reason Code 0x95 (Packet too large),
if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0
&& (m_internalState == BrokerConnected
|| m_internalState == BrokerWaitForConnectAck)) {
if (m_internalState == BrokerConnected || m_internalState == BrokerWaitForConnectAck) {
const quint32 maxSize = m_clientPrivate->m_connectionProperties.maximumPacketSize();
if (maxSize > 0 && packetEnd > maxSize) {
qCDebug(lcMqttConnection) << "Packet size exceeds the announced maximum.";
m_clientPrivate->m_client->setError(QMqttClient::ProtocolViolation);
sendControlDisconnect(QMqtt::ReasonCode::PacketTooLarge);
qCDebug(lcMqttConnection) << "Packet size exceeds the maximum packet size.";
if (m_clientPrivate->m_protocolVersion == QMqttClient::MQTT_5_0) {
// MQTT 5: 3.1.2.11.4 Maximum Packet Size
// If client receives a packet whose size exceeds this limit,
// this is a Protocol Error, the Client uses DISCONNECT with
// Reason Code 0x95 (Packet too large).
m_clientPrivate->m_client->setError(QMqttClient::ProtocolViolation);
sendControlDisconnect(QMqtt::ReasonCode::PacketTooLarge);
} else {
// MQTT 3.1 and 3.1.1 do not define a maximum packet size property, but we
// can still enforce the limit locally and close the connection if the broker
// attempts to send a packet that exceeds it.
// There are no reason codes before MQTT 5.0, and a DISCONNECT is not
// required. Just close the connection.
closeConnection(QMqttClient::ProtocolViolation);
}
return false;
}
}

View File

@ -304,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)
{