Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / asn_application.c
1 /*\r
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
3  * Redistribution and modifications are permitted subject to BSD license.\r
4  */\r
5 #include <asn_internal.h>\r
6 #include <asn_application.h>\r
7 #include <errno.h>\r
8 \r
9 static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,\r
10                                           enum asn_transfer_syntax syntax,\r
11                                           const asn_TYPE_descriptor_t *td,\r
12                                           const void *sptr,\r
13                                           asn_app_consume_bytes_f *callback,\r
14                                           void *callback_key);\r
15 \r
16 \r
17 struct callback_count_bytes_key {\r
18     asn_app_consume_bytes_f *callback;\r
19     void *callback_key;\r
20     size_t computed_size;\r
21 };\r
22 \r
23 /*\r
24  * Encoder which just counts bytes that come through it.\r
25  */\r
26 static int\r
27 callback_count_bytes_cb(const void *data, size_t size, void *keyp) {\r
28     struct callback_count_bytes_key *key = keyp;\r
29     int ret;\r
30 \r
31     ret = key->callback(data, size, key->callback_key);\r
32     if(ret >= 0) {\r
33         key->computed_size += size;\r
34     }\r
35 \r
36     return ret;\r
37 }\r
38 \r
39 struct overrun_encoder_key {\r
40     void *buffer;\r
41     size_t buffer_size;\r
42     size_t computed_size;\r
43 };\r
44 \r
45 struct dynamic_encoder_key {\r
46     void *buffer;\r
47     size_t buffer_size;\r
48     size_t computed_size;\r
49 };\r
50 \r
51 struct callback_failure_catch_key {\r
52     asn_app_consume_bytes_f *callback;\r
53     void *callback_key;\r
54     int callback_failed;\r
55 };\r
56 \r
57 /*\r
58  * Encoder which doesn't stop counting bytes\r
59  * even if it reaches the end of the buffer.\r
60  */\r
61 static int\r
62 overrun_encoder_cb(const void *data, size_t size, void *keyp) {\r
63     struct overrun_encoder_key *key = keyp;\r
64 \r
65     if(key->computed_size + size > key->buffer_size) {\r
66         /*\r
67          * Avoid accident on the next call:\r
68          * stop adding bytes to the buffer.\r
69          */\r
70         key->buffer_size = 0;\r
71     } else {\r
72         memcpy((char *)key->buffer + key->computed_size, data, size);\r
73     }\r
74     key->computed_size += size;\r
75 \r
76     return 0;\r
77 }\r
78 \r
79 /*\r
80  * Encoder which dynamically allocates output, and continues\r
81  * to count even if allocation failed.\r
82  */\r
83 static int\r
84 dynamic_encoder_cb(const void *data, size_t size, void *keyp) {\r
85     struct dynamic_encoder_key *key = keyp;\r
86 \r
87     if(key->buffer) {\r
88         if(key->computed_size + size >= key->buffer_size) {\r
89             void *p;\r
90             size_t new_size = key->buffer_size;\r
91 \r
92             do {\r
93                 new_size *= 2;\r
94             } while(new_size <= key->computed_size + size);\r
95 \r
96             p = REALLOC(key->buffer, new_size);\r
97             if(p) {\r
98                 key->buffer = p;\r
99                 key->buffer_size = new_size;\r
100             } else {\r
101                 FREEMEM(key->buffer);\r
102                 key->buffer = 0;\r
103                 key->buffer_size = 0;\r
104                 key->computed_size += size;\r
105                 return 0;\r
106             }\r
107         }\r
108         memcpy((char *)key->buffer + key->computed_size, data, size);\r
109     }\r
110 \r
111     key->computed_size += size;\r
112 \r
113     return 0;\r
114 }\r
115 \r
116 /*\r
117  * Encoder which help convert the application level encoder failure into EIO.\r
118  */\r
119 static int\r
120 callback_failure_catch_cb(const void *data, size_t size, void *keyp) {\r
121     struct callback_failure_catch_key *key = keyp;\r
122     int ret;\r
123 \r
124     ret = key->callback(data, size, key->callback_key);\r
125     if(ret < 0) {\r
126         key->callback_failed = 1;\r
127     }\r
128 \r
129     return ret;\r
130 }\r
131 \r
132 asn_enc_rval_t\r
133 asn_encode(const asn_codec_ctx_t *opt_codec_ctx,\r
134            enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,\r
135            const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {\r
136     struct callback_failure_catch_key cb_key;\r
137     asn_enc_rval_t er = {0,0,0};\r
138 \r
139     if(!callback) {\r
140         errno = EINVAL;\r
141         ASN__ENCODE_FAILED;\r
142     }\r
143 \r
144     cb_key.callback = callback;\r
145     cb_key.callback_key = callback_key;\r
146     cb_key.callback_failed = 0;\r
147 \r
148     er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,\r
149                              callback_failure_catch_cb, &cb_key);\r
150     if(cb_key.callback_failed) {\r
151         assert(er.encoded == -1);\r
152         assert(errno == EBADF);\r
153         errno = EIO;\r
154     }\r
155 \r
156     return er;\r
157 }\r
158 \r
159 asn_enc_rval_t\r
160 asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,\r
161                      enum asn_transfer_syntax syntax,\r
162                      const asn_TYPE_descriptor_t *td, const void *sptr,\r
163                      void *buffer, size_t buffer_size) {\r
164     struct overrun_encoder_key buf_key;\r
165     asn_enc_rval_t er = {0,0,0};\r
166 \r
167     if(buffer_size > 0 && !buffer) {\r
168         errno = EINVAL;\r
169         ASN__ENCODE_FAILED;\r
170     }\r
171 \r
172     buf_key.buffer = buffer;\r
173     buf_key.buffer_size = buffer_size;\r
174     buf_key.computed_size = 0;\r
175 \r
176     er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,\r
177                              overrun_encoder_cb, &buf_key);\r
178 \r
179     if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {\r
180         ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE\r
181                   " yet produced %" ASN_PRI_SIZE " bytes",\r
182                   er.encoded, buf_key.computed_size);\r
183         assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);\r
184     }\r
185 \r
186     return er;\r
187 }\r
188 \r
189 asn_encode_to_new_buffer_result_t\r
190 asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,\r
191                          enum asn_transfer_syntax syntax,\r
192                          const asn_TYPE_descriptor_t *td, const void *sptr) {\r
193     struct dynamic_encoder_key buf_key;\r
194     asn_encode_to_new_buffer_result_t res;\r
195 \r
196     buf_key.buffer_size = 16;\r
197     buf_key.buffer = MALLOC(buf_key.buffer_size);\r
198     buf_key.computed_size = 0;\r
199 \r
200     res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,\r
201                                      dynamic_encoder_cb, &buf_key);\r
202 \r
203     if(res.result.encoded >= 0\r
204        && (size_t)res.result.encoded != buf_key.computed_size) {\r
205         ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE\r
206                   " yet produced %" ASN_PRI_SIZE " bytes",\r
207                   res.result.encoded, buf_key.computed_size);\r
208         assert(res.result.encoded < 0\r
209                || (size_t)res.result.encoded == buf_key.computed_size);\r
210     }\r
211 \r
212     res.buffer = buf_key.buffer;\r
213 \r
214     /* 0-terminate just in case. */\r
215     if(res.buffer) {\r
216         assert(buf_key.computed_size < buf_key.buffer_size);\r
217         ((char *)res.buffer)[buf_key.computed_size] = '\0';\r
218     }\r
219 \r
220     return res;\r
221 }\r
222 \r
223 static asn_enc_rval_t\r
224 asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,\r
225                     enum asn_transfer_syntax syntax,\r
226                     const asn_TYPE_descriptor_t *td, const void *sptr,\r
227                     asn_app_consume_bytes_f *callback, void *callback_key) {\r
228     asn_enc_rval_t er = {0,0,0};\r
229     enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;\r
230 \r
231     (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */\r
232 \r
233     if(!td || !sptr) {\r
234         errno = EINVAL;\r
235         ASN__ENCODE_FAILED;\r
236     }\r
237 \r
238     switch(syntax) {\r
239     case ATS_NONSTANDARD_PLAINTEXT:\r
240         if(td->op->print_struct) {\r
241             struct callback_count_bytes_key cb_key;\r
242             cb_key.callback = callback;\r
243             cb_key.callback_key = callback_key;\r
244             cb_key.computed_size = 0;\r
245             if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,\r
246                                     &cb_key)\r
247                    < 0\r
248                || callback_count_bytes_cb("\n", 1, &cb_key) < 0) {\r
249                 errno = EBADF; /* Structure has incorrect form. */\r
250                 er.encoded = -1;\r
251                 er.failed_type = td;\r
252                 er.structure_ptr = sptr;\r
253             } else {\r
254                 er.encoded = cb_key.computed_size;\r
255                 er.failed_type = 0;\r
256                 er.structure_ptr = 0;\r
257             }\r
258         } else {\r
259             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
260             ASN__ENCODE_FAILED;\r
261         }\r
262         break;\r
263 \r
264     case ATS_RANDOM:\r
265         errno = ENOENT; /* Randomization doesn't make sense on output. */\r
266         ASN__ENCODE_FAILED;\r
267 \r
268     case ATS_BER:\r
269         /* BER is a superset of DER. */\r
270         /* Fall through. */\r
271     case ATS_DER:\r
272         if(td->op->der_encoder) {\r
273             er = der_encode(td, sptr, callback, callback_key);\r
274             if(er.encoded == -1) {\r
275                 if(er.failed_type && er.failed_type->op->der_encoder) {\r
276                     errno = EBADF;  /* Structure has incorrect form. */\r
277                 } else {\r
278                     errno = ENOENT; /* DER is not defined for this type. */\r
279                 }\r
280             }\r
281         } else {\r
282             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
283             ASN__ENCODE_FAILED;\r
284         }\r
285         break;\r
286     case ATS_CER:\r
287         errno = ENOENT; /* Transfer syntax is not defined for any type. */\r
288         ASN__ENCODE_FAILED;\r
289 \r
290 #ifdef  ASN_DISABLE_OER_SUPPORT\r
291     case ATS_BASIC_OER:\r
292     case ATS_CANONICAL_OER:\r
293         errno = ENOENT; /* PER is not defined. */\r
294         ASN__ENCODE_FAILED;\r
295         break;\r
296 #else /* ASN_DISABLE_OER_SUPPORT */\r
297     case ATS_BASIC_OER:\r
298         /* CANONICAL-OER is a superset of BASIC-OER. */\r
299         /* Fall through. */\r
300     case ATS_CANONICAL_OER:\r
301         if(td->op->oer_encoder) {\r
302             er = oer_encode(td, sptr, callback, callback_key);\r
303             if(er.encoded == -1) {\r
304                 if(er.failed_type && er.failed_type->op->oer_encoder) {\r
305                     errno = EBADF;  /* Structure has incorrect form. */\r
306                 } else {\r
307                     errno = ENOENT; /* OER is not defined for this type. */\r
308                 }\r
309             }\r
310         } else {\r
311             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
312             ASN__ENCODE_FAILED;\r
313         }\r
314         break;\r
315 #endif /* ASN_DISABLE_OER_SUPPORT */\r
316 \r
317 #ifdef  ASN_DISABLE_PER_SUPPORT\r
318     case ATS_UNALIGNED_BASIC_PER:\r
319     case ATS_UNALIGNED_CANONICAL_PER:\r
320     case ATS_ALIGNED_BASIC_PER:\r
321     case ATS_ALIGNED_CANONICAL_PER:\r
322         errno = ENOENT; /* PER is not defined. */\r
323         ASN__ENCODE_FAILED;\r
324         break;\r
325 #else /* ASN_DISABLE_PER_SUPPORT */\r
326     case ATS_UNALIGNED_BASIC_PER:\r
327         /* CANONICAL-UPER is a superset of BASIC-UPER. */\r
328         /* Fall through. */\r
329     case ATS_UNALIGNED_CANONICAL_PER:\r
330         if(td->op->uper_encoder) {\r
331             er = uper_encode(td, 0, sptr, callback, callback_key);\r
332             if(er.encoded == -1) {\r
333                 if(er.failed_type && er.failed_type->op->uper_encoder) {\r
334                     errno = EBADF;  /* Structure has incorrect form. */\r
335                 } else {\r
336                     errno = ENOENT; /* UPER is not defined for this type. */\r
337                 }\r
338             } else {\r
339                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);\r
340                 if(er.encoded == 0) {\r
341                     /* Enforce "Complete Encoding" of X.691 #11.1 */\r
342                     if(callback("\0", 1, callback_key) < 0) {\r
343                         errno = EBADF;\r
344                         ASN__ENCODE_FAILED;\r
345                     }\r
346                     er.encoded = 8; /* Exactly 8 zero bits is added. */\r
347                 }\r
348                 /* Convert bits into bytes */\r
349                 er.encoded = (er.encoded + 7) >> 3;\r
350             }\r
351         } else {\r
352             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
353             ASN__ENCODE_FAILED;\r
354         }\r
355         break;\r
356     case ATS_ALIGNED_BASIC_PER:\r
357         /* CANONICAL-APER is a superset of BASIC-APER. */\r
358         /* Fall through. */\r
359     case ATS_ALIGNED_CANONICAL_PER:\r
360         if(td->op->aper_encoder) {\r
361             er = aper_encode(td, 0, sptr, callback, callback_key);\r
362             if(er.encoded == -1) {\r
363                 if(er.failed_type && er.failed_type->op->aper_encoder) {\r
364                     errno = EBADF;  /* Structure has incorrect form. */\r
365                 } else {\r
366                     errno = ENOENT; /* APER is not defined for this type. */\r
367                 }\r
368             } else {\r
369                 ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);\r
370                 if(er.encoded == 0) {\r
371                     /* Enforce "Complete Encoding" of X.691 #11.1 */\r
372                     if(callback("\0", 1, callback_key) < 0) {\r
373                         errno = EBADF;\r
374                         ASN__ENCODE_FAILED;\r
375                     }\r
376                     er.encoded = 8; /* Exactly 8 zero bits is added. */\r
377                 }\r
378                 /* Convert bits into bytes */\r
379                 er.encoded = (er.encoded + 7) >> 3;\r
380             }\r
381         } else {\r
382             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
383             ASN__ENCODE_FAILED;\r
384         }\r
385         break;\r
386 #endif  /* ASN_DISABLE_PER_SUPPORT */\r
387 \r
388     case ATS_BASIC_XER:\r
389         /* CANONICAL-XER is a superset of BASIC-XER. */\r
390         xer_flags &= ~XER_F_CANONICAL;\r
391         xer_flags |= XER_F_BASIC;\r
392         /* Fall through. */\r
393     case ATS_CANONICAL_XER:\r
394         if(td->op->xer_encoder) {\r
395             er = xer_encode(td, sptr, xer_flags, callback, callback_key);\r
396             if(er.encoded == -1) {\r
397                 if(er.failed_type && er.failed_type->op->xer_encoder) {\r
398                     errno = EBADF;  /* Structure has incorrect form. */\r
399                 } else {\r
400                     errno = ENOENT; /* XER is not defined for this type. */\r
401                 }\r
402             }\r
403         } else {\r
404             errno = ENOENT; /* Transfer syntax is not defined for this type. */\r
405             ASN__ENCODE_FAILED;\r
406         }\r
407         break;\r
408 \r
409     default:\r
410         errno = ENOENT;\r
411         ASN__ENCODE_FAILED;\r
412     }\r
413 \r
414     return er;\r
415 }\r
416 \r
417 asn_dec_rval_t\r
418 asn_decode(const asn_codec_ctx_t *opt_codec_ctx,\r
419            enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,\r
420            void **sptr, const void *buffer, size_t size) {\r
421     if(!td || !td->op || !sptr || (size && !buffer)) {\r
422         ASN__DECODE_FAILED;\r
423     }\r
424 \r
425     switch(syntax) {\r
426     case ATS_CER:\r
427     case ATS_NONSTANDARD_PLAINTEXT:\r
428     default:\r
429         errno = ENOENT;\r
430         ASN__DECODE_FAILED;\r
431 \r
432     case ATS_RANDOM:\r
433         if(!td->op->random_fill) {\r
434             ASN__DECODE_FAILED;\r
435         } else {\r
436             if(asn_random_fill(td, sptr, 16000) == 0) {\r
437                 asn_dec_rval_t ret = {RC_OK, 0};\r
438                 return ret;\r
439             } else {\r
440                 ASN__DECODE_FAILED;\r
441             }\r
442         }\r
443         break;\r
444 \r
445     case ATS_DER:\r
446     case ATS_BER:\r
447         return ber_decode(opt_codec_ctx, td, sptr, buffer, size);\r
448 \r
449     case ATS_BASIC_OER:\r
450     case ATS_CANONICAL_OER:\r
451 #ifdef  ASN_DISABLE_OER_SUPPORT\r
452         errno = ENOENT;\r
453         ASN__DECODE_FAILED;\r
454 #else\r
455         return oer_decode(opt_codec_ctx, td, sptr, buffer, size);\r
456 #endif\r
457 \r
458     case ATS_UNALIGNED_BASIC_PER:\r
459     case ATS_UNALIGNED_CANONICAL_PER:\r
460 #ifdef  ASN_DISABLE_PER_SUPPORT\r
461         errno = ENOENT;\r
462         ASN__DECODE_FAILED;\r
463 #else\r
464         return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);\r
465 #endif\r
466 \r
467     case ATS_ALIGNED_BASIC_PER:\r
468     case ATS_ALIGNED_CANONICAL_PER:\r
469 #ifdef  ASN_DISABLE_PER_SUPPORT\r
470         errno = ENOENT;\r
471         ASN__DECODE_FAILED;\r
472 #else\r
473         return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);\r
474 #endif\r
475 \r
476     case ATS_BASIC_XER:\r
477     case ATS_CANONICAL_XER:\r
478         return xer_decode(opt_codec_ctx, td, sptr, buffer, size);\r
479     }\r
480 }\r
481 \r