93 "v5::disconnect_packet fixed_header doesn't exist"
96 fixed_header_ =
static_cast<std::uint8_t
>(buf.front());
100 if (
auto vl_opt = insert_advance_variable_length(buf, remaining_length_buf_)) {
101 remaining_length_ = *
vl_opt;
104 throw make_error(errc::bad_message,
"v5::disconnect_packet remaining length is invalid");
107 if (remaining_length_ == 0) {
109 throw make_error(errc::bad_message,
"v5::disconnect_packet remaining length is invalid");
115 reason_code_.emplace(
static_cast<disconnect_reason_code
>(buf.front()));
116 buf.remove_prefix(1);
117 switch (*reason_code_) {
118 case disconnect_reason_code::normal_disconnection:
119 case disconnect_reason_code::disconnect_with_will_message:
120 case disconnect_reason_code::unspecified_error:
121 case disconnect_reason_code::malformed_packet:
122 case disconnect_reason_code::protocol_error:
123 case disconnect_reason_code::implementation_specific_error:
124 case disconnect_reason_code::not_authorized:
125 case disconnect_reason_code::server_busy:
126 case disconnect_reason_code::server_shutting_down:
127 case disconnect_reason_code::keep_alive_timeout:
128 case disconnect_reason_code::session_taken_over:
129 case disconnect_reason_code::topic_filter_invalid:
130 case disconnect_reason_code::topic_name_invalid:
131 case disconnect_reason_code::receive_maximum_exceeded:
132 case disconnect_reason_code::topic_alias_invalid:
133 case disconnect_reason_code::packet_too_large:
134 case disconnect_reason_code::message_rate_too_high:
135 case disconnect_reason_code::quota_exceeded:
136 case disconnect_reason_code::administrative_action:
137 case disconnect_reason_code::payload_format_invalid:
138 case disconnect_reason_code::retain_not_supported:
139 case disconnect_reason_code::qos_not_supported:
140 case disconnect_reason_code::use_another_server:
141 case disconnect_reason_code::server_moved:
142 case disconnect_reason_code::shared_subscriptions_not_supported:
143 case disconnect_reason_code::connection_rate_exceeded:
144 case disconnect_reason_code::maximum_connect_time:
145 case disconnect_reason_code::subscription_identifiers_not_supported:
146 case disconnect_reason_code::wildcard_subscriptions_not_supported:
151 "v5::disconnect_packet connect reason_code is invalid"
156 if (remaining_length_ == 1) {
158 throw make_error(errc::bad_message,
"v5::disconnect_packet remaining length is invalid");
164 auto it = buf.begin();
165 if (
auto pl_opt = variable_bytes_to_val(it, buf.end())) {
166 property_length_ = *pl_opt;
167 std::copy(buf.begin(), it, std::back_inserter(property_length_buf_));
168 buf.remove_prefix(std::size_t(std::distance(buf.begin(), it)));
169 if (buf.size() < property_length_) {
172 "v5::disconnect_packet properties_don't match its length"
175 auto prop_buf = buf.
substr(0, property_length_);
176 props_ = make_properties(prop_buf, property_location::disconnect);
177 buf.remove_prefix(property_length_);
182 "v5::disconnect_packet property_length is invalid"
189 "v5::disconnect_packet properties don't match its length"
194 constexpr control_packet_type type()
const {
195 return control_packet_type::disconnect;
204 std::vector<as::const_buffer>
ret;
206 ret.emplace_back(as::buffer(&fixed_header_, 1));
207 ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
210 ret.emplace_back(as::buffer(&*reason_code_, 1));
212 if (property_length_buf_.size() != 0) {
213 ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
214 auto props_cbs = async_mqtt::const_buffer_sequence(props_);
229 remaining_length_buf_.size() +
241 [&] () -> std::size_t {
245 [&] () -> std::size_t {
246 if (property_length_buf_.size() == 0)
return 0;
249 async_mqtt::num_of_const_buffer_sequence(props_);
260 disconnect_reason_code
code()
const {
261 if (reason_code_)
return *reason_code_;
262 return disconnect_reason_code::normal_disconnection;
277 if (
v.reason_code_) {
278 o <<
"rc:" << *
v.reason_code_;
280 if (!
v.props().empty()) {
281 o <<
",ps:" <<
v.props();
289 optional<disconnect_reason_code> reason_code,
293 make_fixed_header(control_packet_type::disconnect, 0b0000)
298 reason_code_{reason_code},
299 property_length_(async_mqtt::
size(
props)),
300 props_(force_move(
props))
302 using namespace std::literals;
304 auto guard = unique_scope_guard(
306 auto rb = val_to_variable_bytes(boost::numeric_cast<std::uint32_t>(remaining_length_));
308 remaining_length_buf_.push_back(e);
313 if (!reason_code_)
return;
314 remaining_length_ += 1;
316 if (property_length_ == 0)
return;
318 auto pb = val_to_variable_bytes(boost::numeric_cast<std::uint32_t>(property_length_));
320 property_length_buf_.push_back(e);
323 for (
auto const& prop : props_) {
325 if (!validate_property(property_location::disconnect,
id)) {
328 "v5::disconnect_packet property "s + id_to_str(
id) +
" is not allowed"
333 remaining_length_ += property_length_buf_.size() + property_length_;
337 std::uint8_t fixed_header_;
338 std::size_t remaining_length_;
339 static_vector<char, 4> remaining_length_buf_;
341 optional<disconnect_reason_code> reason_code_;
343 std::size_t property_length_ = 0;
344 static_vector<char, 4> property_length_buf_;