Vanetza
Loading...
Searching...
No Matches
asn1c_wrapper.cpp
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>
8#include <algorithm>
9#include <cassert>
10#include <iterator>
11#include <memory>
12#include <stdexcept>
13#include <string>
14
15namespace vanetza
16{
17namespace asn1
18{
19
20static int write_buffer(const void* in, std::size_t size, void* out_void)
21{
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));
25 return 0;
26}
27
28static int write_null(const void*, std::size_t, void*)
29{
30 return 0;
31}
32
33void* allocate(std::size_t length)
34{
35 void* ptr = calloc(1, length);
36 if (nullptr == ptr) {
37 throw std::runtime_error("Bad ASN.1 memory allocation");
38 }
39 return ptr;
40}
41
42void free(asn_TYPE_descriptor_t& td, void* t)
43{
44 if (t != nullptr) {
45 ASN_STRUCT_FREE(td, t);
46 }
47}
48
49void* copy(asn_TYPE_descriptor_t& td, const void* original)
50{
51 void* copy = nullptr;
52 ByteBuffer buffer;
53
54 asn_enc_rval_t ec;
55 ec = oer_encode(&td, const_cast<void*>(original), write_buffer, &buffer);
56 if (ec.encoded == -1) {
57 throw std::runtime_error("OER encoding failed");
58 }
59
60 asn_dec_rval_t dc;
61 dc = oer_decode(0, &td, &copy, buffer.data(), buffer.size());
62 if (dc.code != RC_OK) {
63 free(td, copy);
64 throw std::runtime_error("OER decoding failed");
65 }
66
67 return copy;
68}
69
70bool validate(asn_TYPE_descriptor_t& td, const void* t)
71{
72 return asn_check_constraints(&td, t, nullptr, nullptr) == 0;
73}
74
75bool validate(asn_TYPE_descriptor_t& td, const void* t, std::string& error)
76{
77 char errbuf[1024];
78 std::size_t errlen = sizeof(errbuf);
79 bool ok = asn_check_constraints(&td, t, errbuf, &errlen) == 0;
80 if (!ok) {
81 error = errbuf;
82 }
83 return ok;
84}
85
86int compare(asn_TYPE_descriptor_t& td, const void* a, const void* b)
87{
88 return td.op->compare_struct(&td, a, b);
89}
90
91int print(FILE* stream, asn_TYPE_descriptor_t& td, const void* t)
92{
93 return asn_fprint(stream, &td, t);
94}
95
96std::size_t size_per(asn_TYPE_descriptor_t& td, const void* t)
97{
98 asn_enc_rval_t ec;
99 ec = uper_encode(&td, nullptr, const_cast<void*>(t), write_null, nullptr);
100 if (ec.encoded < 0) {
101 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
102 const auto error_msg = boost::format(
103 "Can't determine size for unaligned PER encoding of type %1% because of %2% sub-type")
104 % td.name % failed_type;
105 throw std::runtime_error(error_msg.str());
106 }
107
108 // Caution! ec.encoded are bits not bytes!
109 return (ec.encoded + 7) / 8;
110}
111
112ByteBuffer encode_per(asn_TYPE_descriptor_t& td, const void* t)
113{
114 ByteBuffer buffer;
115 asn_enc_rval_t ec = uper_encode(&td, nullptr, const_cast<void*>(t), write_buffer, &buffer);
116 if (ec.encoded == -1) {
117 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
118 const auto error_msg = boost::format(
119 "Unaligned PER encoding of type %1% failed because of %2% sub-type")
120 % td.name % failed_type;
121 throw std::runtime_error(error_msg.str());
122 }
123 return buffer;
124}
125
126bool decode_per(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
127{
128 return decode_per(td, t, buffer.data(), buffer.size());
129}
130
131bool decode_per(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
132{
133 asn_codec_ctx_t ctx {};
134 asn_dec_rval_t ec = uper_decode_complete(&ctx, &td, t, buffer, size);
135 return ec.code == RC_OK;
136}
137
138std::size_t size_oer(asn_TYPE_descriptor_t& td, const void* t)
139{
140 asn_enc_rval_t ec;
141 ec = oer_encode(&td, const_cast<void*>(t), write_null, nullptr);
142 if (ec.encoded < 0) {
143 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
144 const auto error_msg = boost::format(
145 "Can't determine size for OER encoding of type %1% because of %2% sub-type")
146 % td.name % failed_type;
147 throw std::runtime_error(error_msg.str());
148 }
149
150 // ec.encoded are bytes for OER encoding
151 return ec.encoded;
152}
153
154ByteBuffer encode_oer(asn_TYPE_descriptor_t& td, const void* t)
155{
156 ByteBuffer buffer;
157 asn_enc_rval_t ec = oer_encode(&td, const_cast<void*>(t), write_buffer, &buffer);
158 if (ec.encoded == -1) {
159 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
160 const auto error_msg = boost::format(
161 "OER encoding of type %1% failed because of %2% sub-type")
162 % td.name % failed_type;
163 throw std::runtime_error(error_msg.str());
164 }
165 return buffer;
166}
167
168bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
169{
170 return decode_oer(td, t, buffer.data(), buffer.size());
171}
172
173bool decode_oer(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
174{
175 asn_codec_ctx_t ctx {};
176 asn_dec_rval_t ec = oer_decode(&ctx, &td, t, buffer, size);
177 return ec.code == RC_OK;
178}
179
180std::size_t size_xer(asn_TYPE_descriptor_t& td, const void* t)
181{
182 asn_enc_rval_t ec;
183 ec = xer_encode(&td, const_cast<void*>(t), XER_F_BASIC, write_null, nullptr);
184 if (ec.encoded < 0) {
185 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
186 const auto error_msg = boost::format(
187 "Can't determine size for XER encoding of type %1% because of %2% sub-type")
188 % td.name % failed_type;
189 throw std::runtime_error(error_msg.str());
190 }
191
192 // ec.encoded are bytes for XER encoding
193 return ec.encoded;
194}
195
196ByteBuffer encode_xer(asn_TYPE_descriptor_t& td, const void* t)
197{
198 ByteBuffer buffer;
199 asn_enc_rval_t ec = xer_encode(&td, const_cast<void*>(t), XER_F_BASIC, write_buffer, &buffer);
200 if (ec.encoded == -1) {
201 const char* failed_type = ec.failed_type ? ec.failed_type->name : "unknown";
202 const auto error_msg = boost::format(
203 "XER encoding of type %1% failed because of %2% sub-type")
204 % td.name % failed_type;
205 throw std::runtime_error(error_msg.str());
206 }
207 return buffer;
208}
209
210bool decode_xer(asn_TYPE_descriptor_t& td, void** t, const ByteBuffer& buffer)
211{
212 return decode_xer(td, t, buffer.data(), buffer.size());
213}
214
215bool decode_xer(asn_TYPE_descriptor_t& td, void** t, const void* buffer, std::size_t size)
216{
217 asn_codec_ctx_t ctx {};
218 asn_dec_rval_t ec = xer_decode(&ctx, &td, t, buffer, size);
219 return ec.code == RC_OK;
220}
221
222} // namespace asn1
223} // namespace vanetza
224