blob: f0d07ac72447abb1d0eccdc768ce626357bae19d [file] [log] [blame]
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +02001/* csn1_dec.c
2 * Routines for CSN1 dissection in wireshark.
3 *
4 * Copyright (C) 2011 Ivan Klyuchnikov
5 *
6 * By Vincent Helfre, based on original code by Jari Sassi
7 * with the gracious authorization of STE
8 * Copyright (c) 2011 ST-Ericsson
9 *
10 * $Id: packet-csn1.c 39140 2011-09-25 22:01:50Z wmeier $
11 *
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +020025 */
26
27#include <assert.h>
28#include <string.h>
29#define __STDC_FORMAT_MACROS
30#include <inttypes.h>
31#include "csn1.h"
32#include <gprs_debug.h>
33
34#include <osmocom/core/logging.h>
35#include <osmocom/core/utils.h>
36
37extern const unsigned char ixBitsTab[];
38guint8 get_masked_bits8(struct bitvec *vector, unsigned *readIndex, gint bit_offset, const gint no_of_bits);
39
40/**
41 * ================================================================================================
42 * Return TRUE if tag in bit stream indicates existence of next list element,
43 * otherwise return FALSE.
44 * Will work for tag values equal to both 0 and 1.
45 * ================================================================================================
46 */
47
48static gboolean
49existNextElement(struct bitvec *vector, unsigned *readIndex, guint8 Tag)
50{
51 int res = bitvec_get_bit_pos(vector, (*readIndex)++);
52 if (Tag == STANDARD_TAG)
53 {
54 return (res > 0);
55 }
56 return (res == 0);
57}
58
59
60gint16
61csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *readIndex, void* data)
62{
63 gint remaining_bits_len = ar->remaining_bits_len;
64 gint bit_offset = ar->bit_offset;
65 guint8* pui8 = NULL;
66 guint16* pui16;
67 guint32* pui32;
68 guint64* pui64;
69 guint8 Tag = STANDARD_TAG;
70 unsigned ib;
71
72 if (remaining_bits_len < 0)
73 {
74 return ProcessError(readIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
75 }
76
77 do
78 {
79 switch (pDescr->type)
80 {
81 case CSN_BIT:
82 {
83 if (remaining_bits_len > 0)
84 {
85 pui8 = pui8DATA(data, pDescr->offset);
86 *pui8 = bitvec_read_field(vector, readIndex, 1);
87 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
88 /* end add the bit value to protocol tree */
89 }
90 else if (pDescr->may_be_null)
91 {
92 pui8 = pui8DATA(data, pDescr->offset);
93 *pui8 = 0;
94 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
95 }
96 else
97 {
98 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
99 }
100
101 pDescr++;
102 remaining_bits_len--;
103 bit_offset++;
104 break;
105 }
106
107 case CSN_NULL:
108 { /* Empty member! */
109 bit_offset += pDescr->i;
110 pDescr++;
111 break;
112 }
113
114 case CSN_UINT:
115 {
116 guint8 no_of_bits = (guint8) pDescr->i;
117
118 if (remaining_bits_len >= no_of_bits)
119 {
120 if (no_of_bits <= 8)
121 {
122 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
123 pui8 = pui8DATA(data, pDescr->offset);
124 *pui8 = ui8;
125 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
126 }
127 else if (no_of_bits <= 16)
128 {
129 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
130 pui16 = pui16DATA(data, pDescr->offset);
131 *pui16 = ui16;
132 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
133 }
134 else if (no_of_bits <= 32)
135 {
136 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
137 pui32 = pui32DATA(data, pDescr->offset);
138 *pui32 = ui32;
139 LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%08x | ", pDescr->sz , *pui32);
140 }
141 else
142 {
143 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
144 }
145 remaining_bits_len -= no_of_bits;
146 bit_offset += no_of_bits;
147 }
148 else if (pDescr->may_be_null)
149 {
150 if (no_of_bits <= 8)
151 {
152 pui8 = pui8DATA(data, pDescr->offset);
153 *pui8 = 0;
154 }
155 else if (no_of_bits <= 16)
156 {
157 pui16 = pui16DATA(data, pDescr->offset);
158 *pui16 = 0;
159 }
160 else if (no_of_bits <= 32)
161 {
162 pui32 = pui32DATA(data, pDescr->offset);
163 *pui32 = 0;
164 }
165 LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz);
166 }
167 else
168 {
169 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
170 }
171
172 pDescr++;
173 break;
174 }
175
176 case CSN_UINT_OFFSET:
177 {
178 guint8 no_of_bits = (guint8) pDescr->i;
179
180 if (remaining_bits_len >= no_of_bits)
181 {
182 if (no_of_bits <= 8)
183 {
184 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
185 pui8 = pui8DATA(data, pDescr->offset);
186 *pui8 = ui8 + (guint8)pDescr->descr.value;
187 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
188 }
189 else if (no_of_bits <= 16)
190 {
191 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
192 pui16 = pui16DATA(data, pDescr->offset);
193 *pui16 = ui16 + (guint16)pDescr->descr.value;
194 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
195 }
196 else if (no_of_bits <= 32)
197 {
198 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
199 pui32 = pui32DATA(data, pDescr->offset);
200 *pui32 = ui32 + (guint16)pDescr->descr.value;
201 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
202 }
203 else
204 {
205 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
206 }
207 }
208 else
209 {
210 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
211 }
212
213 remaining_bits_len -= no_of_bits;
214 bit_offset += no_of_bits;
215 pDescr++;
216 break;
217 }
218
219 case CSN_UINT_LH:
220 {
221 guint8 no_of_bits = (guint8) pDescr->i;
222
223 if (remaining_bits_len >= no_of_bits)
224 {
225 if (no_of_bits <= 8)
226 {
227 guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
228 pui8 = pui8DATA(data, pDescr->offset);
229 *pui8 = ui8;
230 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
231 }
232 else
233 {/* Maybe we should support more than 8 bits ? */
234 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
235 }
236 }
237 else
238 {
239 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
240 }
241
242 remaining_bits_len -= no_of_bits;
243 bit_offset += no_of_bits;
244 pDescr++;
245 break;
246 }
247
248 case CSN_UINT_ARRAY:
249 {
250 guint8 no_of_bits = (guint8) pDescr->i;
251 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
252
253 if (pDescr->value != 0)
254 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
255 nCount = *pui16DATA(data, nCount);
256 }
257
258 if (remaining_bits_len >= (no_of_bits * nCount))
259 {
260 remaining_bits_len -= (no_of_bits*nCount);
261 if (no_of_bits <= 8)
262 {
263 pui8 = pui8DATA(data, pDescr->offset);
264 do
265 {
266 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
267 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
268 pui8++;
269 bit_offset += no_of_bits;
270 } while (--nCount > 0);
271 }
272 else if (no_of_bits <= 16)
273 {
274 return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr);
275 }
276 else if (no_of_bits <= 32)
277 {
278 return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr);
279 }
280 else
281 {
282 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
283 }
284 }
285 else
286 {
287 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
288 }
289 pDescr++;
290 break;
291 }
292
293 case CSN_VARIABLE_TARRAY_OFFSET:
294 case CSN_VARIABLE_TARRAY:
295 case CSN_TYPE_ARRAY:
296 {
297 gint16 Status;
298 csnStream_t arT = *ar;
299 gint16 nCount = pDescr->i;
300 guint16 nSize = (guint16)(gint32)pDescr->value;
301
302 pui8 = pui8DATA(data, pDescr->offset);
303 if (pDescr->type == CSN_VARIABLE_TARRAY)
304 { /* Count specified in field */
305 nCount = *pui8DATA(data, pDescr->i);
306 }
307 else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET)
308 { /* Count specified in field */
309 nCount = *pui8DATA(data, pDescr->i);
310 /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */
311 }
312
313 while (nCount > 0)
314 { /* resulting array of length 0 is possible
315 * but no bits shall be read from bitstream
316 */
317
318 LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz);
319 csnStreamInit(&arT, bit_offset, remaining_bits_len);
320 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
321 if (Status >= 0)
322 {
323 pui8 += nSize;
324 remaining_bits_len = arT.remaining_bits_len;
325 bit_offset = arT.bit_offset;
326 }
327 else
328 {
329 return Status;
330 }
331 nCount--;
332 }
333
334 pDescr++;
335 break;
336 }
337
338 case CSN_BITMAP:
339 { /* bitmap with given length. The result is left aligned! */
340 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
341
342 if (no_of_bits > 0)
343 {
344 if (no_of_bits > remaining_bits_len)
345 {
346 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
347 }
348
349 if (no_of_bits <= 32)
350 {
351 for(ib = 0; ib < 4; ib++)
352 {
353 guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
354 pui8 = pui8DATA(data, pDescr->offset+ib);
355 *pui8 = ui8;
356 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
357 }
358 }
359 else if (no_of_bits <= 64)
360 {
361 for(ib = 0; ib < 8; ib++)
362 {
363 guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
364 pui8 = pui8DATA(data, pDescr->offset+ib);
365 *pui8 = ui8;
366 LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
367 }
368 }
369 else
370 {
371 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
372 }
373
374 remaining_bits_len -= no_of_bits;
375 bit_offset += no_of_bits;
376 }
377 /* bitmap was successfully extracted or it was empty */
378
379 pDescr++;
380 break;
381 }
382
383 case CSN_TYPE:
384 {
385 gint16 Status;
386 csnStream_t arT = *ar;
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200387 if (pDescr->may_be_null && remaining_bits_len == 0)
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200388 {
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200389 LOGPC(DCSN1, LOGL_DEBUG, " : %s = NULL | ", pDescr->sz);
390 } else {
391 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
392 csnStreamInit(&arT, bit_offset, remaining_bits_len);
393 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
394 LOGPC(DCSN1, LOGL_DEBUG, ": End %s | ", pDescr->sz);
395 if (Status >= 0)
396 {
397 remaining_bits_len = arT.remaining_bits_len;
398 bit_offset = arT.bit_offset;
399 }
400 else
401 {
402 /* Has already been processed: ProcessError("csnStreamDecoder", Status, pDescr); */
403 return Status;
404 }
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200405 }
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200406 pDescr++;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200407 break;
408 }
409
410 case CSN_CHOICE:
411 {
412 gint16 count = pDescr->i;
413 guint8 i = 0;
414 CSN_ChoiceElement_t* pChoice = (CSN_ChoiceElement_t*) pDescr->descr.ptr;
415
416 /* Make sure that the list of choice items is not empty */
417 if (!count)
418 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
419 else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */
420 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
421
422 while (count > 0)
423 {
424 guint8 no_of_bits = pChoice->bits;
425 guint8 value = bitvec_read_field(vector, readIndex, no_of_bits);
426 if (value == pChoice->value)
427 {
428 CSN_DESCR descr[2];
429 gint16 Status;
430 csnStream_t arT = *ar;
431
432 descr[0] = pChoice->descr;
433 memset(&descr[1], 0x00, sizeof(CSN_DESCR));
434 descr[1].type = CSN_END;
435 pui8 = pui8DATA(data, pDescr->offset);
436 *pui8 = i;
437 LOGPC(DCSN1, LOGL_DEBUG, "Choice %s = %u | ", pDescr->sz , (unsigned)value);
438 if (!pChoice->keep_bits) {
439 bit_offset += no_of_bits;
440 remaining_bits_len -= no_of_bits;
441 }
442
443 csnStreamInit(&arT, bit_offset, remaining_bits_len);
444 Status = csnStreamDecoder(&arT, descr, vector, readIndex, data);
445
446 if (Status >= 0)
447 {
448 remaining_bits_len = arT.remaining_bits_len;
449 bit_offset = arT.bit_offset;
450 }
451 else
452 {
453 return Status;
454 }
455 break;
456 }
457
458 *readIndex -= no_of_bits;
459 count--;
460 pChoice++;
461 i++;
462 }
463
464 /* Neither of the choice items matched => unknown value */
465 if (!count)
466 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
467
468 pDescr++;
469 break;
470 }
471
472 case CSN_SERIALIZE:
473 {
474 StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn;
475 csnStream_t arT = *ar;
476 guint8 length_len = pDescr->i;
477 gint16 Status = -1;
478
479 guint8 length = bitvec_read_field(vector, readIndex, length_len);
480
481 LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , length);
482 bit_offset += length_len;
483 remaining_bits_len -= length_len;
484
485 csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len);
486 arT.direction = 1;
487 LOGPC(DCSN1, LOGL_DEBUG, "offset = %u | ", pDescr->offset);
488 Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
489
490 if (Status >= 0)
491 {
492 if (length > 0) {
493 remaining_bits_len -= length;
494 bit_offset += length;
495 } else {
496 remaining_bits_len = arT.remaining_bits_len;
497 bit_offset = arT.bit_offset;
498 }
499
500 /* Skip bits not handled by serialize(), if any */
501 if (Status > 0) {
502 LOGPC(DCSN1, LOGL_DEBUG, "skipped = %d | ", Status);
503 *readIndex += Status;
504 }
505
506 pDescr++;
507 }
508 else
509 {
510 /* Has already been processed: */
511 return Status;
512 }
513
514 break;
515 }
516
517 case CSN_UNION_LH:
518 case CSN_UNION:
519 {
520 gint16 Bits;
521 guint8 index;
522 gint16 count = pDescr->i;
523 const CSN_DESCR* pDescrNext = pDescr;
524
525 pDescrNext += count + 1; /* now this is next after the union */
526 if ((count <= 0) || (count > 16))
527 {
528 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr);
529 }
530
531 /* Now get the bits to extract the index */
532 Bits = ixBitsTab[count];
533 index = 0;
534
535 while (Bits > 0)
536 {
537 index <<= 1;
538
539 if (CSN_UNION_LH == pDescr->type)
540 {
541 index |= get_masked_bits8(vector, readIndex, bit_offset, 1);
542 }
543 else
544 {
545 index |= bitvec_read_field(vector, readIndex, 1);
546 }
547 remaining_bits_len--;
548 bit_offset++;
549 Bits--;
550 }
551
552 /* Assign UnionType */
553 pui8 = pui8DATA(data, pDescr->offset);
554 *pui8 = index;
555
556
557 /* script index to continue on, limited in case we do not have a power of 2 */
558 pDescr += (MIN(index + 1, count));
559 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
560
561 switch (pDescr->type)
562 { /* get the right element of the union based on computed index */
563
564 case CSN_BIT:
565 {
566 pui8 = pui8DATA(data, pDescr->offset);
567 *pui8 = 0x00;
568 if (bitvec_read_field(vector, readIndex, 1) > 0)
569 {
570 *pui8 = 0x01;
571 }
572 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
573 remaining_bits_len -= 1;
574 bit_offset++;
575 pDescr++;
576 break;
577 }
578
579 case CSN_NULL:
580 { /* Empty member! */
581 bit_offset += pDescr->i;
582 pDescr++;
583 break;
584 }
585
586 case CSN_UINT:
587 {
588 guint8 no_of_bits = (guint8) pDescr->i;
589 if (remaining_bits_len >= no_of_bits)
590 {
591 if (no_of_bits <= 8)
592 {
593 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
594 pui8 = pui8DATA(data, pDescr->offset);
595 *pui8 = ui8;
596 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
597 }
598 else if (no_of_bits <= 16)
599 {
600 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
601 pui16 = pui16DATA(data, pDescr->offset);
602 *pui16 = ui16;
603 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
604 }
605 else if (no_of_bits <= 32)
606 {
607 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
608 pui32 = pui32DATA(data, pDescr->offset);
609 *pui32 = ui32;
610 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
611 }
612 else
613 {
614 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
615 }
616 }
617 else
618 {
619 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
620 }
621
622 remaining_bits_len -= no_of_bits;
623 bit_offset += no_of_bits;
624 pDescr++;
625 break;
626 }
627
628 case CSN_UINT_OFFSET:
629 {
630 guint8 no_of_bits = (guint8) pDescr->i;
631
632 if (remaining_bits_len >= no_of_bits)
633 {
634 if (no_of_bits <= 8)
635 {
636 guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
637 pui8 = pui8DATA(data, pDescr->offset);
638 *pui8 = ui8 + (guint8)pDescr->descr.value;
639 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
640 }
641 else if (no_of_bits <= 16)
642 {
643 guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
644 pui16 = pui16DATA(data, pDescr->offset);
645 *pui16 = ui16 + (guint16)pDescr->descr.value;
646 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
647 }
648 else if (no_of_bits <= 32)
649 {
650 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
651 pui32 = pui32DATA(data, pDescr->offset);
652 *pui32 = ui32 + (guint16)pDescr->descr.value;
653 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32);
654 }
655 else
656 {
657 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
658 }
659 }
660 else
661 {
662 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
663 }
664
665 remaining_bits_len -= no_of_bits;
666 bit_offset += no_of_bits;
667 pDescr++;
668 break;
669 }
670
671 case CSN_UINT_LH:
672 {
673 guint8 no_of_bits = (guint8) pDescr->i;
674
675 if (remaining_bits_len >= no_of_bits)
676 {
677 if (no_of_bits <= 8)
678 {
679 guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
680 pui8 = pui8DATA(data, pDescr->offset);
681 *pui8 = ui8;
682 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
683 }
684 else
685 { /* Maybe we should support more than 8 bits ? */
686 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
687 }
688 }
689 else
690 {
691 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
692 }
693
694 remaining_bits_len -= no_of_bits;
695 bit_offset += no_of_bits;
696 pDescr++;
697 break;
698 }
699
700 case CSN_UINT_ARRAY:
701 {
702 guint8 no_of_bits = (guint8) pDescr->i;
703 guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */
704
705 if (pDescr->value != 0)
706 { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */
707 nCount = *pui16DATA(data, nCount);
708 }
709
710 if (remaining_bits_len >= (no_of_bits * nCount))
711 {
712 remaining_bits_len -= (no_of_bits * nCount);
713 if (no_of_bits <= 8)
714 {
715 pui8 = pui8DATA(data, pDescr->offset);
716
717 while (nCount > 0)
718 {
719 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
720 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
721 pui8++;
722 bit_offset += no_of_bits;
723 nCount--;
724 }
725 }
726 else if (no_of_bits <= 16)
727 {
728 pui16 = pui16DATA(data, pDescr->offset);
729
730 while (nCount > 0)
731 {
732 *pui16 = bitvec_read_field(vector, readIndex, no_of_bits);
733 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16);
734 pui16++;
735 bit_offset += no_of_bits;
736 nCount--;
737 }
738 }
739 else if (no_of_bits <= 32)
740 { /* not supported */
741 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
742 }
743 else
744 {
745 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr);
746 }
747 }
748 else
749 {
750 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
751 }
752
753 pDescr++;
754 break;
755 }
756
757 case CSN_VARIABLE_TARRAY_OFFSET:
758 case CSN_VARIABLE_TARRAY:
759 case CSN_TYPE_ARRAY:
760 {
761 gint16 Status;
762 csnStream_t arT = *ar;
763 guint16 nCount = (guint16) pDescr->i;
764 guint16 nSize = (guint16)(guint32)pDescr->value;
765
766 pui8 = pui8DATA(data, pDescr->offset);
767
768 if (CSN_VARIABLE_TARRAY == pDescr->type)
769 { /* Count specified in field */
770 nCount = *pui8DATA(data, pDescr->i);
771 }
772 else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type)
773 { /* Count specified in field */
774 nCount = *pui8DATA(data, pDescr->i);
775 nCount--; /* Offset 1 */
776 }
777
778 while (nCount--) /* Changed to handle length = 0. */
779 {
780 LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz);
781 csnStreamInit(&arT, bit_offset, remaining_bits_len);
782 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
783 if (Status >= 0)
784 {
785 pui8 += nSize;
786 remaining_bits_len = arT.remaining_bits_len;
787 bit_offset = arT.bit_offset;
788 }
789 else
790 {
791 return Status;
792 }
793 }
794
795 pDescr++;
796 break;
797 }
798
799 case CSN_BITMAP:
800 { /* bitmap with given length. The result is left aligned! */
801 guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */
802
803 if (no_of_bits > 0)
804 {
805 if (no_of_bits > remaining_bits_len)
806 {
807 return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
808 }
809
810 if (no_of_bits <= 32)
811 {
812 guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
813 pui32 = pui32DATA(data, pDescr->offset);
814 *pui32 = ui32;
815 }
816 else if (no_of_bits <= 64)
817 {
818 guint64 ui64 = bitvec_read_field(vector, readIndex, no_of_bits);
819 pui64 = pui64DATA(data, pDescr->offset);
820 *pui64 = ui64;
821 LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64);
822 }
823 else
824 {
825 return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr);
826 }
827
828 remaining_bits_len -= no_of_bits;
829 bit_offset += no_of_bits;
830 }
831 /* bitmap was successfully extracted or it was empty */
832
833 pDescr++;
834 break;
835 }
836
837 case CSN_TYPE:
838 {
839 gint16 Status;
840 csnStream_t arT = *ar;
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200841 if (pDescr->may_be_null && remaining_bits_len == 0)
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200842 {
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200843 LOGPC(DCSN1, LOGL_DEBUG, " : %s = NULL | ", pDescr->sz);
844 } else {
845 LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz);
846 csnStreamInit(&arT, bit_offset, remaining_bits_len);
847 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
848 LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz);
849 if (Status >= 0)
850 {
851 remaining_bits_len = arT.remaining_bits_len;
852 bit_offset = arT.bit_offset;
853 }
854 else
855 { /* return error code Has already been processed: */
856 return Status;
857 }
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200858 }
Pau Espin Pedrolebdc0d82021-10-19 16:48:16 +0200859 pDescr++;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200860 break;
861 }
862
863 default:
864 { /* descriptions of union elements other than above are illegal */
865 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr);
866 }
867 }
868
869 pDescr = pDescrNext;
870 break;
871 }
872
873 case CSN_EXIST:
874 case CSN_EXIST_LH:
875 {
876 guint8 fExist;
877
878 pui8 = pui8DATA(data, pDescr->offset);
879
880 if (CSN_EXIST_LH == pDescr->type)
881 {
882 fExist = get_masked_bits8(vector, readIndex, bit_offset, 1);
883 }
884 else
885 {
886 fExist = bitvec_read_field(vector, readIndex, 1);
887 }
888
889 *pui8 = fExist;
890 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
891 pDescr++;
892 bit_offset++;
893 remaining_bits_len -= 1;
894
895 if (!fExist)
896 {
897 ar->remaining_bits_len = remaining_bits_len;
898 ar->bit_offset = bit_offset;
899 return remaining_bits_len;
900 }
901
902 break;
903 }
904
905 case CSN_NEXT_EXIST:
906 {
907 guint8 fExist;
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200908 guint8 isnull;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200909
910 pui8 = pui8DATA(data, pDescr->offset);
911
912 /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */
913 if ((pDescr->may_be_null) && (remaining_bits_len == 0))
914 { /* no more bits to decode is fine here - end of message detected and allowed */
915
916 /* Skip i entries + this entry */
917 pDescr += pDescr->i + 1;
918
919 /* Set the data member to "not exist" */
920 *pui8 = 0;
921 break;
922 }
923
924 /* the "regular" M_NEXT_EXIST description element */
925
926 fExist = 0x00;
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200927 isnull = 1;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200928 if (bitvec_read_field(vector, readIndex, 1))
929 {
930 fExist = 0x01;
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200931 if (remaining_bits_len == 1) {
932 /* If { 1 < end > } and all next items may be null, store it as { 0 } */
933 const CSN_DESCR* pDescrNext = pDescr + 1;
934 guint8 i;
935 for (i = 0; i < pDescr->i; i++, pDescrNext++)
936 {
937 if (!pDescrNext->may_be_null)
938 isnull = 0;
939 }
940 } else {
941 isnull = 0;
942 }
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200943 }
944
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200945 *pui8 = !isnull;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200946 remaining_bits_len -= 1;
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200947 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u%s | ", pDescr->sz, (unsigned)fExist, fExist && isnull ? " (NULL)" : "");
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200948 ++bit_offset;
949
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200950 if (isnull)
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200951 { /* Skip 'i' entries */
952 pDescr += pDescr->i;
953 }
954
955 pDescr++;
956 break;
957 }
958
959 case CSN_NEXT_EXIST_LH:
960 {
961 guint8 fExist;
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200962 guint8 isnull;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200963 pui8 = pui8DATA(data, pDescr->offset);
964
965 /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */
966 if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0))
967 { /* no more bits to decode is fine here - end of message detected and allowed */
968
969 /* skip 'i' entries + this entry */
970 pDescr += pDescr->i + 1;
971
972 /* set the data member to "not exist" */
973 *pui8 = 0;
974 break;
975 }
976
977 /* the "regular" M_NEXT_EXIST_LH description element */
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +0200978 isnull = 1;
979 if ((fExist = get_masked_bits8(vector, readIndex, bit_offset, 1)))
980 {
981 if (remaining_bits_len == 1) {
982 /* If { 1 < end > } and all next items may be null, store it as { 0 } */
983 const CSN_DESCR* pDescrNext = pDescr + 1;
984 guint8 i;
985 for (i = 0; i < pDescr->i; i++, pDescrNext++)
986 {
987 if (!pDescrNext->may_be_null)
988 isnull = 0;
989 }
990 } else {
991 isnull = 0;
992 }
993 }
994 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u%s | ", pDescr->sz , (unsigned)fExist, fExist && isnull ? " (NULL)" : "");
Pau Espin Pedrol9ecdc112021-10-20 17:21:34 +0200995 *pui8++ = !isnull;
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +0200996 remaining_bits_len -= 1;
997
998 bit_offset++;
999
Pau Espin Pedrol1859ec32021-10-19 17:39:03 +02001000 if (isnull)
Pau Espin Pedrolc90e6f82021-10-19 14:45:17 +02001001 { /* Skip 'i' entries */
1002 pDescr += pDescr->i;
1003 }
1004 pDescr++;
1005
1006 break;
1007 }
1008
1009 case CSN_VARIABLE_BITMAP_1:
1010 { /* Bitmap from here and to the end of message */
1011
1012 *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
1013
1014 /*no break -
1015 * with a length set we have a regular variable length bitmap so we continue */
1016 }
1017 /* FALL THROUGH */
1018 case CSN_VARIABLE_BITMAP:
1019 { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1020 * <N: bit (5)> <bitmap: bit(N + offset)>
1021 * Bit array with length (in bits) specified in parameter (pDescr->descr)
1022 * The result is right aligned!
1023 */
1024 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);
1025
1026 no_of_bits += pDescr->i; /* adjusted by offset */
1027
1028 if (no_of_bits > 0)
1029 {
1030 remaining_bits_len -= no_of_bits;
1031
1032 if (remaining_bits_len < 0)
1033 {
1034 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1035 }
1036
1037 { /* extract bits */
1038 guint8* pui8 = pui8DATA(data, pDescr->offset);
1039 gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */
1040
1041 if (nB1 > 0)
1042 { /* take care of the first byte - it will be right aligned */
1043 *pui8 = bitvec_read_field(vector, readIndex, nB1);
1044 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
1045 pui8++;
1046 no_of_bits -= nB1;
1047 bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */
1048 }
1049
1050 /* remaining no_of_bits is a multiple of 8 or 0 */
1051 while (no_of_bits > 0)
1052 {
1053 *pui8 = bitvec_read_field(vector, readIndex, 8);
1054 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
1055 pui8++;
1056 no_of_bits -= 8;
1057 }
1058 }
1059 }
1060 pDescr++;
1061 break;
1062 }
1063
1064 case CSN_LEFT_ALIGNED_VAR_BMP_1:
1065 { /* Bitmap from here and to the end of message */
1066
1067 *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */
1068
1069 /* no break -
1070 * with a length set we have a regular left aligned variable length bitmap so we continue
1071 */
1072 }
1073 /* FALL THROUGH */
1074 case CSN_LEFT_ALIGNED_VAR_BMP:
1075 { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1076 * <N: bit (5)> <bitmap: bit(N + offset)>
1077 * bit array with length (in bits) specified in parameter (pDescr->descr)
1078 */
1079 gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */
1080
1081 no_of_bits += pDescr->i;/* size adjusted by offset */
1082
1083 if (no_of_bits > 0)
1084 {
1085 remaining_bits_len -= no_of_bits;
1086
1087 if (remaining_bits_len < 0)
1088 {
1089 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1090 }
1091
1092 { /* extract bits */
1093 guint8* pui8 = pui8DATA(data, pDescr->offset);
1094
1095 while (no_of_bits >= 8)
1096 {
1097 *pui8 = bitvec_read_field(vector, readIndex, 8);
1098 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
1099 pui8++;
1100 no_of_bits -= 8;
1101 }
1102 if (no_of_bits > 0)
1103 {
1104 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
1105 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
1106 pui8++;
1107 bit_offset += no_of_bits;
1108 no_of_bits = 0;
1109 }
1110 }
1111 }
1112
1113 /* bitmap was successfully extracted or it was empty */
1114 pDescr++;
1115 break;
1116 }
1117
1118 case CSN_PADDING_BITS:
1119 { /* Padding from here and to the end of message */
1120 LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz);
1121 if (remaining_bits_len > 0)
1122 {
1123 while (remaining_bits_len > 0)
1124 {
1125 guint bits_to_handle = remaining_bits_len%8;
1126 if (bits_to_handle > 0)
1127 {
1128 LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, bits_to_handle));
1129 remaining_bits_len -= bits_to_handle;
1130 bit_offset += bits_to_handle;
1131 }
1132 else if (bits_to_handle == 0)
1133 {
1134 LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, 8));
1135 remaining_bits_len -= 8;
1136 bit_offset += 8;
1137 }
1138 }
1139 }
1140 if (remaining_bits_len < 0)
1141 {
1142 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1143 }
1144
1145 /* Padding was successfully extracted or it was empty */
1146 pDescr++;
1147 break;
1148 }
1149
1150 case CSN_VARIABLE_ARRAY:
1151 { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR;
1152 * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1153 * Array with length specified in parameter:
1154 * <count: bit (x)>
1155 * <list: octet(count + offset)>
1156 */
1157 gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value);
1158
1159 count += pDescr->i; /* Adjusted by offset */
1160
1161 if (count > 0)
1162 {
1163 remaining_bits_len -= count * 8;
1164
1165 if (remaining_bits_len < 0)
1166 {
1167 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1168 }
1169
1170 pui8 = pui8DATA(data, pDescr->offset);
1171
1172 while (count > 0)
1173 {
1174 *pui8 = bitvec_read_field(vector, readIndex, 8);
1175 LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%x | ", pDescr->sz , (unsigned)*pui8);
1176 pui8++;
1177 bit_offset += 8;
1178 count--;
1179 }
1180 }
1181
1182 pDescr++;
1183 break;
1184 }
1185
1186 case CSN_RECURSIVE_ARRAY:
1187 { /* Recursive way to specify an array: <list> ::= {1 <number: bit (4)> <list> | 0}
1188 * or more generally: <list> ::= { <tag> <element> <list> | <EndTag> }
1189 * where <element> ::= bit(value)
1190 * <tag> ::= 0 | 1
1191 * <EndTag> ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa
1192 * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER}
1193 * REMARK: recursive way to specify an array but an iterative implementation!
1194 */
1195 gint16 no_of_bits = pDescr->i;
1196 guint8 ElementCount = 0;
1197
1198 pui8 = pui8DATA(data, pDescr->offset);
1199
1200 while (existNextElement(vector, readIndex, Tag))
1201 { /* tag control shows existence of next list elements */
1202 LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz);
1203 bit_offset++;
1204 remaining_bits_len--;
1205
1206 /* extract and store no_of_bits long element from bitstream */
1207 *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
1208 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
1209 pui8++;
1210 remaining_bits_len -= no_of_bits;
1211 ElementCount++;
1212
1213 if (remaining_bits_len < 0)
1214 {
1215 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1216 }
1217
1218 bit_offset += no_of_bits;
1219 }
1220
1221 LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1));
1222 /* existNextElement() returned FALSE, 1 bit consumed */
1223 bit_offset++;
1224 remaining_bits_len--;
1225
1226 /* Store the counted number of elements of the array */
1227 *pui8DATA(data, (gint16)pDescr->descr.value) = ElementCount;
1228
1229 pDescr++;
1230 break;
1231 }
1232
1233 case CSN_RECURSIVE_TARRAY:
1234 { /* Recursive way to specify an array of type: <lists> ::= { 1 <type> } ** 0 ;
1235 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
1236 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
1237 */
1238 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
1239 guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
1240 guint8 ElementCount = 0;
1241 pui8 = pui8DATA(data, pDescr->offset);
1242
1243 while (existNextElement(vector, readIndex, Tag))
1244 { /* tag control shows existence of next list elements */
1245 LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz);
1246 /* existNextElement() returned TRUE, 1 bit consumed */
1247 bit_offset++;
1248 remaining_bits_len--;
1249 ElementCount++;
1250
1251 if (ElementCount > nSizeArray)
1252 {
1253 LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
1254 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
1255 }
1256
1257 { /* unpack the following data structure */
1258 csnStream_t arT = *ar;
1259 gint16 Status;
1260 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1261 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
1262
1263 if (Status >= 0)
1264 { /* successful completion */
1265 pui8 += nSizeElement; /* -> to next data element */
1266 remaining_bits_len = arT.remaining_bits_len;
1267 bit_offset = arT.bit_offset;
1268 }
1269 else
1270 { /* something went awry */
1271 return Status;
1272 }
1273 }
1274
1275 if (remaining_bits_len < 0)
1276 {
1277 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1278 }
1279 }
1280
1281 LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1));
1282
1283 /* existNextElement() returned FALSE, 1 bit consumed */
1284 remaining_bits_len--;
1285 bit_offset++;
1286
1287 /* Store the counted number of elements of the array */
1288 *pui8DATA(data, (gint16)(gint32)pDescr->i) = ElementCount;
1289
1290 pDescr++;
1291 break;
1292 }
1293
1294 case CSN_RECURSIVE_TARRAY_2:
1295 { /* Recursive way to specify an array of type: <list> ::= <type> { 0 <type> } ** 1 ; */
1296
1297 Tag = REVERSED_TAG;
1298
1299 /* NO break -
1300 * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue
1301 */
1302 }
1303 /* FALL THROUGH */
1304 case CSN_RECURSIVE_TARRAY_1:
1305 { /* Recursive way to specify an array of type: <lists> ::= <type> { 1 <type> } ** 0 ;
1306 * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField)
1307 * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)}
1308 */
1309 gint16 nSizeElement = (gint16)(gint32)pDescr->value;
1310 guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn);
1311 guint8 ElementCount = 0;
1312 csnStream_t arT = *ar;
1313 gboolean EndOfList = FALSE;
1314 gint16 Status;
1315 pui8 = pui8DATA(data, pDescr->offset);
1316
1317 do
1318 { /* get data element */
1319 ElementCount++;
1320
1321 if (ElementCount > nSizeArray)
1322 {
1323 LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray);
1324 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr);
1325 }
1326
1327 LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz);
1328
1329 csnStreamInit(&arT, bit_offset, remaining_bits_len);
1330 Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
1331
1332 if (Status >= 0)
1333 { /* successful completion */
1334 pui8 += nSizeElement; /* -> to next */
1335 remaining_bits_len = arT.remaining_bits_len;
1336 bit_offset = arT.bit_offset;
1337 }
1338 else
1339 { /* something went awry */
1340 return Status;
1341 }
1342
1343 if (remaining_bits_len < 0)
1344 {
1345 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1346 }
1347
1348 /* control of next element's tag */
1349 LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz);
1350 EndOfList = !(existNextElement(vector, readIndex, Tag));
1351
1352 bit_offset++;
1353 remaining_bits_len--; /* 1 bit consumed (tag) */
1354 } while (!EndOfList);
1355
1356
1357 /* Store the count of the array */
1358 *pui8DATA(data, pDescr->i) = ElementCount;
1359 Tag = STANDARD_TAG; /* in case it was set to "reversed" */
1360 pDescr++;
1361 break;
1362 }
1363
1364 case CSN_FIXED:
1365 { /* Verify the fixed bits */
1366 guint8 no_of_bits = (guint8) pDescr->i;
1367 guint32 ui32;
1368
1369 if (no_of_bits <= 32)
1370 {
1371 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
1372 }
1373 else
1374 {
1375 return ProcessError(readIndex,"no_of_bits > 32", -1, pDescr);
1376 }
1377 if (ui32 != (unsigned)(gint32)pDescr->offset)
1378 {
1379 return ProcessError(readIndex,"csnStreamDecoder FIXED value does not match", -1, pDescr);
1380 }
1381
1382 LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)ui32);
1383 remaining_bits_len -= no_of_bits;
1384 bit_offset += no_of_bits;
1385 pDescr++;
1386 break;
1387 }
1388
1389 case CSN_CALLBACK:
1390 {
1391 guint16 no_of_bits;
1392 DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn;
1393 LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz);
1394 no_of_bits = callback(vector, readIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset));
1395 remaining_bits_len -= no_of_bits;
1396 bit_offset += no_of_bits;
1397 pDescr++;
1398 break;
1399 }
1400
1401 case CSN_TRAP_ERROR:
1402 {
1403 return ProcessError(readIndex,"csnStreamDecoder", pDescr->i, pDescr);
1404 }
1405
1406 case CSN_END:
1407 {
1408 ar->remaining_bits_len = remaining_bits_len;
1409 ar->bit_offset = bit_offset;
1410 return remaining_bits_len;
1411 }
1412
1413 default:
1414 {
1415 assert(0);
1416 }
1417
1418
1419 }
1420
1421 } while (remaining_bits_len >= 0);
1422
1423 return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr);
1424}