Skip to content

Commit

Permalink
BNER support: Add top-level bner {en,de}coding
Browse files Browse the repository at this point in the history
The BNER support in the asn1c compiler will only support the BNER variable
encoding rules. The bner_{en,de}code() functions will to see if the PDU
being {en,de}coded is one that requires BNER fixed encoding rules (these
are "BACnet.*PDU". If it is, then it will call bner_fixed_{en,de}coder()
These two functions are declared as weak functions that will return an
error. The intent here is that an external project will provide replacement
functions for these two functions.
  • Loading branch information
ringlej committed Nov 19, 2017
1 parent 6497c12 commit 66e4a97
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 0 deletions.
2 changes: 2 additions & 0 deletions skeletons/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ check_PROGRAMS = \

# BNER Support
libasn1cskeletons_la_SOURCES += \
bner_decoder.c bner_decoder.h \
bner_encoder.c bner_encoder.h \
bner_support.c bner_support.h \
constr_CHOICE_bner.c \
constr_SEQUENCE_bner.c \
Expand Down
75 changes: 75 additions & 0 deletions skeletons/bner_decoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2017 Jon Ringle <[email protected]>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <bner_decoder.h>
#include <errno.h>

/*
* The BNER decoder of any type.
*/
asn_dec_rval_t
bner_decode(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **struct_ptr, const void *ptr,
size_t size) {
asn_codec_ctx_t s_codec_ctx;

if(!td) {
asn_dec_rval_t tmp_error = {RC_FAIL, 0};
ASN_DEBUG("%s: Failed to decode. type_descriptor NULL", __func__);
return tmp_error;
}

/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}

if(is_bner_fixed_pdu(td->name)) {
return bner_fixed_decoder(opt_codec_ctx, td,
struct_ptr, /* Pointer to the dest struct */
ptr, size /* Buffer and its size */
);
}

/*
* Invoke type-specific decoder.
*/
return td->op->bner_decoder(opt_codec_ctx, td,
struct_ptr, /* Pointer to the dest struct */
ptr, size, /* Buffer and its size */
0 /* Default tag mode is 0 */
);
}


