SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_SET_OF_ber.c
1 /*
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 #include <asn_internal.h>
7 #include <constr_SET_OF.h>
8 #include <asn_SET_OF.h>
9
10 /*
11  * Number of bytes left for this structure.
12  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
13  * (size) contains the number of bytes in the buffer passed.
14  */
15 #define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
16
17 /*
18  * If the subprocessor function returns with an indication that it wants
19  * more data, it may well be a fatal decoding problem, because the
20  * size is constrained by the <TLV>'s L, even if the buffer size allows
21  * reading more data.
22  * For example, consider the buffer containing the following TLVs:
23  * <T:5><L:1><V> <T:6>...
24  * The TLV length clearly indicates that one byte is expected in V, but
25  * if the V processor returns with "want more data" even if the buffer
26  * contains way more data than the V processor have seen.
27  */
28 #define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size)
29
30 /*
31  * This macro "eats" the part of the buffer which is definitely "consumed",
32  * i.e. was correctly converted into local representation or rightfully skipped.
33  */
34 #undef ADVANCE
35 #define ADVANCE(num_bytes)                \
36     do {                                  \
37         size_t num = num_bytes;           \
38         ptr = ((const char *)ptr) + num;  \
39         size -= num;                      \
40         if(ctx->left >= 0)                \
41             ctx->left -= num;             \
42         consumed_myself += num;           \
43     } while(0)
44
45 /*
46  * Switch to the next phase of parsing.
47  */
48 #undef NEXT_PHASE
49 #define NEXT_PHASE(ctx)  \
50     do {                 \
51         ctx->phase++;    \
52         ctx->step = 0;   \
53     } while(0)
54 #undef PHASE_OUT
55 #define PHASE_OUT(ctx)    \
56     do {                  \
57         ctx->phase = 10;  \
58     } while(0)
59
60 /*
61  * Return a standardized complex structure.
62  */
63 #undef RETURN
64 #define RETURN(_code)                     \
65     do {                                  \
66         rval.code = _code;                \
67         rval.consumed = consumed_myself;  \
68         return rval;                      \
69     } while(0)
70
71 /*
72  * The decoder of the SET OF type.
73  */
74 asn_dec_rval_t
75 SET_OF_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
76                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
77                   const void *ptr, size_t size, int tag_mode) {
78     /*
79      * Bring closer parts of structure description.
80      */
81     const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
82     const asn_TYPE_member_t *elm = td->elements; /* Single one */
83
84     /*
85      * Parts of the structure being constructed.
86      */
87     void *st = *struct_ptr;  /* Target structure. */
88     asn_struct_ctx_t *ctx;   /* Decoder context */
89
90     ber_tlv_tag_t tlv_tag;  /* T from TLV */
91     asn_dec_rval_t rval;    /* Return code from subparsers */
92
93     ssize_t consumed_myself = 0;  /* Consumed bytes from ptr */
94
95     ASN_DEBUG("Decoding %s as SET OF", td->name);
96
97     /*
98      * Create the target structure if it is not present already.
99      */
100     if(st == 0) {
101         st = *struct_ptr = CALLOC(1, specs->struct_size);
102         if(st == 0) {
103             RETURN(RC_FAIL);
104         }
105     }
106
107     /*
108      * Restore parsing context.
109      */
110     ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
111
112     /*
113      * Start to parse where left previously
114      */
115     switch(ctx->phase) {
116     case 0:
117         /*
118          * PHASE 0.
119          * Check that the set of tags associated with given structure
120          * perfectly fits our expectations.
121          */
122
123         rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
124                               tag_mode, 1, &ctx->left, 0);
125         if(rval.code != RC_OK) {
126             ASN_DEBUG("%s tagging check failed: %d",
127                       td->name, rval.code);
128             return rval;
129         }
130
131         if(ctx->left >= 0)
132             ctx->left += rval.consumed;  /* ?Subtracted below! */
133         ADVANCE(rval.consumed);
134
135         ASN_DEBUG("Structure consumes %ld bytes, "
136                   "buffer %ld", (long)ctx->left, (long)size);
137
138         NEXT_PHASE(ctx);
139         /* Fall through */
140     case 1:
141         /*
142          * PHASE 1.
143          * From the place where we've left it previously,
144          * try to decode the next item.
145          */
146         for(;; ctx->step = 0) {
147             ssize_t tag_len;  /* Length of TLV's T */
148
149             if(ctx->step & 1)
150                 goto microphase2;
151
152             /*
153              * MICROPHASE 1: Synchronize decoding.
154              */
155
156             if(ctx->left == 0) {
157                 ASN_DEBUG("End of SET OF %s", td->name);
158                 /*
159                  * No more things to decode.
160                  * Exit out of here.
161                  */
162                 PHASE_OUT(ctx);
163                 RETURN(RC_OK);
164             }
165
166             /*
167              * Fetch the T from TLV.
168              */
169             tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
170             switch(tag_len) {
171             case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
172                 /* Fall through */
173             case -1: RETURN(RC_FAIL);
174             }
175
176             if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
177                 if(LEFT < 2) {
178                     if(SIZE_VIOLATION)
179                         RETURN(RC_FAIL);
180                     else
181                         RETURN(RC_WMORE);
182                 } else if(((const uint8_t *)ptr)[1] == 0) {
183                     /*
184                      * Found the terminator of the
185                      * indefinite length structure.
186                      */
187                     break;
188                 }
189             }
190
191             /* Outmost tag may be unknown and cannot be fetched/compared */
192             if(elm->tag != (ber_tlv_tag_t)-1) {
193                 if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
194                 /*
195                  * The new list member of expected type has arrived.
196                  */
197                 } else {
198                     ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
199                               ber_tlv_tag_string(tlv_tag), td->name);
200                     ASN_DEBUG("%s SET OF has tag %s",
201                               td->name, ber_tlv_tag_string(elm->tag));
202                     RETURN(RC_FAIL);
203                 }
204             }
205
206             /*
207              * MICROPHASE 2: Invoke the member-specific decoder.
208              */
209             ctx->step |= 1;  /* Confirm entering next microphase */
210         microphase2:
211
212             /*
213              * Invoke the member fetch routine according to member's type
214              */
215             rval = elm->type->op->ber_decoder(opt_codec_ctx,
216                                               elm->type, &ctx->ptr,
217                                               ptr, LEFT, 0);
218             ASN_DEBUG("In %s SET OF %s code %d consumed %d",
219                       td->name, elm->type->name,
220                       rval.code, (int)rval.consumed);
221             switch(rval.code) {
222             case RC_OK:
223                 {
224                     asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
225                     if(ASN_SET_ADD(list, ctx->ptr) != 0)
226                         RETURN(RC_FAIL);
227                     else
228                         ctx->ptr = 0;
229                 }
230                 break;
231             case RC_WMORE:  /* More data expected */
232                 if(!SIZE_VIOLATION) {
233                     ADVANCE(rval.consumed);
234                     RETURN(RC_WMORE);
235                 }
236                 /* Fall through */
237             case RC_FAIL:  /* Fatal error */
238                 ASN_STRUCT_FREE(*elm->type, ctx->ptr);
239                 ctx->ptr = 0;
240                 RETURN(RC_FAIL);
241             }  /* switch(rval) */
242
243             ADVANCE(rval.consumed);
244         }  /* for(all list members) */
245
246         NEXT_PHASE(ctx);
247     case 2:
248         /*
249          * Read in all "end of content" TLVs.
250          */
251         while(ctx->left < 0) {
252             if(LEFT < 2) {
253                 if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
254                     /* Unexpected tag */
255                     RETURN(RC_FAIL);
256                 } else {
257                     RETURN(RC_WMORE);
258                 }
259             }
260             if(((const char *)ptr)[0] == 0
261             && ((const char *)ptr)[1] == 0) {
262                 ADVANCE(2);
263                 ctx->left++;
264             } else {
265                 RETURN(RC_FAIL);
266             }
267         }
268
269         PHASE_OUT(ctx);
270     }
271
272     RETURN(RC_OK);
273 }
274
275 /*
276  * The DER encoder of the SET OF type.
277  */
278 asn_enc_rval_t
279 SET_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
280                   int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
281                   void *app_key) {
282     const asn_TYPE_member_t *elm = td->elements;
283     const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
284     size_t computed_size = 0;
285     ssize_t encoding_size = 0;
286     struct _el_buffer *encoded_els;
287     int edx;
288
289     ASN_DEBUG("Estimating size for SET OF %s", td->name);
290
291     /*
292      * Gather the length of the underlying members sequence.
293      */
294     for(edx = 0; edx < list->count; edx++) {
295         void *memb_ptr = list->array[edx];
296         asn_enc_rval_t erval = {0,0,0};
297
298         if(!memb_ptr) ASN__ENCODE_FAILED;
299
300         erval =
301             elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag, 0, 0);
302         if(erval.encoded == -1) return erval;
303         computed_size += erval.encoded;
304     }
305
306     /*
307      * Encode the TLV for the sequence itself.
308      */
309     encoding_size =
310         der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
311     if(encoding_size < 0) {
312         ASN__ENCODE_FAILED;
313     }
314     computed_size += encoding_size;
315
316     if(!cb || list->count == 0) {
317         asn_enc_rval_t erval = {0,0,0};
318         erval.encoded = computed_size;
319         ASN__ENCODED_OK(erval);
320     }
321
322     ASN_DEBUG("Encoding members of %s SET OF", td->name);
323
324     /*
325      * DER mandates dynamic sorting of the SET OF elements
326      * according to their encodings. Build an array of the
327      * encoded elements.
328      */
329     encoded_els = SET_OF__encode_sorted(elm, list, SOES_DER);
330
331     /*
332      * Report encoded elements to the application.
333      * Dispose of temporary sorted members table.
334      */
335     for(edx = 0; edx < list->count; edx++) {
336         struct _el_buffer *encoded_el = &encoded_els[edx];
337         /* Report encoded chunks to the application */
338         if(cb(encoded_el->buf, encoded_el->length, app_key) < 0) {
339             break;
340         } else {
341             encoding_size += encoded_el->length;
342         }
343     }
344
345     SET_OF__encode_sorted_free(encoded_els, list->count);
346
347     if(edx == list->count) {
348         asn_enc_rval_t erval = {0,0,0};
349         assert(computed_size == (size_t)encoding_size);
350         erval.encoded = computed_size;
351         ASN__ENCODED_OK(erval);
352     } else {
353         ASN__ENCODE_FAILED;
354     }
355 }