blob: 5fb697cbe05d5fa3394ca6def4e37d7d99689fed [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 (void)specs;
85
86 /*
87 * Create the target structure if it is not present already.
88 */
89 if(st == 0) {
90 st = *struct_ptr = CALLOC(1, specs->struct_size);
91 if(st == 0) {
92 RETURN(RC_FAIL);
93 }
94 }
95
96 /*
97 * Restore parsing context.
98 */
99 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
100 if(ctx->ptr == 0) {
101 ctx->ptr = CALLOC(1, sizeof(asn_per_data_t));
102 if(!ctx->ptr) {
103 RETURN(RC_FAIL);
104 }
105 }
106
107 /*
108 * Start to parse where left previously.
109 */
110 switch(ctx->phase) {
111 case 0: {
112 /*
113 * Fetch preamble.
114 */
115 asn_per_data_t *preamble = ctx->ptr;
Lev Walkin890e6032017-07-24 01:48:59 +0400116 int has_extensions_bit = (specs->ext_before >= 0);
117 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
118 size_t preamble_bytes = ((7 + preamble_bits) >> 3);
Lev Walkind88bea92017-07-20 11:21:30 +0300119 uint8_t *pbytes;
120
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700121 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
122
Lev Walkin890e6032017-07-24 01:48:59 +0400123 ASN_DEBUG(
124 "Expecting preamble bits %zu for %s (including %d extension bits)",
125 preamble_bits, td->name, has_extensions_bit);
126
Lev Walkind88bea92017-07-20 11:21:30 +0300127 if(size < preamble_bytes) {
128 ASN__DECODE_STARVED;
129 }
130
131 pbytes = MALLOC(preamble_bytes + 1);
132 if(!pbytes) {
133 RETURN(RC_FAIL);
134 }
135 preamble->buffer = (const void *)pbytes;
136 memcpy(pbytes, ptr, preamble_bytes);
137 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400138 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300139 preamble->nbits = preamble_bits;
140 ADVANCE(preamble_bytes);
141 }
142 NEXT_PHASE(ctx);
143 /* FALL THROUGH */
144 case 1: {
145 /* Decode components of the extension root */
146 asn_per_data_t *preamble = ctx->ptr;
147 size_t edx;
148
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700149 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
150
Lev Walkind88bea92017-07-20 11:21:30 +0300151 for(edx = (ctx->step >> 1); edx < td->elements_count;
152 edx++, ctx->step = (ctx->step & ~1) + 2) {
153 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400154 void *memb_tmpptr; /* Temporary reference. */
Lev Walkind88bea92017-07-20 11:21:30 +0300155 void **memb_ptr2; /* Pointer to a pointer to a memmber */
156
Lev Walkin890e6032017-07-24 01:48:59 +0400157 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
158
Lev Walkind88bea92017-07-20 11:21:30 +0300159 if(ctx->step & 1) {
160 goto microphase2_decode_continues;
161 }
162
163
164 if(IN_EXTENSION_GROUP(specs, edx)) {
165 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400166 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300167 }
168
169 if(elm->optional) {
170 int32_t present = per_get_few_bits(preamble, 1);
171 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400172 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300173 RETURN(RC_FAIL);
174 } else if(present == 0) {
175 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300176 /* Fill-in DEFAULT */
Lev Walkin890e6032017-07-24 01:48:59 +0400177 if(elm->default_value(1, element_ptrptr(st, elm))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300178 RETURN(RC_FAIL);
179 }
180 }
181 /* The member is not present. */
182 continue;
183 }
184 /* Present OPTIONAL or DEFAULT component. */
185 }
186
187 /*
188 * MICROPHASE 2: Invoke the member-specific decoder.
189 */
190 ctx->step |= 1; /* Confirm entering next microphase */
191 microphase2_decode_continues:
192 if(elm->flags & ATF_POINTER) {
193 /* Member is a pointer to another structure */
194 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
195 } else {
Lev Walkin890e6032017-07-24 01:48:59 +0400196 memb_tmpptr = (char *)st + elm->memb_offset;
197 memb_ptr2 = &memb_tmpptr; /* Ensure this & remains in scope! */
Lev Walkind88bea92017-07-20 11:21:30 +0300198 }
199
200 rval = elm->type->oer_decoder(opt_codec_ctx, elm->type,
201 elm->oer_constraints, memb_ptr2, ptr,
202 size);
203 switch(rval.code) {
204 case RC_OK:
205 ADVANCE(rval.consumed);
206 break;
207 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400208 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
209 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300210 ADVANCE(rval.consumed);
211 RETURN(RC_WMORE);
212 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400213 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
214 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300215 RETURN(RC_FAIL);
216 }
217 } /* for(all root members) */
218
219 }
220 NEXT_PHASE(ctx);
221 /* FALL THROUGH */
222 case 2: {
223 /* Cleanup preamble. */
224 asn_per_data_t *preamble = ctx->ptr;
225 asn_per_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400226 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300227 int extensions_present =
Lev Walkin890e6032017-07-24 01:48:59 +0400228 has_extensions_bit && (((const uint8_t *)preamble->buffer)[0] & 0x80);
Lev Walkind88bea92017-07-20 11:21:30 +0300229 uint8_t unused_bits;
230 size_t len = 0;
231 ssize_t len_len;
232 uint8_t *ebytes;
233
234 union {
235 const uint8_t *cptr;
236 uint8_t *uptr;
237 } unconst;
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700238
239 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
240
Lev Walkind88bea92017-07-20 11:21:30 +0300241 unconst.cptr = preamble->buffer;
242 FREEMEM(unconst.uptr);
243 preamble->buffer = 0;
244
245 if(!extensions_present) {
246 ctx->phase = 10;
247 RETURN(RC_OK);
248 }
249
250 /*
251 * X.696 (08/2015) #16.1 (c), #16.4
252 * Read in the extension addition presence bitmap.
253 */
254
255 len_len = oer_fetch_length(ptr, size, &len);
256 if(len_len > 0) {
257 ADVANCE(len_len);
258 } if(len_len < 0) {
259 RETURN(RC_FAIL);
260 } else {
261 RETURN(RC_WMORE);
262 }
263
264 if(len == 0) {
265 /* 16.4.1-2 */
266 RETURN(RC_FAIL);
267 } else if(len > size) {
268 RETURN(RC_WMORE);
269 }
270
271 /* Account for unused bits */
272 unused_bits = 0x7 & *(const uint8_t *)ptr;
273 ADVANCE(1);
274 len--;
275 if(unused_bits && len == 0) {
276 RETURN(RC_FAIL);
277 }
278
279 /* Get the extensions map */
280 ebytes = MALLOC(len + 1);
281 if(!ebytes) {
282 RETURN(RC_FAIL);
283 }
284 memcpy(ebytes, ptr, len);
285 ebytes[len] = '\0';
286
287 extadds = preamble;
288 memset(extadds, 0, sizeof(*extadds));
289 extadds->buffer = ebytes;
290 extadds->nboff = 0;
291 extadds->nbits = 8 * len - unused_bits;
292
293 ADVANCE(len);
294 }
295 NEXT_PHASE(ctx);
296 ctx->step = (specs->ext_after + 1);
297 /* Fall through */
298 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400299 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
300 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkind88bea92017-07-20 11:21:30 +0300301 asn_per_data_t *extadds = ctx->ptr;
302 size_t edx = ctx->step;
303 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400304 void **memb_ptr2 = element_ptrptr(st, elm);
Lev Walkind88bea92017-07-20 11:21:30 +0300305
306 switch(per_get_few_bits(extadds, 1)) {
307 case -1:
308 /*
309 * Not every one of our extensions is known to the remote side.
310 * Continue filling in their defaults though.
311 */
312 /* Fall through */
313 case 0:
314 /* Fill-in DEFAULT */
315 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
316 RETURN(RC_FAIL);
317 }
318 continue;
319 case 1: {
320 /* Read OER open type */
321 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
322 elm->oer_constraints,
323 memb_ptr2, ptr, size);
324 if(ot_size > 0) {
325 ADVANCE(ot_size);
326 } else if(ot_size < 0) {
327 RETURN(RC_FAIL);
328 } else {
329 /* Roll back open type parsing */
330 per_get_undo(extadds, 1);
331 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
332 *memb_ptr2 = NULL;
333 RETURN(RC_WMORE);
334 }
335 break;
336 }
337 default:
338 RETURN(RC_FAIL);
339 }
340 }
341
342 NEXT_PHASE(ctx);
343 /* Fall through */
344 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400345 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300346 /* Read in the rest of Open Types while ignoring them */
347 for(;;) {
348 asn_per_data_t *extadds = ctx->ptr;
349 switch(per_get_few_bits(extadds, 1)) {
350 case 0:
351 continue;
352 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300353 ssize_t skipped = oer_open_type_skip(ptr, size);
354 if(skipped > 0) {
355 ADVANCE(skipped);
356 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300357 RETURN(RC_FAIL);
358 } else {
359 per_get_undo(extadds, 1);
360 RETURN(RC_WMORE);
361 }
362 continue;
363 }
364 case -1:
365 /* No more Open Type encoded components */
366 break;
367 default:
368 RETURN(RC_FAIL);
369 }
370 break;
371 }
372 }
373
374 return rval;
375}
376
377/*
378 * Encode as Canonical OER.
379 */
380asn_enc_rval_t
381SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700382 const asn_oer_constraints_t *constraints, void *sptr,
383 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin890e6032017-07-24 01:48:59 +0400384 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
385 size_t computed_size = 0;
386 int has_extensions_bit = (specs->ext_before >= 0);
387 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
388 uint32_t has_extensions = 0;
389 size_t edx;
390 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300391
Lev Walkin494fb702017-08-07 20:07:00 -0700392 (void)constraints;
393
Lev Walkin890e6032017-07-24 01:48:59 +0400394 if(preamble_bits) {
395 asn_per_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300396
Lev Walkin890e6032017-07-24 01:48:59 +0400397 memset(&preamble, 0, sizeof(preamble));
398 preamble.outper = cb;
399 preamble.op_key = app_key;
400
401 if(has_extensions_bit) {
Lev Walkin494fb702017-08-07 20:07:00 -0700402 for(edx = specs->ext_after + 1;
403 (ssize_t)edx < specs->ext_before - 1; edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400404 asn_TYPE_member_t *elm = &td->elements[edx];
405 if(element_ptr(sptr, elm)) {
406 has_extensions = 1;
407 break;
408 }
409 }
410 ret = per_put_few_bits(&preamble, has_extensions, 1);
411 assert(ret == 0);
412 if(ret < 0) {
413 ASN__ENCODE_FAILED;
414 }
415 }
416
417 /*
418 * Encode optional components bitmap.
419 */
420 if(specs->roms_count) {
421 for(edx = 0; edx < td->elements_count; edx++) {
422 asn_TYPE_member_t *elm = &td->elements[edx];
423
424 if(IN_EXTENSION_GROUP(specs, edx)) break;
425
426 if(elm->optional) {
427 uint32_t has_component = (element_ptr(sptr, elm) != NULL);
428 ret = per_put_few_bits(&preamble, has_component, 1);
429 if(ret < 0) {
430 ASN__ENCODE_FAILED;
431 }
432 }
433 }
434 }
435
436 per_put_aligned_flush(&preamble);
437 computed_size += preamble.flushed_bytes;
438 } /* if(preamble_bits) */
439
440 /*
441 * Put root components and extensions root.
442 */
443 for(edx = 0; edx < td->elements_count; edx++) {
444 asn_TYPE_member_t *elm = &td->elements[edx];
445 asn_enc_rval_t er;
446 void *memb_ptr;
447
448 if(IN_EXTENSION_GROUP(specs, edx)) break;
449
450 memb_ptr = element_ptr(sptr, elm);
451 if(!memb_ptr) {
452 if(elm->optional) continue;
453 /* Mandatory element is missing */
454 ASN__ENCODE_FAILED;
455 }
456 if(!elm->type->oer_encoder) {
457 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
458 ASN__ENCODE_FAILED;
459 }
460 er = elm->type->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
461 cb, app_key);
462 if(er.encoded == -1) {
463 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
464 elm->name);
465 return er;
466 }
467 computed_size += er.encoded;
468 }
469
470 /*
471 * Before encode extensions, encode extensions additions presense bitmap
472 # X.696 (08/2015) #16.4.
473 */
474 if(has_extensions) {
475 asn_per_outp_t extadds;
476
477 /* Special case allowing us to use exactly one byte for #8.6 */
478 size_t aoms_length_bits = specs->aoms_count;
479 size_t aoms_length_bytes = (7 + specs->aoms_count) >> 3;
480 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
481
482 assert(1 + aoms_length_bytes <= 127);
483
484 memset(&extadds, 0, sizeof(extadds));
485 extadds.outper = cb;
486 extadds.op_key = app_key;
487
488 /* #8.6 length determinant */
489 ret = per_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
490 if(ret < 0) ASN__ENCODE_FAILED;
491
492 /* Number of unused bytes, #16.4.2 */
493 ret = per_put_few_bits(&extadds, unused_bits, 8);
494 if(ret < 0) ASN__ENCODE_FAILED;
495
496 /* Encode presence bitmap #16.4.3 */
Lev Walkin494fb702017-08-07 20:07:00 -0700497 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
498 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400499 asn_TYPE_member_t *elm = &td->elements[edx];
500 void *memb_ptr = element_ptr(sptr, elm);
501 ret |= per_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
502 }
503 if(ret < 0) ASN__ENCODE_FAILED;
504
505 per_put_aligned_flush(&extadds);
506 computed_size += extadds.flushed_bytes;
507
508 /* Now, encode extensions */
Lev Walkin494fb702017-08-07 20:07:00 -0700509 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
510 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400511 asn_TYPE_member_t *elm = &td->elements[edx];
512 void *memb_ptr = element_ptr(sptr, elm);
513
514 if(memb_ptr) {
515 asn_enc_rval_t er = elm->type->oer_encoder(
516 elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
517 if(er.encoded == -1) {
518 return er;
519 }
520 computed_size += er.encoded;
521 } else if(!elm->optional) {
522 ASN__ENCODE_FAILED;
523 }
524 }
525 } /* if(has_extensions) */
526
527
528 {
529 asn_enc_rval_t er = {0, 0, 0};
530 er.encoded = computed_size;
531 ASN__ENCODED_OK(er);
532 }
Lev Walkind88bea92017-07-20 11:21:30 +0300533}
534
535#endif /* ASN_DISABLE_OER_SUPPORT */