__attribute__((weak)) asn_dec_rval_t
bner_fixed_decoder(const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *td,
void **struct_ptr, /* Ptr to a target struct's ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
) {
(void)opt_codec_ctx;
(void)td;
(void)struct_ptr;
(void)buffer;
(void)size;

asn_dec_rval_t tmp_error = {RC_FAIL, 0};
ASN_DEBUG("Failed to decode %s. No bner_fixed_decoder function provided",
td->name);
return tmp_error;
}
48 changes: 48 additions & 0 deletions skeletons/bner_decoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2017 Jon Ringle <[email protected]>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BNER_DECODER_H_
#define _BNER_DECODER_H_

#include <asn_application.h>
#include <bner_support.h>

#ifdef __cplusplus
extern "C" {
#endif

struct asn_TYPE_descriptor_s; /* Forward declaration */
struct asn_codec_ctx_s; /* Forward declaration */

/*
* Type of generic function which decodes the byte stream into the structure.
*/
typedef asn_dec_rval_t(bner_type_decoder_f)(
const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
const void *buf_ptr, size_t size, int tag_mode);

/*
* The BNER decoder of any type.
* This function may be invoked directly from the application.
*/
asn_dec_rval_t bner_decode(const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *td,
void **struct_ptr, /* Ptr to target's struct ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);

asn_dec_rval_t bner_fixed_decoder(const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *td,
void **struct_ptr, /* Ptr to target ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);

#ifdef __cplusplus
}
#endif

#endif /* _BNER_DECODER_H_ */
95 changes: 95 additions & 0 deletions skeletons/bner_encoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2017 Jon Ringle <[email protected]>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <bner_encoder.h>
#include <errno.h>

/*
* The BNER encoder of any type.
*/
asn_enc_rval_t
bner_encode(const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_consume_bytes_f *consume_bytes, void *app_key) {
if(!td) ASN__ENCODE_FAILED;

ASN_DEBUG("BNER encoder invoked for %s", td->name);

if(is_bner_fixed_pdu(td->name)) {
return bner_fixed_encoder(td, sptr, consume_bytes, app_key);
}

/*
* Invoke type-specific encoder.
*/
return td->op->bner_encoder(td, sptr, 0, 0, consume_bytes, app_key);
}

/*
* Argument type and callback necessary for bner_encode_to_buffer().
*/
typedef struct enc_to_buf_arg {
void *buffer;
size_t left;
} enc_to_buf_arg;

static int
encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
enc_to_buf_arg *arg = (enc_to_buf_arg *)key;

if(arg->left < size) return -1; /* Data exceeds the available buffer size */

memcpy(arg->buffer, buffer, size);
arg->buffer = ((char *)arg->buffer) + size;
arg->left -= size;

return 0;
}

/*
* A variant of the bner_encode() which encodes the data into the provided
* buffer
*/
asn_enc_rval_t
bner_encode_to_buffer(const asn_TYPE_descriptor_t *td,
const void *struct_ptr, void *buffer,
size_t buffer_size) {
enc_to_buf_arg arg;
asn_enc_rval_t ec;

arg.buffer = buffer;
arg.left = buffer_size;

if(is_bner_fixed_pdu(td->name)) {
ec = bner_fixed_encoder(td, struct_ptr,
encode_to_buffer_cb, &arg);
} else {
ec = td->op->bner_encoder(
td,
struct_ptr, /* Pointer to the destination structure */
0, 0, encode_to_buffer_cb, &arg);
}

if(ec.encoded != -1) {
assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
/* Return the encoded contents size */
}
return ec;
}

__attribute__((weak)) asn_enc_rval_t
bner_fixed_encoder(const struct asn_TYPE_descriptor_s *td,
const void *sptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key /* Arbitrary callback argument */
) {
(void)td;
(void)sptr;
(void)consume_bytes_cb;
(void)app_key;

ASN_DEBUG("Failed to decode %s. No bner_fixed_encoder function provided",
td->name);
ASN__ENCODE_FAILED;
}
54 changes: 54 additions & 0 deletions skeletons/bner_encoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2017 Jon Ringle <[email protected]>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _BNER_ENCODER_H_
#define _BNER_ENCODER_H_

#include <asn_application.h>
#include <bner_support.h>

#ifdef __cplusplus
extern "C" {
#endif

struct asn_TYPE_descriptor_s; /* Forward declaration */
struct asn_codec_ctx_s; /* Forward declaration */

/*
* Type of the generic BNER encoder.
*/
typedef asn_enc_rval_t(bner_type_encoder_f)(
const struct asn_TYPE_descriptor_s *td,
const void *struct_ptr, /* Structure to be encoded */
int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */
ber_tlv_tag_t tag, asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */
void *app_key /* Arbitrary callback argument */
);

/*
* The BNER encoder of any type.
* This function may be invoked directly by the application.
*/
asn_enc_rval_t bner_encode(const struct asn_TYPE_descriptor_s *td,
const void *struct_ptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key /* Arbitrary callback argument */
);

/* A variant of bner_encode() which encodes data into a pre-allocated buffer */
asn_enc_rval_t bner_encode_to_buffer(const struct asn_TYPE_descriptor_s *td,
const void *struct_ptr, void *buffer,
size_t buffer_size);

asn_enc_rval_t bner_fixed_encoder(const struct asn_TYPE_descriptor_s *td,
const void *sptr, /* Struct to encode */
asn_app_consume_bytes_f *consume_bytes_cb,
void *app_key /* Arbitrary callback arg */
);

#ifdef __cplusplus
}
#endif

#endif /* _BNER_ENCODER_H_ */
3 changes: 3 additions & 0 deletions skeletons/constr_TYPE.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ typedef void asn_oer_constraints_t;
#include <oer_encoder.h> /* Octet Encoding Rules encoder */
#endif

#include <bner_decoder.h> /* BACnet Encoding Rules decoder */
#include <bner_encoder.h> /* BACnet Encoding Rules encoder */

/*
* Free the structure according to its specification.
* Use one of ASN_STRUCT_{FREE,RESET,CONTENTS_ONLY} macros instead.
Expand Down

0 comments on commit 66e4a97

Please sign in to comment.