blob: 84b0db9ed5967a35b3b7fe68748b2f4a41e00898 [file] [log] [blame]
Lev Walkind88bea92017-07-20 11:21:30 +03001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
5 */
6#ifndef ASN_DISABLE_OER_SUPPORT
7
8#include <asn_internal.h>
9#include <constr_SEQUENCE.h>
10#include <errno.h>
11
12/*
13 * This macro "eats" the part of the buffer which is definitely "consumed",
14 * i.e. was correctly converted into local representation or rightfully skipped.
15 */
16#undef ADVANCE
17#define ADVANCE(num_bytes) \
18 do { \
19 size_t num = num_bytes; \
20 ptr = ((const char *)ptr) + num; \
21 size -= num; \
22 consumed_myself += num; \
23 } while(0)
24
25/*
26 * Switch to the next phase of parsing.
27 */
28#undef NEXT_PHASE
29#undef PHASE_OUT
30#define NEXT_PHASE(ctx) \
31 do { \
32 ctx->phase++; \
33 ctx->step = 0; \
34 } while(0)
35
36/*
37 * Check whether we are inside the extensions group.
38 */
39#define IN_EXTENSION_GROUP(specs, memb_idx) \
Lev Walkin494fb702017-08-07 20:07:00 -070040 ( (((ssize_t)(memb_idx)) > (specs)->ext_after) \
41 &&(((ssize_t)(memb_idx)) < (specs)->ext_before))
Lev Walkind88bea92017-07-20 11:21:30 +030042
43/*
44 * Return a standardized complex structure.
45 */
46#undef RETURN
47#define RETURN(_code) do { \
48 rval.code = _code; \
49 rval.consumed = consumed_myself;\
50 return rval; \
51 } while(0)
52
Lev Walkin890e6032017-07-24 01:48:59 +040053/*
54 * Return pointer to a member.
55 */
56static void **element_ptrptr(void *struct_ptr, asn_TYPE_member_t *elm) {
57 assert(elm->flags & ATF_POINTER);
58 /* Member is a pointer to another structure */
59 return (void **)((char *)struct_ptr + elm->memb_offset);
60}
61
62static void *element_ptr(void *struct_ptr, asn_TYPE_member_t *elm) {
63 if(elm->flags & ATF_POINTER) {
64 /* Member is a pointer to another structure */
65 return *(void **)((char *)struct_ptr + elm->memb_offset);
66 } else {
67 return (void *)((char *)struct_ptr + elm->memb_offset);
68 }
69}
70
Lev Walkind88bea92017-07-20 11:21:30 +030071asn_dec_rval_t
72SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -070073 const asn_oer_constraints_t *constraints, void **struct_ptr,
74 const void *ptr, size_t size) {
Lev Walkind88bea92017-07-20 11:21:30 +030075 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
76 asn_dec_rval_t rval = {RC_OK, 0};
77 void *st = *struct_ptr; /* Target structure */
78 asn_struct_ctx_t *ctx; /* Decoder context */
79 size_t consumed_myself = 0; /* Consumed bytes from ptr. */
80
81
82 (void)opt_codec_ctx;
Lev Walkin494fb702017-08-07 20:07:00 -070083 (void)constraints;
Lev Walkind88bea92017-07-20 11:21:30 +030084
85 /*
86 * Create the target structure if it is not present already.
87 */
88 if(st == 0) {
89 st = *struct_ptr = CALLOC(1, specs->struct_size);
90 if(st == 0) {
91 RETURN(RC_FAIL);
92 }
93 }
94
95 /*
96 * Restore parsing context.
97 */
98 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
99 if(ctx->ptr == 0) {
100 ctx->ptr = CALLOC(1, sizeof(asn_per_data_t));
101 if(!ctx->ptr) {
102 RETURN(RC_FAIL);
103 }
104 }
105
106 /*
107 * Start to parse where left previously.
108 */
109 switch(ctx->phase) {
110 case 0: {
111 /*
112 * Fetch preamble.
113 */
114 asn_per_data_t *preamble = ctx->ptr;
Lev Walkin890e6032017-07-24 01:48:59 +0400115 int has_extensions_bit = (specs->ext_before >= 0);
116 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
117 size_t preamble_bytes = ((7 + preamble_bits) >> 3);
Lev Walkind88bea92017-07-20 11:21:30 +0300118 uint8_t *pbytes;
119
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700120 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
121
Lev Walkin890e6032017-07-24 01:48:59 +0400122 ASN_DEBUG(
123 "Expecting preamble bits %zu for %s (including %d extension bits)",
124 preamble_bits, td->name, has_extensions_bit);
125
Lev Walkind88bea92017-07-20 11:21:30 +0300126 if(size < preamble_bytes) {
127 ASN__DECODE_STARVED;
128 }
129
130 pbytes = MALLOC(preamble_bytes + 1);
131 if(!pbytes) {
132 RETURN(RC_FAIL);
133 }
134 preamble->buffer = (const void *)pbytes;
135 memcpy(pbytes, ptr, preamble_bytes);
136 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400137 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300138 preamble->nbits = preamble_bits;
139 ADVANCE(preamble_bytes);
140 }
141 NEXT_PHASE(ctx);
142 /* FALL THROUGH */
143 case 1: {
144 /* Decode components of the extension root */
145 asn_per_data_t *preamble = ctx->ptr;
146 size_t edx;
147
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700148 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
149
Lev Walkind88bea92017-07-20 11:21:30 +0300150 for(edx = (ctx->step >> 1); edx < td->elements_count;
151 edx++, ctx->step = (ctx->step & ~1) + 2) {
152 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400153 void *memb_tmpptr; /* Temporary reference. */
Lev Walkind88bea92017-07-20 11:21:30 +0300154 void **memb_ptr2; /* Pointer to a pointer to a memmber */
155
Lev Walkin890e6032017-07-24 01:48:59 +0400156 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
157
Lev Walkind88bea92017-07-20 11:21:30 +0300158 if(ctx->step & 1) {
159 goto microphase2_decode_continues;
160 }
161
162
163 if(IN_EXTENSION_GROUP(specs, edx)) {
164 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400165 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300166 }
167
168 if(elm->optional) {
169 int32_t present = per_get_few_bits(preamble, 1);
170 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400171 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300172 RETURN(RC_FAIL);
173 } else if(present == 0) {
174 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300175 /* Fill-in DEFAULT */
Lev Walkin890e6032017-07-24 01:48:59 +0400176 if(elm->default_value(1, element_ptrptr(st, elm))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300177 RETURN(RC_FAIL);
178 }
179 }
180 /* The member is not present. */
181 continue;
182 }
183 /* Present OPTIONAL or DEFAULT component. */
184 }
185
186 /*
187 * MICROPHASE 2: Invoke the member-specific decoder.
188 */
189 ctx->step |= 1; /* Confirm entering next microphase */
190 microphase2_decode_continues:
191 if(elm->flags & ATF_POINTER) {
192 /* Member is a pointer to another structure */
193 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
194 } else {
Lev Walkin890e6032017-07-24 01:48:59 +0400195 memb_tmpptr = (char *)st + elm->memb_offset;
196 memb_ptr2 = &memb_tmpptr; /* Ensure this & remains in scope! */
Lev Walkind88bea92017-07-20 11:21:30 +0300197 }
198
Lev Walkin7c876302017-08-10 06:11:24 -0700199 if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) {
200 asn_TYPE_descriptor_t *et = elm->type_selector(td, st);
201 ssize_t ot_ret;
202 if(!et) {
203 ASN__DECODE_FAILED;
204 }
205 ot_ret = oer_open_type_get(opt_codec_ctx, et, NULL, memb_ptr2,
206 ptr, size);
207 switch(ot_ret) {
208 case -1:
209 rval.code = RC_FAIL;
210 rval.consumed = 0;
211 break;
212 case 0:
213 rval.code = RC_WMORE;
214 rval.consumed = 1;
215 break;
216 default:
217 rval.code = RC_OK;
218 rval.consumed = ot_ret;
219 break;
220 }
221 } else {
222 rval = elm->type->oer_decoder(opt_codec_ctx, elm->type,
223 elm->oer_constraints, memb_ptr2,
224 ptr, size);
225 }
Lev Walkind88bea92017-07-20 11:21:30 +0300226 switch(rval.code) {
227 case RC_OK:
228 ADVANCE(rval.consumed);
229 break;
230 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400231 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
232 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300233 ADVANCE(rval.consumed);
234 RETURN(RC_WMORE);
235 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400236 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
237 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300238 RETURN(RC_FAIL);
239 }
240 } /* for(all root members) */
241
242 }
243 NEXT_PHASE(ctx);
244 /* FALL THROUGH */
245 case 2: {
246 /* Cleanup preamble. */
247 asn_per_data_t *preamble = ctx->ptr;
248 asn_per_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400249 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300250 int extensions_present =
Lev Walkin890e6032017-07-24 01:48:59 +0400251 has_extensions_bit && (((const uint8_t *)preamble->buffer)[0] & 0x80);
Lev Walkind88bea92017-07-20 11:21:30 +0300252 uint8_t unused_bits;
253 size_t len = 0;
254 ssize_t len_len;
255 uint8_t *ebytes;
256
257 union {
258 const uint8_t *cptr;
259 uint8_t *uptr;
260 } unconst;
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700261
262 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
263
Lev Walkind88bea92017-07-20 11:21:30 +0300264 unconst.cptr = preamble->buffer;
265 FREEMEM(unconst.uptr);
266 preamble->buffer = 0;
267
268 if(!extensions_present) {
269 ctx->phase = 10;
270 RETURN(RC_OK);
271 }
272
273 /*
274 * X.696 (08/2015) #16.1 (c), #16.4
275 * Read in the extension addition presence bitmap.
276 */
277
278 len_len = oer_fetch_length(ptr, size, &len);
279 if(len_len > 0) {
280 ADVANCE(len_len);
281 } if(len_len < 0) {
282 RETURN(RC_FAIL);
283 } else {
284 RETURN(RC_WMORE);
285 }
286
287 if(len == 0) {
288 /* 16.4.1-2 */
289 RETURN(RC_FAIL);
290 } else if(len > size) {
291 RETURN(RC_WMORE);
292 }
293
294 /* Account for unused bits */
295 unused_bits = 0x7 & *(const uint8_t *)ptr;
296 ADVANCE(1);
297 len--;
298 if(unused_bits && len == 0) {
299 RETURN(RC_FAIL);
300 }
301
302 /* Get the extensions map */
303 ebytes = MALLOC(len + 1);
304 if(!ebytes) {
305 RETURN(RC_FAIL);
306 }
307 memcpy(ebytes, ptr, len);
308 ebytes[len] = '\0';
309
310 extadds = preamble;
311 memset(extadds, 0, sizeof(*extadds));
312 extadds->buffer = ebytes;
313 extadds->nboff = 0;
314 extadds->nbits = 8 * len - unused_bits;
315
316 ADVANCE(len);
317 }
318 NEXT_PHASE(ctx);
319 ctx->step = (specs->ext_after + 1);
320 /* Fall through */
321 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400322 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
323 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkind88bea92017-07-20 11:21:30 +0300324 asn_per_data_t *extadds = ctx->ptr;
325 size_t edx = ctx->step;
326 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400327 void **memb_ptr2 = element_ptrptr(st, elm);
Lev Walkind88bea92017-07-20 11:21:30 +0300328
329 switch(per_get_few_bits(extadds, 1)) {
330 case -1:
331 /*
332 * Not every one of our extensions is known to the remote side.
333 * Continue filling in their defaults though.
334 */
335 /* Fall through */
336 case 0:
337 /* Fill-in DEFAULT */
338 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
339 RETURN(RC_FAIL);
340 }
341 continue;
342 case 1: {
343 /* Read OER open type */
344 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
345 elm->oer_constraints,
346 memb_ptr2, ptr, size);
347 if(ot_size > 0) {
348 ADVANCE(ot_size);
349 } else if(ot_size < 0) {
350 RETURN(RC_FAIL);
351 } else {
352 /* Roll back open type parsing */
353 per_get_undo(extadds, 1);
354 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
355 *memb_ptr2 = NULL;
356 RETURN(RC_WMORE);
357 }
358 break;
359 }
360 default:
361 RETURN(RC_FAIL);
362 }
363 }
364
365 NEXT_PHASE(ctx);
366 /* Fall through */
367 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400368 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300369 /* Read in the rest of Open Types while ignoring them */
370 for(;;) {
371 asn_per_data_t *extadds = ctx->ptr;
372 switch(per_get_few_bits(extadds, 1)) {
373 case 0:
374 continue;
375 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300376 ssize_t skipped = oer_open_type_skip(ptr, size);
377 if(skipped > 0) {
378 ADVANCE(skipped);
379 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300380 RETURN(RC_FAIL);
381 } else {
382 per_get_undo(extadds, 1);
383 RETURN(RC_WMORE);
384 }
385 continue;
386 }
387 case -1:
388 /* No more Open Type encoded components */
389 break;
390 default:
391 RETURN(RC_FAIL);
392 }
393 break;
394 }
395 }
396
397 return rval;
398}
399
400/*
401 * Encode as Canonical OER.
402 */
403asn_enc_rval_t
404SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700405 const asn_oer_constraints_t *constraints, void *sptr,
406 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin890e6032017-07-24 01:48:59 +0400407 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
408 size_t computed_size = 0;
409 int has_extensions_bit = (specs->ext_before >= 0);
410 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
411 uint32_t has_extensions = 0;
412 size_t edx;
413 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300414
Lev Walkin494fb702017-08-07 20:07:00 -0700415 (void)constraints;
416
Lev Walkin890e6032017-07-24 01:48:59 +0400417 if(preamble_bits) {
418 asn_per_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300419
Lev Walkin890e6032017-07-24 01:48:59 +0400420 memset(&preamble, 0, sizeof(preamble));
421 preamble.outper = cb;
422 preamble.op_key = app_key;
423
424 if(has_extensions_bit) {
Lev Walkin494fb702017-08-07 20:07:00 -0700425 for(edx = specs->ext_after + 1;
426 (ssize_t)edx < specs->ext_before - 1; edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400427 asn_TYPE_member_t *elm = &td->elements[edx];
428 if(element_ptr(sptr, elm)) {
429 has_extensions = 1;
430 break;
431 }
432 }
433 ret = per_put_few_bits(&preamble, has_extensions, 1);
434 assert(ret == 0);
435 if(ret < 0) {
436 ASN__ENCODE_FAILED;
437 }
438 }
439
440 /*
441 * Encode optional components bitmap.
442 */
443 if(specs->roms_count) {
444 for(edx = 0; edx < td->elements_count; edx++) {
445 asn_TYPE_member_t *elm = &td->elements[edx];
446
447 if(IN_EXTENSION_GROUP(specs, edx)) break;
448
449 if(elm->optional) {
450 uint32_t has_component = (element_ptr(sptr, elm) != NULL);
451 ret = per_put_few_bits(&preamble, has_component, 1);
452 if(ret < 0) {
453 ASN__ENCODE_FAILED;
454 }
455 }
456 }
457 }
458
459 per_put_aligned_flush(&preamble);
460 computed_size += preamble.flushed_bytes;
461 } /* if(preamble_bits) */
462
463 /*
464 * Put root components and extensions root.
465 */
466 for(edx = 0; edx < td->elements_count; edx++) {
467 asn_TYPE_member_t *elm = &td->elements[edx];
468 asn_enc_rval_t er;
469 void *memb_ptr;
470
471 if(IN_EXTENSION_GROUP(specs, edx)) break;
472
473 memb_ptr = element_ptr(sptr, elm);
474 if(!memb_ptr) {
475 if(elm->optional) continue;
476 /* Mandatory element is missing */
477 ASN__ENCODE_FAILED;
478 }
479 if(!elm->type->oer_encoder) {
480 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
481 ASN__ENCODE_FAILED;
482 }
483 er = elm->type->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
484 cb, app_key);
485 if(er.encoded == -1) {
486 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
487 elm->name);
488 return er;
489 }
490 computed_size += er.encoded;
491 }
492
493 /*
494 * Before encode extensions, encode extensions additions presense bitmap
495 # X.696 (08/2015) #16.4.
496 */
497 if(has_extensions) {
498 asn_per_outp_t extadds;
499
500 /* Special case allowing us to use exactly one byte for #8.6 */
501 size_t aoms_length_bits = specs->aoms_count;
502 size_t aoms_length_bytes = (7 + specs->aoms_count) >> 3;
503 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
504
505 assert(1 + aoms_length_bytes <= 127);
506
507 memset(&extadds, 0, sizeof(extadds));
508 extadds.outper = cb;
509 extadds.op_key = app_key;
510
511 /* #8.6 length determinant */
512 ret = per_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
513 if(ret < 0) ASN__ENCODE_FAILED;
514
515 /* Number of unused bytes, #16.4.2 */
516 ret = per_put_few_bits(&extadds, unused_bits, 8);
517 if(ret < 0) ASN__ENCODE_FAILED;
518
519 /* Encode presence bitmap #16.4.3 */
Lev Walkin494fb702017-08-07 20:07:00 -0700520 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
521 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400522 asn_TYPE_member_t *elm = &td->elements[edx];
523 void *memb_ptr = element_ptr(sptr, elm);
524 ret |= per_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
525 }
526 if(ret < 0) ASN__ENCODE_FAILED;
527
528 per_put_aligned_flush(&extadds);
529 computed_size += extadds.flushed_bytes;
530
531 /* Now, encode extensions */
Lev Walkin494fb702017-08-07 20:07:00 -0700532 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
533 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400534 asn_TYPE_member_t *elm = &td->elements[edx];
535 void *memb_ptr = element_ptr(sptr, elm);
536
537 if(memb_ptr) {
538 asn_enc_rval_t er = elm->type->oer_encoder(
539 elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
540 if(er.encoded == -1) {
541 return er;
542 }
543 computed_size += er.encoded;
544 } else if(!elm->optional) {
545 ASN__ENCODE_FAILED;
546 }
547 }
548 } /* if(has_extensions) */
549
550
551 {
552 asn_enc_rval_t er = {0, 0, 0};
553 er.encoded = computed_size;
554 ASN__ENCODED_OK(er);
555 }
Lev Walkind88bea92017-07-20 11:21:30 +0300556}
557
558#endif /* ASN_DISABLE_OER_SUPPORT */