aboutsummaryrefslogtreecommitdiffstats
path: root/skeletons
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2005-11-08 03:06:16 +0000
committerLev Walkin <vlm@lionet.info>2005-11-08 03:06:16 +0000
commitd1bfea65a046b1b8e3ba8fe5eb7260416a1e086a (patch)
tree34eb1b922345a3f43418887adcfb1c1d9efca351 /skeletons
parent5ab96cda95eaaa50473346d3aaa0c2b869e9e93a (diff)
SET OF/SEQUENCE OF interaction with named and unnamed CHOICE
Diffstat (limited to 'skeletons')
-rw-r--r--skeletons/OCTET_STRING.c4
-rw-r--r--skeletons/asn-decoder-template.c179
-rw-r--r--skeletons/asn_internal.h2
-rw-r--r--skeletons/constr_CHOICE.c18
-rw-r--r--skeletons/constr_SEQUENCE_OF.c7
-rw-r--r--skeletons/constr_SET_OF.c23
-rw-r--r--skeletons/tests/check-XER.c4
-rw-r--r--skeletons/xer_decoder.c4
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.
*/