119 make_fixed_header(control_packet_type::connect, 0b0000)
132 protocol_name_and_level_{0x00, 0x04,
'M',
'Q',
'T',
'T', 0x04},
134 client_id_length_buf_(2),
138 endian_store(boost::numeric_cast<std::uint16_t>(client_id_.size()), client_id_length_buf_.data());
140 if (!utf8string_check(client_id_)) {
143 "v3_1_1::connect_packet client_id invalid utf8"
147 if (
clean_session) connect_flags_ |= connect_flags::mask_clean_session;
152 "v3_1_1::connect_packet user name invalid utf8"
155 connect_flags_ |= connect_flags::mask_user_name_flag;
157 user_name_length_buf_ = endian_static_vector(boost::numeric_cast<std::uint16_t>(user_name_.size()));
158 remaining_length_ += 2 + user_name_.size();
161 connect_flags_ |= connect_flags::mask_password_flag;
163 password_length_buf_ = endian_static_vector(boost::numeric_cast<std::uint16_t>(password_.size()));
164 remaining_length_ += 2 + password_.size();
167 connect_flags_ |= connect_flags::mask_will_flag;
168 if (
w->get_retain() == pub::retain::yes) connect_flags_ |= connect_flags::mask_will_retain;
169 connect_flags::set_will_qos(connect_flags_,
w->get_qos());
170 if (!utf8string_check(
w->topic())) {
173 "v3_1_1::connect_packet will topic invalid utf8"
176 will_topic_ = force_move(
w->topic());
177 will_topic_length_buf_ = endian_static_vector(boost::numeric_cast<std::uint16_t>(will_topic_.size()));
178 if (
w->message().size() > 0xffffL) {
181 "v3_1_1::connect_packet will message too long"
184 will_message_ = force_move(
w->message());
185 will_message_length_buf_ = endian_static_vector(boost::numeric_cast<std::uint16_t>(will_message_.size()));
187 remaining_length_ += 2 + will_topic_.size() + 2 + will_message_.size();
190 auto rb = val_to_variable_bytes(boost::numeric_cast<std::uint32_t>(remaining_length_));
192 remaining_length_buf_.push_back(
e);
201 "v3_1_1::connect_packet fixed_header doesn't exist"
204 fixed_header_ =
static_cast<std::uint8_t
>(buf.front());
205 buf.remove_prefix(1);
206 auto cpt_opt = get_control_packet_type_with_check(fixed_header_);
210 "v3_1_1::connect_packet fixed_header is invalid"
215 if (
auto vl_opt = insert_advance_variable_length(buf, remaining_length_buf_)) {
216 remaining_length_ = *vl_opt;
219 throw make_error(errc::bad_message,
"v3_1_1::connect_packet remaining length is invalid");
221 if (remaining_length_ != buf.size()) {
222 throw make_error(errc::bad_message,
"v3_1_1::connect_packet remaining length doesn't match buf.size()");
226 if (!insert_advance(buf, protocol_name_and_level_)) {
229 "v3_1_1::connect_packet length of protocol_name or level is invalid"
232 static_vector<char, 7> expected_protocol_name_and_level {
233 0, 4,
'M',
'Q',
'T',
'T', 4
235 if (protocol_name_and_level_ != expected_protocol_name_and_level) {
238 "v3_1_1::connect_packet contents of protocol_name or level is invalid"
243 if (buf.size() < 1) {
246 "v3_1_1::connect_packet connect_flags doesn't exist"
249 connect_flags_ = buf.front();
250 if (connect_flags_ & 0b00000001) {
253 "v3_1_1::connect_packet connect_flags reserved bit0 is 1 (must be 0)"
256 buf.remove_prefix(1);
259 if (!insert_advance(buf, keep_alive_buf_)) {
262 "v3_1_1::connect_packet keep_alive is invalid"
267 if (!insert_advance(buf, client_id_length_buf_)) {
270 "v3_1_1::connect_packet length of client_id is invalid"
273 auto client_id_length = endian_load<std::uint16_t>(client_id_length_buf_.data());
276 if (buf.size() < client_id_length) {
279 "v3_1_1::connect_packet client_id doesn't match its length"
282 client_id_ = buf.
substr(0, client_id_length);
283 if (!utf8string_check(client_id_)) {
286 "v3_1_1::connect_packet client_id invalid utf8"
289 buf.remove_prefix(client_id_length);
292 if (connect_flags::has_will_flag(connect_flags_)) {
293 auto will_qos = connect_flags::will_qos(connect_flags_);
294 if (will_qos != qos::at_most_once &&
295 will_qos != qos::at_least_once &&
296 will_qos != qos::exactly_once) {
299 "v3_1_1::connect_packet will_qos is invalid"
303 if (!insert_advance(buf, will_topic_length_buf_)) {
306 "v3_1_1::connect_packet length of will_topic is invalid"
309 auto will_topic_length = endian_load<std::uint16_t>(will_topic_length_buf_.data());
312 if (buf.size() < will_topic_length) {
315 "v3_1_1::connect_packet will_topic doesn't match its length"
318 will_topic_ = buf.
substr(0, will_topic_length);
319 if (!utf8string_check(will_topic_)) {
322 "v3_1_1::connect_packet will topic invalid utf8"
325 buf.remove_prefix(will_topic_length);
328 if (!insert_advance(buf, will_message_length_buf_)) {
331 "v3_1_1::connect_packet length of will_message is invalid"
334 auto will_message_length = endian_load<std::uint16_t>(will_message_length_buf_.data());
337 if (buf.size() < will_message_length) {
340 "v3_1_1::connect_packet will_message doesn't match its length"
343 will_message_ = buf.
substr(0, will_message_length);
344 buf.remove_prefix(will_message_length);
347 auto will_retain = connect_flags::will_retain(connect_flags_);
348 auto will_qos = connect_flags::will_qos(connect_flags_);
349 if (will_retain == pub::retain::yes) {
352 "v3_1_1::connect_packet combination of will_flag and will_retain is invalid"
355 if (will_qos != qos::at_most_once) {
358 "v3_1_1::connect_packet combination of will_flag and will_qos is invalid"
363 if (connect_flags::has_user_name_flag(connect_flags_)) {
365 if (!insert_advance(buf, user_name_length_buf_)) {
368 "v3_1_1::connect_packet length of user_name is invalid"
371 auto user_name_length = endian_load<std::uint16_t>(user_name_length_buf_.data());
374 if (buf.size() < user_name_length) {
377 "v3_1_1::connect_packet user_name doesn't match its length"
380 user_name_ = buf.
substr(0, user_name_length);
381 if (!utf8string_check(user_name_)) {
384 "v3_1_1::connect_packet user name invalid utf8"
387 buf.remove_prefix(user_name_length);
391 if (connect_flags::has_password_flag(connect_flags_)) {
393 if (!insert_advance(buf, password_length_buf_)) {
396 "v3_1_1::connect_packet length of password is invalid"
399 auto password_length = endian_load<std::uint16_t>(password_length_buf_.data());
402 if (buf.size() != password_length) {
405 "v3_1_1::connect_packet password doesn't match its length"
408 password_ = buf.
substr(0, password_length);
409 buf.remove_prefix(password_length);
413 constexpr control_packet_type type()
const {
414 return control_packet_type::connect;
423 std::vector<as::const_buffer>
ret;
426 ret.emplace_back(as::buffer(&fixed_header_, 1));
427 ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
428 ret.emplace_back(as::buffer(protocol_name_and_level_.data(), protocol_name_and_level_.size()));
429 ret.emplace_back(as::buffer(&connect_flags_, 1));
430 ret.emplace_back(as::buffer(keep_alive_buf_.data(), keep_alive_buf_.size()));
432 ret.emplace_back(as::buffer(client_id_length_buf_.data(), client_id_length_buf_.size()));
433 ret.emplace_back(as::buffer(client_id_));
435 if (connect_flags::has_will_flag(connect_flags_)) {
436 ret.emplace_back(as::buffer(will_topic_length_buf_.data(), will_topic_length_buf_.size()));
437 ret.emplace_back(as::buffer(will_topic_));
438 ret.emplace_back(as::buffer(will_message_length_buf_.data(), will_message_length_buf_.size()));
439 ret.emplace_back(as::buffer(will_message_));
442 if (connect_flags::has_user_name_flag(connect_flags_)) {
443 ret.emplace_back(as::buffer(user_name_length_buf_.data(), user_name_length_buf_.size()));
444 ret.emplace_back(as::buffer(user_name_));
447 if (connect_flags::has_password_flag(connect_flags_)) {
448 ret.emplace_back(as::buffer(password_length_buf_.data(), password_length_buf_.size()));
449 ret.emplace_back(as::buffer(password_));
462 remaining_length_buf_.size() +
480 [&] () -> std::size_t {
481 if (connect_flags::has_will_flag(connect_flags_)) {
488 [&] () -> std::size_t {
489 if (connect_flags::has_user_name_flag(connect_flags_)) {
494 [&] () -> std::size_t {
495 if (connect_flags::has_password_flag(connect_flags_)) {
507 return connect_flags::has_clean_session(connect_flags_);
531 if (connect_flags::has_user_name_flag(connect_flags_)) {
544 if (connect_flags::has_password_flag(connect_flags_)) {
557 if (connect_flags::has_will_flag(connect_flags_)) {
559 connect_flags::will_retain(connect_flags_) |
560 connect_flags::will_qos(connect_flags_);
575 std::uint8_t fixed_header_;
578 std::size_t remaining_length_;