2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
\r
3 * Redistribution and modifications are permitted subject to BSD license.
\r
5 #include <asn_internal.h>
\r
6 #include <asn_application.h>
\r
9 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
\r
10 enum asn_transfer_syntax syntax,
\r
11 const asn_TYPE_descriptor_t *td,
\r
13 asn_app_consume_bytes_f *callback,
\r
14 void *callback_key);
\r
17 struct callback_count_bytes_key {
\r
18 asn_app_consume_bytes_f *callback;
\r
20 size_t computed_size;
\r
24 * Encoder which just counts bytes that come through it.
\r
27 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
\r
28 struct callback_count_bytes_key *key = keyp;
\r
31 ret = key->callback(data, size, key->callback_key);
\r
33 key->computed_size += size;
\r
39 struct overrun_encoder_key {
\r
42 size_t computed_size;
\r
45 struct dynamic_encoder_key {
\r
48 size_t computed_size;
\r
51 struct callback_failure_catch_key {
\r
52 asn_app_consume_bytes_f *callback;
\r
54 int callback_failed;
\r
58 * Encoder which doesn't stop counting bytes
\r
59 * even if it reaches the end of the buffer.
\r
62 overrun_encoder_cb(const void *data, size_t size, void *keyp) {
\r
63 struct overrun_encoder_key *key = keyp;
\r
65 if(key->computed_size + size > key->buffer_size) {
\r
67 * Avoid accident on the next call:
\r
68 * stop adding bytes to the buffer.
\r
70 key->buffer_size = 0;
\r
72 memcpy((char *)key->buffer + key->computed_size, data, size);
\r
74 key->computed_size += size;
\r
80 * Encoder which dynamically allocates output, and continues
\r
81 * to count even if allocation failed.
\r
84 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
\r
85 struct dynamic_encoder_key *key = keyp;
\r
88 if(key->computed_size + size >= key->buffer_size) {
\r
90 size_t new_size = key->buffer_size;
\r
94 } while(new_size <= key->computed_size + size);
\r
96 p = REALLOC(key->buffer, new_size);
\r
99 key->buffer_size = new_size;
\r
101 FREEMEM(key->buffer);
\r
103 key->buffer_size = 0;
\r
104 key->computed_size += size;
\r
108 memcpy((char *)key->buffer + key->computed_size, data, size);
\r
111 key->computed_size += size;
\r
117 * Encoder which help convert the application level encoder failure into EIO.
\r
120 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
\r
121 struct callback_failure_catch_key *key = keyp;
\r
124 ret = key->callback(data, size, key->callback_key);
\r
126 key->callback_failed = 1;
\r
133 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
\r
134 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
\r
135 const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
\r
136 struct callback_failure_catch_key cb_key;
\r
137 asn_enc_rval_t er = {0,0,0};
\r
141 ASN__ENCODE_FAILED;
\r
144 cb_key.callback = callback;
\r
145 cb_key.callback_key = callback_key;
\r
146 cb_key.callback_failed = 0;
\r
148 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
\r
149 callback_failure_catch_cb, &cb_key);
\r
150 if(cb_key.callback_failed) {
\r
151 assert(er.encoded == -1);
\r
152 assert(errno == EBADF);
\r
160 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
\r
161 enum asn_transfer_syntax syntax,
\r
162 const asn_TYPE_descriptor_t *td, const void *sptr,
\r
163 void *buffer, size_t buffer_size) {
\r
164 struct overrun_encoder_key buf_key;
\r
165 asn_enc_rval_t er = {0,0,0};
\r
167 if(buffer_size > 0 && !buffer) {
\r
169 ASN__ENCODE_FAILED;
\r
172 buf_key.buffer = buffer;
\r
173 buf_key.buffer_size = buffer_size;
\r
174 buf_key.computed_size = 0;
\r
176 er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
\r
177 overrun_encoder_cb, &buf_key);
\r
179 if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
\r
180 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
\r
181 " yet produced %" ASN_PRI_SIZE " bytes",
\r
182 er.encoded, buf_key.computed_size);
\r
183 assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
\r
189 asn_encode_to_new_buffer_result_t
\r
190 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
\r
191 enum asn_transfer_syntax syntax,
\r
192 const asn_TYPE_descriptor_t *td, const void *sptr) {
\r
193 struct dynamic_encoder_key buf_key;
\r
194 asn_encode_to_new_buffer_result_t res;
\r
196 buf_key.buffer_size = 16;
\r
197 buf_key.buffer = MALLOC(buf_key.buffer_size);
\r
198 buf_key.computed_size = 0;
\r
200 res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
\r
201 dynamic_encoder_cb, &buf_key);
\r
203 if(res.result.encoded >= 0
\r
204 && (size_t)res.result.encoded != buf_key.computed_size) {
\r
205 ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
\r
206 " yet produced %" ASN_PRI_SIZE " bytes",
\r
207 res.result.encoded, buf_key.computed_size);
\r
208 assert(res.result.encoded < 0
\r
209 || (size_t)res.result.encoded == buf_key.computed_size);
\r
212 res.buffer = buf_key.buffer;
\r
214 /* 0-terminate just in case. */
\r
216 assert(buf_key.computed_size < buf_key.buffer_size);
\r
217 ((char *)res.buffer)[buf_key.computed_size] = '\0';
\r
223 static asn_enc_rval_t
\r
224 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
\r
225 enum asn_transfer_syntax syntax,
\r
226 const asn_TYPE_descriptor_t *td, const void *sptr,
\r
227 asn_app_consume_bytes_f *callback, void *callback_key) {
\r
228 asn_enc_rval_t er = {0,0,0};
\r
229 enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
\r
231 (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
\r
235 ASN__ENCODE_FAILED;
\r
239 case ATS_NONSTANDARD_PLAINTEXT:
\r
240 if(td->op->print_struct) {
\r
241 struct callback_count_bytes_key cb_key;
\r
242 cb_key.callback = callback;
\r
243 cb_key.callback_key = callback_key;
\r
244 cb_key.computed_size = 0;
\r
245 if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
\r
248 || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
\r
249 errno = EBADF; /* Structure has incorrect form. */
\r
251 er.failed_type = td;
\r
252 er.structure_ptr = sptr;
\r
254 er.encoded = cb_key.computed_size;
\r
255 er.failed_type = 0;
\r
256 er.structure_ptr = 0;
\r
259 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
260 ASN__ENCODE_FAILED;
\r
265 errno = ENOENT; /* Randomization doesn't make sense on output. */
\r
266 ASN__ENCODE_FAILED;
\r
269 /* BER is a superset of DER. */
\r
270 /* Fall through. */
\r
272 if(td->op->der_encoder) {
\r
273 er = der_encode(td, sptr, callback, callback_key);
\r
274 if(er.encoded == -1) {
\r
275 if(er.failed_type && er.failed_type->op->der_encoder) {
\r
276 errno = EBADF; /* Structure has incorrect form. */
\r
278 errno = ENOENT; /* DER is not defined for this type. */
\r
282 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
283 ASN__ENCODE_FAILED;
\r
287 errno = ENOENT; /* Transfer syntax is not defined for any type. */
\r
288 ASN__ENCODE_FAILED;
\r
290 #ifdef ASN_DISABLE_OER_SUPPORT
\r
291 case ATS_BASIC_OER:
\r
292 case ATS_CANONICAL_OER:
\r
293 errno = ENOENT; /* PER is not defined. */
\r
294 ASN__ENCODE_FAILED;
\r
296 #else /* ASN_DISABLE_OER_SUPPORT */
\r
297 case ATS_BASIC_OER:
\r
298 /* CANONICAL-OER is a superset of BASIC-OER. */
\r
299 /* Fall through. */
\r
300 case ATS_CANONICAL_OER:
\r
301 if(td->op->oer_encoder) {
\r
302 er = oer_encode(td, sptr, callback, callback_key);
\r
303 if(er.encoded == -1) {
\r
304 if(er.failed_type && er.failed_type->op->oer_encoder) {
\r
305 errno = EBADF; /* Structure has incorrect form. */
\r
307 errno = ENOENT; /* OER is not defined for this type. */
\r
311 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
312 ASN__ENCODE_FAILED;
\r
315 #endif /* ASN_DISABLE_OER_SUPPORT */
\r
317 #ifdef ASN_DISABLE_PER_SUPPORT
\r
318 case ATS_UNALIGNED_BASIC_PER:
\r
319 case ATS_UNALIGNED_CANONICAL_PER:
\r
320 case ATS_ALIGNED_BASIC_PER:
\r
321 case ATS_ALIGNED_CANONICAL_PER:
\r
322 errno = ENOENT; /* PER is not defined. */
\r
323 ASN__ENCODE_FAILED;
\r
325 #else /* ASN_DISABLE_PER_SUPPORT */
\r
326 case ATS_UNALIGNED_BASIC_PER:
\r
327 /* CANONICAL-UPER is a superset of BASIC-UPER. */
\r
328 /* Fall through. */
\r
329 case ATS_UNALIGNED_CANONICAL_PER:
\r
330 if(td->op->uper_encoder) {
\r
331 er = uper_encode(td, 0, sptr, callback, callback_key);
\r
332 if(er.encoded == -1) {
\r
333 if(er.failed_type && er.failed_type->op->uper_encoder) {
\r
334 errno = EBADF; /* Structure has incorrect form. */
\r
336 errno = ENOENT; /* UPER is not defined for this type. */
\r
339 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
\r
340 if(er.encoded == 0) {
\r
341 /* Enforce "Complete Encoding" of X.691 #11.1 */
\r
342 if(callback("\0", 1, callback_key) < 0) {
\r
344 ASN__ENCODE_FAILED;
\r
346 er.encoded = 8; /* Exactly 8 zero bits is added. */
\r
348 /* Convert bits into bytes */
\r
349 er.encoded = (er.encoded + 7) >> 3;
\r
352 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
353 ASN__ENCODE_FAILED;
\r
356 case ATS_ALIGNED_BASIC_PER:
\r
357 /* CANONICAL-APER is a superset of BASIC-APER. */
\r
358 /* Fall through. */
\r
359 case ATS_ALIGNED_CANONICAL_PER:
\r
360 if(td->op->aper_encoder) {
\r
361 er = aper_encode(td, 0, sptr, callback, callback_key);
\r
362 if(er.encoded == -1) {
\r
363 if(er.failed_type && er.failed_type->op->aper_encoder) {
\r
364 errno = EBADF; /* Structure has incorrect form. */
\r
366 errno = ENOENT; /* APER is not defined for this type. */
\r
369 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
\r
370 if(er.encoded == 0) {
\r
371 /* Enforce "Complete Encoding" of X.691 #11.1 */
\r
372 if(callback("\0", 1, callback_key) < 0) {
\r
374 ASN__ENCODE_FAILED;
\r
376 er.encoded = 8; /* Exactly 8 zero bits is added. */
\r
378 /* Convert bits into bytes */
\r
379 er.encoded = (er.encoded + 7) >> 3;
\r
382 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
383 ASN__ENCODE_FAILED;
\r
386 #endif /* ASN_DISABLE_PER_SUPPORT */
\r
388 case ATS_BASIC_XER:
\r
389 /* CANONICAL-XER is a superset of BASIC-XER. */
\r
390 xer_flags &= ~XER_F_CANONICAL;
\r
391 xer_flags |= XER_F_BASIC;
\r
392 /* Fall through. */
\r
393 case ATS_CANONICAL_XER:
\r
394 if(td->op->xer_encoder) {
\r
395 er = xer_encode(td, sptr, xer_flags, callback, callback_key);
\r
396 if(er.encoded == -1) {
\r
397 if(er.failed_type && er.failed_type->op->xer_encoder) {
\r
398 errno = EBADF; /* Structure has incorrect form. */
\r
400 errno = ENOENT; /* XER is not defined for this type. */
\r
404 errno = ENOENT; /* Transfer syntax is not defined for this type. */
\r
405 ASN__ENCODE_FAILED;
\r
411 ASN__ENCODE_FAILED;
\r
418 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
\r
419 enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
\r
420 void **sptr, const void *buffer, size_t size) {
\r
421 if(!td || !td->op || !sptr || (size && !buffer)) {
\r
422 ASN__DECODE_FAILED;
\r
427 case ATS_NONSTANDARD_PLAINTEXT:
\r
430 ASN__DECODE_FAILED;
\r
433 if(!td->op->random_fill) {
\r
434 ASN__DECODE_FAILED;
\r
436 if(asn_random_fill(td, sptr, 16000) == 0) {
\r
437 asn_dec_rval_t ret = {RC_OK, 0};
\r
440 ASN__DECODE_FAILED;
\r
447 return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
\r
449 case ATS_BASIC_OER:
\r
450 case ATS_CANONICAL_OER:
\r
451 #ifdef ASN_DISABLE_OER_SUPPORT
\r
453 ASN__DECODE_FAILED;
\r
455 return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
\r
458 case ATS_UNALIGNED_BASIC_PER:
\r
459 case ATS_UNALIGNED_CANONICAL_PER:
\r
460 #ifdef ASN_DISABLE_PER_SUPPORT
\r
462 ASN__DECODE_FAILED;
\r
464 return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
\r
467 case ATS_ALIGNED_BASIC_PER:
\r
468 case ATS_ALIGNED_CANONICAL_PER:
\r
469 #ifdef ASN_DISABLE_PER_SUPPORT
\r
471 ASN__DECODE_FAILED;
\r
473 return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
\r
476 case ATS_BASIC_XER:
\r
477 case ATS_CANONICAL_XER:
\r
478 return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
\r