Improved CONNECT & CONNACK property client functions

Summary: related to T13427

Reviewers: ivica

Reviewed By: ivica

Subscribers: miljen, iljazovic

Differential Revision: https://repo.mireo.local/D27218
This commit is contained in:
Korina Šimičević
2024-01-04 15:31:06 +01:00
parent 6f5c179929
commit 123e70d8fe
13 changed files with 126 additions and 60 deletions

View File

@ -89,7 +89,7 @@ public:
_read_buff.cbegin(), _data_span.first()
);
_read_buff.resize(
_svc.connect_prop(prop::maximum_packet_size).value_or(max_recv_size)
_svc.connect_property(prop::maximum_packet_size).value_or(max_recv_size)
);
_data_span = {
_read_buff.cbegin(),
@ -157,7 +157,7 @@ public:
}
auto recv_size = static_cast<size_t>(
_svc.connect_prop(prop::maximum_packet_size).value_or(max_recv_size)
_svc.connect_property(prop::maximum_packet_size).value_or(max_recv_size)
);
if (*varlen > recv_size - std::distance(_data_span.first(), first))
return complete(client::error::malformed_packet, 0, {}, {});

View File

@ -147,7 +147,7 @@ public:
// all the packets that require resending.
_write_in_progress = true;
auto new_limit = _svc._stream_context.connack_prop(prop::receive_maximum);
auto new_limit = _svc._stream_context.connack_property(prop::receive_maximum);
_limit = new_limit.value_or(MAX_LIMIT);
_quota = _limit;

View File

