]> git.stg.codes - stg.git/blob - libs/smux/oer_encoder.c
Merge remote-tracking branch 'github/master'
[stg.git] / libs / smux / oer_encoder.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_internal.h>
6 #include <asn_codecs_prim.h>
7
8 /*
9  * The OER encoder of any type.
10  */
11 asn_enc_rval_t
12 oer_encode(const asn_TYPE_descriptor_t *type_descriptor, const void *struct_ptr,
13            asn_app_consume_bytes_f *consume_bytes, void *app_key) {
14     ASN_DEBUG("OER encoder invoked for %s", type_descriptor->name);
15
16     /*
17      * Invoke type-specific encoder.
18      */
19     return type_descriptor->op->oer_encoder(
20         type_descriptor, 0,
21         struct_ptr, /* Pointer to the destination structure */
22         consume_bytes, app_key);
23 }
24
25 /*
26  * Argument type and callback necessary for oer_encode_to_buffer().
27  */
28 typedef struct enc_to_buf_arg {
29         void *buffer;
30         size_t left;
31 } enc_to_buf_arg;
32 static int
33 encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
34     enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
35
36     if(arg->left < size) return -1; /* Data exceeds the available buffer size */
37
38     memcpy(arg->buffer, buffer, size);
39     arg->buffer = ((char *)arg->buffer) + size;
40     arg->left -= size;
41
42     return 0;
43 }
44
45 /*
46  * A variant of the oer_encode() which encodes the data into the provided buffer
47  */
48 asn_enc_rval_t
49 oer_encode_to_buffer(const asn_TYPE_descriptor_t *type_descriptor,
50                      const asn_oer_constraints_t *constraints,
51                      const void *struct_ptr, /* Structure to be encoded */
52                      void *buffer,           /* Pre-allocated buffer */
53                      size_t buffer_size      /* Initial buffer size (maximum) */
54 ) {
55     enc_to_buf_arg arg;
56     asn_enc_rval_t ec;
57
58     arg.buffer = buffer;
59     arg.left = buffer_size;
60
61     if(type_descriptor->op->oer_encoder == NULL) {
62         ec.encoded = -1;
63         ec.failed_type = type_descriptor;
64         ec.structure_ptr = struct_ptr;
65         ASN_DEBUG("OER encoder is not defined for %s",
66                 type_descriptor->name);
67     } else {
68         ec = type_descriptor->op->oer_encoder(
69             type_descriptor, constraints,
70             struct_ptr, /* Pointer to the destination structure */
71             encode_to_buffer_cb, &arg);
72         if(ec.encoded != -1) {
73             assert(ec.encoded == (ssize_t)(buffer_size - arg.left));
74             /* Return the encoded contents size */
75         }
76     }
77     return ec;
78 }
79
80 asn_enc_rval_t
81 oer_encode_primitive(const asn_TYPE_descriptor_t *td,
82                      const asn_oer_constraints_t *constraints, const void *sptr,
83                      asn_app_consume_bytes_f *cb, void *app_key) {
84     const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
85     asn_enc_rval_t er = {0, 0, 0};
86     ssize_t ret;
87
88     (void)constraints;
89
90     if(!st) ASN__ENCODE_FAILED;
91
92     ASN_DEBUG("Encoding %s (%" ASN_PRI_SIZE " bytes)", td ? td->name : "", st->size);
93
94     /*
95      * X.696 (08/2015) #27.2
96      */
97     ret = oer_serialize_length(st->size, cb, app_key);
98     if(ret < 0) {
99         ASN__ENCODE_FAILED;
100     }
101     er.encoded += ret;
102
103     er.encoded += st->size;
104     if(cb(st->buf, st->size, app_key) < 0) {
105         ASN__ENCODE_FAILED;
106     } else {
107         ASN__ENCODED_OK(er);
108     }
109 }
110
111 static int
112 oer__count_bytes(const void *buffer, size_t size, void *bytes_ptr) {
113     size_t *bytes = bytes_ptr;
114     (void)buffer;
115     *bytes += size;
116     return 0;
117 }
118
119 ssize_t
120 oer_open_type_put(const asn_TYPE_descriptor_t *td,
121                   const asn_oer_constraints_t *constraints, const void *sptr,
122                   asn_app_consume_bytes_f *cb, void *app_key) {
123     size_t serialized_byte_count = 0;
124     asn_enc_rval_t er;
125     ssize_t len_len;
126
127     er = td->op->oer_encoder(td, constraints, sptr, oer__count_bytes,
128                              &serialized_byte_count);
129     if(er.encoded < 0) return -1;
130     assert(serialized_byte_count == (size_t)er.encoded);
131
132     len_len = oer_serialize_length(serialized_byte_count, cb, app_key);
133     if(len_len == -1) return -1;
134
135     er = td->op->oer_encoder(td, constraints, sptr, cb, app_key);
136     if(er.encoded < 0) return -1;
137     assert(serialized_byte_count == (size_t)er.encoded);
138
139     return len_len + er.encoded;
140 }
141