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 {
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(
asio::get_associated_executor(handler, ex),
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>
concept has_async_write = requires(T a) {
a.async_write(

View File

@ -75,7 +75,7 @@ public:
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>
auto operator|(const flag_def<rhs_bits, rhs_repr>& rhs) const {
@ -103,13 +103,13 @@ class int_val : public encoder {
public:
int_val(T val) : _val(val) {}
uint16_t byte_size() const {
size_t byte_size() const {
if constexpr (is_optional<T>) {
if (_val) return uint16_t(val_length(*_val));
return uint16_t(0);
if (_val) return val_length(*_val);
return 0;
}
else
return uint16_t(val_length(_val));
return val_length(_val);
}
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>);
}
uint16_t byte_size() const {
size_t byte_size() const {
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
return uint16_t(_with_length * 2 + val_length(_val));
return _with_length * 2 + val_length(_val);
}
std::string& encode(std::string& s) const {
@ -215,12 +215,12 @@ private:
template <typename U>
std::string& encode_val(std::string& s, U&& u) const {
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 (_with_length) {
size_t sz = s.size(); s.resize(sz + 2);
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);
return s;
@ -266,8 +266,8 @@ public:
composed_val(T lhs, U rhs) :
_lhs(std::forward<T>(lhs)), _rhs(std::forward<U>(rhs)) {}
uint16_t byte_size() const {
return uint16_t(_lhs.byte_size() + _rhs.byte_size());
size_t byte_size() const {
return _lhs.byte_size() + _rhs.byte_size();
}
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_EQUAL(*packet_id_, packet_id);
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::content_type], content_type);
BOOST_CHECK_EQUAL(pprops[prop::user_property][0], publish_prop_1);
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) {
// testing variables
uint16_t packet_id = 9199;