obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
345 lines
9.7 KiB
C++
345 lines
9.7 KiB
C++
#ifndef ASN1C_WRAPPER_HPP_ZCNDO8E5
|
|
#define ASN1C_WRAPPER_HPP_ZCNDO8E5
|
|
|
|
#include <vanetza/asn1/support/asn_system.h>
|
|
#include <vanetza/asn1/support/constr_TYPE.h>
|
|
#include <vanetza/asn1/type_traits.hpp>
|
|
#include <vanetza/common/byte_buffer.hpp>
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
namespace vanetza
|
|
{
|
|
namespace asn1
|
|
{
|
|
|
|
void* allocate(std::size_t);
|
|
void free(asn_TYPE_descriptor_t&, void*);
|
|
void* copy(asn_TYPE_descriptor_t&, const void*);
|
|
bool validate(asn_TYPE_descriptor_t&, const void*);
|
|
bool validate(asn_TYPE_descriptor_t&, const void*, std::string&);
|
|
int compare(asn_TYPE_descriptor_t&, const void*, const void*);
|
|
int print(FILE* stream, asn_TYPE_descriptor_t&, const void*);
|
|
std::size_t size_per(asn_TYPE_descriptor_t&, const void*);
|
|
std::size_t size_oer(asn_TYPE_descriptor_t&, const void*);
|
|
std::size_t size_xer(asn_TYPE_descriptor_t&, const void*);
|
|
ByteBuffer encode_per(asn_TYPE_descriptor_t&, const void*);
|
|
bool decode_per(asn_TYPE_descriptor_t&, void**, const ByteBuffer&);
|
|
bool decode_per(asn_TYPE_descriptor_t&, void**, const void* buffer, std::size_t size);
|
|
ByteBuffer encode_oer(asn_TYPE_descriptor_t&, const void*);
|
|
bool decode_oer(asn_TYPE_descriptor_t&, void**, const ByteBuffer&);
|
|
bool decode_oer(asn_TYPE_descriptor_t&, void**, const void* buffer, std::size_t size);
|
|
ByteBuffer encode_xer(asn_TYPE_descriptor_t&, const void*);
|
|
bool decode_xer(asn_TYPE_descriptor_t&, void**, const ByteBuffer&);
|
|
bool decode_xer(asn_TYPE_descriptor_t&, void**, const void* buffer, std::size_t size);
|
|
|
|
template<class T>
|
|
T* allocate()
|
|
{
|
|
return static_cast<T*>(allocate(sizeof(T)));
|
|
}
|
|
|
|
/// Deleter freeing an asn1c struct through its ASN.1 type descriptor.
|
|
struct deleter
|
|
{
|
|
asn_TYPE_descriptor_t* descriptor = nullptr;
|
|
|
|
void operator()(void* ptr) const;
|
|
};
|
|
|
|
/**
|
|
* Allocate an asn1c struct owned by a unique_ptr that deep-frees it via its descriptor.
|
|
* \param descriptor ASN.1 type descriptor matching T
|
|
* \return owning unique_ptr
|
|
*/
|
|
template<class T>
|
|
std::unique_ptr<T, deleter> make_unique(asn_TYPE_descriptor_t& descriptor)
|
|
{
|
|
return std::unique_ptr<T, deleter> { allocate<T>(), deleter { &descriptor } };
|
|
}
|
|
|
|
/**
|
|
* Allocate an asn1c struct owned by a unique_ptr, taking the type descriptor
|
|
* from the asn1_type_traits specialization of T.
|
|
* \return owning unique_ptr
|
|
*/
|
|
template<class T>
|
|
std::unique_ptr<T, deleter> make_unique()
|
|
{
|
|
return make_unique<T>(asn1_type_traits<T>::descriptor());
|
|
}
|
|
|
|
template<class T>
|
|
class asn1c_wrapper_common
|
|
{
|
|
|
|
public:
|
|
typedef T asn1c_type;
|
|
|
|
asn1c_wrapper_common(asn_TYPE_descriptor_t& desc) :
|
|
m_struct(vanetza::asn1::allocate<asn1c_type>()), m_type(desc) {}
|
|
asn1c_wrapper_common(asn_TYPE_descriptor_t& desc, const T* ptr) :
|
|
m_struct(static_cast<T*>(copy(desc, ptr))), m_type(desc) {}
|
|
~asn1c_wrapper_common() { vanetza::asn1::free(m_type, m_struct); }
|
|
|
|
// copy semantics
|
|
asn1c_wrapper_common(const asn1c_wrapper_common& other) :
|
|
m_struct(static_cast<asn1c_type*>(copy(other.m_type, other.m_struct))), m_type(other.m_type) {}
|
|
asn1c_wrapper_common& operator=(const asn1c_wrapper_common& other)
|
|
{
|
|
asn1c_wrapper_common tmp = other;
|
|
swap(tmp);
|
|
return *this;
|
|
}
|
|
|
|
// move semantics
|
|
asn1c_wrapper_common(asn1c_wrapper_common&& other) noexcept :
|
|
m_struct(nullptr), m_type(other.m_type) { swap(other); }
|
|
asn1c_wrapper_common& operator=(asn1c_wrapper_common&& other) noexcept
|
|
{
|
|
swap(other);
|
|
return *this;
|
|
}
|
|
|
|
// dereferencing
|
|
asn1c_type& operator*() { return *m_struct; }
|
|
asn1c_type* operator->() { return m_struct; }
|
|
const asn1c_type& operator*() const { return *m_struct; }
|
|
const asn1c_type* operator->() const { return m_struct; }
|
|
|
|
// direct access to content structure
|
|
const asn1c_type* content() const { return m_struct; }
|
|
asn1c_type* content() { return m_struct; }
|
|
|
|
// compare semantics
|
|
bool operator==(const asn1c_wrapper_common& rhs) const
|
|
{
|
|
return vanetza::asn1::compare(m_type, m_struct, rhs.m_struct) == 0;
|
|
}
|
|
bool operator!=(const asn1c_wrapper_common& rhs) const
|
|
{
|
|
return vanetza::asn1::compare(m_type, m_struct, rhs.m_struct) != 0;
|
|
}
|
|
|
|
/**
|
|
* Check ASN.1 constraints
|
|
* \param error (optional) copy of error message
|
|
* \return true if valid
|
|
*/
|
|
bool validate() const
|
|
{
|
|
return vanetza::asn1::validate(m_type, m_struct);
|
|
}
|
|
|
|
/**
|
|
* Check ASN.1 constraints
|
|
* \param error Error message if any constraint failed
|
|
* \return true if valid
|
|
*/
|
|
bool validate(std::string& error) const
|
|
{
|
|
return vanetza::asn1::validate(m_type, m_struct, error);
|
|
}
|
|
|
|
/**
|
|
* Compare ASN.1 types
|
|
* \param other Other ASN.1 type to compare with
|
|
* \return 0 if equal, <0 if other is "greater", >0 if other is "smaller"
|
|
*/
|
|
int compare(const asn1c_wrapper_common& other) const
|
|
{
|
|
return vanetza::asn1::compare(m_type, m_struct, other.m_struct);
|
|
}
|
|
|
|
/**
|
|
* Print ASN.1 type to standard output
|
|
* \return 0 on success, -1 on error
|
|
*/
|
|
int print() const
|
|
{
|
|
return vanetza::asn1::print(stdout, m_type, m_struct);
|
|
}
|
|
|
|
/**
|
|
* Print ASN.1 type to some file stream
|
|
* \param stream Output stream
|
|
* \return 0 on success, -1 on error
|
|
*/
|
|
int print(FILE* stream) const
|
|
{
|
|
return vanetza::asn1::print(stream, m_type, m_struct);
|
|
}
|
|
|
|
/**
|
|
* Swap ASN.1 wrapper content
|
|
* \param other wrapper
|
|
*/
|
|
void swap(asn1c_wrapper_common& other) noexcept
|
|
{
|
|
std::swap(m_struct, other.m_struct);
|
|
std::swap(m_type, other.m_type);
|
|
}
|
|
|
|
protected:
|
|
asn1c_type* m_struct;
|
|
asn_TYPE_descriptor_t& m_type;
|
|
};
|
|
|
|
template<typename T>
|
|
void swap(asn1c_wrapper_common<T>& lhs, asn1c_wrapper_common<T>& rhs)
|
|
{
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
|
|
template<class T>
|
|
class asn1c_per_wrapper : public asn1c_wrapper_common<T>
|
|
{
|
|
public:
|
|
using base = asn1c_wrapper_common<T>;
|
|
using base::base;
|
|
|
|
/**
|
|
* Encode ASN.1 struct into byte buffer
|
|
* \return byte buffer containing serialized ASN.1 struct
|
|
*/
|
|
ByteBuffer encode() const
|
|
{
|
|
return vanetza::asn1::encode_per(base::m_type, base::m_struct);
|
|
}
|
|
|
|
/**
|
|
* Try to decode ASN.1 struct from byte buffer
|
|
* \param buffer input data
|
|
* \return true if decoding has been successful
|
|
*/
|
|
bool decode(const ByteBuffer& buffer)
|
|
{
|
|
return vanetza::asn1::decode_per(base::m_type, (void**)&(base::m_struct), buffer);
|
|
}
|
|
|
|
bool decode(ByteBuffer::const_iterator begin, ByteBuffer::const_iterator end)
|
|
{
|
|
return vanetza::asn1::decode_per(base::m_type, (void**)&(base::m_struct), &(*begin), std::distance(begin, end));
|
|
}
|
|
|
|
bool decode(const void* buffer, std::size_t len)
|
|
{
|
|
return vanetza::asn1::decode_per(base::m_type, (void**)&(base::m_struct), buffer, len);
|
|
}
|
|
|
|
/**
|
|
* Get size of encoded ASN.1 struct
|
|
* \return size in bytes
|
|
*/
|
|
std::size_t size() const
|
|
{
|
|
return vanetza::asn1::size_per(base::m_type, base::m_struct);
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
using asn1c_wrapper = asn1c_per_wrapper<T>;
|
|
|
|
|
|
template<class T>
|
|
class asn1c_oer_wrapper : public asn1c_wrapper_common<T>
|
|
{
|
|
public:
|
|
using base = asn1c_wrapper_common<T>;
|
|
using base::base;
|
|
|
|
/**
|
|
* Encode ASN.1 struct into byte buffer
|
|
* \return byte buffer containing serialized ASN.1 struct
|
|
*/
|
|
ByteBuffer encode() const
|
|
{
|
|
return vanetza::asn1::encode_oer(base::m_type, base::m_struct);
|
|
}
|
|
|
|
/**
|
|
* Try to decode ASN.1 struct from byte buffer
|
|
* \param buffer input data
|
|
* \deprecated use decode_per instead
|
|
* \return true if decoding has been successful
|
|
*/
|
|
bool decode(const ByteBuffer& buffer)
|
|
{
|
|
return vanetza::asn1::decode_oer(base::m_type, (void**)&(base::m_struct), buffer);
|
|
}
|
|
|
|
bool decode(ByteBuffer::const_iterator begin, ByteBuffer::const_iterator end)
|
|
{
|
|
return vanetza::asn1::decode_oer(base::m_type, (void**)&(base::m_struct), &(*begin), std::distance(begin, end));
|
|
}
|
|
|
|
bool decode(const void* buffer, std::size_t len)
|
|
{
|
|
return vanetza::asn1::decode_oer(base::m_type, (void**)&(base::m_struct), buffer, len);
|
|
}
|
|
|
|
/**
|
|
* Get size of encoded ASN.1 struct
|
|
* \return size in bytes
|
|
*/
|
|
std::size_t size() const
|
|
{
|
|
return vanetza::asn1::size_oer(base::m_type, base::m_struct);
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
class asn1c_xer_wrapper : public asn1c_wrapper_common<T>
|
|
{
|
|
public:
|
|
using base = asn1c_wrapper_common<T>;
|
|
using base::base;
|
|
|
|
/**
|
|
* Encode ASN.1 struct into byte buffer
|
|
* \return byte buffer containing serialized ASN.1 struct
|
|
*/
|
|
ByteBuffer encode() const
|
|
{
|
|
return vanetza::asn1::encode_xer(base::m_type, base::m_struct);
|
|
}
|
|
|
|
/**
|
|
* Try to decode ASN.1 struct from byte buffer
|
|
* \param buffer input data
|
|
* \return true if decoding has been successful
|
|
*/
|
|
bool decode(const ByteBuffer& buffer)
|
|
{
|
|
return vanetza::asn1::decode_xer(base::m_type, (void**)&(base::m_struct), buffer);
|
|
}
|
|
|
|
bool decode(ByteBuffer::const_iterator begin, ByteBuffer::const_iterator end)
|
|
{
|
|
return vanetza::asn1::decode_xer(base::m_type, (void**)&(base::m_struct), &(*begin), std::distance(begin, end));
|
|
}
|
|
|
|
bool decode(const void* buffer, std::size_t len)
|
|
{
|
|
return vanetza::asn1::decode_xer(base::m_type, (void**)&(base::m_struct), buffer, len);
|
|
}
|
|
|
|
/**
|
|
* Get size of encoded ASN.1 struct
|
|
* \return size in bytes
|
|
*/
|
|
std::size_t size() const
|
|
{
|
|
return vanetza::asn1::size_xer(base::m_type, base::m_struct);
|
|
}
|
|
};
|
|
|
|
} // namespace asn1
|
|
} // namespace vanetza
|
|
|
|
#endif /* ASN1C_WRAPPER_HPP_ZCNDO8E5 */
|
|
|