From e73187936b9f79995f6ad4bc5b54ba45e837c29e Mon Sep 17 00:00:00 2001 From: Lev Walkin <vlm@lionet.info> Date: Sun, 26 Sep 2004 13:11:01 +0000 Subject: [PATCH] generic primitive codec added --- skeletons/ber_codec_prim.c | 131 +++++++++++++++++++++++++++++++++++++ skeletons/ber_codec_prim.h | 19 ++++++ 2 files changed, 150 insertions(+) create mode 100644 skeletons/ber_codec_prim.c create mode 100644 skeletons/ber_codec_prim.h diff --git a/skeletons/ber_codec_prim.c b/skeletons/ber_codec_prim.c new file mode 100644 index 00000000..6bb36135 --- /dev/null +++ b/skeletons/ber_codec_prim.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include <asn_internal.h> +#include <ber_codec_prim.h> +#include <assert.h> +#include <errno.h> + +/* + * Decode an always-primitive type. + */ +ber_dec_rval_t +ber_decode_primitive(asn1_TYPE_descriptor_t *td, + void **sptr, void *buf_ptr, size_t size, int tag_mode) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr; + ber_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(st == NULL) { + (void *)st = *sptr = CALLOC(1, sizeof(*st)); + if(st == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as plain primitive (tm=%d)", + td->name, tag_mode); + + /* + * Check tags and extract value length. + */ + rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + st->buf = (uint8_t *)MALLOC(length + 1); + if(st->buf) { + st->size = length; + } else { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + memcpy(st->buf, buf_ptr, length); + st->buf[length] = '\0'; /* Just in case */ + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s", + (long)rval.consumed, + (long)length, td->name); + + return rval; +} + +/* + * Encode an always-primitive type using DER. + */ +asn_enc_rval_t +der_encode_primitive(asn1_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + ASN_DEBUG("%s %s as a primitive type (tm=%d)", + cb?"Encoding":"Estimating", td->name, tag_mode); + + erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag, + cb, app_key); + ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + + if(cb && st->buf) { + if(cb(st->buf, st->size, app_key) < 0) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + } else { + assert(st->buf || st->size == 0); + } + + erval.encoded += st->size; + + return erval; +} + +void +ASN__PRIMITIVE_TYPE_free(asn1_TYPE_descriptor_t *td, void *sptr, + int contents_only) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + if(!td || !sptr) + return; + + ASN_DEBUG("Freeing %s as a primitive type", td->name); + + if(st->buf) + FREEMEM(st->buf); + + if(!contents_only) + FREEMEM(st); +} + diff --git a/skeletons/ber_codec_prim.h b/skeletons/ber_codec_prim.h new file mode 100644 index 00000000..aa6a5c59 --- /dev/null +++ b/skeletons/ber_codec_prim.h @@ -0,0 +1,19 @@ +/*- + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_CODEC_of_PRIMITIVE_TYPE_H_ +#define _BER_CODEC_of_PRIMITIVE_TYPE_H_ + +#include <asn_application.h> + +typedef struct ASN__PRIMITIVE_TYPE_s { + uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */ + int size; /* Size of the buffer */ +} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */ + +asn_struct_free_f ASN__PRIMITIVE_TYPE_free; +ber_type_decoder_f ber_decode_primitive; +der_type_encoder_f der_encode_primitive; + +#endif /* _BER_CODEC_of_PRIMITIVE_TYPE_H_ */ -- GitLab