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

Update data receiving

transportReadReady might contain more than one MQTT message. Hence
iterate on the buffer itself and do not use readAll().
This commit is contained in:
Maurice Kalinowski 2017-02-17 10:40:39 +01:00
parent cc16b02378
commit 8c8e505310

View File

@ -260,102 +260,116 @@ void QMqttConnection::transportConnectionClosed()
void QMqttConnection::transportReadReady()
{
QByteArray data = m_transport->readAll();
Q_ASSERT(data.size());
const quint8 *ptr = reinterpret_cast<const quint8 *>(data.constData());
switch (ptr[0]) {
case QMqttControlPacket::CONNACK: {
if (m_internalState != BrokerWaitForConnectAck) {
qWarning("Received CONNACK at unexpected time!");
break;
}
quint8 payloadSize = ptr[1];
if (payloadSize != 2 || (payloadSize != data.size() - 2)) {
qWarning("Unexpected FRAME size in CONNACK");
// ## SET SOME ERROR
break;
}
quint8 ackFlags = ptr[2];
if (ackFlags > 1) { // MQTT-3.2.2.1
qWarning("Unexpected CONNACK Flags set");
// ## SET SOME ERROR
break;
}
bool sessionPresent = ackFlags == 1;
// ### TODO: This heavily relies on the fact that messages are fully sent
// before transport ReadReady is invoked.
qint64 available = m_transport->bytesAvailable();
while (available > 0) {
quint8 msg;
m_transport->read((char*)&msg, 1);
switch (msg) {
case QMqttControlPacket::CONNACK: {
if (m_internalState != BrokerWaitForConnectAck) {
qWarning("Received CONNACK at unexpected time!");
break;
}
//quint8 payloadSize = ptr[1];
quint8 payloadSize;
m_transport->read((char*)&payloadSize, 1);
if (payloadSize != 2) {
qWarning("Unexpected FRAME size in CONNACK");
// ## SET SOME ERROR
break;
}
quint8 ackFlags;
m_transport->read((char*)&ackFlags, 1);
if (ackFlags > 1) { // MQTT-3.2.2.1
qWarning("Unexpected CONNACK Flags set");
// ## SET SOME ERROR
break;
}
bool sessionPresent = ackFlags == 1;
// ### TODO: MQTT-3.2.2-1
// ### TODO: MQTT-3.2.2-2
if (sessionPresent) {
qWarning("Connected with a clean session, ack contains session present");
// ## SET SOME ERROR
// ### TODO: MQTT-3.2.2-1
// ### TODO: MQTT-3.2.2-2
if (sessionPresent) {
qWarning("Connected with a clean session, ack contains session present");
// ## SET SOME ERROR
//break;
}
quint8 connectResultValue;
m_transport->read((char*)&connectResultValue, 1);
if (connectResultValue != 0) {
qWarning("Connection has been rejected");
// MQTT-3.2.2-5
// ConnectionError
m_transport->close();
}
m_internalState = BrokerConnected;
m_client->setState(QMqttClient::Connected);
m_pingTimer.setInterval(m_client->keepAlive() * 1000);
m_pingTimer.start();
break;
}
quint8 connectResultValue = ptr[3];
if (connectResultValue != 0) {
qWarning("Connection has been rejected");
// MQTT-3.2.2-5
// ConnectionError
m_transport->close();
}
m_internalState = BrokerConnected;
m_client->setState(QMqttClient::Connected);
m_pingTimer.setInterval(m_client->keepAlive() * 1000);
m_pingTimer.start();
break;
}
case QMqttControlPacket::SUBACK: {
const quint16 id = qFromBigEndian<quint16>(reinterpret_cast<const quint16 *>(&ptr[2])[0]);
if (!m_pendingSubscriptionAck.contains(id)) {
qWarning("Received SUBACK for unknown subscription request");
case QMqttControlPacket::SUBACK: {
char offset;
m_transport->read(&offset, 1);
quint16 id;
m_transport->read((char*)&id, 2);
id = qFromBigEndian<quint16>(id);
if (!m_pendingSubscriptionAck.contains(id)) {
qWarning("Received SUBACK for unknown subscription request");
break;
}
quint8 result;
m_transport->read((char*)&result, 1);
if (result <= 2) {
// ### TODO: subscriptionSucceeded/Failed
emit m_client->subscribed();
// 0 Success with QoS 0
// 1 Success with QoS 1
// 2 Success with QoS 2
m_pendingSubscriptionAck.remove(id);
} else if (result == 0x80) {
// ### TODO: subscriptionFailed
qWarning("Subscription failed");
} else {
qWarning("Received invalid SUBACK result value");
}
break;
}
const quint8 result = ptr[4];
if (result <= 2) {
// ### TODO: subscriptionSucceeded/Failed
emit m_client->subscribed();
// 0 Success with QoS 0
// 1 Success with QoS 1
// 2 Success with QoS 2
m_pendingSubscriptionAck.remove(id);
} else if (result == 0x80) {
// ### TODO: subscriptionFailed
qWarning("Subscription failed");
} else {
qWarning("Received invalid SUBACK result value");
}
break;
}
case QMqttControlPacket::PUBLISH: {
const quint8 *msgPtr = ptr;
// PUBLISH byte
msgPtr++;
// remaining length
msgPtr++;
// String topic
const quint16 topicLength = qFromBigEndian<quint16>(reinterpret_cast<const quint16 *>(msgPtr)[0]);
msgPtr += 2;
const QString topic = QString::fromUtf8(reinterpret_cast<const char *>(msgPtr), topicLength);
msgPtr += topicLength;
// String message
const quint16 messageLength = qFromBigEndian<quint16>(reinterpret_cast<const quint16 *>(msgPtr)[0]);
msgPtr += 2;
const QString message = QString::fromUtf8(reinterpret_cast<const char *>(msgPtr), messageLength);
case QMqttControlPacket::PUBLISH: {
// remaining length
char offset;
m_transport->read(&offset, 1); // ### TODO: Should we care about remaining length???
emit m_client->messageReceived(topic, message);
break;
}
case QMqttControlPacket::PINGRESP: {
if (ptr[1] != 0)
qWarning("Received a PINGRESP with payload!");
emit m_client->pingResponse();
break;
}
default: {
qWarning("Transport received unknown data");
}
}
// String topic
const quint16 topicLength = qFromBigEndian<quint16>(reinterpret_cast<const quint16 *>(m_transport->read(2).constData()));
const QString topic = QString::fromUtf8(reinterpret_cast<const char *>(m_transport->read(topicLength).constData()));
// String message
const quint16 messageLength = qFromBigEndian<quint16>(reinterpret_cast<const quint16 *>(m_transport->read(2).constData()));
const QString message = QString::fromUtf8(reinterpret_cast<const char *>(m_transport->read(messageLength).constData()));
emit m_client->messageReceived(topic, message);
break;
}
case QMqttControlPacket::PINGRESP: {
quint8 v;
m_transport->read((char*)&v, 1);
if (v != 0)
//if (ptr[1] != 0)
qWarning("Received a PINGRESP with payload!");
emit m_client->pingResponse();
break;
}
default: {
qWarning("Transport received unknown data");
}
}
available = m_transport->bytesAvailable();
} // available
}
bool QMqttConnection::writePacketToTransport(const QMqttControlPacket &p)