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