fix: fixed properties map

This commit is contained in:
brenodetomini
2024-01-28 17:14:31 -03:00
parent 067d7111a4
commit 36bc53753d
6 changed files with 128 additions and 64 deletions

View File

@@ -60,6 +60,9 @@ void ConnectPacket::set_variable_header() {
set_protocol_version();
set_connection_flags();
set_keepalive();
auto header_properties_start = std::next(raw_data.begin(), keepalive_start_byte+2);
PacketInterface::set_variable_header_properties(header_properties_start);
}
ConnectionFlagValue ConnectPacket::get_connection_flag(ConnectFlags flag) {
@@ -84,6 +87,7 @@ std::string ConnectPacket::to_string() {
packet_str << "Protocol Version is " << std::to_string(this->protocol_version)
<< std::endl;
packet_str << "KeepAlive is " << this->keepalive << std::endl;
packet_str << *(this->variable_header) << std::endl;
return packet_str.str();
}

View File

@@ -1,4 +1,5 @@
#include "packet_interface.hpp"
#include "spdlog/spdlog.h"
PacketInterface::PacketInterface(const std::vector<std::byte> &data) {
this->raw_data = data;
@@ -43,30 +44,35 @@ std::string PacketInterface::to_string() {
void PacketInterface::set_variable_header_properties(
const std::vector<std::byte>::const_iterator &it) {
// Length of the properties in bytes
int_vb properties_length(it);
auto current_byte = std::next(it, properties_length.size());
while (std::distance(it, current_byte) < properties_length) {
// Length of the properties in bytes
this->variable_header->property_length = int_vb(it);
auto current_byte =
std::next(it, this->variable_header->property_length.size());
while (std::distance(it, current_byte) <
this->variable_header->property_length) {
uint next_property_offset = 0;
PropertyIdentifier current_property =
PropertyIdentifier(std::to_integer<uint32_t>(*current_byte));
PropertyIdentifier(std::to_integer<uint8_t>(*current_byte));
spdlog::trace("Parsing Variable Header Property with identifier " +
std::to_string(int(current_property)));
switch (current_property) {
case PropertyIdentifier::PAYLOAD_FORMAT_INDICATOR: {
next_property_offset = 2;
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
variable_header
->properties[PropertyIdentifier::PAYLOAD_FORMAT_INDICATOR] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::MESSAGE_EXPIRY_INTERVAL: {
next_property_offset = 5;
uint32_t property_value = 0;
for (int i = 0; i < 4; i++)
property_value |=
std::to_integer<uint32_t>(*(std::next(it + 1 + i)) << (i * 8));
uint32_t property_value =
utilities::types::get_fixed_size_integer<uint32_t>(
std::next(current_byte));
;
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::MESSAGE_EXPIRY_INTERVAL] =
PropertyValue{property_value};
break;
@@ -98,11 +104,11 @@ void PacketInterface::set_variable_header_properties(
next_property_offset = 1 + 2 + property_value.size();
}
case PropertyIdentifier::SESSION_EXPIRY_INTERVAL: {
next_property_offset = 5;
uint32_t property_value = 0;
for (int i = 0; i < 4; i++)
property_value |=
std::to_integer<uint32_t>(*(std::next(it + 1 + i)) << (i * 8));
uint32_t property_value =
utilities::types::get_fixed_size_integer<uint32_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
spdlog::trace("SESSION_EXPIRY_INTERVAL: {}", property_value);
variable_header->properties[PropertyIdentifier::SESSION_EXPIRY_INTERVAL] =
PropertyValue{property_value};
break;
@@ -116,11 +122,10 @@ void PacketInterface::set_variable_header_properties(
break;
}
case PropertyIdentifier::SEREVR_KEEP_ALIVE: {
next_property_offset = 3;
uint32_t property_value = 0;
for (int i = 0; i < 2; i++)
property_value |=
std::to_integer<uint32_t>(*(std::next(it + 1 + i)) << (i * 8));
uint16_t property_value =
utilities::types::get_fixed_size_integer<uint16_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::SESSION_EXPIRY_INTERVAL] =
PropertyValue{property_value};
break;
@@ -140,25 +145,24 @@ void PacketInterface::set_variable_header_properties(
}
case PropertyIdentifier::REQUEST_PROBLEM_INFORMATION: {
next_property_offset = 2;
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
variable_header
->properties[PropertyIdentifier::REQUEST_PROBLEM_INFORMATION] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::WILL_DELAY_INTERVAL: {
next_property_offset = 5;
uint32_t property_value = 0;
for (int i = 0; i < 4; i++)
property_value |=
std::to_integer<uint32_t>(*(std::next(it + 1 + i)) << (i * 8));
uint32_t property_value =
utilities::types::get_fixed_size_integer<uint32_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::WILL_DELAY_INTERVAL] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::REQUEST_RESPONSE_INFORMATION: {
next_property_offset = 2;
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
variable_header
->properties[PropertyIdentifier::REQUEST_RESPONSE_INFORMATION] =
PropertyValue{property_value};
@@ -186,44 +190,41 @@ void PacketInterface::set_variable_header_properties(
break;
}
case PropertyIdentifier::RECEIVE_MAXIMUM: {
uint16_t property_value = 0;
uint16_t property_value =
utilities::types::get_fixed_size_integer<uint16_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
for (int i = 0; i < sizeof(property_value); i++)
property_value |=
std::to_integer<uint16_t>(*(std::next(it + 1 + i)) << (i * 8));
variable_header->properties[PropertyIdentifier::RECEIVE_MAXIMUM] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::TOPIC_ALIAS_MAXIMUM: {
uint16_t property_value = 0;
uint16_t property_value =
utilities::types::get_fixed_size_integer<uint16_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
for (int i = 0; i < sizeof(property_value); i++)
property_value |=
std::to_integer<uint16_t>(*(std::next(it + 1 + i)) << (i * 8));
variable_header->properties[PropertyIdentifier::TOPIC_ALIAS_MAXIMUM] =
variable_header->properties[PropertyIdentifier::RECEIVE_MAXIMUM] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::TOPIC_ALIAS: {
uint16_t property_value = 0;
uint16_t property_value =
utilities::types::get_fixed_size_integer<uint16_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
for (int i = 0; i < sizeof(property_value); i++)
property_value |=
std::to_integer<uint16_t>(*(std::next(it + 1 + i)) << (i * 8));
variable_header->properties[PropertyIdentifier::TOPIC_ALIAS] =
variable_header->properties[PropertyIdentifier::RECEIVE_MAXIMUM] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::MAXIMUM_QOS: {
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::MAXIMUM_QOS] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::RETAIN_AVAILABLE: {
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::RETAIN_AVAILABLE] =
PropertyValue{property_value};
@@ -237,39 +238,44 @@ void PacketInterface::set_variable_header_properties(
break;
}
case PropertyIdentifier::MAXIMUM_PACKET_SIZE: {
uint32_t property_value = 0;
uint32_t property_value =
utilities::types::get_fixed_size_integer<uint32_t>(
std::next(current_byte));
next_property_offset = 1 + sizeof(property_value);
for (int i = 0; i < 4; i++)
property_value |=
std::to_integer<uint32_t>(*(std::next(it + 1 + i)) << (i * 8));
variable_header->properties[PropertyIdentifier::MAXIMUM_PACKET_SIZE] =
variable_header->properties[PropertyIdentifier::RECEIVE_MAXIMUM] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::WILDCARD_SUBSCRIPTON_AVAILABLE: {
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::WILDCARD_SUBSCRIPTON_AVAILABLE] =
variable_header
->properties[PropertyIdentifier::WILDCARD_SUBSCRIPTON_AVAILABLE] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::SUBSCRIPTION_IDENTIFIER_AVAILABLE: {
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::SUBSCRIPTION_IDENTIFIER_AVAILABLE] =
variable_header
->properties[PropertyIdentifier::SUBSCRIPTION_IDENTIFIER_AVAILABLE] =
PropertyValue{property_value};
break;
}
case PropertyIdentifier::SHARED_SUBSCRIPTION_AVAILABLE: {
std::byte property_value = *(std::next(it, 1));
std::byte property_value = *(std::next(current_byte, 1));
next_property_offset = 1 + sizeof(property_value);
variable_header->properties[PropertyIdentifier::SHARED_SUBSCRIPTION_AVAILABLE] =
variable_header
->properties[PropertyIdentifier::SHARED_SUBSCRIPTION_AVAILABLE] =
PropertyValue{property_value};
break;
}
default:
throw std::runtime_error("Invalid property received");
default: {
uint8_t byte_value = std::to_integer<uint8_t>(*current_byte);
throw std::runtime_error("Invalid property received (" +
std::to_string(byte_value) + ")");
}
current_byte = std::next(it, next_property_offset);
}
current_byte = std::next(current_byte, next_property_offset);
}
}

View File

@@ -6,6 +6,7 @@
#include <memory>
#include <variable_byte_int.hpp>
#include <vector>
#include <utilities.hpp>
#include <sstream>

View File

@@ -0,0 +1,30 @@
#include "spdlog/spdlog.h"
#include <variable_header.hpp>
struct VariantPrinter {
std::ostream &os;
template <typename T> void operator()(const T &value) const { os << value; }
};
std::ostream &operator<<(std::ostream &os, const std::byte &value) {
os << std::to_string(std::to_integer<uint8_t>(value));
return os;
}
std::ostream &operator<<(std::ostream &os, const PropertyValue &value) {
std::visit(VariantPrinter{os}, value);
return os;
}
std::ostream &operator<<(std::ostream &os, const variable_header_t &value) {
os << "Packet identifier is " << value.packet_identifier << std::endl;
os << "Property length is " << value.property_length << std::endl;
os << "Property map" << std::endl;
if (value.property_length > 0) {
for (const auto &[key, value] : value.properties) {
os << "\t" << "\u21B3" << int(key) << ": " << value << std::endl;
}
}
return os;
}

View File

@@ -1,9 +1,9 @@
#ifndef INCLUDE_PACKET_INTERFACE_VARIABLE_HEADER_HPP_
#define INCLUDE_PACKET_INTERFACE_VARIABLE_HEADER_HPP_
#include <variable_byte_int.hpp>
#include <utf8_string.hpp>
#include <binary_data.hpp>
#include <utf8_string.hpp>
#include <variable_byte_int.hpp>
#include <map>
#include <variant>
@@ -38,7 +38,9 @@ enum class PropertyIdentifier : uint32_t {
SHARED_SUBSCRIPTION_AVAILABLE = 42
};
using PropertyValue = std::variant<std::byte, uint32_t, uint16_t, int_vb, binary_data, utf8_str>;
using PropertyValue =
std::variant<std::byte, uint32_t, uint16_t, int_vb, binary_data, utf8_str>;
using PropertyMap = std::map<PropertyIdentifier, PropertyValue>;
struct variable_header {
@@ -49,5 +51,8 @@ struct variable_header {
typedef struct variable_header variable_header_t;
#endif // INCLUDE_PACKET_INTERFACE_VARIABLE_HEADER_HPP_
std::ostream &operator<<(std::ostream &os, const std::byte &value);
std::ostream &operator<<(std::ostream &os, const PropertyValue &value);
std::ostream &operator<<(std::ostream &os, const variable_header_t &value);
#endif // INCLUDE_PACKET_INTERFACE_VARIABLE_HEADER_HPP_

View File

@@ -1,6 +1,10 @@
#ifndef INCLUDE_LIBMQTTD_UTILITIES_HPP_
#define INCLUDE_LIBMQTTD_UTILITIES_HPP_
#include <cstdint>
#include <iostream>
#include <type_traits>
#include <vector>
namespace utilities {
namespace bit {
@@ -14,6 +18,20 @@ template <typename T> bool get(T num, int position) {
return (num & mask) != 0;
}
} // namespace bit
namespace types {
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
get_fixed_size_integer(const std::vector<std::byte>::const_iterator &it) {
T value = 0;
for (unsigned int i = 0; i < sizeof(T); i++) {
uint8_t byte_value = std::to_integer<uint8_t>(*(std::next(it, i)));
value = (value << 8) | byte_value;
std::cout << "Byte " << std::to_string(byte_value) << std::endl;
}
return value;
}
} // namespace types
} // namespace utilities
#endif // INCLUDE_LIBMQTTD_UTILITIES_HPP_
#endif // INCLUDE_LIBMQTTD_UTILITIES_HPP_