7#if !defined(ASYNC_MQTT_PACKET_V3_1_1_PUBLISH_HPP)
8#define ASYNC_MQTT_PACKET_V3_1_1_PUBLISH_HPP
13#include <boost/numeric/conversion/cast.hpp>
15#include <async_mqtt/exception.hpp>
16#include <async_mqtt/buffer.hpp>
17#include <async_mqtt/variable_bytes.hpp>
19#include <async_mqtt/util/move.hpp>
20#include <async_mqtt/util/static_vector.hpp>
21#include <async_mqtt/util/endian_convert.hpp>
22#include <async_mqtt/util/utf8validate.hpp>
24#include <async_mqtt/packet/packet_iterator.hpp>
25#include <async_mqtt/packet/packet_id_type.hpp>
26#include <async_mqtt/packet/fixed_header.hpp>
28#include <async_mqtt/packet/copy_to_static_vector.hpp>
30#if defined(ASYNC_MQTT_PRINT_PAYLOAD)
31#include <async_mqtt/util/json_like_out.hpp>
34namespace async_mqtt::v3_1_1 {
36namespace as = boost::asio;
49template <std::
size_t PacketIdBytes>
52 using packet_id_t =
typename packet_id_type<PacketIdBytes>::type;
74 typename std::enable_if<
86 make_fixed_header(control_packet_type::publish, 0b0000) | std::uint8_t(
pubopts)
98 topic_name_length_buf_.resize(topic_name_length_buf_.capacity());
100 boost::numeric_cast<std::uint16_t>(topic_name_.size()),
101 topic_name_length_buf_.data()
103 auto b = buffer_sequence_begin(
payloads);
107 for (;
b !=
e; ++
b) {
109 remaining_length_ +=
payload.size();
113 if (!utf8string_check(topic_name_)) {
116 "v3_1_1::publish_packet topic name invalid utf8"
120 auto rb = val_to_variable_bytes(boost::numeric_cast<std::uint32_t>(remaining_length_));
122 remaining_length_buf_.push_back(
e);
125 case qos::at_most_once:
129 "v3_1_1::publish_packet qos0 but non 0 packet_id"
132 endian_store(0, packet_id_.data());
134 case qos::at_least_once:
135 case qos::exactly_once:
139 "v3_1_1::publish_packet qos not 0 but packet_id is 0"
142 endian_store(
packet_id, packet_id_.data());
147 "v3_1_1::publish_packet qos is invalid"
168 typename std::enable_if<
186 "v3_1_1::publish_packet fixed_header doesn't exist"
189 fixed_header_ =
static_cast<std::uint8_t
>(buf.front());
190 auto qos_value = pub::get_qos(fixed_header_);
191 buf.remove_prefix(1);
192 auto cpt_opt = get_control_packet_type_with_check(
static_cast<std::uint8_t
>(fixed_header_));
196 "v3_1_1::publish_packet fixed_header is invalid"
201 if (
auto vl_opt = insert_advance_variable_length(buf, remaining_length_buf_)) {
202 remaining_length_ = *vl_opt;
205 throw make_error(errc::bad_message,
"v3_1_1::publish_packet remaining length is invalid");
207 if (remaining_length_ != buf.size()) {
208 throw make_error(errc::bad_message,
"v3_1_1::publish_packet remaining length doesn't match buf.size()");
212 if (!insert_advance(buf, topic_name_length_buf_)) {
215 "v3_1_1::publish_packet length of topic_name is invalid"
218 auto topic_name_length = endian_load<std::uint16_t>(topic_name_length_buf_.data());
221 if (buf.size() < topic_name_length) {
224 "v3_1_1::publish_packet topic_name doesn't match its length"
227 topic_name_ = buf.
substr(0, topic_name_length);
229 if (!utf8string_check(topic_name_)) {
232 "v3_1_1::publish_packet topic name invalid utf8"
236 buf.remove_prefix(topic_name_length);
240 case qos::at_most_once:
241 endian_store(packet_id_t{0}, packet_id_.data());
243 case qos::at_least_once:
244 case qos::exactly_once:
245 if (!copy_advance(buf, packet_id_)) {
248 "v3_1_1::publish_packet packet_id doesn't exist"
255 "v3_1_1::publish_packet qos is invalid"
262 payloads_.emplace_back(force_move(buf));
266 constexpr control_packet_type type()
const {
267 return control_packet_type::publish;
276 std::vector<as::const_buffer>
ret;
278 ret.emplace_back(as::buffer(&fixed_header_, 1));
279 ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
280 ret.emplace_back(as::buffer(topic_name_length_buf_.data(), topic_name_length_buf_.size()));
281 ret.emplace_back(as::buffer(topic_name_));
283 ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
285 for (
auto const&
payload : payloads_) {
298 remaining_length_buf_.size() +
311 [&] () -> std::size_t {
356 return make_packet_range(payloads_);
364 pub::set_dup(fixed_header_, dup);
368 std::uint8_t fixed_header_;
372 std::vector<buffer> payloads_;
373 std::size_t remaining_length_;
377template <std::
size_t PacketIdBytes>
379 o <<
"v3_1_1::publish{" <<
380 "topic:" <<
v.topic() <<
"," <<
381 "qos:" <<
v.opts().get_qos() <<
"," <<
382 "retain:" <<
v.opts().get_retain() <<
"," <<
383 "dup:" <<
v.opts().get_dup();
384 if (
v.opts().get_qos() == qos::at_least_once ||
385 v.opts().get_qos() == qos::exactly_once) {
386 o <<
",pid:" <<
v.packet_id();
388#if defined(ASYNC_MQTT_PRINT_PAYLOAD)
390 for (
auto const& e : v.payload()) {
391 o << json_like_out(e);
Definition packet_variant.hpp:49
buffer that has string_view interface This class provides string_view interface. This class hold stri...
Definition buffer.hpp:30
buffer substr(size_type pos=0, size_type count=npos) const &
get substring The returned buffer ragnge is the same as string_view::substr(). In addition the lifeti...
Definition buffer.hpp:201
MQTT PUBLISH packet (v3.1.1)
Definition v3_1_1_publish.hpp:50
basic_publish_packet(buffer topic_name, BufferSequence payloads, pub::opts pubopts)
constructor for QoS0 This constructor doesn't have packet_id parameter. The packet_id is set to 0 int...
Definition v3_1_1_publish.hpp:173
std::vector< as::const_buffer > const_buffer_sequence() const
Create const buffer sequence it is for boost asio APIs.
Definition v3_1_1_publish.hpp:275
auto payload_range() const
Get payload range.
Definition v3_1_1_publish.hpp:355
constexpr buffer const & topic() const
Get topic name.
Definition v3_1_1_publish.hpp:339
std::size_t num_of_const_buffer_sequence() const
Get number of element of const_buffer_sequence.
Definition v3_1_1_publish.hpp:306
constexpr void set_dup(bool dup)
Set dup flag.
Definition v3_1_1_publish.hpp:363
std::vector< buffer > const & payload() const
Get payload.
Definition v3_1_1_publish.hpp:347
packet_id_t packet_id() const
Get packet id.
Definition v3_1_1_publish.hpp:323
std::size_t size() const
Get packet size.
Definition v3_1_1_publish.hpp:295
basic_publish_packet(packet_id_t packet_id, buffer topic_name, BufferSequence payloads, pub::opts pubopts)
constructor
Definition v3_1_1_publish.hpp:79
constexpr pub::opts opts() const
Get publish_options.
Definition v3_1_1_publish.hpp:331
qos
MQTT QoS.
Definition qos.hpp:23
@ exactly_once
Exactly once delivery.
@ at_least_once
At least once delivery.
MQTT PublishOptions.
Definition pubopts.hpp:87