#include <cstring>
#include <limits>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio/ip/address_v6.hpp>
#include "../include/routing_info_entry.hpp"
namespace vsomeip_v3 {
namespace protocol {
routing_info_entry::routing_info_entry()
: type_(routing_info_entry_type_e::RIE_UNKNOWN),
port_(0) {
}
routing_info_entry::routing_info_entry(const routing_info_entry &_source)
: type_(_source.type_),
client_(_source.client_),
address_(_source.address_),
port_(_source.port_),
services_(_source.services_) {
}
void
routing_info_entry::serialize(std::vector<byte_t> &_buffer,
size_t &_index, error_e &_error) const {
_buffer[_index] = static_cast<byte_t>(type_);
_index += sizeof(type_);
size_t its_size = get_size() - sizeof(uint32_t) - 1;
if (its_size > std::numeric_limits<uint32_t>::max()) {
_error = error_e::ERROR_MALFORMED;
return;
}
uint32_t its_size32(static_cast<uint32_t>(its_size));
std::memcpy(&_buffer[_index], &its_size32, sizeof(its_size32));
_index += sizeof(its_size32);
uint32_t its_client_size(sizeof(client_));
if (!address_.is_unspecified()) {
if (address_.is_v4()) {
its_client_size += uint32_t(sizeof(boost::asio::ip::address_v4::bytes_type)
+ sizeof(port_));
} else {
its_client_size += uint32_t(sizeof(boost::asio::ip::address_v6::bytes_type)
+ sizeof(port_));
}
}
if (type_ > routing_info_entry_type_e::RIE_DELETE_CLIENT) {
std::memcpy(&_buffer[_index], &its_client_size, sizeof(its_client_size));
_index += sizeof(its_client_size);
}
std::memcpy(&_buffer[_index], &client_, sizeof(client_));
_index += sizeof(client_);
if (!address_.is_unspecified()) {
if (address_.is_v4()) {
std::memcpy(&_buffer[_index], address_.to_v4().to_bytes().data(),
sizeof(boost::asio::ip::address_v4::bytes_type));
_index += sizeof(boost::asio::ip::address_v4::bytes_type);
} else {
std::memcpy(&_buffer[_index], address_.to_v6().to_bytes().data(),
sizeof(boost::asio::ip::address_v6::bytes_type));
_index += sizeof(boost::asio::ip::address_v6::bytes_type);
}
std::memcpy(&_buffer[_index], &port_, sizeof(port_));
_index += sizeof(port_);
}
if (type_ > routing_info_entry_type_e::RIE_DELETE_CLIENT) {
its_size = (services_.size() *
(sizeof(service_t) + sizeof(instance_t) +
sizeof(major_version_t) + sizeof(minor_version_t)));
if (its_size > std::numeric_limits<uint32_t>::max()) {
_error = error_e::ERROR_MALFORMED;
return;
}
its_size32 = static_cast<uint32_t>(its_size);
std::memcpy(&_buffer[_index], &its_size32, sizeof(its_size32));
_index += sizeof(its_size32);
for (const auto &s : services_) {
std::memcpy(&_buffer[_index], &s.service_, sizeof(s.service_));
_index += sizeof(s.service_);
std::memcpy(&_buffer[_index], &s.instance_, sizeof(s.instance_));
_index += sizeof(s.instance_);
std::memcpy(&_buffer[_index], &s.major_, sizeof(s.major_));
_index += sizeof(s.major_);
std::memcpy(&_buffer[_index], &s.minor_, sizeof(s.minor_));
_index += sizeof(s.minor_);
}
}
}
void
routing_info_entry::deserialize(const std::vector<byte_t> &_buffer,
size_t &_index, error_e &_error) {
uint32_t its_size;
uint32_t its_client_size;
if (_buffer.size() < _index + sizeof(type_) + sizeof(its_size)
+ sizeof(client_)) {
_error = error_e::ERROR_NOT_ENOUGH_BYTES;
return;
}
type_ = static_cast<routing_info_entry_type_e>(_buffer[_index++]);
if (type_ == routing_info_entry_type_e::RIE_UNKNOWN) {
_error = error_e::ERROR_MALFORMED;
return;
}
std::memcpy(&its_size, &_buffer[_index], sizeof(its_size));
_index += sizeof(its_size);
if (type_ > routing_info_entry_type_e::RIE_DELETE_CLIENT) {
std::memcpy(&its_client_size, &_buffer[_index], sizeof(its_client_size));
_index += sizeof(its_client_size);
} else {
its_client_size = its_size;
}
std::memcpy(&client_, &_buffer[_index], sizeof(client_));
_index += sizeof(client_);
if (its_client_size > sizeof(client_)) {
uint32_t its_address_size = its_client_size
- uint32_t(sizeof(client_t) + sizeof(port_));
if (its_address_size == sizeof(boost::asio::ip::address_v4::bytes_type)) {
boost::asio::ip::address_v4::bytes_type its_array;
std::memcpy(&its_array, &_buffer[_index], its_array.size());
address_ = boost::asio::ip::address_v4(its_array);
_index += its_array.size();
} else if (its_address_size == sizeof(boost::asio::ip::address_v6::bytes_type)) {
boost::asio::ip::address_v6::bytes_type its_array;
std::memcpy(&its_array, &_buffer[_index], its_array.size());
address_ = boost::asio::ip::address_v6(its_array);
_index += its_array.size();
} else {
_error = error_e::ERROR_MALFORMED;
return;
}
std::memcpy(&port_, &_buffer[_index], sizeof(port_));
_index += sizeof(port_);
}
if (type_ > routing_info_entry_type_e::RIE_DELETE_CLIENT) {
if (_buffer.size() < _index + sizeof(its_size)) {
_error = error_e::ERROR_NOT_ENOUGH_BYTES;
return;
}
std::memcpy(&its_size, &_buffer[_index], sizeof(its_size));
_index += sizeof(its_size);
if (_buffer.size() < _index + its_size) {
_error = error_e::ERROR_NOT_ENOUGH_BYTES;
return;
}
size_t its_n = (its_size /
(sizeof(service_t) + sizeof(instance_t) +
sizeof(major_version_t) + sizeof(minor_version_t)));
for (size_t i = 0; i < its_n; i++) {
service its_service;
std::memcpy(&its_service.service_, &_buffer[_index], sizeof(its_service.service_));
_index += sizeof(its_service.service_);
std::memcpy(&its_service.instance_, &_buffer[_index], sizeof(its_service.instance_));
_index += sizeof(its_service.instance_);
its_service.major_ = static_cast<major_version_t>(_buffer[_index]);
_index += sizeof(its_service.major_);
std::memcpy(&its_service.minor_, &_buffer[_index], sizeof(its_service.minor_));
_index += sizeof(its_service.minor_);
services_.emplace_back(its_service);
}
}
}
routing_info_entry_type_e
routing_info_entry::get_type() const {
return type_;
}
void
routing_info_entry::set_type(routing_info_entry_type_e _type) {
type_ = _type;
}
size_t
routing_info_entry::get_size() const {
size_t its_size(ROUTING_INFO_ENTRY_HEADER_SIZE);
if (!address_.is_unspecified()) {
if (address_.is_v4()) {
its_size += (sizeof(boost::asio::ip::address_v4::bytes_type)
+ sizeof(port_));
} else {
its_size += (sizeof(boost::asio::ip::address_v6::bytes_type)
+ sizeof(port_));
}
}
if (type_ > routing_info_entry_type_e::RIE_DELETE_CLIENT) {
its_size += sizeof(uint32_t); its_size += sizeof(uint32_t); its_size += (services_.size() *
(sizeof(service_t) + sizeof(instance_t) +
sizeof(major_version_t) + sizeof(minor_version_t)));
}
return its_size;
}
client_t
routing_info_entry::get_client() const {
return client_;
}
void
routing_info_entry::set_client(client_t _client) {
client_ = _client;
}
boost::asio::ip::address
routing_info_entry::get_address() const {
return address_;
}
void
routing_info_entry::set_address(const boost::asio::ip::address &_address) {
address_ = _address;
}
port_t
routing_info_entry::get_port() const {
return port_;
}
void
routing_info_entry::set_port(port_t _port) {
port_ = _port;
}
const std::vector<service> &
routing_info_entry::get_services() const {
return services_;
}
void
routing_info_entry::add_service(const service &_service) {
services_.push_back(_service);
}
} }