diff options
author | Lev Walkin <vlm@lionet.info> | 2005-11-08 03:06:16 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2005-11-08 03:06:16 +0000 |
commit | d1bfea65a046b1b8e3ba8fe5eb7260416a1e086a (patch) | |
tree | 34eb1b922345a3f43418887adcfb1c1d9efca351 /skeletons | |
parent | 5ab96cda95eaaa50473346d3aaa0c2b869e9e93a (diff) |
SET OF/SEQUENCE OF interaction with named and unnamed CHOICE
Diffstat (limited to 'skeletons')
-rw-r--r-- | skeletons/OCTET_STRING.c | 4 | ||||
-rw-r--r-- | skeletons/asn-decoder-template.c | 179 | ||||
-rw-r--r-- | skeletons/asn_internal.h | 2 | ||||
-rw-r--r-- | skeletons/constr_CHOICE.c | 18 | ||||
-rw-r--r-- | skeletons/constr_SEQUENCE_OF.c | 7 | ||||
-rw-r--r-- | skeletons/constr_SET_OF.c | 23 | ||||
-rw-r--r-- | skeletons/tests/check-XER.c | 4 | ||||
-rw-r--r-- | skeletons/xer_decoder.c | 4 |
8 files changed, 162 insertions, 79 deletions
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c index b43c18fe..de53c1db 100644 --- a/skeletons/OCTET_STRING.c +++ b/skeletons/OCTET_STRING.c @@ -549,6 +549,8 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, if(!cb) { er.encoded += (type_variant == _TT_BIT_STRING) + st->size; + er.structure_ptr = 0; + er.failed_type = 0; return er; } @@ -572,6 +574,8 @@ OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, } er.encoded += st->size; + er.structure_ptr = 0; + er.failed_type = 0; return er; cb_failed: _ASN_ENCODE_FAILED; diff --git a/skeletons/asn-decoder-template.c b/skeletons/asn-decoder-template.c index 0febbf46..348c3731 100644 --- a/skeletons/asn-decoder-template.c +++ b/skeletons/asn-decoder-template.c @@ -1,5 +1,5 @@ /* - * Generic BER decoder template for any defined ASN.1 type. + * Generic decoder template for a selected ASN.1 type. * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved. * * To compile with your own ASN.1 type, please redefine the asn_DEF as shown: @@ -21,21 +21,32 @@ #include <asn_application.h> extern asn_TYPE_descriptor_t asn_DEF; /* ASN.1 type to be decoded */ +static asn_TYPE_descriptor_t *pduType = &asn_DEF; /* * Open file and parse its contens. */ static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU, const char *fname, ssize_t suggested_bufsize); +static int write_out(const void *buffer, size_t size, void *key); int opt_debug; /* -d */ static int opt_check; /* -c */ static int opt_stack; /* -s */ -static enum output_method { - OUT_NONE, /* No pretty-printing */ - OUT_PRINT, /* -p flag */ - OUT_XML /* -x flag */ -} opt_ometh; /* -p or -x */ + +/* Input data format selector */ +static enum input_format { + INP_BER, /* -iber: BER input */ + INP_XER /* -ixer: XER input */ +} iform; /* -i<format> */ + +/* Output data format selector */ +static enum output_format { + OUT_XER, /* -oxer: XER (XML) output */ + OUT_DER, /* -oder: DER output */ + OUT_TEXT, /* -otext: semi-structured text */ + OUT_NULL /* -onull: No pretty-printing */ +} oform; /* -o<format> */ #define DEBUG(fmt, args...) do { \ if(!opt_debug) break; \ @@ -46,7 +57,6 @@ static enum output_method { int main(int ac, char **av) { ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */ - asn_TYPE_descriptor_t *pduType = &asn_DEF; int number_of_iterations = 1; int num; int ch; @@ -54,8 +64,22 @@ main(int ac, char **av) { /* * Pocess the command-line argments. */ - while((ch = getopt(ac, av, "b:cdn:hps:x")) != -1) + while((ch = getopt(ac, av, "i:o:b:cdn:hs:")) != -1) switch(ch) { + case 'i': + if(optarg[0] == 'b') { iform = INP_BER; break; } + if(optarg[0] == 'x') { iform = INP_XER; break; } + fprintf(stderr, "-i<format>: '%s': improper format selector", + optarg); + exit(EX_UNAVAILABLE); + case 'o': + if(optarg[0] == 'd') { oform = OUT_DER; break; } + if(optarg[0] == 'x') { oform = OUT_XER; break; } + if(optarg[0] == 't') { oform = OUT_TEXT; break; } + if(optarg[0] == 'n') { oform = OUT_NULL; break; } + fprintf(stderr, "-o<format>: '%s': improper format selector", + optarg); + exit(EX_UNAVAILABLE); case 'b': suggested_bufsize = atoi(optarg); if(suggested_bufsize < 1 @@ -80,9 +104,6 @@ main(int ac, char **av) { exit(EX_UNAVAILABLE); } break; - case 'p': - opt_ometh = OUT_PRINT; - break; case 's': opt_stack = atoi(optarg); if(opt_stack <= 0) { @@ -92,25 +113,22 @@ main(int ac, char **av) { exit(EX_UNAVAILABLE); } break; - case 'x': - opt_ometh = OUT_XML; - break; case 'h': default: fprintf(stderr, "Usage: %s [options] <data.ber> ...\n" "Where options are:\n" + " -iber (I) Input is in BER (Basic Encoding Rules)\n" + " -ixer Input is in XER (XML Encoding Rules)\n" + " -oder Output in DER (Distinguished Encoding Rules)\n" + " -oxer (O) Output in XER (XML Encoding Rules)\n" + " -otext Output in plain semi-structured text (dump)\n" + " -onull Verify (decode) input, but do not output\n" " -b <size> Set the i/o buffer size (default is %ld)\n" " -c Check ASN.1 constraints after decoding\n" " -d Enable debugging (-dd is even better)\n" " -n <num> Process files <num> times\n" " -s <size> Set the stack usage limit\n" - " -p Print out the decoded contents\n" - " -x Print out as XML" -#ifdef ASN_DECODER_DEFAULT_OUTPUT_XML - " (default)" -#endif - "\n" , av[0], (long)suggested_bufsize); exit(EX_USAGE); } @@ -119,14 +137,12 @@ main(int ac, char **av) { av += optind; if(ac < 1) { - fprintf(stderr, "Error: missing filename\n"); + fprintf(stderr, "%s: No input files specified. " + "Try '-h' for more information\n", + av[-optind]); exit(EX_USAGE); } -#ifdef ASN_DECODER_DEFAULT_OUTPUT_XML - if(opt_ometh == OUT_NONE) opt_ometh = OUT_XML; -#endif - setvbuf(stdout, 0, _IOLBF, 0); for(num = 0; num < number_of_iterations; num++) { @@ -137,6 +153,7 @@ main(int ac, char **av) { for(ac_i = 0; ac_i < ac; ac_i++) { char *fname = av[ac_i]; void *structure; + asn_enc_rval_t erv; /* * Decode the encoded structure from file. @@ -148,32 +165,40 @@ main(int ac, char **av) { exit(EX_DATAERR); } - switch(opt_ometh) { - case OUT_NONE: + /* Check ASN.1 constraints */ + if(opt_check) { + char errbuf[128]; + size_t errlen = sizeof(errbuf); + if(asn_check_constraints(pduType, structure, + errbuf, &errlen)) { + fprintf(stderr, "%s: ASN.1 constraint " + "check failed: %s\n", fname, errbuf); + exit(EX_DATAERR); + } + } + + switch(oform) { + case OUT_NULL: fprintf(stderr, "%s: decoded successfully\n", fname); break; - case OUT_PRINT: /* -p */ + case OUT_TEXT: /* -otext */ asn_fprint(stdout, pduType, structure); break; - case OUT_XML: /* -x */ + case OUT_XER: /* -oxer */ if(xer_fprint(stdout, pduType, structure)) { fprintf(stderr, "%s: Cannot convert into XML\n", fname); exit(EX_UNAVAILABLE); } break; - } - - /* Check ASN.1 constraints */ - if(opt_check) { - char errbuf[128]; - size_t errlen = sizeof(errbuf); - if(asn_check_constraints(pduType, structure, - errbuf, &errlen)) { - fprintf(stderr, "%s: ASN.1 constraint " - "check failed: %s\n", fname, errbuf); - exit(EX_DATAERR); + case OUT_DER: + erv = der_encode(pduType, structure, write_out, stdout); + if(erv.encoded < 0) { + fprintf(stderr, "%s: Cannot convert into DER\n", + fname); + exit(EX_UNAVAILABLE); } + break; } pduType->free_struct(pduType, structure, 0); @@ -183,6 +208,10 @@ main(int ac, char **av) { return 0; } +/* Dump the buffer */ +static int write_out(const void *buffer, size_t size, void *key) { + return (fwrite(buffer, 1, size, key) == size) ? 0 : -1; +} static char *buffer; static size_t buf_offset; /* Offset from the start */ @@ -194,7 +223,7 @@ static off_t buf_shifted; /* Number of bytes ever shifted */ #define bufend (buffer + buf_offset + buf_len) /* - * Ensure that the buffer contains at least this amoount of free space. + * Ensure that the buffer contains at least this amount of free space. */ static void buf_extend(size_t bySize) { @@ -231,6 +260,7 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f static asn_codec_ctx_t s_codec_ctx; asn_codec_ctx_t *opt_codec_ctx = 0; void *structure = 0; + asn_dec_rval_t rval; size_t rd; FILE *fp; @@ -239,9 +269,14 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f opt_codec_ctx = &s_codec_ctx; } - DEBUG("Processing file %s", fname); - - fp = fopen(fname, "r"); + if(strcmp(fname, "-")) { + DEBUG("Processing file %s", fname); + fp = fopen(fname, "r"); + } else { + DEBUG("Processing standard input"); + fname = "stdin"; + fp = stdin; + } if(!fp) { fprintf(stderr, "%s: %s\n", fname, strerror(errno)); @@ -262,9 +297,13 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f buf_offset = 0; buf_len = 0; + /* Pretend immediate EOF */ + rval.code = RC_WMORE; + rval.consumed = 0; + while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) { - asn_dec_rval_t rval; - int using_local_buf; + char *i_bptr; + size_t i_size; /* * Copy the data over, or use the original buffer. @@ -275,26 +314,27 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f memcpy(bufend, fbuf, rd); buf_len += rd; - rval = ber_decode(opt_codec_ctx, pduType, - (void **)&structure, bufptr, buf_len); - DEBUG("ber_decode(%ld) consumed %ld, code %d", - (long)buf_len, (long)rval.consumed, rval.code); - - /* - * Adjust position inside the source buffer. - */ - assert(rval.consumed <= buf_len); - buf_offset += rval.consumed; - buf_len -= rval.consumed; + i_bptr = bufptr; + i_size = buf_len; } else { - using_local_buf = 1; + i_bptr = fbuf; + i_size = rd; + } - /* Feed the chunk of data into a decoder routine */ + switch(iform) { + case INP_BER: rval = ber_decode(opt_codec_ctx, pduType, - (void **)&structure, fbuf, rd); - DEBUG("ber_decode(%ld) consumed %ld, code %d", - (long)rd, (long)rval.consumed, rval.code); + (void **)&structure, i_bptr, i_size); + break; + case INP_XER: + rval = xer_decode(opt_codec_ctx, pduType, + (void **)&structure, i_bptr, i_size); + break; + } + DEBUG("decode(%ld) consumed %ld, code %d", + (long)buf_len, (long)rval.consumed, rval.code); + if(buf_len == 0) { /* * Switch the remainder into the intermediate buffer. */ @@ -310,10 +350,16 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f switch(rval.code) { case RC_OK: DEBUG("RC_OK, finishing up"); - fclose(fp); + if(fp != stdin) fclose(fp); return structure; case RC_WMORE: DEBUG("RC_WMORE, continuing..."); + /* + * Adjust position inside the source buffer. + */ + buf_offset += rval.consumed; + buf_len -= rval.consumed; + rval.consumed = 0; continue; case RC_FAIL: break; @@ -327,8 +373,11 @@ static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *f pduType->free_struct(pduType, structure, 0); fprintf(stderr, "%s: " - "Decode failed past %lld byte\n", - fname, (long long)(buf_shifted + buf_offset)); + "Decode failed past byte %ld: %s\n", + fname, (long)(buf_shifted + buf_offset + rval.consumed), + (rval.code == RC_WMORE) + ? "Unexpected end of input" + : "Input processing error"); return 0; } diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h index 09d407c5..4a86141d 100644 --- a/skeletons/asn_internal.h +++ b/skeletons/asn_internal.h @@ -20,7 +20,7 @@ extern "C" { #endif /* Environment version might be used to avoid running with the old library */ -#define ASN1C_ENVIRONMENT_VERSION 919 /* Compile-time version */ +#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ int get_asn1c_environment_version(void); /* Run-time version */ #define CALLOC(nmemb, size) calloc(nmemb, size) diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c index b3af333a..f832812a 100644 --- a/skeletons/constr_CHOICE.c +++ b/skeletons/constr_CHOICE.c @@ -572,7 +572,8 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, * Restore parsing context. */ ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); - + if(ctx->phase == 0 && !*xml_tag) + ctx->phase = 1; /* Skip the outer tag checking phase */ /* * Phases of XER/XML processing: @@ -625,6 +626,12 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* Fall through */ } + /* No need to wait for closing tag; special mode. */ + if(ctx->phase == 3 && !*xml_tag) { + ctx->phase = 5; /* Phase out */ + RETURN(RC_OK); + } + /* * Get the next part of the XML stream. */ @@ -644,6 +651,12 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d", + ch_size>0?((uint8_t *)buf_ptr)[0]:'?', + ch_size>1?((uint8_t *)buf_ptr)[1]:'?', + ch_size>2?((uint8_t *)buf_ptr)[2]:'?', + ch_size>3?((uint8_t *)buf_ptr)[3]:'?', + xml_tag, tcv); /* Skip the extensions section */ if(ctx->phase == 4) { @@ -739,7 +752,8 @@ CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, break; } - ASN_DEBUG("Unexpected XML tag in CHOICE"); + ASN_DEBUG("Unexpected XML tag in CHOICE (ph=%d, tag=%s)", + ctx->phase, xml_tag); break; } diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c index 55307649..12233a6c 100644 --- a/skeletons/constr_SEQUENCE_OF.c +++ b/skeletons/constr_SEQUENCE_OF.c @@ -51,6 +51,8 @@ SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, computed_size += encoding_size; if(!cb) { erval.encoded = computed_size; + erval.structure_ptr = 0; + erval.failed_type = 0; return erval; } @@ -79,6 +81,8 @@ SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, erval.structure_ptr = ptr; } else { erval.encoded = computed_size; + erval.structure_ptr = 0; + erval.failed_type = 0; } return erval; @@ -116,8 +120,7 @@ SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, ilevel + 1, flags, cb, app_key); if(tmper.encoded == -1) return tmper; if(tmper.encoded == 0 && specs->as_XMLValueList) { - const char *name = (*elm->name) - ? elm->name : elm->type->xml_tag; + const char *name = elm->type->xml_tag; size_t len = strlen(name); if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel + 1); _ASN_CALLBACK3("<", 1, name, len, "/>", 2); diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index e578ccbb..bd25b3d8 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -471,8 +471,7 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; asn_TYPE_member_t *element = td->elements; - const char *elm_tag = ((*element->name) - ? element->name : element->type->xml_tag); + const char *elm_tag; const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; /* @@ -492,6 +491,14 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, if(st == 0) RETURN(RC_FAIL); } + /* Which tag is expected for the downstream */ + if(specs->as_XMLValueList) { + elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; + } else { + elm_tag = (*element->name) + ? element->name : element->type->xml_tag; + } + /* * Restore parsing context. */ @@ -515,6 +522,7 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_dec_rval_t tmprval; /* Invoke the inner type decoder, m.b. multiple times */ + ASN_DEBUG("XER/SET OF element [%s]", elm_tag); tmprval = element->type->xer_decoder(opt_codec_ctx, element->type, &ctx->ptr, elm_tag, buf_ptr, size); @@ -553,7 +561,8 @@ SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); - ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d", tcv, ctx->phase); + ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", + tcv, ctx->phase, xml_tag); switch(tcv) { case XCT_CLOSING: if(ctx->phase == 0) break; @@ -682,18 +691,18 @@ SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); } - if(!xcan && specs->as_XMLValueList) + if(!xcan && specs->as_XMLValueList == 1) _i_ASN_TEXT_INDENT(1, ilevel + 1); tmper = elm->type->xer_encoder(elm->type, memb_ptr, - ilevel + 1, flags, cb, app_key); + ilevel + (specs->as_XMLValueList != 2), + flags, cb, app_key); if(tmper.encoded == -1) { td = tmper.failed_type; sptr = tmper.structure_ptr; goto cb_failed; } if(tmper.encoded == 0 && specs->as_XMLValueList) { - const char *name = (*elm->name) - ? elm->name : elm->type->xml_tag; + const char *name = elm->type->xml_tag; size_t len = strlen(name); _ASN_CALLBACK3("<", 1, name, len, "/>", 2); } diff --git a/skeletons/tests/check-XER.c b/skeletons/tests/check-XER.c index 10b0a317..6e2f1ce5 100644 --- a/skeletons/tests/check-XER.c +++ b/skeletons/tests/check-XER.c @@ -46,8 +46,8 @@ main() { check("</", "", XCT_BROKEN); check("/>", "", XCT_BROKEN); - check("<>", "", XCT_OPENING); - check("</>", "", XCT_CLOSING); + check("<>", "", XCT_UNKNOWN_OP); + check("</>", "", XCT_UNKNOWN_CL); check("", "a", XCT_BROKEN); check("<>", "a", XCT_UNKNOWN_OP); diff --git a/skeletons/xer_decoder.c b/skeletons/xer_decoder.c index b112a72d..e48a5ed0 100644 --- a/skeletons/xer_decoder.c +++ b/skeletons/xer_decoder.c @@ -124,6 +124,10 @@ xer_check_tag(const void *buf_ptr, int size, const char *need_tag) { } } + /* Sometimes we don't care about the tag */ + if(!need_tag || !*need_tag) + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + /* * Determine the tag name. */ |