push code back with legal issues fix
[ric-plt/e2mgr.git] / E2Manager / asn1codec / e2ap_engine / asn_codecs_prim.c
1
2 /*-
3  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <asn_codecs_prim.h>
8 #include <errno.h>
9
10 /*
11  * Decode an always-primitive type.
12  */
13 asn_dec_rval_t
14 ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
15                      const asn_TYPE_descriptor_t *td, void **sptr,
16                      const void *buf_ptr, size_t size, int tag_mode) {
17     ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
18         asn_dec_rval_t rval;
19         ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
20
21         /*
22          * If the structure is not there, allocate it.
23          */
24         if(st == NULL) {
25                 st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
26                 if(st == NULL) ASN__DECODE_FAILED;
27                 *sptr = (void *)st;
28         }
29
30         ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
31                 td->name, tag_mode);
32
33         /*
34          * Check tags and extract value length.
35          */
36         rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
37                         tag_mode, 0, &length, 0);
38         if(rval.code != RC_OK)
39                 return rval;
40
41         ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
42
43         /*
44          * Make sure we have this length.
45          */
46         buf_ptr = ((const char *)buf_ptr) + rval.consumed;
47         size -= rval.consumed;
48         if(length > (ber_tlv_len_t)size) {
49                 rval.code = RC_WMORE;
50                 rval.consumed = 0;
51                 return rval;
52         }
53
54         st->size = (int)length;
55         /* The following better be optimized away. */
56         if(sizeof(st->size) != sizeof(length)
57                         && (ber_tlv_len_t)st->size != length) {
58                 st->size = 0;
59                 ASN__DECODE_FAILED;
60         }
61
62         st->buf = (uint8_t *)MALLOC(length + 1);
63         if(!st->buf) {
64                 st->size = 0;
65                 ASN__DECODE_FAILED;
66         }
67
68         memcpy(st->buf, buf_ptr, length);
69         st->buf[length] = '\0';         /* Just in case */
70
71         rval.code = RC_OK;
72         rval.consumed += length;
73
74         ASN_DEBUG("Took %ld/%ld bytes to encode %s",
75                 (long)rval.consumed,
76                 (long)length, td->name);
77
78         return rval;
79 }
80
81 /*
82  * Encode an always-primitive type using DER.
83  */
84 asn_enc_rval_t
85 der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
86                      int tag_mode, ber_tlv_tag_t tag,
87                      asn_app_consume_bytes_f *cb, void *app_key) {
88         asn_enc_rval_t erval = {0,0,0};
89         const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
90
91         ASN_DEBUG("%s %s as a primitive type (tm=%d)",
92                 cb?"Encoding":"Estimating", td->name, tag_mode);
93
94         erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
95                 cb, app_key);
96         ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
97         if(erval.encoded == -1) {
98                 erval.failed_type = td;
99                 erval.structure_ptr = sptr;
100                 return erval;
101         }
102
103         if(cb && st->buf) {
104                 if(cb(st->buf, st->size, app_key) < 0) {
105                         erval.encoded = -1;
106                         erval.failed_type = td;
107                         erval.structure_ptr = sptr;
108                         return erval;
109                 }
110         } else {
111                 assert(st->buf || st->size == 0);
112         }
113
114         erval.encoded += st->size;
115         ASN__ENCODED_OK(erval);
116 }
117
118 void
119 ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
120                          enum asn_struct_free_method method) {
121     ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
122
123         if(!td || !sptr)
124                 return;
125
126         ASN_DEBUG("Freeing %s as a primitive type", td->name);
127
128         if(st->buf)
129                 FREEMEM(st->buf);
130
131     switch(method) {
132     case ASFM_FREE_EVERYTHING:
133         FREEMEM(sptr);
134         break;
135     case ASFM_FREE_UNDERLYING:
136         break;
137     case ASFM_FREE_UNDERLYING_AND_RESET:
138         memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
139         break;
140     }
141 }
142
143
144 /*
145  * Local internal type passed around as an argument.
146  */
147 struct xdp_arg_s {
148     const asn_TYPE_descriptor_t *type_descriptor;
149     void *struct_key;
150         xer_primitive_body_decoder_f *prim_body_decoder;
151         int decoded_something;
152         int want_more;
153 };
154
155 /*
156  * Since some kinds of primitive values can be encoded using value-specific
157  * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
158  * be supplied with such tags to parse them as needed.
159  */
160 static int
161 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
162         struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
163         enum xer_pbd_rval bret;
164
165         /*
166          * The chunk_buf is guaranteed to start at '<'.
167          */
168         assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
169
170         /*
171          * Decoding was performed once already. Prohibit doing it again.
172          */
173         if(arg->decoded_something)
174                 return -1;
175
176         bret = arg->prim_body_decoder(arg->type_descriptor,
177                 arg->struct_key, chunk_buf, chunk_size);
178         switch(bret) {
179         case XPBD_SYSTEM_FAILURE:
180         case XPBD_DECODER_LIMIT:
181         case XPBD_BROKEN_ENCODING:
182                 break;
183         case XPBD_BODY_CONSUMED:
184                 /* Tag decoded successfully */
185                 arg->decoded_something = 1;
186                 /* Fall through */
187         case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
188                 return 0;
189         }
190
191         return -1;
192 }
193
194 static ssize_t
195 xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
196         struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
197         enum xer_pbd_rval bret;
198         size_t lead_wsp_size;
199
200         if(arg->decoded_something) {
201                 if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
202                         /*
203                          * Example:
204                          * "<INTEGER>123<!--/--> </INTEGER>"
205                          *                      ^- chunk_buf position.
206                          */
207                         return chunk_size;
208                 }
209                 /*
210                  * Decoding was done once already. Prohibit doing it again.
211                  */
212                 return -1;
213         }
214
215         if(!have_more) {
216                 /*
217                  * If we've received something like "1", we can't really
218                  * tell whether it is really `1` or `123`, until we know
219                  * that there is no more data coming.
220                  * The have_more argument will be set to 1 once something
221                  * like this is available to the caller of this callback:
222                  * "1<tag_start..."
223                  */
224                 arg->want_more = 1;
225                 return -1;
226         }
227
228         lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
229         chunk_buf = (const char *)chunk_buf + lead_wsp_size;
230         chunk_size -= lead_wsp_size;
231
232         bret = arg->prim_body_decoder(arg->type_descriptor,
233                 arg->struct_key, chunk_buf, chunk_size);
234         switch(bret) {
235         case XPBD_SYSTEM_FAILURE:
236         case XPBD_DECODER_LIMIT:
237         case XPBD_BROKEN_ENCODING:
238                 break;
239         case XPBD_BODY_CONSUMED:
240                 /* Tag decoded successfully */
241                 arg->decoded_something = 1;
242                 /* Fall through */
243         case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
244                 return lead_wsp_size + chunk_size;
245         }
246
247         return -1;
248 }
249
250
251 asn_dec_rval_t
252 xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
253                      const asn_TYPE_descriptor_t *td, void **sptr,
254                      size_t struct_size, const char *opt_mname,
255                      const void *buf_ptr, size_t size,
256                      xer_primitive_body_decoder_f *prim_body_decoder) {
257     const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
258         asn_struct_ctx_t s_ctx;
259         struct xdp_arg_s s_arg;
260         asn_dec_rval_t rc;
261
262         /*
263          * Create the structure if does not exist.
264          */
265         if(!*sptr) {
266                 *sptr = CALLOC(1, struct_size);
267                 if(!*sptr) ASN__DECODE_FAILED;
268         }
269
270         memset(&s_ctx, 0, sizeof(s_ctx));
271         s_arg.type_descriptor = td;
272         s_arg.struct_key = *sptr;
273         s_arg.prim_body_decoder = prim_body_decoder;
274         s_arg.decoded_something = 0;
275         s_arg.want_more = 0;
276
277         rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
278                 xml_tag, buf_ptr, size,
279                 xer_decode__unexpected_tag, xer_decode__primitive_body);
280         switch(rc.code) {
281         case RC_OK:
282                 if(!s_arg.decoded_something) {
283                         char ch;
284                         ASN_DEBUG("Primitive body is not recognized, "
285                                 "supplying empty one");
286                         /*
287                          * Decoding opportunity has come and gone.
288                          * Where's the result?
289                          * Try to feed with empty body, see if it eats it.
290                          */
291                         if(prim_body_decoder(s_arg.type_descriptor,
292                                 s_arg.struct_key, &ch, 0)
293                                         != XPBD_BODY_CONSUMED) {
294                                 /*
295                                  * This decoder does not like empty stuff.
296                                  */
297                                 ASN__DECODE_FAILED;
298                         }
299                 }
300                 break;
301         case RC_WMORE:
302                 /*
303                  * Redo the whole thing later.
304                  * We don't have a context to save intermediate parsing state.
305                  */
306                 rc.consumed = 0;
307                 break;
308         case RC_FAIL:
309                 rc.consumed = 0;
310                 if(s_arg.want_more)
311                         rc.code = RC_WMORE;
312                 else
313                         ASN__DECODE_FAILED;
314                 break;
315         }
316         return rc;
317 }
318