Vanetza
Loading...
Searching...
No Matches
asn1c_wrapper.cpp
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>
9#include <algorithm>
10#include <cassert>
11#include <cstdlib>
12#include <iterator>
13#include <stdexcept>
14#include <string>
15
16namespace vanetza
17{
18namespace asn1
19{
20
21static int write_buffer(const void* in, std::size_t size, void* out_void)
22{
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));
26 return 0;
27}
28
29static int write_null(const void*, std::size_t, void*)
30{
31 return 0;
32}
33
34void* allocate(std::size_t length)
35{
36 void* ptr = calloc(1, length);
37 if (nullptr == ptr) {
38 throw std::runtime_error("Bad ASN.1 memory allocation");
39 }
40 return ptr;
41}
42
43void free(asn_TYPE_descriptor_t& td, void* t)
44{
45 if (t != nullptr) {
46 ASN_STRUCT_FREE(td, t);
47 }
48}
49
50void deleter::operator()(void* ptr) const
51{
52 if (descriptor && ptr) {
53 free(*descriptor, ptr);
54 }
55}
56
57void* copy(asn_TYPE_descriptor_t& td, const void* original)
58{
59 void* copy = nullptr;
60 ByteBuffer buffer;
61
62 asn_enc_rval_t ec;
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");
66 }
67
68 asn_dec_rval_t dc;
69 dc = oer_decode(0, &td, &copy, buffer.data(), buffer.size());
70 if (dc.code != RC_OK) {
71 free(td, copy);
72 throw std::runtime_error("OER decoding failed");
73 }
74
75 return copy;
76}
77
78bool validate(asn_TYPE_descriptor_t& td, const void* t)
79{
80 return asn_check_constraints(&td, t, nullptr, nullptr) == 0;
81}
82
83bool validate(asn_TYPE_descriptor_t& td, const void* t, std::string& error)
84{
85 char errbuf[1024];
86 std::size_t errlen = sizeof(errbuf);
87 bool ok = asn_check_constraints(&td, t, errbuf, &errlen) == 0;
88 if (!ok) {
89 error = errbuf;
90 }
91 return ok;
92}
93
94int compare(asn_TYPE_descriptor_t& td, const void* a, const void* b)
95{
96 return td.op->compare_struct(&td, a, b);
97}
98
99int print(FILE* stream, asn_TYPE_descriptor_t& td, const void* t)
100{
101 return asn_fprint(stream, &td, t);
102}
103
104std::size_t size_per(asn_TYPE_descriptor_t& td, const void* t)
105{
106 asn_enc_rval_t ec;
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());
114 }
115
116 // Caution! ec.encoded are bits not bytes!
117 return (ec.encoded + 7) / 8;
118}
119
120ByteBuffer encode_per(asn_TYPE_descriptor_t& td, const void* t)
121{
122 ByteBuffer buffer;
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());
130 }
131 return buffer;
132}
133
134bool decode_per(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
135{
136 return decode_per(td, t, buffer.data(), buffer.size());
137}
138
139bool decode_per(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
140{
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;
145}
146
147std::size_t size_oer(asn_TYPE_descriptor_t& td, const void* t)
148{
149 asn_enc_rval_t ec;
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());
157 }
158
159 // ec.encoded are bytes for OER encoding
160 return ec.encoded;
161}
162
163ByteBuffer encode_oer(asn_TYPE_descriptor_t& td, const void* t)
164{
165 ByteBuffer buffer;
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());
173 }
174 return buffer;
175}
176
177bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
178{
179 return decode_oer(td, t, buffer.data(), buffer.size());
180}
181
182bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
183{
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;
188}
189
190std::size_t size_xer(asn_TYPE_descriptor_t& td, const void* t)
191{
192 asn_enc_rval_t ec;
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());
200 }
201
202 // ec.encoded are bytes for XER encoding
203 return ec.encoded;
204}
205
206ByteBuffer encode_xer(asn_TYPE_descriptor_t& td, const void* t)
207{
208 ByteBuffer buffer;
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());
216 }
217 return buffer;
218}
219
220bool decode_xer(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
221{
222 return decode_xer(td, t, buffer.data(), buffer.size());
223}
224
225bool decode_xer(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
226{
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;
231}
232
233} // namespace asn1
234} // namespace vanetza
Deleter freeing an asn1c struct through its ASN.1 type descriptor.