mirror of
https://github.com/qt/qtmqtt.git
synced 2026-10-25 16:16:26 +00:00
Add Control Packet class
Helps for generalizing packet generation and later on for testing...
This commit is contained in:
parent
a89d471be5
commit
ff5bca5436
@ -17,8 +17,10 @@ PRIVATE_HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
qmqttclient.cpp \
|
||||
qmqttconnection.cpp
|
||||
qmqttconnection.cpp \
|
||||
qmqttcontrolpacket.cpp
|
||||
|
||||
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
|
||||
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \
|
||||
qmqttcontrolpacket_p.h
|
||||
|
||||
load(qt_module)
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "qmqttconnection_p.h"
|
||||
#include "qmqttcontrolpacket_p.h"
|
||||
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
|
||||
@ -109,36 +110,20 @@ bool QMqttConnection::ensureTransportOpen()
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void addInt(QByteArray &data, quint16 n)
|
||||
{
|
||||
const quint16 msb = qToBigEndian<quint16>(n);
|
||||
const char * msb_c = reinterpret_cast<const char*>(&msb);
|
||||
data.append(msb_c[0]);
|
||||
data.append(msb_c[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
bool QMqttConnection::sendControlConnect()
|
||||
{
|
||||
QByteArray connectFrame;
|
||||
// Fixed header
|
||||
connectFrame += PacketType::CONNECT;
|
||||
QMqttControlPacket packet(QMqttControlPacket::CONNECT);
|
||||
|
||||
connectFrame += char(0); // Length to be filled later
|
||||
// Variable header
|
||||
// 3.1.2.1 Protocol Name
|
||||
// 3.1.2.2 Protocol Level
|
||||
const quint8 protocolVersion = m_client->protocolVersion();
|
||||
if (protocolVersion == 3) {
|
||||
const QByteArray other("MQIsdp");
|
||||
addInt(connectFrame, other.size());
|
||||
connectFrame += other.data();
|
||||
connectFrame += char(3); // Version 3.1
|
||||
packet.append("MQIsdp");
|
||||
packet.append(char(3)); // Version 3.1
|
||||
} else if (protocolVersion == 4) {
|
||||
connectFrame += char(0); // Length MSB
|
||||
connectFrame += 4; // Length LSB
|
||||
connectFrame += "MQTT";
|
||||
connectFrame += char(4); // Version 3.1.1
|
||||
packet.append("MQTT");
|
||||
packet.append(char(4)); // Version 3.1.1
|
||||
} else {
|
||||
qFatal("Illegal MQTT VERSION");
|
||||
}
|
||||
@ -147,32 +132,29 @@ bool QMqttConnection::sendControlConnect()
|
||||
quint8 flags = 0;
|
||||
// Clean session
|
||||
flags |= 1;
|
||||
connectFrame += char(flags);
|
||||
packet.append(char(flags));
|
||||
|
||||
// 3.1.2.10 Keep Alive
|
||||
addInt(connectFrame, m_client->keepAlive());
|
||||
packet.append(m_client->keepAlive());
|
||||
|
||||
// 3.1.3 Payload
|
||||
// 3.1.3.1 Client Identifier
|
||||
if (protocolVersion == 3) { // no username
|
||||
connectFrame += char(0);
|
||||
connectFrame += char(0);
|
||||
packet.append(char(0));
|
||||
packet.append(char(0));
|
||||
} else if (protocolVersion == 4) {
|
||||
// Client id maximum left is 23
|
||||
const QByteArray clientStringArray = m_client->clientId().left(23).toUtf8();
|
||||
if (clientStringArray.size()) {
|
||||
addInt(connectFrame, clientStringArray.size());
|
||||
connectFrame += clientStringArray;
|
||||
packet.append(clientStringArray);
|
||||
} else {
|
||||
connectFrame += char(0);
|
||||
connectFrame += char(0);
|
||||
packet.append(char(0));
|
||||
packet.append(char(0));
|
||||
}
|
||||
}
|
||||
|
||||
const quint8 frameLength = connectFrame.size();
|
||||
connectFrame[1] = char(frameLength - 2); // The header bytes are not included
|
||||
|
||||
const qint64 res = m_transport->write(connectFrame.constData(), frameLength);
|
||||
const QByteArray send = packet.serialize();
|
||||
const qint64 res = m_transport->write(send.constData(), send.size());
|
||||
if (Q_UNLIKELY(res == -1)) {
|
||||
qWarning("Could not write CONNECT frame to transport");
|
||||
return false;
|
||||
@ -230,7 +212,7 @@ void QMqttConnection::transportReadReady()
|
||||
Q_ASSERT(data.size());
|
||||
const quint8 *ptr = reinterpret_cast<const quint8 *>(data.constData());
|
||||
switch (data[0]) {
|
||||
case PacketType::CONNACK: {
|
||||
case QMqttControlPacket::CONNACK: {
|
||||
if (m_internalState != BrokerWaitForConnectAck) {
|
||||
qWarning("Received CONNACK at unexpected time!");
|
||||
break;
|
||||
@ -261,6 +243,7 @@ void QMqttConnection::transportReadReady()
|
||||
if (connectResultValue != 0) {
|
||||
qWarning("Connection has been rejected");
|
||||
// MQTT-3.2.2-5
|
||||
// ConnectionError
|
||||
m_transport->close();
|
||||
}
|
||||
m_internalState = BrokerConnected;
|
||||
|
||||
@ -49,22 +49,6 @@ QT_BEGIN_NAMESPACE
|
||||
class QMqttConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
enum PacketType {
|
||||
CONNECT = 0x10,
|
||||
CONNACK = 0x20,
|
||||
PUBLISH = 0x30,
|
||||
PUBACK = 0x40,
|
||||
PUBREC = 0x50,
|
||||
PUBREL = 0x60,
|
||||
PUBCOMP = 0x70,
|
||||
SUBSCRIBE = 0x80,
|
||||
SUBACK = 0x90,
|
||||
UNSUBSCRIBE = 0xA0,
|
||||
UNSUBACK = 0xB0,
|
||||
PINGREQ = 0xC0,
|
||||
PINGRESP = 0xD0,
|
||||
DISCONNECT = 0xE0
|
||||
};
|
||||
|
||||
enum InternalConnectionState {
|
||||
BrokerDisconnected = 0,
|
||||
@ -72,6 +56,15 @@ class QMqttConnection : public QObject
|
||||
BrokerConnected
|
||||
};
|
||||
|
||||
enum ConnectionError {
|
||||
NoError = 0,
|
||||
InvalidProtocolVersion = 1,
|
||||
IdRejected = 2,
|
||||
ServerUnavailable = 3,
|
||||
BadUsernameOrPassword = 4,
|
||||
NotAuthorized = 5
|
||||
};
|
||||
|
||||
public:
|
||||
explicit QMqttConnection(QObject *parent = 0);
|
||||
~QMqttConnection();
|
||||
|
||||
98
src/mqtt/qmqttcontrolpacket.cpp
Normal file
98
src/mqtt/qmqttcontrolpacket.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Mqtt module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "qmqttcontrolpacket_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QMqttControlPacket::QMqttControlPacket()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QMqttControlPacket::QMqttControlPacket(quint8 header)
|
||||
: m_header(header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QMqttControlPacket::QMqttControlPacket(quint8 header, const QByteArray &pay)
|
||||
: m_header(header)
|
||||
, m_payload(pay)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QMqttControlPacket::clear()
|
||||
{
|
||||
m_header = 0;
|
||||
m_payload.clear();
|
||||
}
|
||||
|
||||
void QMqttControlPacket::setHeader(quint8 h)
|
||||
{
|
||||
m_header = h;
|
||||
}
|
||||
|
||||
void QMqttControlPacket::append(char value)
|
||||
{
|
||||
m_payload.append(value);
|
||||
}
|
||||
|
||||
void QMqttControlPacket::append(quint16 value)
|
||||
{
|
||||
const quint16 msb = qToBigEndian<quint16>(value);
|
||||
const char * msb_c = reinterpret_cast<const char*>(&msb);
|
||||
m_payload.append(msb_c[0]);
|
||||
m_payload.append(msb_c[1]);
|
||||
}
|
||||
|
||||
void QMqttControlPacket::append(const QByteArray &data)
|
||||
{
|
||||
append(static_cast<quint16>(data.size()));
|
||||
m_payload.append(data.constData());
|
||||
}
|
||||
|
||||
QByteArray QMqttControlPacket::serialize()
|
||||
{
|
||||
// Create ByteArray
|
||||
QByteArray data;
|
||||
// Add Header
|
||||
data.append(char(m_header));
|
||||
// Add length placeholder
|
||||
const quint8 l = m_payload.size();
|
||||
data.append(char(l));
|
||||
// Add payload
|
||||
data.append(m_payload);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
91
src/mqtt/qmqttcontrolpacket_p.h
Normal file
91
src/mqtt/qmqttcontrolpacket_p.h
Normal file
@ -0,0 +1,91 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Mqtt module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMQTTCONTROLPACKET_P_H
|
||||
#define QMQTTCONTROLPACKET_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 <QtCore/QtGlobal>
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMqttControlPacket
|
||||
{
|
||||
public:
|
||||
enum PacketType {
|
||||
CONNECT = 0x10,
|
||||
CONNACK = 0x20,
|
||||
PUBLISH = 0x30,
|
||||
PUBACK = 0x40,
|
||||
PUBREC = 0x50,
|
||||
PUBREL = 0x60,
|
||||
PUBCOMP = 0x70,
|
||||
SUBSCRIBE = 0x80,
|
||||
SUBACK = 0x90,
|
||||
UNSUBSCRIBE = 0xA0,
|
||||
UNSUBACK = 0xB0,
|
||||
PINGREQ = 0xC0,
|
||||
PINGRESP = 0xD0,
|
||||
DISCONNECT = 0xE0
|
||||
};
|
||||
|
||||
QMqttControlPacket();
|
||||
QMqttControlPacket(quint8 header);
|
||||
QMqttControlPacket(quint8 header, const QByteArray &pay);
|
||||
|
||||
void clear();
|
||||
|
||||
void setHeader(quint8 h);
|
||||
inline quint8 header() const { return m_header; }
|
||||
|
||||
void append(char value);
|
||||
void append(quint16 value);
|
||||
void append(const QByteArray &data);
|
||||
|
||||
QByteArray serialize();
|
||||
inline QByteArray payload() const { return m_payload; }
|
||||
private:
|
||||
quint8 m_header;
|
||||
QByteArray m_payload;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMQTTCONTROLPACKET_P_H
|
||||
Loading…
Reference in New Issue
Block a user