blob: fba670235aeaca9d2092a50759631341ce15c459 [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
53asn_dec_rval_t
54SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
55 asn_oer_constraints_t *constraints, void **struct_ptr,
56 const void *ptr, size_t size) {
57 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
58 asn_dec_rval_t rval = {RC_OK, 0};
59 void *st = *struct_ptr; /* Target structure */
60 asn_struct_ctx_t *ctx; /* Decoder context */
61 size_t consumed_myself = 0; /* Consumed bytes from ptr. */
62
63
64 (void)opt_codec_ctx;
65 (void)specs;
66
67 /*
68 * Create the target structure if it is not present already.
69 */
70 if(st == 0) {
71 st = *struct_ptr = CALLOC(1, specs->struct_size);
72 if(st == 0) {
73 RETURN(RC_FAIL);
74 }
75 }
76
77 /*
78 * Restore parsing context.
79 */
80 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
81 if(ctx->ptr == 0) {
82 ctx->ptr = CALLOC(1, sizeof(asn_per_data_t));
83 if(!ctx->ptr) {
84 RETURN(RC_FAIL);
85 }
86 }
87
88 /*
89 * Start to parse where left previously.
90 */
91 switch(ctx->phase) {
92 case 0: {
93 /*
94 * Fetch preamble.
95 */
96 asn_per_data_t *preamble = ctx->ptr;
97 int has_extensions = (specs->ext_before >= 0);
98 size_t preamble_bits = (has_extensions + specs->roms_count);
99 size_t preamble_bytes = (preamble_bits >> 3);
100 uint8_t *pbytes;
101
102 if(size < preamble_bytes) {
103 ASN__DECODE_STARVED;
104 }
105
106 pbytes = MALLOC(preamble_bytes + 1);
107 if(!pbytes) {
108 RETURN(RC_FAIL);
109 }
110 preamble->buffer = (const void *)pbytes;
111 memcpy(pbytes, ptr, preamble_bytes);
112 pbytes[preamble_bytes] = '\0'; /* Just in case */
113 preamble->nboff = has_extensions;
114 preamble->nbits = preamble_bits;
115 ADVANCE(preamble_bytes);
116 }
117 NEXT_PHASE(ctx);
118 /* FALL THROUGH */
119 case 1: {
120 /* Decode components of the extension root */
121 asn_per_data_t *preamble = ctx->ptr;
122 size_t edx;
123
124 for(edx = (ctx->step >> 1); edx < td->elements_count;
125 edx++, ctx->step = (ctx->step & ~1) + 2) {
126 asn_TYPE_member_t *elm = &td->elements[edx];
127 void **memb_ptr2; /* Pointer to a pointer to a memmber */
128
129 if(ctx->step & 1) {
130 goto microphase2_decode_continues;
131 }
132
133
134 if(IN_EXTENSION_GROUP(specs, edx)) {
135 /* Ignore non-root components in PHASE 1 */
136 continue;
137 }
138
139 if(elm->optional) {
140 int32_t present = per_get_few_bits(preamble, 1);
141 if(present < 0) {
142 RETURN(RC_FAIL);
143 } else if(present == 0) {
144 if(elm->default_value) {
145 if(elm->flags & ATF_POINTER) {
146 /* Member is a pointer to another structure */
147 memb_ptr2 =
148 (void **)((char *)st + elm->memb_offset);
149 } else {
150 void *memb_ptr = (char *)st + elm->memb_offset;
151 memb_ptr2 = &memb_ptr;
152 }
153 /* Fill-in DEFAULT */
154 if(elm->default_value(1, memb_ptr2)) {
155 RETURN(RC_FAIL);
156 }
157 }
158 /* The member is not present. */
159 continue;
160 }
161 /* Present OPTIONAL or DEFAULT component. */
162 }
163
164 /*
165 * MICROPHASE 2: Invoke the member-specific decoder.
166 */
167 ctx->step |= 1; /* Confirm entering next microphase */
168 microphase2_decode_continues:
169 if(elm->flags & ATF_POINTER) {
170 /* Member is a pointer to another structure */
171 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
172 } else {
173 void *memb_ptr = (char *)st + elm->memb_offset;
174 memb_ptr2 = &memb_ptr;
175 }
176
177 rval = elm->type->oer_decoder(opt_codec_ctx, elm->type,
178 elm->oer_constraints, memb_ptr2, ptr,
179 size);
180 switch(rval.code) {
181 case RC_OK:
182 ADVANCE(rval.consumed);
183 break;
184 case RC_WMORE:
185 ADVANCE(rval.consumed);
186 RETURN(RC_WMORE);
187 case RC_FAIL:
188 RETURN(RC_FAIL);
189 }
190 } /* for(all root members) */
191
192 }
193 NEXT_PHASE(ctx);
194 /* FALL THROUGH */
195 case 2: {
196 /* Cleanup preamble. */
197 asn_per_data_t *preamble = ctx->ptr;
198 asn_per_data_t *extadds;
199 int has_extensions = (specs->ext_before >= 0);
200 int extensions_present =
201 has_extensions && (((const uint8_t *)preamble->buffer)[0] & 0x80);
202 uint8_t unused_bits;
203 size_t len = 0;
204 ssize_t len_len;
205 uint8_t *ebytes;
206
207 union {
208 const uint8_t *cptr;
209 uint8_t *uptr;
210 } unconst;
211 unconst.cptr = preamble->buffer;
212 FREEMEM(unconst.uptr);
213 preamble->buffer = 0;
214
215 if(!extensions_present) {
216 ctx->phase = 10;
217 RETURN(RC_OK);
218 }
219
220 /*
221 * X.696 (08/2015) #16.1 (c), #16.4
222 * Read in the extension addition presence bitmap.
223 */
224
225 len_len = oer_fetch_length(ptr, size, &len);
226 if(len_len > 0) {
227 ADVANCE(len_len);
228 } if(len_len < 0) {
229 RETURN(RC_FAIL);
230 } else {
231 RETURN(RC_WMORE);
232 }
233
234 if(len == 0) {
235 /* 16.4.1-2 */
236 RETURN(RC_FAIL);
237 } else if(len > size) {
238 RETURN(RC_WMORE);
239 }
240
241 /* Account for unused bits */
242 unused_bits = 0x7 & *(const uint8_t *)ptr;
243 ADVANCE(1);
244 len--;
245 if(unused_bits && len == 0) {
246 RETURN(RC_FAIL);
247 }
248
249 /* Get the extensions map */
250 ebytes = MALLOC(len + 1);
251 if(!ebytes) {
252 RETURN(RC_FAIL);
253 }
254 memcpy(ebytes, ptr, len);
255 ebytes[len] = '\0';
256
257 extadds = preamble;
258 memset(extadds, 0, sizeof(*extadds));
259 extadds->buffer = ebytes;
260 extadds->nboff = 0;
261 extadds->nbits = 8 * len - unused_bits;
262
263 ADVANCE(len);
264 }
265 NEXT_PHASE(ctx);
266 ctx->step = (specs->ext_after + 1);
267 /* Fall through */
268 case 3:
269 for(; ctx->step < specs->ext_before; ctx->step++) {
270 asn_per_data_t *extadds = ctx->ptr;
271 size_t edx = ctx->step;
272 asn_TYPE_member_t *elm = &td->elements[edx];
273 void **memb_ptr2;
274
275 if(elm->flags & ATF_POINTER) {
276 /* Member is a pointer to another structure */
277 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
278 } else {
279 void *memb_ptr = (char *)st + elm->memb_offset;
280 memb_ptr2 = &memb_ptr;
281 assert(elm->flags & ATF_POINTER); /* Extensions are indirect */
282 }
283
284 switch(per_get_few_bits(extadds, 1)) {
285 case -1:
286 /*
287 * Not every one of our extensions is known to the remote side.
288 * Continue filling in their defaults though.
289 */
290 /* Fall through */
291 case 0:
292 /* Fill-in DEFAULT */
293 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
294 RETURN(RC_FAIL);
295 }
296 continue;
297 case 1: {
298 /* Read OER open type */
299 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
300 elm->oer_constraints,
301 memb_ptr2, ptr, size);
302 if(ot_size > 0) {
303 ADVANCE(ot_size);
304 } else if(ot_size < 0) {
305 RETURN(RC_FAIL);
306 } else {
307 /* Roll back open type parsing */
308 per_get_undo(extadds, 1);
309 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
310 *memb_ptr2 = NULL;
311 RETURN(RC_WMORE);
312 }
313 break;
314 }
315 default:
316 RETURN(RC_FAIL);
317 }
318 }
319
320 NEXT_PHASE(ctx);
321 /* Fall through */
322 case 4:
323 /* Read in the rest of Open Types while ignoring them */
324 for(;;) {
325 asn_per_data_t *extadds = ctx->ptr;
326 switch(per_get_few_bits(extadds, 1)) {
327 case 0:
328 continue;
329 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300330 ssize_t skipped = oer_open_type_skip(ptr, size);
331 if(skipped > 0) {
332 ADVANCE(skipped);
333 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300334 RETURN(RC_FAIL);
335 } else {
336 per_get_undo(extadds, 1);
337 RETURN(RC_WMORE);
338 }
339 continue;
340 }
341 case -1:
342 /* No more Open Type encoded components */
343 break;
344 default:
345 RETURN(RC_FAIL);
346 }
347 break;
348 }
349 }
350
351 return rval;
352}
353
354/*
355 * Encode as Canonical OER.
356 */
357asn_enc_rval_t
358SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
359 asn_oer_constraints_t *constraints, void *sptr,
360 asn_app_consume_bytes_f *cb, void *app_key) {
361 asn_enc_rval_t er;
362 const uint8_t *buf;
363 const uint8_t *end;
364 size_t useful_bytes;
365 size_t req_bytes = 0;
366 int encode_as_unsigned;
367 int sign = 0;
368
369 er.encoded = -1;
370
371 return er;
372}
373
374#endif /* ASN_DISABLE_OER_SUPPORT */