blob: c6d86093a2abdc6cd4f0fcd818cc8a5f88be3741 [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) \
40 ( ((memb_idx) > (specs)->ext_after) \
41 &&((memb_idx) < (specs)->ext_before))
42
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,
73 asn_oer_constraints_t *constraints, void **struct_ptr,
74 const void *ptr, size_t size) {
75 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;
83 (void)specs;
84
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: {
Lev Walkin890e6032017-07-24 01:48:59 +0400111 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300112 /*
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 Walkin890e6032017-07-24 01:48:59 +0400121 ASN_DEBUG(
122 "Expecting preamble bits %zu for %s (including %d extension bits)",
123 preamble_bits, td->name, has_extensions_bit);
124
Lev Walkind88bea92017-07-20 11:21:30 +0300125 if(size < preamble_bytes) {
126 ASN__DECODE_STARVED;
127 }
128
129 pbytes = MALLOC(preamble_bytes + 1);
130 if(!pbytes) {
131 RETURN(RC_FAIL);
132 }
133 preamble->buffer = (const void *)pbytes;
134 memcpy(pbytes, ptr, preamble_bytes);
135 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400136 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300137 preamble->nbits = preamble_bits;
138 ADVANCE(preamble_bytes);
139 }
140 NEXT_PHASE(ctx);
141 /* FALL THROUGH */
142 case 1: {
Lev Walkin890e6032017-07-24 01:48:59 +0400143 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300144 /* Decode components of the extension root */
145 asn_per_data_t *preamble = ctx->ptr;
146 size_t edx;
147
148 for(edx = (ctx->step >> 1); edx < td->elements_count;
149 edx++, ctx->step = (ctx->step & ~1) + 2) {
150 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400151 void *memb_tmpptr; /* Temporary reference. */
Lev Walkind88bea92017-07-20 11:21:30 +0300152 void **memb_ptr2; /* Pointer to a pointer to a memmber */
153
Lev Walkin890e6032017-07-24 01:48:59 +0400154 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
155
Lev Walkind88bea92017-07-20 11:21:30 +0300156 if(ctx->step & 1) {
157 goto microphase2_decode_continues;
158 }
159
160
161 if(IN_EXTENSION_GROUP(specs, edx)) {
162 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400163 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300164 }
165
166 if(elm->optional) {
167 int32_t present = per_get_few_bits(preamble, 1);
168 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400169 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300170 RETURN(RC_FAIL);
171 } else if(present == 0) {
172 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300173 /* Fill-in DEFAULT */
Lev Walkin890e6032017-07-24 01:48:59 +0400174 if(elm->default_value(1, element_ptrptr(st, elm))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300175 RETURN(RC_FAIL);
176 }
177 }
178 /* The member is not present. */
179 continue;
180 }
181 /* Present OPTIONAL or DEFAULT component. */
182 }
183
184 /*
185 * MICROPHASE 2: Invoke the member-specific decoder.
186 */
187 ctx->step |= 1; /* Confirm entering next microphase */
188 microphase2_decode_continues:
189 if(elm->flags & ATF_POINTER) {
190 /* Member is a pointer to another structure */
191 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
192 } else {
Lev Walkin890e6032017-07-24 01:48:59 +0400193 memb_tmpptr = (char *)st + elm->memb_offset;
194 memb_ptr2 = &memb_tmpptr; /* Ensure this & remains in scope! */
Lev Walkind88bea92017-07-20 11:21:30 +0300195 }
196
197 rval = elm->type->oer_decoder(opt_codec_ctx, elm->type,
198 elm->oer_constraints, memb_ptr2, ptr,
199 size);
200 switch(rval.code) {
201 case RC_OK:
202 ADVANCE(rval.consumed);
203 break;
204 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400205 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
206 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300207 ADVANCE(rval.consumed);
208 RETURN(RC_WMORE);
209 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400210 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
211 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300212 RETURN(RC_FAIL);
213 }
214 } /* for(all root members) */
215
216 }
217 NEXT_PHASE(ctx);
218 /* FALL THROUGH */
219 case 2: {
Lev Walkin890e6032017-07-24 01:48:59 +0400220 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300221 /* Cleanup preamble. */
222 asn_per_data_t *preamble = ctx->ptr;
223 asn_per_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400224 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300225 int extensions_present =
Lev Walkin890e6032017-07-24 01:48:59 +0400226 has_extensions_bit && (((const uint8_t *)preamble->buffer)[0] & 0x80);
Lev Walkind88bea92017-07-20 11:21:30 +0300227 uint8_t unused_bits;
228 size_t len = 0;
229 ssize_t len_len;
230 uint8_t *ebytes;
231
232 union {
233 const uint8_t *cptr;
234 uint8_t *uptr;
235 } unconst;
236 unconst.cptr = preamble->buffer;
237 FREEMEM(unconst.uptr);
238 preamble->buffer = 0;
239
240 if(!extensions_present) {
241 ctx->phase = 10;
242 RETURN(RC_OK);
243 }
244
245 /*
246 * X.696 (08/2015) #16.1 (c), #16.4
247 * Read in the extension addition presence bitmap.
248 */
249
250 len_len = oer_fetch_length(ptr, size, &len);
251 if(len_len > 0) {
252 ADVANCE(len_len);
253 } if(len_len < 0) {
254 RETURN(RC_FAIL);
255 } else {
256 RETURN(RC_WMORE);
257 }
258
259 if(len == 0) {
260 /* 16.4.1-2 */
261 RETURN(RC_FAIL);
262 } else if(len > size) {
263 RETURN(RC_WMORE);
264 }
265
266 /* Account for unused bits */
267 unused_bits = 0x7 & *(const uint8_t *)ptr;
268 ADVANCE(1);
269 len--;
270 if(unused_bits && len == 0) {
271 RETURN(RC_FAIL);
272 }
273
274 /* Get the extensions map */
275 ebytes = MALLOC(len + 1);
276 if(!ebytes) {
277 RETURN(RC_FAIL);
278 }
279 memcpy(ebytes, ptr, len);
280 ebytes[len] = '\0';
281
282 extadds = preamble;
283 memset(extadds, 0, sizeof(*extadds));
284 extadds->buffer = ebytes;
285 extadds->nboff = 0;
286 extadds->nbits = 8 * len - unused_bits;
287
288 ADVANCE(len);
289 }
290 NEXT_PHASE(ctx);
291 ctx->step = (specs->ext_after + 1);
292 /* Fall through */
293 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400294 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
295 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkind88bea92017-07-20 11:21:30 +0300296 asn_per_data_t *extadds = ctx->ptr;
297 size_t edx = ctx->step;
298 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400299 void **memb_ptr2 = element_ptrptr(st, elm);
Lev Walkind88bea92017-07-20 11:21:30 +0300300
301 switch(per_get_few_bits(extadds, 1)) {
302 case -1:
303 /*
304 * Not every one of our extensions is known to the remote side.
305 * Continue filling in their defaults though.
306 */
307 /* Fall through */
308 case 0:
309 /* Fill-in DEFAULT */
310 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
311 RETURN(RC_FAIL);
312 }
313 continue;
314 case 1: {
315 /* Read OER open type */
316 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
317 elm->oer_constraints,
318 memb_ptr2, ptr, size);
319 if(ot_size > 0) {
320 ADVANCE(ot_size);
321 } else if(ot_size < 0) {
322 RETURN(RC_FAIL);
323 } else {
324 /* Roll back open type parsing */
325 per_get_undo(extadds, 1);
326 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
327 *memb_ptr2 = NULL;
328 RETURN(RC_WMORE);
329 }
330 break;
331 }
332 default:
333 RETURN(RC_FAIL);
334 }
335 }
336
337 NEXT_PHASE(ctx);
338 /* Fall through */
339 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400340 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300341 /* Read in the rest of Open Types while ignoring them */
342 for(;;) {
343 asn_per_data_t *extadds = ctx->ptr;
344 switch(per_get_few_bits(extadds, 1)) {
345 case 0:
346 continue;
347 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300348 ssize_t skipped = oer_open_type_skip(ptr, size);
349 if(skipped > 0) {
350 ADVANCE(skipped);
351 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300352 RETURN(RC_FAIL);
353 } else {
354 per_get_undo(extadds, 1);
355 RETURN(RC_WMORE);
356 }
357 continue;
358 }
359 case -1:
360 /* No more Open Type encoded components */
361 break;
362 default:
363 RETURN(RC_FAIL);
364 }
365 break;
366 }
367 }
368
369 return rval;
370}
371
372/*
373 * Encode as Canonical OER.
374 */
375asn_enc_rval_t
376SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
377 asn_oer_constraints_t *constraints, void *sptr,
378 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin890e6032017-07-24 01:48:59 +0400379 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
380 size_t computed_size = 0;
381 int has_extensions_bit = (specs->ext_before >= 0);
382 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
383 uint32_t has_extensions = 0;
384 size_t edx;
385 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300386
Lev Walkin890e6032017-07-24 01:48:59 +0400387 if(preamble_bits) {
388 asn_per_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300389
Lev Walkin890e6032017-07-24 01:48:59 +0400390 memset(&preamble, 0, sizeof(preamble));
391 preamble.outper = cb;
392 preamble.op_key = app_key;
393
394 if(has_extensions_bit) {
395 for(edx = specs->ext_after + 1; edx < specs->ext_before - 1;
396 edx++) {
397 asn_TYPE_member_t *elm = &td->elements[edx];
398 if(element_ptr(sptr, elm)) {
399 has_extensions = 1;
400 break;
401 }
402 }
403 ret = per_put_few_bits(&preamble, has_extensions, 1);
404 assert(ret == 0);
405 if(ret < 0) {
406 ASN__ENCODE_FAILED;
407 }
408 }
409
410 /*
411 * Encode optional components bitmap.
412 */
413 if(specs->roms_count) {
414 for(edx = 0; edx < td->elements_count; edx++) {
415 asn_TYPE_member_t *elm = &td->elements[edx];
416
417 if(IN_EXTENSION_GROUP(specs, edx)) break;
418
419 if(elm->optional) {
420 uint32_t has_component = (element_ptr(sptr, elm) != NULL);
421 ret = per_put_few_bits(&preamble, has_component, 1);
422 if(ret < 0) {
423 ASN__ENCODE_FAILED;
424 }
425 }
426 }
427 }
428
429 per_put_aligned_flush(&preamble);
430 computed_size += preamble.flushed_bytes;
431 } /* if(preamble_bits) */
432
433 /*
434 * Put root components and extensions root.
435 */
436 for(edx = 0; edx < td->elements_count; edx++) {
437 asn_TYPE_member_t *elm = &td->elements[edx];
438 asn_enc_rval_t er;
439 void *memb_ptr;
440
441 if(IN_EXTENSION_GROUP(specs, edx)) break;
442
443 memb_ptr = element_ptr(sptr, elm);
444 if(!memb_ptr) {
445 if(elm->optional) continue;
446 /* Mandatory element is missing */
447 ASN__ENCODE_FAILED;
448 }
449 if(!elm->type->oer_encoder) {
450 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
451 ASN__ENCODE_FAILED;
452 }
453 er = elm->type->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
454 cb, app_key);
455 if(er.encoded == -1) {
456 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
457 elm->name);
458 return er;
459 }
460 computed_size += er.encoded;
461 }
462
463 /*
464 * Before encode extensions, encode extensions additions presense bitmap
465 # X.696 (08/2015) #16.4.
466 */
467 if(has_extensions) {
468 asn_per_outp_t extadds;
469
470 /* Special case allowing us to use exactly one byte for #8.6 */
471 size_t aoms_length_bits = specs->aoms_count;
472 size_t aoms_length_bytes = (7 + specs->aoms_count) >> 3;
473 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
474
475 assert(1 + aoms_length_bytes <= 127);
476
477 memset(&extadds, 0, sizeof(extadds));
478 extadds.outper = cb;
479 extadds.op_key = app_key;
480
481 /* #8.6 length determinant */
482 ret = per_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
483 if(ret < 0) ASN__ENCODE_FAILED;
484
485 /* Number of unused bytes, #16.4.2 */
486 ret = per_put_few_bits(&extadds, unused_bits, 8);
487 if(ret < 0) ASN__ENCODE_FAILED;
488
489 /* Encode presence bitmap #16.4.3 */
490 for(edx = specs->ext_after + 1; edx < specs->ext_before - 1; edx++) {
491 asn_TYPE_member_t *elm = &td->elements[edx];
492 void *memb_ptr = element_ptr(sptr, elm);
493 ret |= per_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
494 }
495 if(ret < 0) ASN__ENCODE_FAILED;
496
497 per_put_aligned_flush(&extadds);
498 computed_size += extadds.flushed_bytes;
499
500 /* Now, encode extensions */
501 for(edx = specs->ext_after + 1; edx < specs->ext_before - 1; edx++) {
502 asn_TYPE_member_t *elm = &td->elements[edx];
503 void *memb_ptr = element_ptr(sptr, elm);
504
505 if(memb_ptr) {
506 asn_enc_rval_t er = elm->type->oer_encoder(
507 elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
508 if(er.encoded == -1) {
509 return er;
510 }
511 computed_size += er.encoded;
512 } else if(!elm->optional) {
513 ASN__ENCODE_FAILED;
514 }
515 }
516 } /* if(has_extensions) */
517
518
519 {
520 asn_enc_rval_t er = {0, 0, 0};
521 er.encoded = computed_size;
522 ASN__ENCODED_OK(er);
523 }
Lev Walkind88bea92017-07-20 11:21:30 +0300524}
525
526#endif /* ASN_DISABLE_OER_SUPPORT */