Commit 6d46bc3d authored by Lev Walkin's avatar Lev Walkin

introduce generic encoder

parent ffb77b08
...@@ -59,7 +59,8 @@ libasn1cskeletons_la_SOURCES = \ ...@@ -59,7 +59,8 @@ libasn1cskeletons_la_SOURCES = \
VisibleString.c VisibleString.h \ VisibleString.c VisibleString.h \
asn_SEQUENCE_OF.c asn_SEQUENCE_OF.h \ asn_SEQUENCE_OF.c asn_SEQUENCE_OF.h \
asn_SET_OF.c asn_SET_OF.h \ asn_SET_OF.c asn_SET_OF.h \
asn_application.h asn_codecs.h \ asn_application.c asn_application.h \
asn_codecs.h \
asn_codecs_prim.c asn_codecs_prim.h \ asn_codecs_prim.c asn_codecs_prim.h \
asn_internal.h asn_system.h \ asn_internal.h asn_system.h \
asn_bit_data.c asn_bit_data.h \ asn_bit_data.c asn_bit_data.h \
...@@ -88,3 +89,9 @@ libasn1cskeletons_la_SOURCES = \ ...@@ -88,3 +89,9 @@ libasn1cskeletons_la_SOURCES = \
xer_encoder.c xer_encoder.h \ xer_encoder.c xer_encoder.h \
xer_support.c xer_support.h xer_support.c xer_support.h
check_PROGRAMS = check-converter_sample
LDADD = -lm
check_converter_sample_CFLAGS = $(SKELETONS_CFLAGS) -DNO_ASN_PDU
check_converter_sample_SOURCES = converter-sample.c
check_converter_sample_LDADD = libasn1cskeletons.la
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <asn_application.h>
#include <errno.h>
static asn_enc_rval_t asn_encode_internal(
const asn_codec_ctx_t *opt_codec_parameters,
enum asn_transfer_syntax syntax, asn_TYPE_descriptor_t *td,
void *sptr, asn_app_consume_bytes_f *callback, void *callback_key);
struct callback_count_bytes_key {
asn_app_consume_bytes_f *callback;
void *callback_key;
size_t computed_size;
};
/*
* Encoder which just counts bytes that come through it.
*/
static int
callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
struct callback_count_bytes_key *key = keyp;
int ret;
ret = key->callback(data, size, key->callback_key);
if(ret >= 0) {
key->computed_size += size;
}
return ret;
}
struct overrun_encoder_key {
void *buffer;
size_t buffer_size;
size_t computed_size;
};
struct callback_failure_catch_key {
asn_app_consume_bytes_f *callback;
void *callback_key;
int callback_failed;
};
/*
* Encoder which doesn't stop counting bytes
* even if it reaches the end of the buffer.
*/
static int
overrun_encoder_cb(const void *data, size_t size, void *keyp) {
struct overrun_encoder_key *key = keyp;
if(key->computed_size + size > key->buffer_size) {
/*
* Avoid accident on the next call:
* stop adding bytes to the buffer.
*/
key->buffer_size = 0;
} else {
memcpy((char *)key->buffer + key->computed_size, data, size);
key->computed_size += size;
}
return 0;
}
/*
* Encoder which help convert the application level encoder failure into EIO.
*/
static int
callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
struct callback_failure_catch_key *key = keyp;
int ret;
ret = key->callback(data, size, key->callback_key);
if(ret < 0) {
key->callback_failed = 1;
}
return ret;
}
asn_enc_rval_t
asn_encode(const asn_codec_ctx_t *opt_codec_parameters,
enum asn_transfer_syntax syntax, asn_TYPE_descriptor_t *td,
void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
struct callback_failure_catch_key cb_key;
asn_enc_rval_t er;
if(!callback) {
errno = EINVAL;
ASN__ENCODE_FAILED;
}
cb_key.callback = callback;
cb_key.callback_key = callback_key;
cb_key.callback_failed = 0;
er = asn_encode_internal(opt_codec_parameters, syntax, td, sptr,
callback_failure_catch_cb, &cb_key);
if(cb_key.callback_failed) {
assert(er.encoded == -1);
assert(errno == EBADF);
errno = EIO;
}
return er;
}
asn_enc_rval_t
asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_parameters,
enum asn_transfer_syntax syntax, asn_TYPE_descriptor_t *td,
void *sptr, void *buffer, size_t buffer_size) {
struct overrun_encoder_key buf_key;
asn_enc_rval_t er;
if(buffer_size > 0 && !buffer) {
errno = EINVAL;
ASN__ENCODE_FAILED;
}
buf_key.buffer = buffer;
buf_key.buffer_size = buffer_size;
buf_key.computed_size = 0;
er = asn_encode_internal(opt_codec_parameters, syntax, td, sptr,
overrun_encoder_cb, &buf_key);
assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
return er;
}
static asn_enc_rval_t
asn_encode_internal(const asn_codec_ctx_t *opt_codec_parameters,
enum asn_transfer_syntax syntax, asn_TYPE_descriptor_t *td,
void *sptr, asn_app_consume_bytes_f *callback,
void *callback_key) {
asn_enc_rval_t er;
enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
(void)opt_codec_parameters; /* Parameters are not checked on encode yet. */
if(!td || !sptr) {
errno = EINVAL;
ASN__ENCODE_FAILED;
}
switch(syntax) {
case ATS_BER:
/* BER is a superset of DER. */
/* Fall through. */
case ATS_DER:
if(td->op->der_encoder) {
er = der_encode(td, sptr, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->der_encoder) {
errno = EBADF; /* Structure has incorrect form. */
} else {
errno = ENOENT; /* DER is not defined for this type. */
}
}
} else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED;
}
break;
case ATS_CER:
errno = ENOENT; /* Transfer syntax is not defined for any type. */
ASN__ENCODE_FAILED;
#ifdef ASN_DISABLE_OER_SUPPORT
case ATS_BASIC_OER:
case ATS_CANONICAL_OER:
errno = ENOENT; /* PER is not defined. */
ASN__ENCODE_FAILED;
break;
#else /* ASN_DISABLE_OER_SUPPORT */
case ATS_BASIC_OER:
/* CANONICAL-OER is a superset of BASIC-OER. */
/* Fall through. */
case ATS_CANONICAL_OER:
if(td->op->oer_encoder) {
er = oer_encode(td, sptr, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->oer_encoder) {
errno = EBADF; /* Structure has incorrect form. */
} else {
errno = ENOENT; /* OER is not defined for this type. */
}
}
} else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED;
}
break;
#endif /* ASN_DISABLE_OER_SUPPORT */
#ifdef ASN_DISABLE_PER_SUPPORT
case ATS_UNALIGNED_BASIC_PER:
case ATS_UNALIGNED_CANONICAL_PER:
errno = ENOENT; /* PER is not defined. */
ASN__ENCODE_FAILED;
break;
#else /* ASN_DISABLE_PER_SUPPORT */
case ATS_UNALIGNED_BASIC_PER:
/* CANONICAL-UPER is a superset of BASIC-UPER. */
/* Fall through. */
case ATS_UNALIGNED_CANONICAL_PER:
if(td->op->uper_encoder) {
er = uper_encode(td, sptr, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->uper_encoder) {
errno = EBADF; /* Structure has incorrect form. */
} else {
errno = ENOENT; /* UPER 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:
/* CANONICAL-XER is a superset of BASIC-XER. */
xer_flags &= ~XER_F_CANONICAL;
xer_flags |= XER_F_BASIC;
/* Fall through. */
case ATS_CANONICAL_XER:
if(td->op->xer_encoder) {
er = xer_encode(td, sptr, xer_flags, callback, callback_key);
if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->xer_encoder) {
errno = EBADF; /* Structure has incorrect form. */
} else {
errno = ENOENT; /* XER is not defined for this type. */
}
}
} else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED;
}
break;
case ATS_NONSTANDARD_PLAINTEXT:
if(td->op->print_struct) {
struct callback_count_bytes_key cb_key;
cb_key.callback = callback;
cb_key.callback_key = callback_key;
cb_key.computed_size = 0;
if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
&cb_key)
< 0
|| callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
errno = EBADF; /* Structure has incorrect form. */
er.encoded = -1;
er.failed_type = td;
er.structure_ptr = sptr;
} else {
er.encoded = cb_key.computed_size;
er.failed_type = 0;
er.structure_ptr = 0;
}
} else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED;
}
break;
default:
errno = ENOENT;
ASN__ENCODE_FAILED;
}
return er;
}
...@@ -15,6 +15,72 @@ ...@@ -15,6 +15,72 @@
extern "C" { extern "C" {
#endif #endif
/*
* A selection of ASN.1 Transfer Syntaxes to use with generalized
* encoder and decoders declared further in this .h file.
*/
enum asn_transfer_syntax {
/* Avoid appearance of a default transfer syntax. */
ATS_INVALID = 0,
/* Plaintext output, useful for debugging. */
ATS_NONSTANDARD_PLAINTEXT,
/*
* X.690:
* BER: Basic Encoding Rules.
* DER: Distinguished Encoding Rules.
* CER: Canonical Encoding Rules.
* DER and CER are more strict variants of BER.
*/
ATS_BER,
ATS_DER,
ATS_CER, /* Only decoding is supported */
/*
* X.696:
* OER: Octet Encoding Rules.
* CANONICAL-OER is a more strict variant of BASIC-OER.
*/
ATS_BASIC_OER,
ATS_CANONICAL_OER,
/*
* X.691:
* PER: Packed Encoding Rules.
* CANONICAL-PER is a more strict variant of BASIC-PER.
* NOTE: Produces or consumes a complete encoding (X.691 (08/2015) #11.1).
*/
ATS_UNALIGNED_BASIC_PER,
ATS_UNALIGNED_CANONICAL_PER,
/*
* X.693:
* XER: XML Encoding Rules.
* CANONICAL-XER is a more strict variant of BASIC-XER.
*/
ATS_BASIC_XER,
ATS_CANONICAL_XER,
};
/*
* A generic encoder for any supported transfer syntax.
* RETURN VALUES:
* The (.encoded) field of the return value is REDEFINED to mean the following:
* >=0: The computed size of the encoded data. Can exceed the (buffer_size).
* -1: Error encoding the structure. See the error code in (errno):
* EINVAL: Incorrect parameters to the function, such as NULLs.
* ENOENT: Encoding transfer syntax is not defined (for this type).
* EBADF: The structure has invalid form or content constraint failed.
* The (.failed_type) and (.structure_ptr) MIGHT be set to the appropriate
* values at the place of failure, if at all possible.
* WARNING: The (.encoded) field of the return value can exceed the buffer_size.
* This is similar to snprintf(3) contract which might return values
* greater than the buffer size.
*/
asn_enc_rval_t asn_encode_to_buffer(
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
enum asn_transfer_syntax,
struct asn_TYPE_descriptor_s *type_to_encode,
void *structure_to_encode,
void *buffer, size_t buffer_size);
/* /*
* Generic type of an application-defined callback to return various * Generic type of an application-defined callback to return various
* types of data to the application. * types of data to the application.
...@@ -22,9 +88,30 @@ extern "C" { ...@@ -22,9 +88,30 @@ extern "C" {
* -1: Failed to consume bytes. Abort the mission. * -1: Failed to consume bytes. Abort the mission.
* Non-negative return values indicate success, and ignored. * Non-negative return values indicate success, and ignored.
*/ */
typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size, typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size,
void *application_specific_key); void *application_specific_key);
/*
* A generic encoder for any supported transfer syntax.
* Returns the comprehensive encoding result descriptor (see asn_codecs.h).
* RETURN VALUES:
* The negative (.encoded) field of the return values is accompanied with the
* following error codes (errno):
* EINVAL: Incorrect parameters to the function, such as NULLs.
* ENOENT: Encoding transfer syntax is not defined (for this type).
* EBADF: The structure has invalid form or content constraint failed.
* EIO: The (callback) has returned negative value during encoding.
*/
asn_enc_rval_t asn_encode(
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
enum asn_transfer_syntax,
struct asn_TYPE_descriptor_s *type_to_encode,
void *structure_to_encode,
asn_app_consume_bytes_f *callback, void *callback_key);
/* /*
* A callback of this type is called whenever constraint validation fails * A callback of this type is called whenever constraint validation fails
* on some ASN.1 type. See "constraints.h" for more details on constraint * on some ASN.1 type. See "constraints.h" for more details on constraint
...@@ -38,6 +125,7 @@ typedef void (asn_app_constraint_failed_f)(void *application_specific_key, ...@@ -38,6 +125,7 @@ typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
const void *structure_which_failed_ptr, const void *structure_which_failed_ptr,
const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5); const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -22,20 +22,31 @@ ...@@ -22,20 +22,31 @@
#include <asn_internal.h> /* for ASN__DEFAULT_STACK_MAX */ #include <asn_internal.h> /* for ASN__DEFAULT_STACK_MAX */
/* Convert "Type" defined by -DPDU into "asn_DEF_Type" */ /* Convert "Type" defined by -DPDU into "asn_DEF_Type" */
#ifndef NO_ASN_PDU
#ifndef PDU
#error Define -DPDU to compile this sample converter.
#endif
#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */
extern asn_TYPE_descriptor_t *asn_pdu_collection[];
#endif
#define ASN_DEF_PDU(t) asn_DEF_ ## t #define ASN_DEF_PDU(t) asn_DEF_ ## t
#define DEF_PDU_Type(t) ASN_DEF_PDU(t) #define DEF_PDU_Type(t) ASN_DEF_PDU(t)
#define PDU_Type DEF_PDU_Type(PDU) #define PDU_Type DEF_PDU_Type(PDU)
extern asn_TYPE_descriptor_t PDU_Type; /* ASN.1 type to be decoded */ extern asn_TYPE_descriptor_t PDU_Type; /* ASN.1 type to be decoded */
#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */ #define PDU_Type_Ptr (&PDU_Type)
extern asn_TYPE_descriptor_t *asn_pdu_collection[]; #else /* NO_ASN_PDU */
#endif #define PDU_Type_Ptr NULL
#endif /* NO_ASN_PDU */
/* /*
* Open file and parse its contens. * Open file and parse its contens.
*/ */
static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU, static void *data_decode_from_file(enum asn_transfer_syntax,
FILE *file, const char *name, ssize_t suggested_bufsize, int first_pdu); asn_TYPE_descriptor_t *asnTypeOfPDU,
FILE *file, const char *name,
ssize_t suggested_bufsize, int first_pdu);
static int write_out(const void *buffer, size_t size, void *key); static int write_out(const void *buffer, size_t size, void *key);
static FILE *argument_to_file(char *av[], int idx); static FILE *argument_to_file(char *av[], int idx);
static char *argument_to_name(char *av[], int idx); static char *argument_to_name(char *av[], int idx);
...@@ -46,24 +57,6 @@ static int opt_stack; /* -s (maximum stack size) */ ...@@ -46,24 +57,6 @@ static int opt_stack; /* -s (maximum stack size) */
static int opt_nopad; /* -per-nopad (PER input is not padded) */ static int opt_nopad; /* -per-nopad (PER input is not padded) */
static int opt_onepdu; /* -1 (decode single PDU) */ static int opt_onepdu; /* -1 (decode single PDU) */
/* Input data format selector */
static enum input_format {
INP_BER, /* -iber: BER input */
INP_XER, /* -ixer: XER input */
INP_OER, /* -ioer: OER input */
INP_PER /* -iper: Unaligned PER input */
} iform; /* -i<format> */
/* Output data format selector */
static enum output_format {
OUT_XER, /* -oxer: XER (XML) output */
OUT_DER, /* -oder: DER (BER) output */
OUT_OER, /* -ooer: Canonical OER output */
OUT_PER, /* -oper: Unaligned PER output */
OUT_TEXT, /* -otext: semi-structured text */
OUT_NULL /* -onull: No pretty-printing */
} oform; /* -o<format> */
#ifdef JUNKTEST /* Enable -J <probability> */ #ifdef JUNKTEST /* Enable -J <probability> */
#define JUNKOPT "J:" #define JUNKOPT "J:"
static double opt_jprob; /* Junk bit probability */ static double opt_jprob; /* Junk bit probability */
...@@ -85,20 +78,60 @@ DEBUG(const char *fmt, ...) { ...@@ -85,20 +78,60 @@ DEBUG(const char *fmt, ...) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
static const char *
ats_simple_name(enum asn_transfer_syntax syntax) {
switch(syntax) {
case ATS_INVALID:
return "/dev/null";
case ATS_NONSTANDARD_PLAINTEXT:
return "plaintext";
case ATS_BER:
return "BER";
case ATS_DER:
return "DER";
case ATS_CER:
return "CER";
case ATS_BASIC_OER:
case ATS_CANONICAL_OER:
return "OER";
case ATS_BASIC_XER:
case ATS_CANONICAL_XER:
return "XER";
case ATS_UNALIGNED_BASIC_PER:
case ATS_UNALIGNED_CANONICAL_PER:
return "PER";
default:
return "<?>";
}
}
int int
main(int ac, char *av[]) { main(int ac, char *av[]) {
FILE *binary_out; FILE *binary_out;
static asn_TYPE_descriptor_t *pduType = &PDU_Type; static asn_TYPE_descriptor_t *pduType = PDU_Type_Ptr;
ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */ ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */
int number_of_iterations = 1; int number_of_iterations = 1;
int num; int num;
int ch; int ch;
enum asn_transfer_syntax isyntax = ATS_INVALID;
enum asn_transfer_syntax osyntax = ATS_INVALID;
#ifndef PDU
if(!pduType) {
fprintf(stderr, "No -DPDU defined during compilation.\n");
#ifdef NO_ASN_PDU
exit(0);
#else
exit(EX_SOFTWARE);
#endif
}
#endif
/* Figure out if specialty decoder needs to be default */ /* Figure out if specialty decoder needs to be default */
if(pduType->op->oer_decoder) if(pduType->op->oer_decoder)
iform = INP_OER; isyntax = ATS_BASIC_OER;
else if(pduType->op->uper_decoder) else if(pduType->op->uper_decoder)
iform = INP_PER; isyntax = ATS_UNALIGNED_BASIC_PER;
/* /*
* Pocess the command-line argments. * Pocess the command-line argments.
...@@ -106,24 +139,24 @@ main(int ac, char *av[]) { ...@@ -106,24 +139,24 @@ main(int ac, char *av[]) {
while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1) while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
switch(ch) { switch(ch) {
case 'i': case 'i':
if(optarg[0] == 'b') { iform = INP_BER; break; } if(optarg[0] == 'b') { isyntax = ATS_BER; break; }
if(optarg[0] == 'x') { iform = INP_XER; break; } if(optarg[0] == 'x') { isyntax = ATS_BASIC_XER; break; }
if(pduType->op->oer_decoder if(pduType->op->oer_decoder
&& optarg[0] == 'o') { iform = INP_OER; break; } && optarg[0] == 'o') { isyntax = ATS_BASIC_OER; break; }
if(pduType->op->uper_decoder if(pduType->op->uper_decoder
&& optarg[0] == 'p') { iform = INP_PER; break; } && optarg[0] == 'p') { isyntax = ATS_UNALIGNED_BASIC_PER; break; }
fprintf(stderr, "-i<format>: '%s': improper format selector\n", fprintf(stderr, "-i<format>: '%s': improper format selector\n",
optarg); optarg);
exit(EX_UNAVAILABLE); exit(EX_UNAVAILABLE);
case 'o': case 'o':
if(optarg[0] == 'd') { oform = OUT_DER; break; } if(optarg[0] == 'd') { osyntax = ATS_DER; break; }
if(pduType->op->oer_encoder if(pduType->op->oer_encoder
&& optarg[0] == 'o') { oform = OUT_OER; break; } && optarg[0] == 'o') { osyntax = ATS_CANONICAL_OER; break; }
if(pduType->op->uper_encoder if(pduType->op->uper_encoder
&& optarg[0] == 'p') { oform = OUT_PER; break; } && optarg[0] == 'p') { osyntax = ATS_UNALIGNED_CANONICAL_PER; break; }
if(optarg[0] == 'x') { oform = OUT_XER; break; } if(optarg[0] == 'x') { osyntax = ATS_BASIC_XER; break; }
if(optarg[0] == 't') { oform = OUT_TEXT; break; } if(optarg[0] == 't') { osyntax = ATS_NONSTANDARD_PLAINTEXT; break; }
if(optarg[0] == 'n') { oform = OUT_NULL; break; } if(optarg[0] == 'n') { osyntax = ATS_INVALID; break; }
fprintf(stderr, "-o<format>: '%s': improper format selector\n", fprintf(stderr, "-o<format>: '%s': improper format selector\n",
optarg); optarg);
exit(EX_UNAVAILABLE); exit(EX_UNAVAILABLE);
...@@ -219,14 +252,14 @@ main(int ac, char *av[]) { ...@@ -219,14 +252,14 @@ main(int ac, char *av[]) {
if(pduType->op->oer_decoder) if(pduType->op->oer_decoder)
fprintf(stderr, fprintf(stderr,
" -ioer Input is in OER (Octet Encoding Rules)%s\n", " -ioer Input is in OER (Octet Encoding Rules)%s\n",
iform == INP_OER ? " (DEFAULT)" : ""); isyntax == ATS_BASIC_OER ? " (DEFAULT)" : "");
if(pduType->op->uper_decoder) if(pduType->op->uper_decoder)
fprintf(stderr, fprintf(stderr,
" -iper Input is in Unaligned PER (Packed Encoding Rules)%s\n", " -iper Input is in Unaligned PER (Packed Encoding Rules)%s\n",
iform == INP_PER ? " (DEFAULT)" : ""); isyntax == ATS_UNALIGNED_BASIC_PER ? " (DEFAULT)" : "");
fprintf(stderr, fprintf(stderr,
" -iber Input is in BER (Basic Encoding Rules)%s\n", " -iber Input is in BER (Basic Encoding Rules)%s\n",
iform == INP_BER ? " (DEFAULT)" : ""); isyntax == ATS_BER ? " (DEFAULT)" : "");
fprintf(stderr, fprintf(stderr,
" -ixer Input is in XER (XML Encoding Rules)\n"); " -ixer Input is in XER (XML Encoding Rules)\n");
if(pduType->op->oer_encoder) if(pduType->op->oer_encoder)
...@@ -273,7 +306,7 @@ main(int ac, char *av[]) { ...@@ -273,7 +306,7 @@ main(int ac, char *av[]) {
} }
if(isatty(1)) { if(isatty(1)) {
const int is_text_output = oform == OUT_TEXT || oform == OUT_XER; const int is_text_output = osyntax == ATS_NONSTANDARD_PLAINTEXT || osyntax == ATS_CANONICAL_XER || osyntax == ATS_BASIC_XER;
if(is_text_output) { if(is_text_output) {
binary_out = stdout; binary_out = stdout;
} else { } else {
...@@ -301,11 +334,11 @@ main(int ac, char *av[]) { ...@@ -301,11 +334,11 @@ main(int ac, char *av[]) {
char *name = argument_to_name(av, ac_i); char *name = argument_to_name(av, ac_i);
int first_pdu; int first_pdu;
for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) { for(first_pdu = 1; file && (first_pdu || !opt_onepdu); first_pdu = 0) {
/* /*
* Decode the encoded structure from file. * Decode the encoded structure from file.
*/ */
structure = data_decode_from_file(pduType, file, name, structure = data_decode_from_file(isyntax, pduType, file, name,
suggested_bufsize, first_pdu); suggested_bufsize, first_pdu);
if(!structure) { if(!structure) {
if(errno) { if(errno) {
...@@ -330,59 +363,24 @@ main(int ac, char *av[]) { ...@@ -330,59 +363,24 @@ main(int ac, char *av[]) {
} }
} }
switch(oform) { if(osyntax == ATS_INVALID) {
case OUT_NULL:
#ifdef JUNKTEST #ifdef JUNKTEST
if(opt_jprob == 0.0) if(opt_jprob == 0.0) {
#endif
fprintf(stderr, "%s: decoded successfully\n", name); fprintf(stderr, "%s: decoded successfully\n", name);
break;
case OUT_TEXT: /* -otext */
asn_fprint(stdout, pduType, structure);
break;
case OUT_XER: /* -oxer */
if(xer_fprint(stdout, pduType, structure)) {
fprintf(stderr, "%s: Cannot convert %s into XML\n", name,
pduType->name);
exit(EX_UNAVAILABLE);
}
break;
case OUT_DER:
erv = der_encode(pduType, structure, write_out, binary_out);
if(erv.encoded < 0) {
fprintf(stderr, "%s: Cannot convert %s into DER\n", name,
pduType->name);
exit(EX_UNAVAILABLE);
} }
DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
break;
case OUT_OER:
#ifdef ASN_DISABLE_OER_SUPPORT
erv.encoded = -1;
#else #else
erv = oer_encode(pduType, structure, write_out, binary_out); fprintf(stderr, "%s: decoded successfully\n", name);
#endif
if(erv.encoded < 0) {
fprintf(stderr, "%s: Cannot convert %s into OER\n", name,
pduType->name);
exit(EX_UNAVAILABLE);
}
DEBUG("Encoded in %ld bytes of OER", (long)erv.encoded);
break;
case OUT_PER:
#ifdef ASN_DISABLE_PER_SUPPORT
erv.encoded = -1;
#else
erv = uper_encode(pduType, structure, write_out, binary_out);
#endif #endif
if(erv.encoded < 0) { } else {
fprintf(stderr, erv = asn_encode(NULL, osyntax, pduType, structure, write_out, binary_out);
"%s: Cannot convert %s into Unaligned PER\n", name,
pduType->name); if(erv.encoded == -1) {
fprintf(stderr, "%s: Cannot convert %s into %s\n", name,
pduType->name, ats_simple_name(osyntax));
exit(EX_UNAVAILABLE); exit(EX_UNAVAILABLE);
} }
DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded); DEBUG("Encoded in %zd bytes of %s", erv.encoded,
break; ats_simple_name(osyntax));
} }
ASN_STRUCT_FREE(*pduType, structure); ASN_STRUCT_FREE(*pduType, structure);
...@@ -610,7 +608,7 @@ static void add_bytes_to_buffer(const void *data2add, size_t bytes) { ...@@ -610,7 +608,7 @@ static void add_bytes_to_buffer(const void *data2add, size_t bytes) {
} }
static void * static void *
data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) { data_decode_from_file(enum asn_transfer_syntax isyntax, asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
static uint8_t *fbuf; static uint8_t *fbuf;
static ssize_t fbuf_size; static ssize_t fbuf_size;
static asn_codec_ctx_t s_codec_ctx; static asn_codec_ctx_t s_codec_ctx;
...@@ -688,12 +686,12 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na ...@@ -688,12 +686,12 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na
junk_bytes_with_probability(i_bptr, i_size, opt_jprob); junk_bytes_with_probability(i_bptr, i_size, opt_jprob);
#endif #endif
switch(iform) { switch(isyntax) {
case INP_BER: case ATS_BER:
rval = ber_decode(opt_codec_ctx, pduType, rval = ber_decode(opt_codec_ctx, pduType,
(void **)&structure, i_bptr, i_size); (void **)&structure, i_bptr, i_size);
break; break;
case INP_OER: case ATS_BASIC_OER:
#ifdef ASN_DISABLE_OER_SUPPORT #ifdef ASN_DISABLE_OER_SUPPORT
rval.code = RC_FAIL; rval.code = RC_FAIL;
rval.consumed = 0; rval.consumed = 0;
...@@ -702,11 +700,11 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na ...@@ -702,11 +700,11 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na
(void **)&structure, i_bptr, i_size); (void **)&structure, i_bptr, i_size);
#endif #endif
break; break;
case INP_XER: case ATS_BASIC_XER:
rval = xer_decode(opt_codec_ctx, pduType, rval = xer_decode(opt_codec_ctx, pduType,
(void **)&structure, i_bptr, i_size); (void **)&structure, i_bptr, i_size);
break; break;
case INP_PER: case ATS_UNALIGNED_BASIC_PER:
#ifdef ASN_DISABLE_PER_SUPPORT #ifdef ASN_DISABLE_PER_SUPPORT
rval.code = RC_FAIL; rval.code = RC_FAIL;
rval.consumed = 0; rval.consumed = 0;
...@@ -740,6 +738,9 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na ...@@ -740,6 +738,9 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na
break; break;
} }
break; break;
default:
rval.consumed = 0;
/* Fall through */
} }
DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d", DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d",
(long)DynamicBuffer.length, (long)DynamicBuffer.length,
...@@ -804,7 +805,7 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na ...@@ -804,7 +805,7 @@ data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *na
*/ */
if(on_first_pdu if(on_first_pdu
|| DynamicBuffer.length || DynamicBuffer.length
|| new_offset - old_offset > ((iform == INP_XER)?sizeof("\r\n")-1:0) || new_offset - old_offset > ((isyntax == ATS_BASIC_XER)?sizeof("\r\n")-1:0)
) { ) {
#ifdef JUNKTEST #ifdef JUNKTEST
......
...@@ -41,7 +41,7 @@ constr_SET.h constr_SET.c ...@@ -41,7 +41,7 @@ constr_SET.h constr_SET.c
constr_SET_OF.h constr_SET_OF.c asn_SET_OF.h constr_SET_OF.h constr_SET_OF.c asn_SET_OF.h
COMMON-FILES: # THIS IS A SPECIAL SECTION COMMON-FILES: # THIS IS A SPECIAL SECTION
asn_application.h # Applications should include this file asn_application.h asn_application.c # Applications should include this file
asn_ioc.h # Information Object Classes, runtime support asn_ioc.h # Information Object Classes, runtime support
asn_system.h # Platform-dependent types asn_system.h # Platform-dependent types
asn_codecs.h # Return types of encoders and decoders asn_codecs.h # Return types of encoders and decoders
......
...@@ -15,8 +15,8 @@ extern "C" { ...@@ -15,8 +15,8 @@ extern "C" {
struct asn_TYPE_descriptor_s; /* Forward declaration */ struct asn_TYPE_descriptor_s; /* Forward declaration */
/* /*
* Unaligned PER decoder of a "complete encoding" as per X.691#10.1. * Unaligned PER decoder of a "complete encoding" as per X.691 (08/2015) #11.1.
* On success, this call always returns (.consumed >= 1), as per X.691#10.1.3. * On success, this call always returns (.consumed >= 1), as per #11.1.3.
*/ */
asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment