fix: fixed properties map
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
#include <variable_byte_int.hpp>
|
||||
#include <vector>
|
||||
#include <utilities.hpp>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
||||
30
src/libmqttd/network/packet_interface/variable_header.cpp
Normal file
30
src/libmqttd/network/packet_interface/variable_header.cpp
Normal 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;
|
||||
}
|
||||
@@ -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_
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user