3 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <asn_application.h>
10 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
11 enum asn_transfer_syntax syntax,
12 const asn_TYPE_descriptor_t *td,
14 asn_app_consume_bytes_f *callback,
18 struct callback_count_bytes_key {
19 asn_app_consume_bytes_f *callback;
25 * Encoder which just counts bytes that come through it.
28 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
29 struct callback_count_bytes_key *key = keyp;
32 ret = key->callback(data, size, key->callback_key);
34 key->computed_size += size;
40 struct overrun_encoder_key {
46 struct dynamic_encoder_key {
52 struct callback_failure_catch_key {
53 asn_app_consume_bytes_f *callback;
59 * Encoder which doesn't stop counting bytes
60 * even if it reaches the end of the buffer.
63 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
64 struct overrun_encoder_key *key = keyp;
66 if(key->computed_size + size > key->buffer_size) {
68 * Avoid accident on the next call:
69 * stop adding bytes to the buffer.
73 memcpy((char *)key->buffer + key->computed_size, data, size);
75 key->computed_size += size;
81 * Encoder which dynamically allocates output, and continues
82 * to count even if allocation failed.
85 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
86 struct dynamic_encoder_key *key = keyp;
89 if(key->computed_size + size >= key->buffer_size) {
91 size_t new_size = key->buffer_size;
95 } while(new_size <= key->computed_size + size);
97 p = REALLOC(key->buffer, new_size);
100 key->buffer_size = new_size;
102 FREEMEM(key->buffer);
104 key->buffer_size = 0;
105 key->computed_size += size;
109 memcpy((char *)key->buffer + key->computed_size, data, size);
112 key->computed_size += size;
118 * Encoder which help convert the application level encoder failure into EIO.
121 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
122 struct callback_failure_catch_key *key = keyp;
125 ret = key->callback(data, size, key->callback_key);
127 key->callback_failed = 1;
134 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
135 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
136 const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
137 struct callback_failure_catch_key cb_key;
138 asn_enc_rval_t er = {0,0,0};
145 cb_key.callback = callback;
146 cb_key.callback_key = callback_key;
147 cb_key.callback_failed = 0;
149 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
150 callback_failure_catch_cb, &cb_key);
151 if(cb_key.callback_failed) {
152 assert(er.encoded == -1);
153 assert(errno == EBADF);
161 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
162 enum asn_transfer_syntax syntax,
163 const asn_TYPE_descriptor_t *td, const void *sptr,
164 void *buffer, size_t buffer_size) {
165 struct overrun_encoder_key buf_key;
166 asn_enc_rval_t er = {0,0,0};
168 if(buffer_size > 0 && !buffer) {
173 buf_key.buffer = buffer;
174 buf_key.buffer_size = buffer_size;
175 buf_key.computed_size = 0;
177 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
178 overrun_encoder_cb, &buf_key);
180 if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
181 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
182 " yet produced %" ASN_PRI_SIZE " bytes",
183 er.encoded, buf_key.computed_size);
184 assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
190 asn_encode_to_new_buffer_result_t
191 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
192 enum asn_transfer_syntax syntax,
193 const asn_TYPE_descriptor_t *td, const void *sptr) {
194 struct dynamic_encoder_key buf_key;
195 asn_encode_to_new_buffer_result_t res;
197 buf_key.buffer_size = 16;
198 buf_key.buffer = MALLOC(buf_key.buffer_size);
199 buf_key.computed_size = 0;
201 res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
202 dynamic_encoder_cb, &buf_key);
204 if(res.result.encoded >= 0
205 && (size_t)res.result.encoded != buf_key.computed_size) {
206 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
207 " yet produced %" ASN_PRI_SIZE " bytes",
208 res.result.encoded, buf_key.computed_size);
209 assert(res.result.encoded < 0
210 || (size_t)res.result.encoded == buf_key.computed_size);
213 res.buffer = buf_key.buffer;
215 /* 0-terminate just in case. */
217 assert(buf_key.computed_size < buf_key.buffer_size);
218 ((char *)res.buffer)[buf_key.computed_size] = '\0';
224 static asn_enc_rval_t
225 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
226 enum asn_transfer_syntax syntax,
227 const asn_TYPE_descriptor_t *td, const void *sptr,
228 asn_app_consume_bytes_f *callback, void *callback_key) {
229 asn_enc_rval_t er = {0,0,0};
230 enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
232 (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
240 case ATS_NONSTANDARD_PLAINTEXT:
241 if(td->op->print_struct) {
242 struct callback_count_bytes_key cb_key;
243 cb_key.callback = callback;
244 cb_key.callback_key = callback_key;
245 cb_key.computed_size = 0;
246 if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
249 || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
250 errno = EBADF; /* Structure has incorrect form. */
253 er.structure_ptr = sptr;
255 er.encoded = cb_key.computed_size;
257 er.structure_ptr = 0;
260 errno = ENOENT; /* Transfer syntax is not defined for this type. */
266 errno = ENOENT; /* Randomization doesn't make sense on output. */
270 /* BER is a superset of DER. */
273 if(td->op->der_encoder) {
274 er = der_encode(td, sptr, callback, callback_key);
275 if(er.encoded == -1) {
276 if(er.failed_type && er.failed_type->op->der_encoder) {
277 errno = EBADF; /* Structure has incorrect form. */
279 errno = ENOENT; /* DER is not defined for this type. */
283 errno = ENOENT; /* Transfer syntax is not defined for this type. */
288 errno = ENOENT; /* Transfer syntax is not defined for any type. */
291 #ifdef ASN_DISABLE_OER_SUPPORT
293 case ATS_CANONICAL_OER:
294 errno = ENOENT; /* PER is not defined. */
297 #else /* ASN_DISABLE_OER_SUPPORT */
299 /* CANONICAL-OER is a superset of BASIC-OER. */
301 case ATS_CANONICAL_OER:
302 if(td->op->oer_encoder) {
303 er = oer_encode(td, sptr, callback, callback_key);
304 if(er.encoded == -1) {
305 if(er.failed_type && er.failed_type->op->oer_encoder) {
306 errno = EBADF; /* Structure has incorrect form. */
308 errno = ENOENT; /* OER is not defined for this type. */
312 errno = ENOENT; /* Transfer syntax is not defined for this type. */
316 #endif /* ASN_DISABLE_OER_SUPPORT */
318 #ifdef ASN_DISABLE_PER_SUPPORT
319 case ATS_UNALIGNED_BASIC_PER:
320 case ATS_UNALIGNED_CANONICAL_PER:
321 case ATS_ALIGNED_BASIC_PER:
322 case ATS_ALIGNED_CANONICAL_PER:
323 errno = ENOENT; /* PER is not defined. */
326 #else /* ASN_DISABLE_PER_SUPPORT */
327 case ATS_UNALIGNED_BASIC_PER:
328 /* CANONICAL-UPER is a superset of BASIC-UPER. */
330 case ATS_UNALIGNED_CANONICAL_PER:
331 if(td->op->uper_encoder) {
332 er = uper_encode(td, 0, sptr, callback, callback_key);
333 if(er.encoded == -1) {
334 if(er.failed_type && er.failed_type->op->uper_encoder) {
335 errno = EBADF; /* Structure has incorrect form. */
337 errno = ENOENT; /* UPER is not defined for this type. */
340 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
341 if(er.encoded == 0) {
342 /* Enforce "Complete Encoding" of X.691 #11.1 */
343 if(callback("\0", 1, callback_key) < 0) {
347 er.encoded = 8; /* Exactly 8 zero bits is added. */
349 /* Convert bits into bytes */
350 er.encoded = (er.encoded + 7) >> 3;
353 errno = ENOENT; /* Transfer syntax is not defined for this type. */
357 case ATS_ALIGNED_BASIC_PER:
358 /* CANONICAL-APER is a superset of BASIC-APER. */
360 case ATS_ALIGNED_CANONICAL_PER:
361 if(td->op->aper_encoder) {
362 er = aper_encode(td, 0, sptr, callback, callback_key);
363 if(er.encoded == -1) {
364 if(er.failed_type && er.failed_type->op->aper_encoder) {
365 errno = EBADF; /* Structure has incorrect form. */
367 errno = ENOENT; /* APER is not defined for this type. */
370 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
371 if(er.encoded == 0) {
372 /* Enforce "Complete Encoding" of X.691 #11.1 */
373 if(callback("\0", 1, callback_key) < 0) {
377 er.encoded = 8; /* Exactly 8 zero bits is added. */
379 /* Convert bits into bytes */
380 er.encoded = (er.encoded + 7) >> 3;
383 errno = ENOENT; /* Transfer syntax is not defined for this type. */
387 #endif /* ASN_DISABLE_PER_SUPPORT */
390 /* CANONICAL-XER is a superset of BASIC-XER. */
391 xer_flags &= ~XER_F_CANONICAL;
392 xer_flags |= XER_F_BASIC;
394 case ATS_CANONICAL_XER:
395 if(td->op->xer_encoder) {
396 er = xer_encode(td, sptr, xer_flags, callback, callback_key);
397 if(er.encoded == -1) {
398 if(er.failed_type && er.failed_type->op->xer_encoder) {
399 errno = EBADF; /* Structure has incorrect form. */
401 errno = ENOENT; /* XER is not defined for this type. */
405 errno = ENOENT; /* Transfer syntax is not defined for this type. */
419 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
420 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
421 void **sptr, const void *buffer, size_t size) {
422 if(!td || !td->op || !sptr || (size && !buffer)) {
428 case ATS_NONSTANDARD_PLAINTEXT:
434 if(!td->op->random_fill) {
437 if(asn_random_fill(td, sptr, 16000) == 0) {
438 asn_dec_rval_t ret = {RC_OK, 0};
448 return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
451 case ATS_CANONICAL_OER:
452 #ifdef ASN_DISABLE_OER_SUPPORT
456 return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
459 case ATS_UNALIGNED_BASIC_PER:
460 case ATS_UNALIGNED_CANONICAL_PER:
461 #ifdef ASN_DISABLE_PER_SUPPORT
465 return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
468 case ATS_ALIGNED_BASIC_PER:
469 case ATS_ALIGNED_CANONICAL_PER:
470 #ifdef ASN_DISABLE_PER_SUPPORT
474 return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
478 case ATS_CANONICAL_XER:
479 return xer_decode(opt_codec_ctx, td, sptr, buffer, size);