Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:51:36

0001 //
0002 // Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MQTT5_MESSAGE_ENCODERS_HPP
0009 #define BOOST_MQTT5_MESSAGE_ENCODERS_HPP
0010 
0011 #include <boost/mqtt5/types.hpp>
0012 
0013 #include <boost/mqtt5/impl/codecs/base_encoders.hpp>
0014 
0015 #include <cstdint>
0016 #include <optional>
0017 #include <string>
0018 #include <string_view>
0019 #include <vector>
0020 
0021 namespace boost::mqtt5::encoders {
0022 
0023 template <typename encoder>
0024 std::string encode(const encoder& e) {
0025     std::string s;
0026     s.reserve(e.byte_size());
0027     s << e;
0028     return s;
0029 }
0030 
0031 inline std::string encode_connect(
0032     std::string_view client_id,
0033     std::optional<std::string_view> user_name,
0034     std::optional<std::string_view> password,
0035     uint16_t keep_alive, bool clean_start,
0036     const connect_props& props,
0037     const std::optional<will>& w
0038 ) {
0039 
0040     auto packet_type_ =
0041         basic::flag<4>(0b0001) |
0042         basic::flag<4>(0);
0043 
0044     auto conn_flags_ =
0045         basic::flag<1>(user_name) |
0046         basic::flag<1>(password) |
0047         basic::flag<1>(w, &will::retain) |
0048         basic::flag<2>(w, &will::qos) |
0049         basic::flag<1>(w) |
0050         basic::flag<1>(clean_start) |
0051         basic::flag<1>(0);
0052 
0053     auto var_header_ =
0054         basic::utf8_("MQTT") &
0055         basic::byte_(uint8_t(5)) &
0056         conn_flags_ &
0057         basic::int16_(keep_alive) &
0058         prop::props_(props);
0059 
0060     auto payload_ =
0061         basic::utf8_(client_id) &
0062         prop::props_(w) &
0063         basic::utf8_(w, &will::topic) &
0064         basic::binary_(w, &will::message) &
0065         basic::utf8_(user_name) &
0066         basic::utf8_(password);
0067 
0068     auto message_body_ = var_header_ & payload_;
0069 
0070     auto fixed_header_ =
0071         packet_type_ &
0072         basic::varlen_(message_body_.byte_size());
0073 
0074     auto connect_message_ = fixed_header_ & message_body_;
0075 
0076     return encode(connect_message_);
0077 }
0078 
0079 inline std::string encode_connack(
0080     bool session_present,
0081     uint8_t reason_code,
0082     const connack_props& props
0083 ) {
0084 
0085     auto packet_type_ =
0086         basic::flag<4>(0b0010) |
0087         basic::flag<4>(0);
0088 
0089     auto var_header_ =
0090         basic::flag<1>(session_present) &
0091         basic::byte_(reason_code) &
0092         prop::props_(props);
0093 
0094     auto fixed_header_ =
0095         packet_type_ &
0096         basic::varlen_(var_header_.byte_size());
0097 
0098     auto connack_message_ = fixed_header_ & var_header_;
0099 
0100     return encode(connack_message_);
0101 }
0102 
0103 inline std::string encode_publish(
0104     uint16_t packet_id,
0105     std::string_view topic_name,
0106     std::string_view payload,
0107     qos_e qos, retain_e retain, dup_e dup,
0108     const publish_props& props
0109 ) {
0110 
0111     std::optional<uint16_t> used_packet_id;
0112     if (qos != qos_e::at_most_once) used_packet_id.emplace(packet_id);
0113 
0114     auto packet_type_ =
0115         basic::flag<4>(0b0011) |
0116         basic::flag<1>(dup) |
0117         basic::flag<2>(qos) |
0118         basic::flag<1>(retain);
0119 
0120     auto var_header_ =
0121         basic::utf8_(topic_name) &
0122         basic::int16_(used_packet_id) &
0123         prop::props_(props);
0124 
0125     auto message_body_ = var_header_ & basic::verbatim_(payload);
0126 
0127     auto fixed_header_ =
0128         packet_type_ &
0129         basic::varlen_(message_body_.byte_size());
0130 
0131     auto publish_message_ = fixed_header_ & message_body_;
0132 
0133     return encode(publish_message_);
0134 }
0135 
0136 inline std::string encode_puback(
0137     uint16_t packet_id,
0138     uint8_t reason_code,
0139     const puback_props& props
0140 ) {
0141 
0142     auto packet_type_ =
0143         basic::flag<4>(0b0100) |
0144         basic::flag<4>(0);
0145 
0146     auto var_header_ =
0147         basic::int16_(packet_id) &
0148         basic::byte_(reason_code) &
0149         prop::props_may_omit_(props);
0150 
0151     auto fixed_header_ =
0152         packet_type_ &
0153         basic::varlen_(var_header_.byte_size());
0154 
0155     auto puback_message_ = fixed_header_ & var_header_;
0156 
0157     return encode(puback_message_);
0158 }
0159 
0160 inline std::string encode_pubrec(
0161     uint16_t packet_id,
0162     uint8_t reason_code,
0163     const pubrec_props& props
0164 ) {
0165 
0166     auto packet_type_ =
0167         basic::flag<4>(0b0101) |
0168         basic::flag<4>(0b0000);
0169 
0170     auto var_header_ =
0171         basic::int16_(packet_id) &
0172         basic::byte_(reason_code) &
0173         prop::props_may_omit_(props);
0174 
0175     auto fixed_header_ =
0176         packet_type_ &
0177         basic::varlen_(var_header_.byte_size());
0178 
0179     auto pubrec_message_ = fixed_header_ & var_header_;
0180 
0181     return encode(pubrec_message_);
0182 }
0183 
0184 inline std::string encode_pubrel(
0185     uint16_t packet_id,
0186     uint8_t reason_code,
0187     const pubrel_props& props
0188 ) {
0189 
0190     auto packet_type_ =
0191         basic::flag<4>(0b0110) |
0192         basic::flag<4>(0b0010);
0193 
0194     auto var_header_ =
0195         basic::int16_(packet_id) &
0196         basic::byte_(reason_code) &
0197         prop::props_may_omit_(props);
0198 
0199     auto fixed_header_ =
0200         packet_type_ &
0201         basic::varlen_(var_header_.byte_size());
0202 
0203     auto pubrel_message_ = fixed_header_ & var_header_;
0204 
0205     return encode(pubrel_message_);
0206 }
0207 
0208 inline std::string encode_pubcomp(
0209     uint16_t packet_id,
0210     uint8_t reason_code,
0211     const pubcomp_props& props
0212 ) {
0213 
0214     auto packet_type_ =
0215         basic::flag<4>(0b0111) |
0216         basic::flag<4>(0b0000);
0217 
0218     auto var_header_ =
0219         basic::int16_(packet_id) &
0220         basic::byte_(reason_code) &
0221         prop::props_may_omit_(props);
0222 
0223     auto fixed_header_ =
0224         packet_type_ &
0225         basic::varlen_(var_header_.byte_size());
0226 
0227     auto pubcomp_message_ = fixed_header_ & var_header_;
0228 
0229     return encode(pubcomp_message_);
0230 }
0231 
0232 inline std::string encode_subscribe(
0233     uint16_t packet_id,
0234     const std::vector<subscribe_topic>& topics,
0235     const subscribe_props& props
0236 ) {
0237 
0238     auto packet_type_ =
0239         basic::flag<4>(0b1000) |
0240         basic::flag<4>(0b0010);
0241 
0242     size_t payload_size = 0;
0243     for (const auto& [topic_filter, _]: topics)
0244         payload_size += basic::utf8_(topic_filter).byte_size() + 1;
0245 
0246     auto var_header_ =
0247         basic::int16_(packet_id) &
0248         prop::props_(props);
0249 
0250     auto message_ =
0251         packet_type_ &
0252         basic::varlen_(var_header_.byte_size()  + payload_size) &
0253         var_header_;
0254 
0255     auto s = encode(message_);
0256     s.reserve(s.size() + payload_size);
0257 
0258     for (const auto& [topic_filter, sub_opts]: topics) {
0259         auto opts_ =
0260             basic::flag<2>(sub_opts.retain_handling) |
0261             basic::flag<1>(sub_opts.retain_as_published) |
0262             basic::flag<1>(sub_opts.no_local) |
0263             basic::flag<2>(sub_opts.max_qos);
0264         auto filter_ = basic::utf8_(topic_filter) & opts_;
0265         s << filter_;
0266     }
0267 
0268     return s;
0269 }
0270 
0271 inline std::string encode_suback(
0272     uint16_t packet_id,
0273     const std::vector<uint8_t>& reason_codes,
0274     const suback_props& props
0275 ) {
0276 
0277     auto packet_type_ =
0278         basic::flag<4>(0b1001) |
0279         basic::flag<4>(0b0000);
0280 
0281     auto var_header_ =
0282         basic::int16_(packet_id) &
0283         prop::props_(props);
0284 
0285     auto message_ =
0286         packet_type_ &
0287         basic::varlen_(var_header_.byte_size()  + reason_codes.size()) &
0288         var_header_;
0289 
0290     auto s = encode(message_);
0291     s.reserve(s.size() + reason_codes.size());
0292 
0293     for (auto reason_code: reason_codes)
0294         s << basic::byte_(reason_code);
0295 
0296     return s;
0297 }
0298 
0299 inline std::string encode_unsubscribe(
0300     uint16_t packet_id,
0301     const std::vector<std::string>& topics,
0302     const unsubscribe_props& props
0303 ) {
0304 
0305     auto packet_type_ =
0306         basic::flag<4>(0b1010) |
0307         basic::flag<4>(0b0010);
0308 
0309     size_t payload_size = 0;
0310     for (const auto& topic: topics)
0311         payload_size += basic::utf8_(topic).byte_size();
0312 
0313     auto var_header_ =
0314         basic::int16_(packet_id) &
0315         prop::props_(props);
0316 
0317     auto message_ =
0318         packet_type_ &
0319         basic::varlen_(var_header_.byte_size()  + payload_size) &
0320         var_header_;
0321 
0322     auto s = encode(message_);
0323     s.reserve(s.size() + payload_size);
0324 
0325     for (const auto& topic: topics)
0326         s << basic::utf8_(topic);
0327 
0328     return s;
0329 }
0330 
0331 inline std::string encode_unsuback(
0332     uint16_t packet_id,
0333     const std::vector<uint8_t>& reason_codes,
0334     const unsuback_props& props
0335 ) {
0336 
0337     auto packet_type_ =
0338         basic::flag<4>(0b1011) |
0339         basic::flag<4>(0b0000);
0340 
0341     auto var_header_ =
0342         basic::int16_(packet_id) &
0343         prop::props_(props);
0344 
0345     auto message_ =
0346         packet_type_ &
0347         basic::varlen_(var_header_.byte_size()  + reason_codes.size()) &
0348         var_header_;
0349 
0350     auto s = encode(message_);
0351     s.reserve(s.size() + reason_codes.size());
0352 
0353     for (auto reason_code: reason_codes)
0354         s << basic::byte_(reason_code);
0355 
0356     return s;
0357 }
0358 
0359 inline std::string encode_pingreq() {
0360     auto packet_type_ =
0361         basic::flag<4>(0b1100) |
0362         basic::flag<4>(0);
0363 
0364     auto remaining_len_ =
0365         basic::byte_(uint8_t(0));
0366 
0367     auto ping_req_ = packet_type_ & remaining_len_;
0368 
0369     return encode(ping_req_);
0370 }
0371 
0372 inline std::string encode_pingresp() {
0373     auto packet_type_ =
0374         basic::flag<4>(0b1101) |
0375         basic::flag<4>(0);
0376 
0377     auto remaining_len_ =
0378         basic::byte_(uint8_t(0));
0379 
0380     auto ping_resp_ = packet_type_ & remaining_len_;
0381 
0382     return encode(ping_resp_);
0383 }
0384 
0385 inline std::string encode_disconnect(
0386     uint8_t reason_code,
0387     const disconnect_props& props
0388 ) {
0389 
0390     auto packet_type_ =
0391         basic::flag<4>(0b1110) |
0392         basic::flag<4>(0b0000);
0393 
0394     auto var_header_ =
0395         basic::byte_(reason_code) &
0396         prop::props_(props);
0397 
0398     auto fixed_header_ =
0399         packet_type_ &
0400         basic::varlen_(var_header_.byte_size());
0401 
0402     auto disconnect_message_ = fixed_header_ & var_header_;
0403 
0404     return encode(disconnect_message_);
0405 }
0406 
0407 inline std::string encode_auth(
0408     uint8_t reason_code,
0409     const auth_props& props
0410 ) {
0411 
0412     auto packet_type_ =
0413         basic::flag<4>(0b1111) |
0414         basic::flag<4>(0b0000);
0415 
0416     auto var_header_ =
0417         basic::byte_(reason_code) &
0418         prop::props_(props);
0419 
0420     auto fixed_header_ =
0421         packet_type_ &
0422         basic::varlen_(var_header_.byte_size());
0423 
0424     auto auth_message_ = fixed_header_ & var_header_;
0425 
0426     return encode(auth_message_);
0427 }
0428 
0429 
0430 } // end namespace boost::mqtt5::encoders
0431 
0432 #endif // !BOOST_MQTT5_MESSAGE_ENCODERS_HPP