Moving in e2sim originally from it/test/simulators
[sim/e2-interface.git] / e2sim / ASN1c / per_opentype.c
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 #                                                                            *
5 # Licensed under the Apache License, Version 2.0 (the "License");            *
6 # you may not use this file except in compliance with the License.           *
7 # You may obtain a copy of the License at                                    *
8 #                                                                            *
9 #      http://www.apache.org/licenses/LICENSE-2.0                            *
10 #                                                                            *
11 # Unless required by applicable law or agreed to in writing, software        *
12 # distributed under the License is distributed on an "AS IS" BASIS,          *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
14 # See the License for the specific language governing permissions and        *
15 # limitations under the License.                                             *
16 #                                                                            *
17 ******************************************************************************/
18
19 /*
20  * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
21  * Redistribution and modifications are permitted subject to BSD license.
22  */
23 #include <asn_internal.h>
24 #include <per_support.h>
25 #include <constr_TYPE.h>
26 #include <per_opentype.h>
27
28 typedef struct uper_ugot_key {
29         asn_per_data_t oldpd;   /* Old per data source */
30         size_t unclaimed;
31         size_t ot_moved;        /* Number of bits moved by OT processing */
32         int repeat;
33 } uper_ugot_key;
34
35 static int uper_ugot_refill(asn_per_data_t *pd);
36 static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
37 static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
38                                     const asn_TYPE_descriptor_t *td,
39                                     const asn_per_constraints_t *constraints,
40                                     void **sptr, asn_per_data_t *pd);
41
42 /*
43  * Encode an "open type field".
44  * #10.1, #10.2
45  */
46 int
47 uper_open_type_put(const asn_TYPE_descriptor_t *td,
48                    const asn_per_constraints_t *constraints, const void *sptr,
49                    asn_per_outp_t *po) {
50     void *buf;
51     void *bptr;
52     ssize_t size;
53
54     ASN_DEBUG("Open type put %s ...", td->name);
55
56     size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
57     if(size <= 0) return -1;
58
59     ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
60               size);
61
62     bptr = buf;
63     do {
64         int need_eom = 0;
65         ssize_t may_save = uper_put_length(po, size, &need_eom);
66         ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
67                   " to %s and allowing to save %" ASN_PRI_SSIZE,
68                   size, td->name, may_save);
69         if(may_save < 0) break;
70         if(per_put_many_bits(po, bptr, may_save * 8)) break;
71         bptr = (char *)bptr + may_save;
72         size -= may_save;
73         if(need_eom && uper_put_length(po, 0, 0)) {
74             FREEMEM(buf);
75             return -1;
76         }
77     } while(size);
78
79     FREEMEM(buf);
80     if(size) return -1;
81
82     return 0;
83 }
84
85 static asn_dec_rval_t
86 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
87                           const asn_TYPE_descriptor_t *td,
88                           const asn_per_constraints_t *constraints, void **sptr,
89                           asn_per_data_t *pd) {
90     asn_dec_rval_t rv;
91         ssize_t chunk_bytes;
92         int repeat;
93         uint8_t *buf = 0;
94         size_t bufLen = 0;
95         size_t bufSize = 0;
96         asn_per_data_t spd;
97         size_t padding;
98
99         ASN__STACK_OVERFLOW_CHECK(ctx);
100
101         ASN_DEBUG("Getting open type %s...", td->name);
102
103         do {
104                 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
105                 if(chunk_bytes < 0) {
106                         FREEMEM(buf);
107                         ASN__DECODE_STARVED;
108                 }
109                 if(bufLen + chunk_bytes > bufSize) {
110                         void *ptr;
111                         bufSize = chunk_bytes + (bufSize << 2);
112                         ptr = REALLOC(buf, bufSize);
113                         if(!ptr) {
114                                 FREEMEM(buf);
115                                 ASN__DECODE_FAILED;
116                         }
117                         buf = ptr;
118                 }
119                 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
120                         FREEMEM(buf);
121                         ASN__DECODE_STARVED;
122                 }
123                 bufLen += chunk_bytes;
124         } while(repeat);
125
126         ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
127                 (long)bufLen);
128
129         memset(&spd, 0, sizeof(spd));
130         spd.buffer = buf;
131         spd.nbits = bufLen << 3;
132
133         ASN_DEBUG_INDENT_ADD(+4);
134         rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
135         ASN_DEBUG_INDENT_ADD(-4);
136
137         if(rv.code == RC_OK) {
138                 /* Check padding validity */
139                 padding = spd.nbits - spd.nboff;
140                 if (((padding > 0 && padding < 8) ||
141                 /* X.691#10.1.3 */
142                 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
143                     per_get_few_bits(&spd, padding) == 0) {
144                         /* Everything is cool */
145                         FREEMEM(buf);
146                         return rv;
147                 }
148                 FREEMEM(buf);
149                 if(padding >= 8) {
150                         ASN_DEBUG("Too large padding %d in open type", (int)padding);
151                         ASN__DECODE_FAILED;
152                 } else {
153                         ASN_DEBUG("No padding");
154                 }
155         } else {
156                 FREEMEM(buf);
157                 /* rv.code could be RC_WMORE, nonsense in this context */
158                 rv.code = RC_FAIL; /* Noone would give us more */
159         }
160
161         return rv;
162 }
163
164 static asn_dec_rval_t CC_NOTUSED
165 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
166                            const asn_TYPE_descriptor_t *td,
167                            asn_per_constraints_t *constraints, void **sptr,
168                            asn_per_data_t *pd) {
169     uper_ugot_key arg;
170         asn_dec_rval_t rv;
171         ssize_t padding;
172
173         ASN__STACK_OVERFLOW_CHECK(ctx);
174
175         ASN_DEBUG("Getting open type %s from %s", td->name,
176                 asn_bit_data_string(pd));
177         arg.oldpd = *pd;
178         arg.unclaimed = 0;
179         arg.ot_moved = 0;
180         arg.repeat = 1;
181         pd->refill = uper_ugot_refill;
182         pd->refill_key = &arg;
183         pd->nbits = pd->nboff;  /* 0 good bits at this point, will refill */
184         pd->moved = 0;  /* This now counts the open type size in bits */
185
186         ASN_DEBUG_INDENT_ADD(+4);
187         rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
188         ASN_DEBUG_INDENT_ADD(-4);
189
190 #define UPDRESTOREPD    do {                                            \
191         /* buffer and nboff are valid, preserve them. */                \
192         pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);       \
193         pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);       \
194         pd->refill = arg.oldpd.refill;                                  \
195         pd->refill_key = arg.oldpd.refill_key;                          \
196   } while(0)
197
198         if(rv.code != RC_OK) {
199                 UPDRESTOREPD;
200                 return rv;
201         }
202
203         ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
204                 asn_bit_data_string(pd),
205                 asn_bit_data_string(&arg.oldpd),
206                 (int)arg.unclaimed, (int)arg.repeat);
207
208         padding = pd->moved % 8;
209         if(padding) {
210                 int32_t pvalue;
211                 if(padding > 7) {
212                         ASN_DEBUG("Too large padding %d in open type",
213                                 (int)padding);
214                         rv.code = RC_FAIL;
215                         UPDRESTOREPD;
216                         return rv;
217                 }
218                 padding = 8 - padding;
219                 ASN_DEBUG("Getting padding of %d bits", (int)padding);
220                 pvalue = per_get_few_bits(pd, padding);
221                 switch(pvalue) {
222                 case -1:
223                         ASN_DEBUG("Padding skip failed");
224                         UPDRESTOREPD;
225                         ASN__DECODE_STARVED;
226                 case 0: break;
227                 default:
228                         ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
229                                 (int)padding, (int)pvalue);
230                         UPDRESTOREPD;
231                         ASN__DECODE_FAILED;
232                 }
233         }
234         if(pd->nboff != pd->nbits) {
235                 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
236                         asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
237                 if(1) {
238                         UPDRESTOREPD;
239                         ASN__DECODE_FAILED;
240                 } else {
241                         arg.unclaimed += pd->nbits - pd->nboff;
242                 }
243         }
244
245         /* Adjust pd back so it points to original data */
246         UPDRESTOREPD;
247
248         /* Skip data not consumed by the decoder */
249         if(arg.unclaimed) {
250                 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
251                 switch(per_skip_bits(pd, arg.unclaimed)) {
252                 case -1:
253                         ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
254                         ASN__DECODE_STARVED;
255                 case 0:
256                         ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
257                         break;
258                 default:
259                         /* Padding must be blank */
260                         ASN_DEBUG("Non-blank unconsumed padding");
261                         ASN__DECODE_FAILED;
262                 }
263                 arg.unclaimed = 0;
264         }
265
266         if(arg.repeat) {
267                 ASN_DEBUG("Not consumed the whole thing");
268                 rv.code = RC_FAIL;
269                 return rv;
270         }
271
272         return rv;
273 }
274
275
276 asn_dec_rval_t
277 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
278                    const asn_per_constraints_t *constraints, void **sptr,
279                    asn_per_data_t *pd) {
280     return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
281 }
282
283 int
284 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
285         asn_TYPE_descriptor_t s_td;
286     asn_TYPE_operation_t s_op;
287         asn_dec_rval_t rv;
288
289         s_td.name = "<unknown extension>";
290         s_td.op = &s_op;
291     s_op.uper_decoder = uper_sot_suck;
292
293         rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
294         if(rv.code != RC_OK)
295                 return -1;
296         else
297                 return 0;
298 }
299
300 /*
301  * Internal functions.
302  */
303
304 static asn_dec_rval_t
305 uper_sot_suck(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
306               const asn_per_constraints_t *constraints, void **sptr,
307               asn_per_data_t *pd) {
308     asn_dec_rval_t rv;
309
310         (void)ctx;
311         (void)td;
312         (void)constraints;
313         (void)sptr;
314
315         while(per_get_few_bits(pd, 1) >= 0);
316
317         rv.code = RC_OK;
318         rv.consumed = pd->moved;
319
320         return rv;
321 }
322
323 static int
324 uper_ugot_refill(asn_per_data_t *pd) {
325         uper_ugot_key *arg = pd->refill_key;
326         ssize_t next_chunk_bytes, next_chunk_bits;
327         ssize_t avail;
328
329         asn_per_data_t *oldpd = &arg->oldpd;
330
331         ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
332                 (long)pd->moved, (long)oldpd->moved);
333
334         /* Advance our position to where pd is */
335         oldpd->buffer = pd->buffer;
336         oldpd->nboff  = pd->nboff;
337         oldpd->nbits -= pd->moved - arg->ot_moved;
338         oldpd->moved += pd->moved - arg->ot_moved;
339         arg->ot_moved = pd->moved;
340
341         if(arg->unclaimed) {
342                 /* Refill the container */
343                 if(per_get_few_bits(oldpd, 1))
344                         return -1;
345                 if(oldpd->nboff == 0) {
346                         assert(0);
347                         return -1;
348                 }
349                 pd->buffer = oldpd->buffer;
350                 pd->nboff = oldpd->nboff - 1;
351                 pd->nbits = oldpd->nbits;
352                 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
353                         (long)pd->moved);
354                 return 0;
355         }
356
357         if(!arg->repeat) {
358                 ASN_DEBUG("Want more but refill doesn't have it");
359                 return -1;
360         }
361
362         next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
363         ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
364                 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
365         if(next_chunk_bytes < 0) return -1;
366         if(next_chunk_bytes == 0) {
367                 pd->refill = 0; /* No more refills, naturally */
368                 assert(!arg->repeat);   /* Implementation guarantee */
369         }
370         next_chunk_bits = next_chunk_bytes << 3;
371         avail = oldpd->nbits - oldpd->nboff;
372         if(avail >= next_chunk_bits) {
373                 pd->nbits = oldpd->nboff + next_chunk_bits;
374                 arg->unclaimed = 0;
375                 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
376                         (long)next_chunk_bits, (long)oldpd->moved,
377                         (long)oldpd->nboff, (long)oldpd->nbits,
378                         (long)(oldpd->nbits - oldpd->nboff));
379         } else {
380                 pd->nbits = oldpd->nbits;
381                 arg->unclaimed = next_chunk_bits - avail;
382                 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
383                         (long)avail, (long)next_chunk_bits,
384                         (long)arg->unclaimed);
385         }
386         pd->buffer = oldpd->buffer;
387         pd->nboff = oldpd->nboff;
388         ASN_DEBUG("Refilled pd%s old%s",
389                 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
390         return 0;
391 }
392
393 static int
394 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
395         int hasNonZeroBits = 0;
396         while(skip_nbits > 0) {
397                 int skip;
398
399                 /* per_get_few_bits() is more efficient when nbits <= 24 */
400                 if(skip_nbits < 24)
401                         skip = skip_nbits;
402                 else
403                         skip = 24;
404                 skip_nbits -= skip;
405
406                 switch(per_get_few_bits(pd, skip)) {
407                 case -1: return -1;     /* Starving */
408                 case 0: continue;       /* Skipped empty space */
409                 default: hasNonZeroBits = 1; continue;
410                 }
411         }
412         return hasNonZeroBits;
413 }
414
415 static asn_dec_rval_t
416 aper_open_type_get_simple(const asn_codec_ctx_t *ctx,
417                           const asn_TYPE_descriptor_t *td,
418                           const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
419         asn_dec_rval_t rv;
420         ssize_t chunk_bytes;
421         int repeat;
422         uint8_t *buf = 0;
423         size_t bufLen = 0;
424         size_t bufSize = 0;
425         asn_per_data_t spd;
426         size_t padding;
427
428         ASN__STACK_OVERFLOW_CHECK(ctx);
429
430         ASN_DEBUG("Getting open type %s...", td->name);
431
432         do {
433                 chunk_bytes = aper_get_length(pd, -1, -1, &repeat);
434                 if(chunk_bytes < 0) {
435                         FREEMEM(buf);
436                         ASN__DECODE_STARVED;
437                 }
438                 if(bufLen + chunk_bytes > bufSize) {
439                         void *ptr;
440                         bufSize = chunk_bytes + (bufSize << 2);
441                         ptr = REALLOC(buf, bufSize);
442                         if(!ptr) {
443                                 FREEMEM(buf);
444                                 ASN__DECODE_FAILED;
445                         }
446                         buf = ptr;
447                 }
448                 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
449                         FREEMEM(buf);
450                         ASN__DECODE_STARVED;
451                 }
452                 bufLen += chunk_bytes;
453         } while(repeat);
454
455         ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
456                 (long)bufLen);
457
458         memset(&spd, 0, sizeof(spd));
459         spd.buffer = buf;
460         spd.nbits = bufLen << 3;
461
462         ASN_DEBUG_INDENT_ADD(+4);
463         rv = td->op->aper_decoder(ctx, td, constraints, sptr, &spd);
464         ASN_DEBUG_INDENT_ADD(-4);
465
466         if(rv.code == RC_OK) {
467                 /* Check padding validity */
468                 padding = spd.nbits - spd.nboff;
469                 if (((padding > 0 && padding < 8) ||
470                 /* X.691#10.1.3 */
471                 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
472                     per_get_few_bits(&spd, padding) == 0) {
473                         /* Everything is cool */
474                         FREEMEM(buf);
475                         return rv;
476                 }
477                 FREEMEM(buf);
478                 if(padding >= 8) {
479                         ASN_DEBUG("Too large padding %d in open type", (int)padding);
480                         ASN__DECODE_FAILED;
481                 } else {
482                         ASN_DEBUG("No padding");
483                 }
484         } else {
485                 FREEMEM(buf);
486                 /* rv.code could be RC_WMORE, nonsense in this context */
487                 rv.code = RC_FAIL; /* Noone would give us more */
488         }
489
490         return rv;
491 }
492
493 int
494 aper_open_type_put(const asn_TYPE_descriptor_t *td,
495                    const asn_per_constraints_t *constraints,
496                    const void *sptr, asn_per_outp_t *po) {
497         void *buf;
498         void *bptr;
499         ssize_t size;
500         size_t toGo;
501
502         ASN_DEBUG("Open type put %s ...", td->name);
503
504         size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
505         if(size <= 0) return -1;
506
507         for(bptr = buf, toGo = size; toGo;) {
508                 ssize_t maySave = aper_put_length(po, -1, toGo);
509                 if(maySave < 0) break;
510                 if(per_put_many_bits(po, bptr, maySave * 8)) break;
511                 bptr = (char *)bptr + maySave;
512                 toGo -= maySave;
513         }
514
515         FREEMEM(buf);
516         if(toGo) return -1;
517
518         ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
519                           td->name, size);
520
521         return 0;
522 }
523
524 asn_dec_rval_t
525 aper_open_type_get(const asn_codec_ctx_t *ctx,
526                    const asn_TYPE_descriptor_t *td,
527                    const asn_per_constraints_t *constraints,
528                    void **sptr, asn_per_data_t *pd) {
529
530         return aper_open_type_get_simple(ctx, td, constraints, sptr, pd);
531 }
532
533 int
534 aper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
535         asn_TYPE_descriptor_t s_td;
536         asn_dec_rval_t rv;
537         asn_TYPE_operation_t op_t;
538
539         memset(&op_t, 0, sizeof(op_t));
540         s_td.name = "<unknown extension>";
541         s_td.op = &op_t;
542         s_td.op->aper_decoder = uper_sot_suck;
543
544         rv = aper_open_type_get(ctx, &s_td, 0, 0, pd);
545         if(rv.code != RC_OK)
546                 return -1;
547         else
548                 return 0;
549 }
550
551