1#include <vanetza/asn1/support/asn_application.h>
2#include <vanetza/asn1/support/constraints.h>
3#include <vanetza/asn1/support/uper_decoder.h>
4#include <vanetza/asn1/support/uper_encoder.h>
5#include "asn1c_wrapper.hpp"
6#include <vanetza/common/byte_buffer.hpp>
7#include <boost/format.hpp>
20static int write_buffer(
const void* in, std::size_t size,
void* out_void)
22 assert(out_void !=
nullptr);
23 auto out =
static_cast<ByteBuffer*
>(out_void);
24 std::copy_n(
static_cast<const uint8_t*
>(in), size, std::back_inserter(*out));
28static int write_null(
const void*, std::size_t,
void*)
33void* allocate(std::size_t length)
35 void* ptr = calloc(1, length);
37 throw std::runtime_error(
"Bad ASN.1 memory allocation");
42void free(asn_TYPE_descriptor_t& td,
void* t)
45 ASN_STRUCT_FREE(td, t);
49void* copy(asn_TYPE_descriptor_t& td,
const void* original)
55 ec = der_encode(&td,
const_cast<void*
>(original), write_buffer, &buffer);
56 if (ec.encoded == -1) {
57 throw std::runtime_error(
"DER encoding failed");
61 dc = ber_decode(0, &td, ©, buffer.data(), buffer.size());
62 if (dc.code != RC_OK) {
64 throw std::runtime_error(
"BER decoding failed");
70bool validate(asn_TYPE_descriptor_t& td,
const void* t)
72 return asn_check_constraints(&td, t,
nullptr,
nullptr) == 0;
75bool validate(asn_TYPE_descriptor_t& td,
const void* t, std::string& error)
78 std::size_t errlen =
sizeof(errbuf);
79 bool ok = asn_check_constraints(&td, t, errbuf, &errlen) == 0;
86std::size_t size_per(asn_TYPE_descriptor_t& td,
const void* t)
89 ec = uper_encode(&td,
nullptr,
const_cast<void*
>(t), write_null,
nullptr);
91 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
92 const auto error_msg = boost::format(
93 "Can't determine size for unaligned PER encoding of type %1% because of %2% sub-type")
94 % td.name % failed_type;
95 throw std::runtime_error(error_msg.str());
99 return (ec.encoded + 7) / 8;
102ByteBuffer encode_per(asn_TYPE_descriptor_t& td,
const void* t)
105 asn_enc_rval_t ec = uper_encode(&td,
nullptr,
const_cast<void*
>(t), write_buffer, &buffer);
106 if (ec.encoded == -1) {
107 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
108 const auto error_msg = boost::format(
109 "Unaligned PER encoding of type %1% failed because of %2% sub-type")
110 % td.name % failed_type;
111 throw std::runtime_error(error_msg.str());
116bool decode_per(asn_TYPE_descriptor_t& td,
void** t,
const ByteBuffer& buffer)
118 return decode_per(td, t, buffer.data(), buffer.size());
121bool decode_per(asn_TYPE_descriptor_t& td,
void** t,
const void* buffer, std::size_t size)
123 asn_codec_ctx_t ctx {};
124 asn_dec_rval_t ec = uper_decode_complete(&ctx, &td, t, buffer, size);
125 return ec.code == RC_OK;
128std::size_t size_oer(asn_TYPE_descriptor_t& td,
const void* t)
131 ec = oer_encode(&td,
const_cast<void*
>(t), write_null,
nullptr);
132 if (ec.encoded < 0) {
133 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
134 const auto error_msg = boost::format(
135 "Can't determine size for OER encoding of type %1% because of %2% sub-type")
136 % td.name % failed_type;
137 throw std::runtime_error(error_msg.str());
141 return (ec.encoded + 7) / 8;
144ByteBuffer encode_oer(asn_TYPE_descriptor_t& td,
const void* t)
147 asn_enc_rval_t ec = oer_encode(&td,
const_cast<void*
>(t), write_buffer, &buffer);
148 if (ec.encoded == -1) {
149 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
150 const auto error_msg = boost::format(
151 "OER encoding of type %1% failed because of %2% sub-type")
152 % td.name % failed_type;
153 throw std::runtime_error(error_msg.str());
158bool decode_oer(asn_TYPE_descriptor_t& td,
void** t,
const ByteBuffer& buffer)
160 return decode_oer(td, t, buffer.data(), buffer.size());
163bool decode_oer(asn_TYPE_descriptor_t& td,
void** t,
const void* buffer, std::size_t size)
165 asn_codec_ctx_t ctx {};
166 asn_dec_rval_t ec = oer_decode(&ctx, &td, t, buffer, size);
167 return ec.code == RC_OK;