diff --git a/skeletons/OPEN_TYPE.c b/skeletons/OPEN_TYPE.c index 8886f0a02..396a568a9 100644 --- a/skeletons/OPEN_TYPE.c +++ b/skeletons/OPEN_TYPE.c @@ -400,5 +400,117 @@ OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td, ASN__ENCODED_OK(er); } +asn_dec_rval_t +OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *td, void *sptr, + const asn_TYPE_member_t *elm, asn_per_data_t *pd) { + asn_type_selector_result_t selected; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + void *inner_value; + asn_dec_rval_t rv; + + if(!(elm->flags & ATF_OPEN_TYPE)) { + ASN__DECODE_FAILED; + } + + if(!elm->type_selector) { + ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s", + td->name, elm->name, elm->type->name); + ASN__DECODE_FAILED; + } + + selected = elm->type_selector(td, sptr); + if(!selected.presence_index) { + ASN__DECODE_FAILED; + } + + /* Fetch the pointer to this member */ + assert(elm->flags == ATF_OPEN_TYPE); + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + } else { + memb_ptr = (char *)sptr + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + if(*memb_ptr2 != NULL) { + /* Make sure we reset the structure first before encoding */ + if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) + != 0) { + ASN__DECODE_FAILED; + } + } + + inner_value = + (char *)*memb_ptr2 + + elm->type->elements[selected.presence_index - 1].memb_offset; + + rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL, + &inner_value, pd); + switch(rv.code) { + case RC_OK: + if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, + selected.presence_index) + == 0) { + break; + } else { + rv.code = RC_FAIL; + } + /* Fall through */ + case RC_WMORE: + case RC_FAIL: + if(*memb_ptr2) { + const asn_CHOICE_specifics_t *specs = + selected.type_descriptor->specifics; + if(elm->flags & ATF_POINTER) { + ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); + *memb_ptr2 = NULL; + } else { + ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor, + inner_value); + memset(*memb_ptr2, 0, specs->struct_size); + } + } + } + return rv; +} + +asn_enc_rval_t +OPEN_TYPE_encode_aper(const asn_TYPE_descriptor_t *td, + const asn_per_constraints_t *constraints, + const void *sptr, asn_per_outp_t *po) { + const void *memb_ptr; /* Pointer to the member */ + asn_TYPE_member_t *elm; /* CHOICE's element */ + asn_enc_rval_t er; + unsigned present; + + (void)constraints; + + present = CHOICE_variant_get_presence(td, sptr); + if(present == 0 || present > td->elements_count) { + ASN__ENCODE_FAILED; + } else { + present--; + } + + ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present); + + elm = &td->elements[present]; + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr = + *(const void *const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) ASN__ENCODE_FAILED; + } else { + memb_ptr = (const char *)sptr + elm->memb_offset; + } + + if(aper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) { + ASN__ENCODE_FAILED; + } + + er.encoded = 0; + ASN__ENCODED_OK(er); +} #endif /* ASN_DISABLE_PER_SUPPORT */ diff --git a/skeletons/OPEN_TYPE.h b/skeletons/OPEN_TYPE.h index 4312e6023..1c091f14f 100644 --- a/skeletons/OPEN_TYPE.h +++ b/skeletons/OPEN_TYPE.h @@ -21,7 +21,6 @@ extern "C" { #define OPEN_TYPE_encode_xer CHOICE_encode_xer #define OPEN_TYPE_decode_uper NULL #define OPEN_TYPE_decode_aper NULL -#define OPEN_TYPE_encode_aper CHOICE_encode_aper extern asn_TYPE_operation_t asn_OP_OPEN_TYPE; @@ -53,11 +52,22 @@ asn_dec_rval_t OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_member_t *element, asn_per_data_t *pd); +asn_dec_rval_t OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *parent_type, + void *parent_structure, + const asn_TYPE_member_t *element, + asn_per_data_t *pd); + asn_enc_rval_t OPEN_TYPE_encode_uper( const asn_TYPE_descriptor_t *type_descriptor, const asn_per_constraints_t *constraints, const void *struct_ptr, asn_per_outp_t *per_output); +asn_enc_rval_t OPEN_TYPE_encode_aper( + const asn_TYPE_descriptor_t *type_descriptor, + const asn_per_constraints_t *constraints, const void *struct_ptr, + asn_per_outp_t *per_output); + #ifdef __cplusplus } #endif diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c index ee74e32fc..fb2a7d416 100644 --- a/skeletons/asn_application.c +++ b/skeletons/asn_application.c @@ -239,6 +239,8 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx, #ifdef ASN_DISABLE_PER_SUPPORT case ATS_UNALIGNED_BASIC_PER: case ATS_UNALIGNED_CANONICAL_PER: + case ATS_ALIGNED_BASIC_PER: + case ATS_ALIGNED_CANONICAL_PER: errno = ENOENT; /* PER is not defined. */ ASN__ENCODE_FAILED; break; @@ -273,6 +275,36 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx, ASN__ENCODE_FAILED; } break; + case ATS_ALIGNED_BASIC_PER: + /* CANONICAL-APER is a superset of BASIC-APER. */ + /* Fall through. */ + case ATS_ALIGNED_CANONICAL_PER: + if(td->op->aper_encoder) { + er = aper_encode(td, 0, sptr, callback, callback_key); + if(er.encoded == -1) { + if(er.failed_type && er.failed_type->op->aper_encoder) { + errno = EBADF; /* Structure has incorrect form. */ + } else { + errno = ENOENT; /* APER is not defined for this type. */ + } + } else { + ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); + if(er.encoded == 0) { + /* Enforce "Complete Encoding" of X.691 #11.1 */ + if(callback("\0", 1, callback_key) < 0) { + errno = EBADF; + ASN__ENCODE_FAILED; + } + er.encoded = 8; /* Exactly 8 zero bits is added. */ + } + /* Convert bits into bytes */ + er.encoded = (er.encoded + 7) >> 3; + } + } else { + errno = ENOENT; /* Transfer syntax is not defined for this type. */ + ASN__ENCODE_FAILED; + } + break; #endif /* ASN_DISABLE_PER_SUPPORT */ case ATS_BASIC_XER: diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c index b68d1f29e..7e35cbffa 100644 --- a/skeletons/constr_SEQUENCE.c +++ b/skeletons/constr_SEQUENCE.c @@ -1594,9 +1594,14 @@ SEQUENCE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx, } /* Fetch the member from the stream */ - ASN_DEBUG("Decoding member %s in %s", elm->name, td->name); - rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type, - elm->encoding_constraints.per_constraints, memb_ptr2, pd); + ASN_DEBUG("Decoding member \"%s\" in %s", elm->name, td->name); + + if(elm->flags & ATF_OPEN_TYPE) { + rv = OPEN_TYPE_aper_get(opt_codec_ctx, td, st, elm, pd); + } else { + rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type, + elm->encoding_constraints.per_constraints, memb_ptr2, pd); + } if(rv.code != RC_OK) { ASN_DEBUG("Failed decode %s in %s", elm->name, td->name); diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c index 63781b254..8a3e39df8 100644 --- a/skeletons/per_decoder.c +++ b/skeletons/per_decoder.c @@ -96,7 +96,9 @@ uper_decode(const asn_codec_ctx_t *opt_codec_ctx, } asn_dec_rval_t -aper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) { +aper_decode_complete(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *td, void **sptr, + const void *buffer, size_t size) { asn_dec_rval_t rval; rval = aper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0); @@ -125,7 +127,9 @@ aper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } asn_dec_rval_t -aper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) { +aper_decode(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, + size_t size, int skip_bits, int unused_bits) { asn_codec_ctx_t s_codec_ctx; asn_dec_rval_t rval; asn_per_data_t pd; diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h index c28e1e2f4..5cbe27911 100644 --- a/skeletons/per_decoder.h +++ b/skeletons/per_decoder.h @@ -44,8 +44,9 @@ asn_dec_rval_t uper_decode( * Aligned PER decoder of a "complete encoding" as per X.691#10.1. * On success, this call always returns (.consumed >= 1), in BITS, as per X.691#10.1.3. */ -asn_dec_rval_t aper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, - struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ +asn_dec_rval_t aper_decode_complete( + const struct asn_codec_ctx_s *opt_codec_ctx, + const struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ void **struct_ptr, /* Pointer to a target structure's pointer */ const void *buffer, /* Data to be decoded */ size_t size /* Size of data buffer */ @@ -55,8 +56,9 @@ asn_dec_rval_t aper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, * Aligned PER decoder of any ASN.1 type. May be invoked by the application. * WARNING: This call returns the number of BITS read from the stream. Beware. */ -asn_dec_rval_t aper_decode(struct asn_codec_ctx_s *opt_codec_ctx, - struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ +asn_dec_rval_t aper_decode( + const struct asn_codec_ctx_s *opt_codec_ctx, + const struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ void **struct_ptr, /* Pointer to a target structure's pointer */ const void *buffer, /* Data to be decoded */ size_t size, /* Size of data buffer */ diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c index 642f1e249..5680aaabd 100644 --- a/skeletons/per_encoder.c +++ b/skeletons/per_encoder.c @@ -155,57 +155,34 @@ _uper_encode_flush_outp(asn_per_outp_t *po) { return po->output(po->tmpspace, buf - po->tmpspace, po->op_key); } -static asn_enc_rval_t aper_encode_internal(const asn_TYPE_descriptor_t *td, - const asn_per_constraints_t *, - const void *sptr, asn_app_consume_bytes_f *cb, void *app_key); - -asn_enc_rval_t -aper_encode(const asn_TYPE_descriptor_t *td, - const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { - return aper_encode_internal(td, 0, sptr, cb, app_key); -} - -asn_enc_rval_t -aper_encode_to_buffer(const asn_TYPE_descriptor_t *td, - const void *sptr, void *buffer, size_t buffer_size) { - enc_to_buf_arg key; - - key.buffer = buffer; - key.left = buffer_size; - - if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name); - - return aper_encode_internal(td, 0, sptr, encode_to_buffer_cb, &key); -} - ssize_t aper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td, - const asn_per_constraints_t *constraints, - const void *sptr, void **buffer_r) { - asn_enc_rval_t er; + const asn_per_constraints_t *constraints, + const void *sptr, void **buffer_r) { + asn_enc_rval_t er; enc_dyn_arg key; memset(&key, 0, sizeof(key)); - er = aper_encode_internal(td, constraints, sptr, encode_dyn_cb, &key); + er = aper_encode(td, constraints, sptr, encode_dyn_cb, &key); switch(er.encoded) { - case -1: - FREEMEM(key.buffer); - return -1; - case 0: - FREEMEM(key.buffer); - key.buffer = MALLOC(1); - if(key.buffer) { - *(char *)key.buffer = '\0'; - *buffer_r = key.buffer; - return 1; - } else { - return -1; - } - default: + case -1: + FREEMEM(key.buffer); + return -1; + case 0: + FREEMEM(key.buffer); + key.buffer = MALLOC(1); + if(key.buffer) { + *(char *)key.buffer = '\0'; *buffer_r = key.buffer; - ASN_DEBUG("Complete encoded in %ld bits", er.encoded); - return ((er.encoded + 7) >> 3); + return 1; + } else { + return -1; + } + default: + *buffer_r = key.buffer; + ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); + return ((er.encoded + 7) >> 3); } } @@ -229,8 +206,8 @@ _aper_encode_flush_outp(asn_per_outp_t *po) { return 0; } -static asn_enc_rval_t -aper_encode_internal(const asn_TYPE_descriptor_t *td, +asn_enc_rval_t +aper_encode(const asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { asn_per_outp_t po; diff --git a/skeletons/per_encoder.h b/skeletons/per_encoder.h index 26be3fe58..b615ef028 100644 --- a/skeletons/per_encoder.h +++ b/skeletons/per_encoder.h @@ -30,6 +30,7 @@ asn_enc_rval_t uper_encode( asn_enc_rval_t aper_encode( const struct asn_TYPE_descriptor_s *type_descriptor, + const asn_per_constraints_t *constraints, const void *struct_ptr, /* Structure to be encoded */ asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */ void *app_key /* Arbitrary callback argument */ @@ -50,6 +51,7 @@ asn_enc_rval_t uper_encode_to_buffer( asn_enc_rval_t aper_encode_to_buffer( const struct asn_TYPE_descriptor_s *type_descriptor, + const asn_per_constraints_t *constraints, const void *struct_ptr, /* Structure to be encoded */ void *buffer, /* Pre-allocated buffer */ size_t buffer_size /* Initial buffer size (max) */