X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/46b0747592074017ff0ea4b33d4a7194235886e5..a500fb72810060e52d87ad2c2e4691531f0bcc5a:/libs/smux/constr_SEQUENCE.c?ds=sidebyside diff --git a/libs/smux/constr_SEQUENCE.c b/libs/smux/constr_SEQUENCE.c index bc14ca5e..5923023d 100644 --- a/libs/smux/constr_SEQUENCE.c +++ b/libs/smux/constr_SEQUENCE.c @@ -1,10 +1,11 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include +#include /* * Number of bytes left for this structure. @@ -33,7 +34,7 @@ #undef ADVANCE #define ADVANCE(num_bytes) do { \ size_t num = num_bytes; \ - ptr = ((const char *)ptr) + num;\ + ptr = ((const char *)ptr) + num; \ size -= num; \ if(ctx->left >= 0) \ ctx->left -= num; \ @@ -309,16 +310,16 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * Resort to a binary search over * sorted array of tags. */ - asn_TYPE_tag2member_t *t2m; + const asn_TYPE_tag2member_t *t2m; asn_TYPE_tag2member_t key; key.el_tag = tlv_tag; key.el_no = edx; - t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + t2m = (const asn_TYPE_tag2member_t *)bsearch(&key, specs->tag2el, specs->tag2el_count, sizeof(specs->tag2el[0]), _t2e_cmp); if(t2m) { - asn_TYPE_tag2member_t *best = 0; - asn_TYPE_tag2member_t *t2m_f, *t2m_l; + const asn_TYPE_tag2member_t *best = 0; + const asn_TYPE_tag2member_t *t2m_f, *t2m_l; int edx_max = edx + elements[edx].optional; /* * Rewind to the first element with that tag, @@ -346,7 +347,8 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * or an extension (...), * or an end of the indefinite-length structure. */ - if(!IN_EXTENSION_GROUP(specs, edx)) { + if(!IN_EXTENSION_GROUP(specs, + edx + elements[edx].optional)) { ASN_DEBUG("Unexpected tag %s (at %d)", ber_tlv_tag_string(tlv_tag), edx); ASN_DEBUG("Expected tag %s (%s)%s", @@ -358,7 +360,10 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } else { /* Skip this tag */ ssize_t skip; + edx += elements[edx].optional; + ASN_DEBUG("Skipping unexpected %s (at %d)", + ber_tlv_tag_string(tlv_tag), edx); skip = ber_skip_length(opt_codec_ctx, BER_TLV_CONSTRUCTED(ptr), (const char *)ptr + tag_len, @@ -527,7 +532,7 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, if(!memb_ptr) { if(elm->optional) continue; /* Mandatory element is missing */ - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; } } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); @@ -548,10 +553,10 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size); if(ret == -1) - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; erval.encoded = computed_size + ret; - if(!cb) _ASN_ENCODED_OK(erval); + if(!cb) ASN__ENCODED_OK(erval); /* * Encode all members. @@ -581,9 +586,9 @@ SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, /* * Encoded size is not equal to the computed size. */ - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; - _ASN_ENCODED_OK(erval); + ASN__ENCODED_OK(erval); } @@ -648,6 +653,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, ssize_t ch_size; /* Chunk size */ xer_check_tag_e tcv; /* Tag check value */ asn_TYPE_member_t *elm; + int n; /* * Go inside the inner member of a sequence. @@ -661,8 +667,7 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st - + elm->memb_offset); + memb_ptr2 = (void **)((char *)st + elm->memb_offset); } else { memb_ptr = (char *)st + elm->memb_offset; memb_ptr2 = &memb_ptr; @@ -687,11 +692,12 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); - switch(ch_size) { - case -1: RETURN(RC_FAIL); - case 0: RETURN(RC_WMORE); - default: + if(ch_size == -1) { + RETURN(RC_FAIL); + } else { switch(ch_type) { + case PXER_WMORE: + RETURN(RC_WMORE); case PXER_COMMENT: /* Got XML comment */ case PXER_TEXT: /* Ignore free-standing text */ XER_ADVANCE(ch_size); /* Skip silently */ @@ -774,7 +780,6 @@ SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, edx_end = edx + elements[edx].optional + 1; if(edx_end > td->elements_count) edx_end = td->elements_count; - int n; for(n = edx; n < edx_end; n++) { elm = &td->elements[n]; tcv = xer_check_tag(buf_ptr, @@ -853,7 +858,7 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int edx; if(!sptr) - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; er.encoded = 0; @@ -870,29 +875,29 @@ SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, if(elm->optional) continue; /* Mandatory element is missing */ - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; } } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); } - if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); - _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + if(!xcan) ASN__TEXT_INDENT(1, ilevel); + ASN__CALLBACK3("<", 1, mname, mlen, ">", 1); /* Print the member itself */ tmper = elm->type->xer_encoder(elm->type, memb_ptr, ilevel + 1, flags, cb, app_key); if(tmper.encoded == -1) return tmper; - _ASN_CALLBACK3("", 1); + ASN__CALLBACK3("", 1); er.encoded += 5 + (2 * mlen) + tmper.encoded; } - if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1); - _ASN_ENCODED_OK(er); + ASN__ENCODED_OK(er); cb_failed: - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; } int @@ -976,7 +981,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, int edx; if(!sptr) { - _ASN_CTFAIL(app_key, td, + ASN__CTFAIL(app_key, td, sptr, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; @@ -994,7 +999,7 @@ SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, if(!memb_ptr) { if(elm->optional) continue; - _ASN_CTFAIL(app_key, td, + ASN__CTFAIL(app_key, td, sptr, "%s: mandatory element %s absent (%s:%d)", td->name, elm->name, __FILE__, __LINE__); return -1; @@ -1027,7 +1032,7 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; void *st = *sptr; /* Target structure. */ - int extpresent = 0; /* Extension additions are present */ + int extpresent; /* Extension additions are present */ uint8_t *opres; /* Presence of optional root members */ asn_per_data_t opmd; asn_dec_rval_t rv; @@ -1035,12 +1040,12 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, (void)constraints; - if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) - _ASN_DECODE_FAILED; + if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx)) + ASN__DECODE_FAILED; if(!st) { st = *sptr = CALLOC(1, specs->struct_size); - if(!st) _ASN_DECODE_FAILED; + if(!st) ASN__DECODE_FAILED; } ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name); @@ -1048,37 +1053,40 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Handle extensions */ if(specs->ext_before >= 0) { extpresent = per_get_few_bits(pd, 1); - if(extpresent < 0) _ASN_DECODE_STARVED; + if(extpresent < 0) ASN__DECODE_STARVED; + } else { + extpresent = 0; } /* Prepare a place and read-in the presence bitmap */ + memset(&opmd, 0, sizeof(opmd)); if(specs->roms_count) { opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1); - if(!opres) _ASN_DECODE_FAILED; + if(!opres) ASN__DECODE_FAILED; /* Get the presence map */ if(per_get_many_bits(pd, opres, 0, specs->roms_count)) { FREEMEM(opres); - _ASN_DECODE_STARVED; + ASN__DECODE_STARVED; } opmd.buffer = opres; - opmd.nboff = 0; opmd.nbits = specs->roms_count; ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)", td->name, specs->roms_count, *opres); } else { opres = 0; - memset(&opmd, 0, sizeof opmd); } /* * Get the sequence ROOT elements. */ - for(edx = 0; edx < ((specs->ext_before < 0) - ? td->elements_count : specs->ext_before + 1); edx++) { + for(edx = 0; edx < td->elements_count; edx++) { asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ + if(IN_EXTENSION_GROUP(specs, edx)) + continue; + /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)st + elm->memb_offset); @@ -1099,8 +1107,9 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Fill-in DEFAULT */ if(elm->default_value(1, memb_ptr2)) { FREEMEM(opres); - _ASN_DECODE_FAILED; + ASN__DECODE_FAILED; } + ASN_DEBUG("Filled-in default"); } /* The member is just not present */ continue; @@ -1120,63 +1129,201 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } } + /* Optionality map is not needed anymore */ + FREEMEM(opres); + /* * Deal with extensions. */ if(extpresent) { - ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name); - _ASN_DECODE_FAILED; - } else { - for(edx = specs->roms_count; edx < specs->roms_count - + specs->aoms_count; edx++) { - asn_TYPE_member_t *elm = &td->elements[edx]; - void *memb_ptr; /* Pointer to the member */ - void **memb_ptr2; /* Pointer to that pointer */ + ssize_t bmlength; + uint8_t *epres; /* Presence of extension members */ + asn_per_data_t epmd; - if(!elm->default_value) continue; + bmlength = uper_get_nslength(pd); + if(bmlength < 0) ASN__DECODE_STARVED; - /* Fetch the pointer to this member */ - if(elm->flags & ATF_POINTER) { - memb_ptr2 = (void **)((char *)st - + elm->memb_offset); - } else { - memb_ptr = (char *)st + elm->memb_offset; - memb_ptr2 = &memb_ptr; - } + ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name); + + epres = (uint8_t *)MALLOC((bmlength + 15) >> 3); + if(!epres) ASN__DECODE_STARVED; + + /* Get the extensions map */ + if(per_get_many_bits(pd, epres, 0, bmlength)) { + FREEMEM(epres); + ASN__DECODE_STARVED; + } + + memset(&epmd, 0, sizeof(epmd)); + epmd.buffer = epres; + epmd.nbits = bmlength; + ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)", + td->name, (long)bmlength, *epres); + + /* Go over extensions and read them in */ + for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; - /* Set default value */ - if(elm->default_value(1, memb_ptr2)) { - FREEMEM(opres); - _ASN_DECODE_FAILED; + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("%d is not extension", edx); + continue; + } + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_ptr = (void *)((char *)st + elm->memb_offset); + memb_ptr2 = &memb_ptr; + } + + present = per_get_few_bits(&epmd, 1); + if(present <= 0) { + if(present < 0) break; /* No more extensions */ + continue; + } + + ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2); + rv = uper_open_type_get(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) { + FREEMEM(epres); + return rv; + } + } + + /* Skip over overflow extensions which aren't present + * in this system's version of the protocol */ + for(;;) { + ASN_DEBUG("Getting overflow extensions"); + switch(per_get_few_bits(&epmd, 1)) { + case -1: break; + case 0: continue; + default: + if(uper_open_type_skip(opt_codec_ctx, pd)) { + FREEMEM(epres); + ASN__DECODE_STARVED; + } } + break; + } + + FREEMEM(epres); + } + + /* Fill DEFAULT members in extensions */ + for(edx = specs->roms_count; edx < specs->roms_count + + specs->aoms_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void **memb_ptr2; /* Pointer to member pointer */ + + if(!elm->default_value) continue; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + if(*memb_ptr2) continue; + } else { + continue; /* Extensions are all optionals */ + } + + /* Set default value */ + if(elm->default_value(1, memb_ptr2)) { + ASN__DECODE_FAILED; } } rv.consumed = 0; rv.code = RC_OK; - FREEMEM(opres); return rv; } +static int +SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr, + asn_per_outp_t *po1, asn_per_outp_t *po2) { + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + int exts_present = 0; + int exts_count = 0; + int edx; + + if(specs->ext_before < 0) + return 0; + + /* Find out which extensions are present */ + for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; + + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx); + continue; + } + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + present = (*memb_ptr2 != 0); + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + present = 1; + } + + ASN_DEBUG("checking %s (@%d) present => %d", + elm->type->name, edx, present); + exts_count++; + exts_present += present; + + /* Encode as presence marker */ + if(po1 && per_put_few_bits(po1, present, 1)) + return -1; + /* Encode as open type field */ + if(po2 && present && uper_open_type_put(elm->type, + elm->per_constraints, *memb_ptr2, po2)) + return -1; + + } + + return exts_present ? exts_count : 0; +} + asn_enc_rval_t SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; asn_enc_rval_t er; + int n_extensions; int edx; int i; (void)constraints; if(!sptr) - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; er.encoded = 0; ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name); - if(specs->ext_before >= 0) - _ASN_ENCODE_FAILED; /* We don't encode extensions yet */ + + + /* + * X.691#18.1 Whether structure is extensible + * and whether to encode extensions + */ + if(specs->ext_before >= 0) { + n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0); + per_put_few_bits(po, n_extensions ? 1 : 0, 1); + } else { + n_extensions = 0; /* There are no extensions to encode */ + } /* Encode a presence bitmap */ for(i = 0; i < specs->roms_count; i++) { @@ -1208,18 +1355,25 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, elm->default_value ? "def" : "wtv", td->name, elm->name, present ? "present" : "absent"); if(per_put_few_bits(po, present, 1)) - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; } /* - * Get the sequence ROOT elements. + * Encode the sequence ROOT elements. */ - for(edx = 0; edx < ((specs->ext_before < 0) - ? td->elements_count : specs->ext_before + 1); edx++) { + ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before); + for(edx = 0; edx < ((specs->ext_after < 0) + ? td->elements_count : specs->ext_before - 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ + if(IN_EXTENSION_GROUP(specs, edx)) + continue; + + ASN_DEBUG("About to encode %s", elm->type->name); + /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); @@ -1229,7 +1383,7 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, if(elm->optional) continue; /* Mandatory element is missing */ - _ASN_ENCODE_FAILED; + ASN__ENCODE_FAILED; } } else { memb_ptr = (void *)((char *)sptr + elm->memb_offset); @@ -1240,12 +1394,32 @@ SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, if(elm->default_value && elm->default_value(0, memb_ptr2) == 1) continue; + ASN_DEBUG("Encoding %s->%s", td->name, elm->name); er = elm->type->uper_encoder(elm->type, elm->per_constraints, *memb_ptr2, po); if(er.encoded == -1) return er; } - _ASN_ENCODED_OK(er); + /* No extensions to encode */ + if(!n_extensions) ASN__ENCODED_OK(er); + + ASN_DEBUG("Length of %d bit-map", n_extensions); + /* #18.8. Write down the presence bit-map length. */ + if(uper_put_nslength(po, n_extensions)) + ASN__ENCODE_FAILED; + + ASN_DEBUG("Bit-map of %d elements", n_extensions); + /* #18.7. Encoding the extensions presence bit-map. */ + /* TODO: act upon NOTE in #18.7 for canonical PER */ + if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions) + ASN__ENCODE_FAILED; + + ASN_DEBUG("Writing %d extensions", n_extensions); + /* #18.9. Encode extensions as open type fields. */ + if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions) + ASN__ENCODE_FAILED; + + ASN__ENCODED_OK(er); }