mirror of
https://github.com/eclipse/paho.mqtt.cpp.git
synced 2025-05-09 11:21:24 +08:00
515 lines
18 KiB
C++
515 lines
18 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
/// @file message.h
|
|
/// Declaration of MQTT message class
|
|
/// @date May 1, 2013
|
|
/// @author Frank Pagliughi
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*******************************************************************************
|
|
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
|
|
*
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v2.0
|
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
*
|
|
* The Eclipse Public License is available at
|
|
* http://www.eclipse.org/legal/epl-v20.html
|
|
* and the Eclipse Distribution License is available at
|
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
|
*
|
|
* Contributors:
|
|
* Frank Pagliughi - initial implementation and documentation
|
|
* Frank Pagliughi - MQTT v5 support (properties)
|
|
*******************************************************************************/
|
|
|
|
#ifndef __mqtt_message_h
|
|
#define __mqtt_message_h
|
|
|
|
#include <memory>
|
|
|
|
#include "MQTTAsync.h"
|
|
#include "mqtt/buffer_ref.h"
|
|
#include "mqtt/exception.h"
|
|
#include "mqtt/platform.h"
|
|
#include "mqtt/properties.h"
|
|
|
|
namespace mqtt {
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* An MQTT message holds everything required for an MQTT PUBLISH message.
|
|
* This holds the binary message payload, topic string, and all the
|
|
* additional meta-data for an MQTT message.
|
|
*
|
|
* The topic and payload buffers are kept as references to const data, so
|
|
* they can be reassigned as needed, but the buffers can not be updated
|
|
* in-place. Normally they would be created externally then copied or moved
|
|
* into the message. The library to transport the messages never touches the
|
|
* payloads or topics.
|
|
*
|
|
* This also means that message objects are fairly cheap to copy, since they
|
|
* don't copy the payloads. They simply copy the reference to the buffers.
|
|
* It is safe to pass these buffer references across threads since all
|
|
* references promise not to update the contents of the buffer.
|
|
*/
|
|
class message
|
|
{
|
|
public:
|
|
/** The default QoS for a message */
|
|
static constexpr int DFLT_QOS = 0;
|
|
/** The default retained flag */
|
|
static constexpr bool DFLT_RETAINED = false;
|
|
|
|
private:
|
|
/** Initializer for the C struct (from the C library) */
|
|
static constexpr MQTTAsync_message DFLT_C_STRUCT MQTTAsync_message_initializer;
|
|
/** A const string to use for references */
|
|
PAHO_MQTTPP_EXPORT static const string EMPTY_STR;
|
|
/** A const binary to use for references */
|
|
PAHO_MQTTPP_EXPORT static const binary EMPTY_BIN;
|
|
|
|
/** The underlying C message struct */
|
|
MQTTAsync_message msg_{DFLT_C_STRUCT};
|
|
/** The topic that the message was (or should be) sent on. */
|
|
string_ref topic_;
|
|
/** The message payload - an arbitrary binary blob. */
|
|
binary_ref payload_;
|
|
/** The properties for the message */
|
|
properties props_;
|
|
|
|
/** The client has special access. */
|
|
friend class async_client;
|
|
|
|
/**
|
|
* Set the dup flag in the underlying message
|
|
* @param dup Whether to set the dup flag.
|
|
*/
|
|
void set_duplicate(bool dup) { msg_.dup = to_int(dup); }
|
|
|
|
public:
|
|
/** Smart/shared pointer to this class. */
|
|
using ptr_t = std::shared_ptr<message>;
|
|
/** Smart/shared pointer to this class. */
|
|
using const_ptr_t = std::shared_ptr<const message>;
|
|
|
|
/**
|
|
* Constructs a message with an empty payload, and all other values set
|
|
* to defaults.
|
|
*/
|
|
message() {}
|
|
/**
|
|
* Constructs a message with the specified array as a payload, and all
|
|
* other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
* @param props The MQTT v5 properties for the message.
|
|
*/
|
|
message(
|
|
string_ref topic, const void* payload, size_t len, int qos, bool retained,
|
|
const properties& props = properties()
|
|
);
|
|
/**
|
|
* Constructs a message with the specified array as a payload, and all
|
|
* other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
*/
|
|
message(string_ref topic, const void* payload, size_t len)
|
|
: message(std::move(topic), payload, len, DFLT_QOS, DFLT_RETAINED) {}
|
|
/**
|
|
* Constructs a message from a byte buffer.
|
|
* Note that the payload accepts copy or move semantics.
|
|
* @param topic The message topic
|
|
* @param payload A byte buffer to use as the message payload.
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
* @param props The MQTT v5 properties for the message.
|
|
*/
|
|
message(
|
|
string_ref topic, binary_ref payload, int qos, bool retained,
|
|
const properties& props = properties()
|
|
);
|
|
/**
|
|
* Constructs a message from a byte buffer.
|
|
* Note that the payload accepts copy or move semantics.
|
|
* @param topic The message topic
|
|
* @param payload A byte buffer to use as the message payload.
|
|
*/
|
|
message(string_ref topic, binary_ref payload)
|
|
: message(std::move(topic), std::move(payload), DFLT_QOS, DFLT_RETAINED) {}
|
|
/**
|
|
* Constructs a message as a copy of the message structure.
|
|
* @param topic The message topic
|
|
* @param cmsg A "C" MQTTAsync_message structure.
|
|
*/
|
|
message(string_ref topic, const MQTTAsync_message& cmsg);
|
|
/**
|
|
* Constructs a message as a copy of the other message.
|
|
* @param other The message to copy into this one.
|
|
*/
|
|
message(const message& other);
|
|
/**
|
|
* Moves the other message to this one.
|
|
* @param other The message to move into this one.
|
|
*/
|
|
message(message&& other);
|
|
/**
|
|
* Destroys a message and frees all associated resources.
|
|
*/
|
|
~message() {}
|
|
|
|
/**
|
|
* Constructs a message with the specified values.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
* @param props The MQTT v5 properties for the message.
|
|
*/
|
|
static ptr_t create(
|
|
string_ref topic, const void* payload, size_t len, int qos, bool retained,
|
|
const properties& props = properties()
|
|
) {
|
|
return std::make_shared<message>(
|
|
std::move(topic), payload, len, qos, retained, props
|
|
);
|
|
}
|
|
/**
|
|
* Constructs a message with the specified array as a payload, and all
|
|
* other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
*/
|
|
static ptr_t create(string_ref topic, const void* payload, size_t len) {
|
|
return std::make_shared<message>(
|
|
std::move(topic), payload, len, DFLT_QOS, DFLT_RETAINED
|
|
);
|
|
}
|
|
/**
|
|
* Constructs a message from a byte buffer.
|
|
* Note that the payload accepts copy or move semantics.
|
|
* @param topic The message topic
|
|
* @param payload A byte buffer to use as the message payload.
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
* @param props The MQTT v5 properties for the message.
|
|
*/
|
|
static ptr_t create(
|
|
string_ref topic, binary_ref payload, int qos, bool retained,
|
|
const properties& props = properties()
|
|
) {
|
|
return std::make_shared<message>(
|
|
std::move(topic), std::move(payload), qos, retained, props
|
|
);
|
|
}
|
|
/**
|
|
* Constructs a message from a byte buffer.
|
|
* Note that the payload accepts copy or move semantics.
|
|
* @param topic The message topic
|
|
* @param payload A byte buffer to use as the message payload.
|
|
*/
|
|
static ptr_t create(string_ref topic, binary_ref payload) {
|
|
return std::make_shared<message>(
|
|
std::move(topic), std::move(payload), DFLT_QOS, DFLT_RETAINED
|
|
);
|
|
}
|
|
/**
|
|
* Constructs a message as a copy of the C message struct.
|
|
* @param topic The message topic
|
|
* @param msg A "C" MQTTAsync_message structure.
|
|
*/
|
|
static ptr_t create(string_ref topic, const MQTTAsync_message& msg) {
|
|
return std::make_shared<message>(std::move(topic), msg);
|
|
}
|
|
/**
|
|
* Copies another message to this one.
|
|
* @param rhs The other message.
|
|
* @return A reference to this message.
|
|
*/
|
|
message& operator=(const message& rhs);
|
|
/**
|
|
* Moves another message to this one.
|
|
* @param rhs The other message.
|
|
* @return A reference to this message.
|
|
*/
|
|
message& operator=(message&& rhs);
|
|
/**
|
|
* Expose the underlying C struct for the unit tests.
|
|
*/
|
|
#if defined(UNIT_TESTS)
|
|
const MQTTAsync_message& c_struct() const { return msg_; }
|
|
#endif
|
|
/**
|
|
* Sets the topic string.
|
|
* @param topic The topic on which the message is published.
|
|
*/
|
|
void set_topic(string_ref topic) {
|
|
topic_ = topic ? std::move(topic) : string_ref(string());
|
|
}
|
|
/**
|
|
* Gets the topic reference for the message.
|
|
* @return The topic reference for the message.
|
|
*/
|
|
const string_ref& get_topic_ref() const { return topic_; }
|
|
/**
|
|
* Gets the topic for the message.
|
|
* @return The topic string for the message.
|
|
*/
|
|
const string& get_topic() const { return topic_ ? topic_.str() : EMPTY_STR; }
|
|
/**
|
|
* Clears the payload, resetting it to be empty.
|
|
*/
|
|
void clear_payload();
|
|
/**
|
|
* Gets the payload reference.
|
|
*/
|
|
const binary_ref& get_payload_ref() const { return payload_; }
|
|
/**
|
|
* Gets the payload
|
|
*/
|
|
const binary& get_payload() const { return payload_ ? payload_.str() : EMPTY_BIN; }
|
|
/**
|
|
* Gets the payload as a string
|
|
*/
|
|
const string& get_payload_str() const { return payload_ ? payload_.str() : EMPTY_STR; }
|
|
/**
|
|
* Returns the quality of service for this message.
|
|
* @return The quality of service for this message.
|
|
*/
|
|
int get_qos() const { return msg_.qos; }
|
|
/**
|
|
* Returns whether or not this message might be a duplicate of one which
|
|
* has already been received.
|
|
* @return true this message might be a duplicate of one which
|
|
* has already been received, false otherwise
|
|
*/
|
|
bool is_duplicate() const { return to_bool(msg_.dup); }
|
|
/**
|
|
* Returns whether or not this message should be/was retained by the
|
|
* server.
|
|
* @return true if this message should be/was retained by the
|
|
* server, false otherwise.
|
|
*/
|
|
bool is_retained() const { return to_bool(msg_.retained); }
|
|
/**
|
|
* Sets the payload of this message to be the specified buffer.
|
|
* Note that this accepts copy or move operations:
|
|
* set_payload(buf);
|
|
* set_payload(std::move(buf));
|
|
* @param payload A buffer to use as the message payload.
|
|
*/
|
|
void set_payload(binary_ref payload);
|
|
/**
|
|
* Sets the payload of this message to be the specified byte array.
|
|
* @param payload the bytes to use as the message payload
|
|
* @param n the number of bytes in the payload
|
|
*/
|
|
void set_payload(const void* payload, size_t n) {
|
|
set_payload(binary_ref(static_cast<const binary_ref::value_type*>(payload), n));
|
|
}
|
|
/**
|
|
* Sets the quality of service for this message.
|
|
* @param qos The integer Quality of Service for the message
|
|
*/
|
|
void set_qos(int qos) {
|
|
validate_qos(qos);
|
|
msg_.qos = qos;
|
|
}
|
|
/**
|
|
* Determines if the QOS value is a valid one.
|
|
* @param qos The QOS value.
|
|
* @throw std::invalid_argument If the qos value is invalid.
|
|
*/
|
|
static void validate_qos(int qos) {
|
|
if (qos < 0 || qos > 2)
|
|
throw exception(MQTTASYNC_BAD_QOS, "Bad QoS");
|
|
}
|
|
/**
|
|
* Whether or not the publish message should be retained by the broker.
|
|
* @param retained @em true if the message should be retained by the
|
|
* broker, @em false if not.
|
|
*/
|
|
void set_retained(bool retained) { msg_.retained = to_int(retained); }
|
|
/**
|
|
* Gets the properties in the message.
|
|
* @return A const reference to the properties in the message.
|
|
*/
|
|
const properties& get_properties() const { return props_; }
|
|
/**
|
|
* Sets the properties in the message.
|
|
* @param props The properties to place into the message.
|
|
*/
|
|
void set_properties(const properties& props) {
|
|
props_ = props;
|
|
msg_.properties = props_.c_struct();
|
|
}
|
|
/**
|
|
* Moves the properties into the message.
|
|
* @param props The properties to move into the message.
|
|
*/
|
|
void set_properties(properties&& props) {
|
|
props_ = std::move(props);
|
|
msg_.properties = props_.c_struct();
|
|
}
|
|
/**
|
|
* Returns a string representation of this messages payload.
|
|
* @return A string representation of this messages payload.
|
|
*/
|
|
string to_string() const { return get_payload_str(); }
|
|
};
|
|
|
|
/** Smart/shared pointer to a message */
|
|
using message_ptr = message::ptr_t;
|
|
|
|
/** Smart/shared pointer to a const message */
|
|
using const_message_ptr = message::const_ptr_t;
|
|
|
|
/**
|
|
* Constructs a message with the specified array as a payload, and all
|
|
* other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
* @param props The MQTT v5 properties for the message.
|
|
*/
|
|
inline message_ptr make_message(
|
|
string_ref topic, const void* payload, size_t len, int qos, bool retained,
|
|
const properties& props = properties()
|
|
) {
|
|
return mqtt::message::create(std::move(topic), payload, len, qos, retained, props);
|
|
}
|
|
|
|
/**
|
|
* Constructs a message with the specified array as a payload, and all
|
|
* other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload the bytes to use as the message payload
|
|
* @param len the number of bytes in the payload
|
|
*/
|
|
inline message_ptr make_message(string_ref topic, const void* payload, size_t len) {
|
|
return mqtt::message::create(std::move(topic), payload, len);
|
|
}
|
|
|
|
/**
|
|
* Constructs a message with the specified values.
|
|
* @param topic The message topic
|
|
* @param payload A buffer to use as the message payload.
|
|
* @param qos The quality of service for the message.
|
|
* @param retained Whether the message should be retained by the broker.
|
|
*/
|
|
inline message_ptr make_message(
|
|
string_ref topic, binary_ref payload, int qos, bool retained,
|
|
const properties& props = properties()
|
|
) {
|
|
return mqtt::message::create(std::move(topic), std::move(payload), qos, retained, props);
|
|
}
|
|
|
|
/**
|
|
* Constructs a message with the specified buffer as a payload, and
|
|
* all other values set to defaults.
|
|
* @param topic The message topic
|
|
* @param payload A string to use as the message payload.
|
|
*/
|
|
inline message_ptr make_message(string_ref topic, binary_ref payload) {
|
|
return mqtt::message::create(std::move(topic), std::move(payload));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Class to build messages.
|
|
*/
|
|
class message_ptr_builder
|
|
{
|
|
/** The underlying message */
|
|
message_ptr msg_;
|
|
|
|
public:
|
|
/** This class */
|
|
using self = message_ptr_builder;
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
message_ptr_builder() : msg_{std::make_shared<message>()} {}
|
|
/**
|
|
* Sets the topic string.
|
|
* @param topic The topic on which the message is published.
|
|
*/
|
|
auto topic(string_ref topic) -> self& {
|
|
msg_->set_topic(topic);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Sets the payload of this message to be the specified buffer.
|
|
* Note that this accepts copy or move operations:
|
|
* set_payload(buf);
|
|
* set_payload(std::move(buf));
|
|
* @param payload A buffer to use as the message payload.
|
|
*/
|
|
auto payload(binary_ref payload) -> self& {
|
|
msg_->set_payload(payload);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Sets the payload of this message to be the specified byte array.
|
|
* @param payload the bytes to use as the message payload
|
|
* @param n the number of bytes in the payload
|
|
*/
|
|
auto payload(const void* payload, size_t n) -> self& {
|
|
msg_->set_payload(payload, n);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Sets the quality of service for this message.
|
|
* @param qos The integer Quality of Service for the message
|
|
*/
|
|
auto qos(int qos) -> self& {
|
|
msg_->set_qos(qos);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Whether or not the publish message should be retained by the broker.
|
|
* @param on @em true if the message should be retained by the broker, @em
|
|
* false if not.
|
|
*/
|
|
auto retained(bool on) -> self& {
|
|
msg_->set_retained(on);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Sets the properties for the disconnect message.
|
|
* @param props The properties for the disconnect message.
|
|
*/
|
|
auto properties(mqtt::properties&& props) -> self& {
|
|
msg_->set_properties(std::move(props));
|
|
return *this;
|
|
}
|
|
/**
|
|
* Sets the properties for the disconnect message.
|
|
* @param props The properties for the disconnect message.
|
|
*/
|
|
auto properties(const mqtt::properties& props) -> self& {
|
|
msg_->set_properties(props);
|
|
return *this;
|
|
}
|
|
/**
|
|
* Finish building the options and return them.
|
|
* @return The option struct as built.
|
|
*/
|
|
message_ptr finalize() { return msg_; }
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
} // namespace mqtt
|
|
|
|
#endif // __mqtt_message_h
|