support large publish packets

Reviewers: ivica

Reviewed By: ivica

Subscribers: korina

Differential Revision: https://repo.mireo.local/D26763
This commit is contained in:
Bruno Iljazovic
2023-11-30 10:42:03 +01:00
parent 8c1c4fab9f
commit dfd4b41a4e
3 changed files with 50 additions and 20 deletions

View File

@@ -28,19 +28,22 @@ void assign_tls_sni(const authority_path& ap, TlsContext& ctx, TlsStream& s);
namespace detail { namespace detail {
template <typename Handler, typename DfltExecutor> template <typename Handler, typename DfltExecutor>
decltype(auto) tracking_executor(const Handler& handler, const DfltExecutor& ex) { using tracking_type = std::decay_t<
typename asio::prefer_result<
asio::associated_executor_t<Handler, DfltExecutor>,
asio::execution::outstanding_work_t::tracked_t
>::type
>;
template <typename Handler, typename DfltExecutor>
tracking_type<Handler, DfltExecutor>
tracking_executor(const Handler& handler, const DfltExecutor& ex) {
return asio::prefer( return asio::prefer(
asio::get_associated_executor(handler, ex), asio::get_associated_executor(handler, ex),
asio::execution::outstanding_work.tracked asio::execution::outstanding_work.tracked
); );
} }
template <typename Handler, typename DfltExecutor>
using tracking_type = typename asio::prefer_result<
asio::associated_executor_t<Handler, DfltExecutor>,
asio::execution::outstanding_work_t::tracked_t
>::type;
template <typename T, typename B> template <typename T, typename B>
concept has_async_write = requires(T a) { concept has_async_write = requires(T a) {
a.async_write( a.async_write(

View File

@@ -75,7 +75,7 @@ public:
return flag_def<bits, repr> { val }; return flag_def<bits, repr> { val };
} }
uint16_t byte_size() const { return sizeof(repr); } size_t byte_size() const { return sizeof(repr); }
template <size_t rhs_bits, typename rhs_repr> template <size_t rhs_bits, typename rhs_repr>
auto operator|(const flag_def<rhs_bits, rhs_repr>& rhs) const { auto operator|(const flag_def<rhs_bits, rhs_repr>& rhs) const {
@@ -103,13 +103,13 @@ class int_val : public encoder {
public: public:
int_val(T val) : _val(val) {} int_val(T val) : _val(val) {}
uint16_t byte_size() const { size_t byte_size() const {
if constexpr (is_optional<T>) { if constexpr (is_optional<T>) {
if (_val) return uint16_t(val_length(*_val)); if (_val) return val_length(*_val);
return uint16_t(0); return 0;
} }
else else
return uint16_t(val_length(_val)); return val_length(_val);
} }
std::string& encode(std::string& s) const { std::string& encode(std::string& s) const {
@@ -185,11 +185,11 @@ public:
static_assert(std::is_reference_v<T> || std::is_same_v<T, std::string_view>); static_assert(std::is_reference_v<T> || std::is_same_v<T, std::string_view>);
} }
uint16_t byte_size() const { size_t byte_size() const {
if constexpr (is_optional<T>) if constexpr (is_optional<T>)
return uint16_t(_val ? _with_length * 2 + val_length(*_val) : 0); return _val ? _with_length * 2 + val_length(*_val) : 0;
else else
return uint16_t(_with_length * 2 + val_length(_val)); return _with_length * 2 + val_length(_val);
} }
std::string& encode(std::string& s) const { std::string& encode(std::string& s) const {
@@ -215,12 +215,12 @@ private:
template <typename U> template <typename U>
std::string& encode_val(std::string& s, U&& u) const { std::string& encode_val(std::string& s, U&& u) const {
using namespace boost::endian; using namespace boost::endian;
int16_t byte_len = int16_t(val_length(std::forward<U>(u))); auto byte_len = val_length(std::forward<U>(u));
if (byte_len == 0 && !_with_length) return s; if (byte_len == 0 && !_with_length) return s;
if (_with_length) { if (_with_length) {
size_t sz = s.size(); s.resize(sz + 2); size_t sz = s.size(); s.resize(sz + 2);
auto p = reinterpret_cast<uint8_t*>(s.data() + sz); auto p = reinterpret_cast<uint8_t*>(s.data() + sz);
endian_store<int16_t, sizeof(int16_t), order::big>(p, byte_len); endian_store<int16_t, sizeof(int16_t), order::big>(p, int16_t(byte_len));
} }
s.append(std::begin(u), std::begin(u) + byte_len); s.append(std::begin(u), std::begin(u) + byte_len);
return s; return s;
@@ -266,8 +266,8 @@ public:
composed_val(T lhs, U rhs) : composed_val(T lhs, U rhs) :
_lhs(std::forward<T>(lhs)), _rhs(std::forward<U>(rhs)) {} _lhs(std::forward<T>(lhs)), _rhs(std::forward<U>(rhs)) {}
uint16_t byte_size() const { size_t byte_size() const {
return uint16_t(_lhs.byte_size() + _rhs.byte_size()); return _lhs.byte_size() + _rhs.byte_size();
} }
std::string& encode(std::string& s) const { std::string& encode(std::string& s) const {

View File

@@ -114,13 +114,40 @@ BOOST_AUTO_TEST_CASE(test_publish) {
BOOST_CHECK(packet_id); BOOST_CHECK(packet_id);
BOOST_CHECK_EQUAL(*packet_id_, packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id);
BOOST_CHECK_EQUAL(topic_, topic); BOOST_CHECK_EQUAL(topic_, topic);
BOOST_CHECK_EQUAL(payload_, payload_); BOOST_CHECK_EQUAL(payload_, payload);
BOOST_CHECK_EQUAL(*pprops[prop::message_expiry_interval], message_expiry); BOOST_CHECK_EQUAL(*pprops[prop::message_expiry_interval], message_expiry);
BOOST_CHECK_EQUAL(*pprops[prop::content_type], content_type); BOOST_CHECK_EQUAL(*pprops[prop::content_type], content_type);
BOOST_CHECK_EQUAL(pprops[prop::user_property][0], publish_prop_1); BOOST_CHECK_EQUAL(pprops[prop::user_property][0], publish_prop_1);
BOOST_CHECK_EQUAL(pprops[prop::user_property][1], publish_prop_2); BOOST_CHECK_EQUAL(pprops[prop::user_property][1], publish_prop_2);
} }
BOOST_AUTO_TEST_CASE(test_large_publish) {
// testing variables
uint16_t packet_id = 40001;
std::string_view topic = "publish_topic";
std::string large_payload(1'000'000, 'a');
auto msg = encoders::encode_publish(
packet_id, topic, large_payload,
qos_e::at_least_once, retain_e::yes, dup_e::no,
publish_props{}
);
byte_citer it = msg.cbegin(), last = msg.cend();
auto header = decoders::decode_fixed_header(it, last);
BOOST_CHECK_MESSAGE(header, "Parsing PUBLISH fixed header failed.");
const auto& [control_byte, remain_length] = *header;
auto rv = decoders::decode_publish(control_byte, remain_length, it);
BOOST_CHECK_MESSAGE(rv, "Parsing PUBLISH failed.");
const auto& [topic_, packet_id_, flags, pprops, payload_] = *rv;
BOOST_CHECK(packet_id);
BOOST_CHECK_EQUAL(*packet_id_, packet_id);
BOOST_CHECK_EQUAL(topic_, topic);
BOOST_CHECK_EQUAL(payload_, large_payload);
}
BOOST_AUTO_TEST_CASE(test_puback) { BOOST_AUTO_TEST_CASE(test_puback) {
// testing variables // testing variables
uint16_t packet_id = 9199; uint16_t packet_id = 9199;