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_DECODERS_HPP
0009 #define BOOST_MQTT5_MESSAGE_DECODERS_HPP
0010 
0011 #include <boost/mqtt5/types.hpp>
0012 
0013 #include <boost/mqtt5/detail/internal_types.hpp>
0014 
0015 #include <boost/mqtt5/impl/codecs/base_decoders.hpp>
0016 
0017 #include <cstdint>
0018 #include <optional>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022 
0023 namespace boost::mqtt5::decoders {
0024 
0025 using byte_citer = detail::byte_citer;
0026 
0027 using fixed_header = std::tuple<
0028     uint8_t, // control byte
0029     uint32_t // remaining_length
0030 >;
0031 
0032 inline std::optional<fixed_header> decode_fixed_header(
0033     byte_citer& it, const byte_citer last
0034 ) {
0035     auto fixed_header_ = x3::byte_ >> basic::varint_;
0036     return type_parse(it, last, fixed_header_);
0037 }
0038 
0039 using packet_id = uint16_t;
0040 
0041 inline std::optional<packet_id> decode_packet_id(
0042     byte_citer& it
0043 ) {
0044     auto packet_id_ = x3::big_word;
0045     return type_parse(it, it + sizeof(uint16_t), packet_id_);
0046 }
0047 
0048 using connect_message = std::tuple<
0049     std::string, // client_id,
0050     std::optional<std::string>, // user_name,
0051     std::optional<std::string>, // password,
0052     uint16_t, // keep_alive,
0053     bool, // clean_start,
0054     connect_props, // props,
0055     std::optional<will> // will
0056 >;
0057 
0058 inline std::optional<connect_message> decode_connect(
0059     uint32_t remain_length, byte_citer& it
0060 ) {
0061     auto var_header_ =
0062         basic::utf8_ >> // MQTT
0063         x3::byte_ >> // (num 5)
0064         x3::byte_ >> // conn_flags_
0065         x3::big_word >> // keep_alive
0066         prop::props_<connect_props>;
0067 
0068     const byte_citer end = it + remain_length;
0069     auto vh = type_parse(it, end, var_header_);
0070     if (!vh)
0071         return std::optional<connect_message>{};
0072 
0073     auto& [mqtt_str, version, flags, keep_alive, cprops] = *vh;
0074 
0075     if (mqtt_str != "MQTT" || version != 5)
0076         return std::optional<connect_message>{};
0077 
0078     bool has_will =  (flags & 0b00000100);
0079     bool has_uname = (flags & 0b10000000);
0080     bool has_pwd =   (flags & 0b01000000);
0081 
0082     auto payload_ =
0083         basic::utf8_ >> // client_id
0084         basic::if_(has_will)[prop::props_<will_props>] >>
0085         basic::if_(has_will)[basic::utf8_] >> // will topic
0086         basic::if_(has_will)[basic::binary_] >> // will message
0087         basic::if_(has_uname)[basic::utf8_] >> // username
0088         basic::if_(has_pwd)[basic::utf8_]; // password
0089 
0090     auto pload = type_parse(it, end, payload_);
0091     if (!pload)
0092         return std::optional<connect_message>{};
0093 
0094     std::optional<will> w;
0095 
0096     if (has_will)
0097         w.emplace(
0098             std::move(*std::get<2>(*pload)), // will_topic
0099             std::move(*std::get<3>(*pload)), // will_message
0100             qos_e((flags & 0b00011000) >> 3),
0101             retain_e((flags & 0b00100000) >> 5),
0102             std::move(*std::get<1>(*pload)) // will props
0103         );
0104 
0105     connect_message retval = {
0106         std::move(std::get<0>(*pload)), // client_id
0107         std::move(std::get<4>(*pload)), // user_name
0108         std::move(std::get<5>(*pload)), // password
0109         keep_alive,
0110         flags & 0b00000010, // clean_start
0111         std::move(cprops), // connect_props
0112         std::move(w) // will
0113     };
0114 
0115     return std::optional<connect_message> { std::move(retval) };
0116 }
0117 
0118 using connack_message = std::tuple<
0119     uint8_t, // session_present
0120     uint8_t, // connect reason code
0121     connack_props // props
0122 >;
0123 
0124 inline std::optional<connack_message> decode_connack(
0125     uint32_t remain_length, byte_citer& it
0126 ) {
0127     auto connack_ = basic::scope_limit_(remain_length)[
0128         x3::byte_ >> x3::byte_ >> prop::props_<connack_props>
0129     ];
0130     return type_parse(it, it + remain_length, connack_);
0131 }
0132 
0133 using publish_message = std::tuple<
0134     std::string, // topic
0135     std::optional<uint16_t>, // packet_id
0136     uint8_t, // dup_e, qos_e, retain_e
0137     publish_props, // publish props
0138     std::string // payload
0139 >;
0140 
0141 inline std::optional<publish_message> decode_publish(
0142     uint8_t control_byte, uint32_t remain_length, byte_citer& it
0143 ) {
0144     uint8_t flags = control_byte & 0b1111;
0145     auto qos = qos_e((flags >> 1) & 0b11);
0146 
0147     auto publish_ = basic::scope_limit_(remain_length)[
0148         basic::utf8_ >> basic::if_(qos != qos_e::at_most_once)[x3::big_word] >>
0149             x3::attr(flags) >> prop::props_<publish_props> >> basic::verbatim_
0150     ];
0151     return type_parse(it, it + remain_length, publish_);
0152 }
0153 
0154 using puback_message = std::tuple<
0155     uint8_t, // puback reason code
0156     puback_props // props
0157 >;
0158 
0159 inline std::optional<puback_message> decode_puback(
0160     uint32_t remain_length, byte_citer& it
0161 ) {
0162     if (remain_length == 0)
0163         return puback_message {};
0164     auto puback_ = basic::scope_limit_(remain_length)[
0165         x3::byte_ >> prop::props_<puback_props>
0166     ];
0167     return type_parse(it, it + remain_length, puback_);
0168 }
0169 
0170 using pubrec_message = std::tuple<
0171     uint8_t, // puback reason code
0172     pubrec_props // props
0173 >;
0174 
0175 inline std::optional<pubrec_message> decode_pubrec(
0176     uint32_t remain_length, byte_citer& it
0177 ) {
0178     if (remain_length == 0)
0179         return pubrec_message {};
0180     auto pubrec_ = basic::scope_limit_(remain_length)[
0181         x3::byte_ >> prop::props_<pubrec_props>
0182     ];
0183     return type_parse(it, it + remain_length, pubrec_);
0184 }
0185 
0186 using pubrel_message = std::tuple<
0187     uint8_t, // puback reason code
0188     pubrel_props // props
0189 >;
0190 
0191 inline std::optional<pubrel_message> decode_pubrel(
0192     uint32_t remain_length, byte_citer& it
0193 ) {
0194     if (remain_length == 0)
0195         return pubrel_message {};
0196     auto pubrel_ = basic::scope_limit_(remain_length)[
0197         x3::byte_ >> prop::props_<pubrel_props>
0198     ];
0199     return type_parse(it, it + remain_length, pubrel_);
0200 }
0201 
0202 using pubcomp_message = std::tuple<
0203     uint8_t, // puback reason code
0204     pubcomp_props // props
0205 >;
0206 
0207 inline std::optional<pubcomp_message> decode_pubcomp(
0208     uint32_t remain_length, byte_citer& it
0209 ) {
0210     if (remain_length == 0)
0211         return pubcomp_message {};
0212     auto pubcomp_ = basic::scope_limit_(remain_length)[
0213         x3::byte_ >> prop::props_<pubcomp_props>
0214     ];
0215     return type_parse(it, it + remain_length, pubcomp_);
0216 }
0217 
0218 using subscribe_message = std::tuple<
0219     subscribe_props,
0220     std::vector<std::tuple<std::string, uint8_t>> // topic filter with opts
0221 >;
0222 
0223 inline std::optional<subscribe_message> decode_subscribe(
0224     uint32_t remain_length, byte_citer& it
0225 ) {
0226     auto subscribe_ = basic::scope_limit_(remain_length)[
0227         prop::props_<subscribe_props> >> +(basic::utf8_ >> x3::byte_)
0228     ];
0229     return type_parse(it, it + remain_length, subscribe_);
0230 }
0231 
0232 using suback_message = std::tuple<
0233     suback_props,
0234     std::vector<uint8_t> // reason_codes
0235 >;
0236 
0237 inline std::optional<suback_message> decode_suback(
0238     uint32_t remain_length, byte_citer& it
0239 ) {
0240     auto suback_ = basic::scope_limit_(remain_length)[
0241         prop::props_<suback_props> >> +x3::byte_
0242     ];
0243     return type_parse(it, it + remain_length, suback_);
0244 }
0245 
0246 using unsubscribe_message = std::tuple<
0247     unsubscribe_props,
0248     std::vector<std::string> // topics
0249 >;
0250 
0251 inline std::optional<unsubscribe_message> decode_unsubscribe(
0252     uint32_t remain_length, byte_citer& it
0253 ) {
0254     auto unsubscribe_ = basic::scope_limit_(remain_length)[
0255         prop::props_<unsubscribe_props> >> +basic::utf8_
0256     ];
0257     return type_parse(it, it + remain_length, unsubscribe_);
0258 }
0259 
0260 using unsuback_message = std::tuple<
0261     unsuback_props,
0262     std::vector<uint8_t> // reason_codes
0263 >;
0264 
0265 inline std::optional<unsuback_message> decode_unsuback(
0266     uint32_t remain_length, byte_citer& it
0267 ) {
0268     auto unsuback_ = basic::scope_limit_(remain_length)[
0269         prop::props_<unsuback_props> >> +x3::byte_
0270     ];
0271     return type_parse(it, it + remain_length, unsuback_);
0272 }
0273 
0274 using disconnect_message = std::tuple<
0275     uint8_t, // reason_code
0276     disconnect_props
0277 >;
0278 
0279 inline std::optional<disconnect_message> decode_disconnect(
0280     uint32_t remain_length, byte_citer& it
0281 ) {
0282     if (remain_length == 0)
0283         return disconnect_message {};
0284     auto disconnect_ = basic::scope_limit_(remain_length)[
0285         x3::byte_ >> prop::props_<disconnect_props>
0286     ];
0287     return type_parse(it, it + remain_length, disconnect_);
0288 }
0289 
0290 using auth_message = std::tuple<
0291     uint8_t, // reason_code
0292     auth_props
0293 >;
0294 
0295 inline std::optional<auth_message> decode_auth(
0296     uint32_t remain_length, byte_citer& it
0297 ) {
0298     if (remain_length == 0)
0299         return auth_message {};
0300     auto auth_ = basic::scope_limit_(remain_length)[
0301         x3::byte_ >> prop::props_<auth_props>
0302     ];
0303     return type_parse(it, it + remain_length, auth_);
0304 }
0305 
0306 
0307 } // end namespace boost::mqtt5::decoders
0308 
0309 #endif // !BOOST_MQTT5_MESSAGE_DECODERS_HPP