1#include <vanetza/asn1/support/asn_application.h>
2#include <vanetza/asn1/support/asn_internal.h>
3#include <vanetza/asn1/support/constraints.h>
4#include <vanetza/asn1/support/uper_decoder.h>
5#include <vanetza/asn1/support/uper_encoder.h>
7#include <vanetza/common/byte_buffer.hpp>
8#include <boost/format.hpp>
21static int write_buffer(
const void* in, std::size_t size,
void* out_void)
23 assert(out_void !=
nullptr);
24 auto out =
static_cast<ByteBuffer*>(out_void);
25 std::copy_n(
static_cast<
const uint8_t*>(in), size, std::back_inserter(*out));
29static int write_null(
const void*, std::size_t,
void*)
34void* allocate(std::size_t length)
36 void* ptr = calloc(1, length);
38 throw std::runtime_error(
"Bad ASN.1 memory allocation");
43void free(asn_TYPE_descriptor_t& td,
void* t)
46 ASN_STRUCT_FREE(td, t);
50void deleter::operator()(
void* ptr)
const
52 if (descriptor && ptr) {
53 free(*descriptor, ptr);
57void* copy(asn_TYPE_descriptor_t& td,
const void* original)
63 ec = oer_encode(&td,
const_cast<
void*>(original), write_buffer, &buffer);
64 if (ec.encoded == -1) {
65 throw std::runtime_error(
"OER encoding failed");
69 dc = oer_decode(0, &td, ©, buffer.data(), buffer.size());
70 if (dc.code != RC_OK) {
72 throw std::runtime_error(
"OER decoding failed");
78bool validate(asn_TYPE_descriptor_t& td,
const void* t)
80 return asn_check_constraints(&td, t,
nullptr,
nullptr) == 0;
83bool validate(asn_TYPE_descriptor_t& td,
const void* t, std::string& error)
86 std::size_t errlen =
sizeof(errbuf);
87 bool ok = asn_check_constraints(&td, t, errbuf, &errlen) == 0;
94int compare(asn_TYPE_descriptor_t& td,
const void* a,
const void* b)
96 return td.op->compare_struct(&td, a, b);
99int print(FILE* stream, asn_TYPE_descriptor_t& td,
const void* t)
101 return asn_fprint(stream, &td, t);
104std::size_t size_per(asn_TYPE_descriptor_t& td,
const void* t)
107 ec = uper_encode(&td,
nullptr,
const_cast<
void*>(t), write_null,
nullptr);
108 if (ec.encoded < 0) {
109 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
110 const auto error_msg = boost::format(
111 "Can't determine size for unaligned PER encoding of type %1% because of %2% sub-type")
112 % td.name % failed_type;
113 throw std::runtime_error(error_msg.str());
117 return (ec.encoded + 7) / 8;
120ByteBuffer encode_per(asn_TYPE_descriptor_t& td,
const void* t)
123 asn_enc_rval_t ec = uper_encode(&td,
nullptr,
const_cast<
void*>(t), write_buffer, &buffer);
124 if (ec.encoded == -1) {
125 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
126 const auto error_msg = boost::format(
127 "Unaligned PER encoding of type %1% failed because of %2% sub-type")
128 % td.name % failed_type;
129 throw std::runtime_error(error_msg.str());
134bool decode_per(asn_TYPE_descriptor_t& td,
void** t,
const ByteBuffer& buffer)
136 return decode_per(td, t, buffer.data(), buffer.size());
139bool decode_per(asn_TYPE_descriptor_t& td,
void** t,
const void* buffer, std::size_t size)
141 asn_codec_ctx_t ctx {};
142 ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
143 asn_dec_rval_t ec = uper_decode_complete(&ctx, &td, t, buffer, size);
144 return ec.code == RC_OK;
147std::size_t size_oer(asn_TYPE_descriptor_t& td,
const void* t)
150 ec = oer_encode(&td,
const_cast<
void*>(t), write_null,
nullptr);
151 if (ec.encoded < 0) {
152 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
153 const auto error_msg = boost::format(
154 "Can't determine size for OER encoding of type %1% because of %2% sub-type")
155 % td.name % failed_type;
156 throw std::runtime_error(error_msg.str());
163ByteBuffer encode_oer(asn_TYPE_descriptor_t& td,
const void* t)
166 asn_enc_rval_t ec = oer_encode(&td,
const_cast<
void*>(t), write_buffer, &buffer);
167 if (ec.encoded == -1) {
168 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
169 const auto error_msg = boost::format(
170 "OER encoding of type %1% failed because of %2% sub-type")
171 % td.name % failed_type;
172 throw std::runtime_error(error_msg.str());
177bool decode_oer(asn_TYPE_descriptor_t& td,
void** t,
const ByteBuffer& buffer)
179 return decode_oer(td, t, buffer.data(), buffer.size());
182bool decode_oer(asn_TYPE_descriptor_t& td,
void** t,
const void* buffer, std::size_t size)
184 asn_codec_ctx_t ctx {};
185 ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
186 asn_dec_rval_t ec = oer_decode(&ctx, &td, t, buffer, size);
187 return ec.code == RC_OK;
190std::size_t size_xer(asn_TYPE_descriptor_t& td,
const void* t)
193 ec = xer_encode(&td,
const_cast<
void*>(t), XER_F_BASIC, write_null,
nullptr);
194 if (ec.encoded < 0) {
195 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
196 const auto error_msg = boost::format(
197 "Can't determine size for XER encoding of type %1% because of %2% sub-type")
198 % td.name % failed_type;
199 throw std::runtime_error(error_msg.str());
206ByteBuffer encode_xer(asn_TYPE_descriptor_t& td,
const void* t)
209 asn_enc_rval_t ec = xer_encode(&td,
const_cast<
void*>(t), XER_F_BASIC, write_buffer, &buffer);
210 if (ec.encoded == -1) {
211 const char* failed_type = ec.failed_type ? ec.failed_type->name :
"unknown";
212 const auto error_msg = boost::format(
213 "XER encoding of type %1% failed because of %2% sub-type")
214 % td.name % failed_type;
215 throw std::runtime_error(error_msg.str());
220bool decode_xer(asn_TYPE_descriptor_t& td,
void** t,
const ByteBuffer& buffer)
222 return decode_xer(td, t, buffer.data(), buffer.size());
225bool decode_xer(asn_TYPE_descriptor_t& td,
void** t,
const void* buffer, std::size_t size)
227 asn_codec_ctx_t ctx {};
228 ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
229 asn_dec_rval_t ec = xer_decode(&ctx, &td, t, buffer, size);
230 return ec.code == RC_OK;
Deleter freeing an asn1c struct through its ASN.1 type descriptor.