@ -62,20 +62,25 @@ public:
}
template <typename Prop>
const auto& connack_prop(Prop p) const {
const auto& connack_property(Prop p) const {
return _mqtt_context.ca_props[p];
}
const auto& connack_props() const {
const auto& connack_properties() const {
return _mqtt_context.ca_props;
}
template <typename Prop>
const auto& connect_prop(Prop p) const {
const auto& connect_property(Prop p) const {
return _mqtt_context.co_props[p];
}
void connect_props(connect_props props) {
template <typename Prop>
auto& connect_property(Prop p) {
return _mqtt_context.co_props[p];
}
void connect_propertiess(connect_props props) {
_mqtt_context.co_props = std::move(props);
}
@ -123,20 +128,25 @@ public:
}
template <typename Prop>
const auto& connack_prop(Prop p) const {
const auto& connack_property(Prop p) const {
return _mqtt_context.ca_props[p];
}
const auto& connack_props() const {
const auto& connack_properties() const {
return _mqtt_context.ca_props;
}
template <typename Prop>
const auto& connect_prop(Prop p) const {
const auto& connect_property(Prop p) const {
return _mqtt_context.co_props[p];
}
void connect_props(connect_props props) {
template <typename Prop>
auto& connect_property(Prop p) {
return _mqtt_context.co_props[p];
}
void connect_properties(connect_props props) {
_mqtt_context.co_props = std::move(props);
}
@ -267,22 +277,27 @@ public:
}
template <typename Prop>
const auto& connect_prop(Prop p) const {
return _stream_context.connect_prop(p);
}
void connect_props(connect_props props) {
if (!is_open())
_stream_context.connect_props(std::move(props));
const auto& connect_property(Prop p) const {
return _stream_context.connect_property(p);
}
template <typename Prop>
const auto& connack_prop(Prop p) const {
return _stream_context.connack_prop(p);
auto& connect_property(Prop p) {
return _stream_context.connect_property(p);
}
const auto& connack_props() const {
return _stream_context.connack_props();
void connect_properties(connect_props props) {
if (!is_open())
_stream_context.connect_properties(std::move(props));
}
template <typename Prop>
const auto& connack_property(Prop p) const {
return _stream_context.connack_property(p);
}
const auto& connack_properties() const {
return _stream_context.connack_properties();
}
void run() {

View File

@ -72,7 +72,7 @@ public:
);
auto max_packet_size = static_cast<size_t>(
_svc_ptr->connack_prop(prop::maximum_packet_size)
_svc_ptr->connack_property(prop::maximum_packet_size)
.value_or(default_max_send_size)
);
if (disconnect.size() > max_packet_size)

View File

@ -121,7 +121,7 @@ public:
);
auto max_packet_size = static_cast<size_t>(
_svc_ptr->connack_prop(prop::maximum_packet_size)
_svc_ptr->connack_property(prop::maximum_packet_size)
.value_or(default_max_send_size)
);
if (publish.size() > max_packet_size)
@ -355,9 +355,9 @@ private:
if (validate_topic_name(topic) != validation_result::valid)
return client::error::invalid_topic;
auto max_qos = _svc_ptr->connack_prop(prop::maximum_qos)
auto max_qos = _svc_ptr->connack_property(prop::maximum_qos)
.value_or(default_maximum_qos);
auto retain_available = _svc_ptr->connack_prop(prop::retain_available)
auto retain_available = _svc_ptr->connack_property(prop::retain_available)
.value_or(default_retain_available);
if (uint8_t(qos_type) > max_qos)
@ -382,7 +382,7 @@ private:
auto topic_alias = props[prop::topic_alias];
if (topic_alias) {
auto topic_alias_max = _svc_ptr->connack_prop(prop::topic_alias_maximum)
auto topic_alias_max = _svc_ptr->connack_property(prop::topic_alias_maximum)
.value_or(default_topic_alias_max);
if (topic_alias_max == 0 || *topic_alias > topic_alias_max)

View File

@ -81,7 +81,7 @@ public:
);
auto max_packet_size = static_cast<size_t>(
_svc_ptr->connack_prop(prop::maximum_packet_size)
_svc_ptr->connack_property(prop::maximum_packet_size)
.value_or(default_max_send_size)
);
if (subscribe.size() > max_packet_size)
@ -169,10 +169,10 @@ private:
}
error_code validate_topic(const subscribe_topic& topic) const {
auto wildcard_available = _svc_ptr->connack_prop(
auto wildcard_available = _svc_ptr->connack_property(
prop::wildcard_subscription_available
).value_or(1);
auto shared_available = _svc_ptr->connack_prop(
auto shared_available = _svc_ptr->connack_property(
prop::shared_subscription_available
).value_or(1);
@ -208,7 +208,7 @@ private:
if (!sub_id.has_value())
return error_code {};
auto sub_id_available = _svc_ptr->connack_prop(
auto sub_id_available = _svc_ptr->connack_property(
prop::subscription_identifier_available
).value_or(1);

View File

@ -76,7 +76,7 @@ public:
);
auto max_packet_size = static_cast<size_t>(
_svc_ptr->connack_prop(prop::maximum_packet_size)
_svc_ptr->connack_property(prop::maximum_packet_size)
.value_or(default_max_send_size)
);
if (unsubscribe.size() > max_packet_size)

View File

@ -274,8 +274,35 @@ public:
return *this;
}
/**
* \brief Assign \__CONNECT_PROPS\__ that will be sent in a \__CONNECT\__ packet.
* \param props \__CONNECT_PROPS\__ sent in a \__CONNECT\__ packet.
* \see See \__CONNECT_PROPS\__ for all eligible properties.
*/
mqtt_client& connect_properties(connect_props props) {
_svc_ptr->connect_props(std::move(props));
_svc_ptr->connect_properties(std::move(props));
return *this;
}
/**
* \brief Assign a property that will be sent in a \__CONNECT\__ packet.
* \param prop The \__CONNECT_PROPS\__ property to set.
* \param value Value that will be assigned to the property.
*
* \par Example
* \code
* client.connect_property(prop::session_expiry_interval, 40); // ok
* client.connect_property(prop::reason_string, "reason"); // does not compile, not a CONNECT prop!
* \endcode
*
* \see See \__CONNECT_PROPS\__ for all eligible properties.
*/
template <prop::property_type p>
mqtt_client& connect_property(
std::integral_constant<prop::property_type, p> prop,
prop::value_type_t<p> value
) {
_svc_ptr->connect_property(prop) = value;
return *this;
}
@ -296,21 +323,30 @@ public:
* For all properties, the return type will be `std::optional` of their respective value type.
* For `async_mqtt5::prop::user_property`, the return type is `std::vector<std::string>`.
*
* \param prop The \__CONNACK\__ property value to retrieve.
* \param prop The \__CONNACK_PROPS\__ property value to retrieve.
*
* \par Example
* \code
* std::optional<std::string> auth_method = client.connection_property(async_mqtt5::prop::authentication_method); // ok
* std::optional<std::string> c_type = client.connection_property(async_mqtt5::prop::content_type); // does not compile!
* std::optional<std::string> auth_method = client.connack_property(async_mqtt5::prop::authentication_method); // ok
* std::optional<std::string> c_type = client.connack_property(async_mqtt5::prop::content_type); // does not compile, not a CONNAK prop!
* \endcode
*
* \see See \__CONNACK_PROPS\__ for all eligible properties.
*/
template <prop::property_type p>
const auto& connection_property(
std::integral_constant<prop::property_type, p> prop
const auto& connack_property(
std::integral_constant<prop::property_type, p> prop
) const {
return _svc_ptr->connack_prop(prop);
return _svc_ptr->connack_property(prop);
}
/**
* \brief Retrieves the \__CONNACK_PROPS\__ from the last \__CONNACK\__ packet received.
*
* \see See \__CONNACK_PROPS\__ for all eligible properties.
*/
const connack_props& connack_properties() const {
return _svc_ptr->connack_properties();
}
/**

View File

@ -56,6 +56,7 @@ inline std::string_view code_to_str(control_code_e code) {
case control_code_e::disconnect: return "DISCONNECT";
case control_code_e::pingreq: return "PINGREQ";
case control_code_e::pingresp: return "PINGRESP";
default: return "NO PACKET";
}
return "UNKNOWN";
}

View File

@ -51,19 +51,11 @@ public:
}
template <typename Prop>
decltype(auto) connack_prop(Prop p) {
return std::as_const(_test_props[p]);
const auto& connack_property(Prop p) const {
return _test_props[p];
}
template <typename Prop0, typename ...Props>
decltype(auto) connack_props(Prop0 p0, Props ...props) {
return std::make_tuple(
std::as_const(_test_props[p0]),
std::as_const(_test_props[props])...
);
}
const auto& connack_props() {
const auto& connack_properties() {
return _test_props;
}

View File

@ -443,7 +443,6 @@ BOOST_AUTO_TEST_CASE(throttling) {
test::msg_exchange broker_side;
error_code success {};
error_code fail = asio::error::not_connected;
broker_side
.expect(connect)
@ -546,7 +545,6 @@ BOOST_AUTO_TEST_CASE(cancel_multiple_ops) {
test::msg_exchange broker_side;
error_code success{};
error_code fail = asio::error::not_connected;
broker_side
.expect(connect)

View File

@ -1,11 +1,16 @@
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/beast/websocket/stream.hpp>
#include <boost/type_traits/remove_cv_ref.hpp>
#include <async_mqtt5/detail/any_authenticator.hpp>
#include <async_mqtt5/detail/async_traits.hpp>
@ -43,7 +48,7 @@ class bad_authenticator {
public:
bad_authenticator() = default;
void async_auth(std::string data) {}
void async_auth(std::string /* data */) {}
std::string_view method() const {
return "method";
@ -93,9 +98,28 @@ BOOST_AUTO_TEST_CASE(client_functions) {
mqtt_client<tcp_layer> tcp_client(ioc, "");
tcp_client.authenticator(good_authenticator());
std::optional<std::string> data = tcp_client.connection_property(
prop::authentication_data
);
connack_props ca_props;
ca_props.visit([&tcp_client](const auto& p, auto&) -> bool {
using ptype = boost::remove_cv_ref_t<decltype(p)>;
prop::value_type_t<ptype::value> value = tcp_client.connack_property(p);
return true;
});
connack_props ret_ca_props = tcp_client.connack_properties();
connect_props co_props;
co_props[prop::maximum_packet_size] = 1234;
tcp_client.connect_properties(std::move(co_props));
tcp_client.connect_property(prop::session_expiry_interval, 40);
tcp_client.connect_property(prop::receive_maximum, int16_t(10123));
tcp_client.connect_property(prop::maximum_packet_size, 103);
tcp_client.connect_property(prop::topic_alias_maximum, uint16_t(12345));
tcp_client.connect_property(prop::request_response_information, uint8_t(1));
tcp_client.connect_property(prop::request_problem_information, uint8_t(0));
tcp_client.connect_property(prop::user_property, std::vector<std::string> { "prop", "prop" });
tcp_client.connect_property(prop::authentication_method, "method");
tcp_client.connect_property(prop::authentication_data, "data");
asio::ssl::context ctx(asio::ssl::context::tls_client);
mqtt_client<

View File

@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(test_wildcard_subscriptions_not_supported) {
auto svc_ptr = std::make_shared<client_service_type>(
ioc.get_executor(), std::move(props)
);
BOOST_ASSERT(svc_ptr->connack_prop(prop::wildcard_subscription_available) == 0);
BOOST_ASSERT(svc_ptr->connack_property(prop::wildcard_subscription_available) == 0);
for (const auto& topic: wildcard_topics) {
auto handler = [&handlers_called](error_code ec, auto, auto) {
@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(test_shared_subscriptions_not_supported) {
auto svc_ptr = std::make_shared<client_service_type>(
ioc.get_executor(), std::move(props)
);
BOOST_ASSERT(svc_ptr->connack_prop(prop::shared_subscription_available) == 0);
BOOST_ASSERT(svc_ptr->connack_property(prop::shared_subscription_available) == 0);
auto handler = [&handlers_called](error_code ec, auto, auto) {
++handlers_called;
@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(test_large_subscription_id) {
auto svc_ptr = std::make_shared<client_service_type>(
ioc.get_executor(), std::move(props)
);
BOOST_ASSERT(svc_ptr->connack_prop(prop::subscription_identifier_available) == 1);
BOOST_ASSERT(svc_ptr->connack_property(prop::subscription_identifier_available) == 1);
auto handler = [&handlers_called](error_code ec, auto, auto) {
++handlers_called;
@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(test_subscription_ids_not_supported) {
auto svc_ptr = std::make_shared<client_service_type>(
ioc.get_executor(), std::move(props)
);
BOOST_ASSERT(svc_ptr->connack_prop(prop::subscription_identifier_available) == 0);
BOOST_ASSERT(svc_ptr->connack_property(prop::subscription_identifier_available) == 0);
auto handler = [&handlers_called](error_code ec, auto, auto) {
++handlers_called;