From c90e6f8de11ef40a9055ce316efd563cebf8caa6 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 19 Oct 2021 14:45:17 +0200 Subject: [PATCH] Split csn1.c into common, enc and dec files The CSN1 encoder/decoder code is already lengthy and complex enough, there's no need to keep it in the same file, specially because when debugging, only is interested in one of the 2 functions, and they both look really similar (long spaghetti switches). Change-Id: I7d1b1f7e6d7f89b052b3fd73a960419bb2673020 --- debian/copyright | 4 +- src/Makefile.am | 2 + src/csn1.c | 2630 +--------------------------------------------- src/csn1.h | 14 + src/csn1_dec.c | 1390 ++++++++++++++++++++++++ src/csn1_enc.c | 1305 +++++++++++++++++++++++ 6 files changed, 2718 insertions(+), 2627 deletions(-) create mode 100644 src/csn1_dec.c create mode 100644 src/csn1_enc.c diff --git a/debian/copyright b/debian/copyright index 99ea408a..4e9347e7 100644 --- a/debian/copyright +++ b/debian/copyright @@ -81,7 +81,9 @@ Copyright: 2012 Andreas Eversberg License: GPL-2.0+ Files: src/csn1.h - src/csn1.cpp + src/csn1.c + src/csn1_dec.c + src/csn1_enc.c src/gsm_rlcmac.cpp src/gsm_rlcmac.h Copyright: 2011 Vincent Helfre diff --git a/src/Makefile.am b/src/Makefile.am index 08b3309b..25fdab2a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,8 @@ noinst_LTLIBRARIES = libgprs.la libgprs_la_SOURCES = \ gprs_debug.cpp \ csn1.c \ + csn1_dec.c \ + csn1_enc.c \ gsm_rlcmac.c \ gprs_bssgp_pcu.c \ gprs_bssgp_rim.c \ diff --git a/src/csn1.c b/src/csn1.c index 2be03923..e165e920 100644 --- a/src/csn1.c +++ b/src/csn1.c @@ -1,4 +1,4 @@ -/* csn1.cpp +/* csn1_enc.c * Routines for CSN1 dissection in wireshark. * * Copyright (C) 2011 Ivan Klyuchnikov @@ -38,20 +38,10 @@ #include #include -#define pvDATA(_pv, _offset) ((void*) ((unsigned char*)_pv + _offset)) -#define pui8DATA(_pv, _offset) ((guint8*) pvDATA(_pv, _offset)) -#define pui16DATA(_pv, _offset) ((guint16*) pvDATA(_pv, _offset)) -#define pui32DATA(_pv, _offset) ((guint32*) pvDATA(_pv, _offset)) -#define pui64DATA(_pv, _offset) ((guint64*) pvDATA(_pv, _offset)) -/* used to tag existence of next element in variable length lists */ -#define STANDARD_TAG 1 -#define REVERSED_TAG 0 - -static const unsigned char ixBitsTab[] = {0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5}; - +const unsigned char ixBitsTab[] = {0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5}; /* Returns no_of_bits (up to 8) masked with 0x2B */ -static guint8 +guint8 get_masked_bits8(struct bitvec *vector, unsigned *readIndex, gint bit_offset, const gint no_of_bits) { static const guint8 maskBits[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; @@ -105,7 +95,7 @@ static const struct value_string csn1_error_names[] = { }; -static gint16 ProcessError_impl(const char *file, int line, unsigned *readIndex, +gint16 ProcessError_impl(const char *file, int line, unsigned *readIndex, const char* sz, gint16 err, const CSN_DESCR* pDescr) { /* Don't add trailing newline, top caller is responsible for appending it */ @@ -115,2615 +105,3 @@ static gint16 ProcessError_impl(const char *file, int line, unsigned *readIndex, pDescr ? pDescr->sz : "-", *readIndex); return err; } - -#define ProcessError(readIndex, sz, err, pDescr) \ - ProcessError_impl(__FILE__, __LINE__, readIndex, sz, err, pDescr) - - -/** - * ================================================================================================ - * Return TRUE if tag in bit stream indicates existence of next list element, - * otherwise return FALSE. - * Will work for tag values equal to both 0 and 1. - * ================================================================================================ - */ - -static gboolean -existNextElement(struct bitvec *vector, unsigned *readIndex, guint8 Tag) -{ - int res = bitvec_get_bit_pos(vector, (*readIndex)++); - if (Tag == STANDARD_TAG) - { - return (res > 0); - } - return (res == 0); -} - - -gint16 -csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *readIndex, void* data) -{ - gint remaining_bits_len = ar->remaining_bits_len; - gint bit_offset = ar->bit_offset; - guint8* pui8 = NULL; - guint16* pui16; - guint32* pui32; - guint64* pui64; - guint8 Tag = STANDARD_TAG; - unsigned ib; - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - do - { - switch (pDescr->type) - { - case CSN_BIT: - { - if (remaining_bits_len > 0) - { - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = bitvec_read_field(vector, readIndex, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - /* end add the bit value to protocol tree */ - } - else if (pDescr->may_be_null) - { - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = 0; - LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pDescr++; - remaining_bits_len--; - bit_offset++; - break; - } - - case CSN_NULL: - { /* Empty member! */ - bit_offset += pDescr->i; - pDescr++; - break; - } - - case CSN_UINT: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); - pui16 = pui16DATA(data, pDescr->offset); - *pui16 = ui16; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = ui32; - LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%08x | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - else if (pDescr->may_be_null) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = 0; - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - *pui16 = 0; - } - else if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = 0; - } - LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pDescr++; - break; - } - - case CSN_UINT_OFFSET: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8 + (guint8)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); - pui16 = pui16DATA(data, pDescr->offset); - *pui16 = ui16 + (guint16)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = ui32 + (guint16)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_LH: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else - {/* Maybe we should support more than 8 bits ? */ - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_ARRAY: - { - guint8 no_of_bits = (guint8) pDescr->i; - guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ - - if (pDescr->value != 0) - { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ - nCount = *pui16DATA(data, nCount); - } - - if (remaining_bits_len >= (no_of_bits * nCount)) - { - remaining_bits_len -= (no_of_bits*nCount); - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - do - { - *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - bit_offset += no_of_bits; - } while (--nCount > 0); - } - else if (no_of_bits <= 16) - { - return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr); - } - else if (no_of_bits <= 32) - { - return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - pDescr++; - break; - } - - case CSN_VARIABLE_TARRAY_OFFSET: - case CSN_VARIABLE_TARRAY: - case CSN_TYPE_ARRAY: - { - gint16 Status; - csnStream_t arT = *ar; - gint16 nCount = pDescr->i; - guint16 nSize = (guint16)(gint32)pDescr->value; - - pui8 = pui8DATA(data, pDescr->offset); - if (pDescr->type == CSN_VARIABLE_TARRAY) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - } - else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ - } - - while (nCount > 0) - { /* resulting array of length 0 is possible - * but no bits shall be read from bitstream - */ - - LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); - if (Status >= 0) - { - pui8 += nSize; - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { - return Status; - } - nCount--; - } - - pDescr++; - break; - } - - case CSN_BITMAP: - { /* bitmap with given length. The result is left aligned! */ - guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ - - if (no_of_bits > 0) - { - if (no_of_bits > remaining_bits_len) - { - return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - if (no_of_bits <= 32) - { - for(ib = 0; ib < 4; ib++) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, 8); - pui8 = pui8DATA(data, pDescr->offset+ib); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); - } - } - else if (no_of_bits <= 64) - { - for(ib = 0; ib < 8; ib++) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, 8); - pui8 = pui8DATA(data, pDescr->offset+ib); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - /* bitmap was successfully extracted or it was empty */ - - pDescr++; - break; - } - - case CSN_TYPE: - { - gint16 Status; - csnStream_t arT = *ar; - LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset)); - LOGPC(DCSN1, LOGL_DEBUG, ": End %s | ", pDescr->sz); - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - pDescr++; - } - else - { - /* Has already been processed: ProcessError("csnStreamDecoder", Status, pDescr); */ - return Status; - } - - break; - } - - case CSN_CHOICE: - { - gint16 count = pDescr->i; - guint8 i = 0; - CSN_ChoiceElement_t* pChoice = (CSN_ChoiceElement_t*) pDescr->descr.ptr; - - /* Make sure that the list of choice items is not empty */ - if (!count) - return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); - else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */ - return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); - - while (count > 0) - { - guint8 no_of_bits = pChoice->bits; - guint8 value = bitvec_read_field(vector, readIndex, no_of_bits); - if (value == pChoice->value) - { - CSN_DESCR descr[2]; - gint16 Status; - csnStream_t arT = *ar; - - descr[0] = pChoice->descr; - memset(&descr[1], 0x00, sizeof(CSN_DESCR)); - descr[1].type = CSN_END; - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = i; - LOGPC(DCSN1, LOGL_DEBUG, "Choice %s = %u | ", pDescr->sz , (unsigned)value); - if (!pChoice->keep_bits) { - bit_offset += no_of_bits; - remaining_bits_len -= no_of_bits; - } - - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, descr, vector, readIndex, data); - - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { - return Status; - } - break; - } - - *readIndex -= no_of_bits; - count--; - pChoice++; - i++; - } - - /* Neither of the choice items matched => unknown value */ - if (!count) - return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); - - pDescr++; - break; - } - - case CSN_SERIALIZE: - { - StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn; - csnStream_t arT = *ar; - guint8 length_len = pDescr->i; - gint16 Status = -1; - - guint8 length = bitvec_read_field(vector, readIndex, length_len); - - LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , length); - bit_offset += length_len; - remaining_bits_len -= length_len; - - csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len); - arT.direction = 1; - LOGPC(DCSN1, LOGL_DEBUG, "offset = %u | ", pDescr->offset); - Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset)); - - if (Status >= 0) - { - if (length > 0) { - remaining_bits_len -= length; - bit_offset += length; - } else { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - - /* Skip bits not handled by serialize(), if any */ - if (Status > 0) { - LOGPC(DCSN1, LOGL_DEBUG, "skipped = %d | ", Status); - *readIndex += Status; - } - - pDescr++; - } - else - { - /* Has already been processed: */ - return Status; - } - - break; - } - - case CSN_UNION_LH: - case CSN_UNION: - { - gint16 Bits; - guint8 index; - gint16 count = pDescr->i; - const CSN_DESCR* pDescrNext = pDescr; - - pDescrNext += count + 1; /* now this is next after the union */ - if ((count <= 0) || (count > 16)) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); - } - - /* Now get the bits to extract the index */ - Bits = ixBitsTab[count]; - index = 0; - - while (Bits > 0) - { - index <<= 1; - - if (CSN_UNION_LH == pDescr->type) - { - index |= get_masked_bits8(vector, readIndex, bit_offset, 1); - } - else - { - index |= bitvec_read_field(vector, readIndex, 1); - } - remaining_bits_len--; - bit_offset++; - Bits--; - } - - /* Assign UnionType */ - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = index; - - - /* script index to continue on, limited in case we do not have a power of 2 */ - pDescr += (MIN(index + 1, count)); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - - switch (pDescr->type) - { /* get the right element of the union based on computed index */ - - case CSN_BIT: - { - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = 0x00; - if (bitvec_read_field(vector, readIndex, 1) > 0) - { - *pui8 = 0x01; - } - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - remaining_bits_len -= 1; - bit_offset++; - pDescr++; - break; - } - - case CSN_NULL: - { /* Empty member! */ - bit_offset += pDescr->i; - pDescr++; - break; - } - - case CSN_UINT: - { - guint8 no_of_bits = (guint8) pDescr->i; - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); - pui16 = pui16DATA(data, pDescr->offset); - *pui16 = ui16; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = ui32; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_OFFSET: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8 + (guint8)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); - pui16 = pui16DATA(data, pDescr->offset); - *pui16 = ui16 + (guint16)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = ui32 + (guint16)pDescr->descr.value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_LH: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits); - pui8 = pui8DATA(data, pDescr->offset); - *pui8 = ui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else - { /* Maybe we should support more than 8 bits ? */ - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_ARRAY: - { - guint8 no_of_bits = (guint8) pDescr->i; - guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ - - if (pDescr->value != 0) - { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ - nCount = *pui16DATA(data, nCount); - } - - if (remaining_bits_len >= (no_of_bits * nCount)) - { - remaining_bits_len -= (no_of_bits * nCount); - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - - while (nCount > 0) - { - *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - bit_offset += no_of_bits; - nCount--; - } - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - - while (nCount > 0) - { - *pui16 = bitvec_read_field(vector, readIndex, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - pui16++; - bit_offset += no_of_bits; - nCount--; - } - } - else if (no_of_bits <= 32) - { /* not supported */ - return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pDescr++; - break; - } - - case CSN_VARIABLE_TARRAY_OFFSET: - case CSN_VARIABLE_TARRAY: - case CSN_TYPE_ARRAY: - { - gint16 Status; - csnStream_t arT = *ar; - guint16 nCount = (guint16) pDescr->i; - guint16 nSize = (guint16)(guint32)pDescr->value; - - pui8 = pui8DATA(data, pDescr->offset); - - if (CSN_VARIABLE_TARRAY == pDescr->type) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - } - else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - nCount--; /* Offset 1 */ - } - - while (nCount--) /* Changed to handle length = 0. */ - { - LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); - if (Status >= 0) - { - pui8 += nSize; - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { - return Status; - } - } - - pDescr++; - break; - } - - case CSN_BITMAP: - { /* bitmap with given length. The result is left aligned! */ - guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ - - if (no_of_bits > 0) - { - if (no_of_bits > remaining_bits_len) - { - return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - if (no_of_bits <= 32) - { - guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - pui32 = pui32DATA(data, pDescr->offset); - *pui32 = ui32; - } - else if (no_of_bits <= 64) - { - guint64 ui64 = bitvec_read_field(vector, readIndex, no_of_bits); - pui64 = pui64DATA(data, pDescr->offset); - *pui64 = ui64; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64); - } - else - { - return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - /* bitmap was successfully extracted or it was empty */ - - pDescr++; - break; - } - - case CSN_TYPE: - { - gint16 Status; - csnStream_t arT = *ar; - LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset)); - LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - pDescr++; - } - else - { /* return error code Has already been processed: */ - return Status; - } - - break; - } - - default: - { /* descriptions of union elements other than above are illegal */ - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); - } - } - - pDescr = pDescrNext; - break; - } - - case CSN_EXIST: - case CSN_EXIST_LH: - { - guint8 fExist; - - pui8 = pui8DATA(data, pDescr->offset); - - if (CSN_EXIST_LH == pDescr->type) - { - fExist = get_masked_bits8(vector, readIndex, bit_offset, 1); - } - else - { - fExist = bitvec_read_field(vector, readIndex, 1); - } - - *pui8 = fExist; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pDescr++; - bit_offset++; - remaining_bits_len -= 1; - - if (!fExist) - { - ar->remaining_bits_len = remaining_bits_len; - ar->bit_offset = bit_offset; - return remaining_bits_len; - } - - break; - } - - case CSN_NEXT_EXIST: - { - guint8 fExist; - - pui8 = pui8DATA(data, pDescr->offset); - - /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */ - if ((pDescr->may_be_null) && (remaining_bits_len == 0)) - { /* no more bits to decode is fine here - end of message detected and allowed */ - - /* Skip i entries + this entry */ - pDescr += pDescr->i + 1; - - /* Set the data member to "not exist" */ - *pui8 = 0; - break; - } - - /* the "regular" M_NEXT_EXIST description element */ - - fExist = 0x00; - if (bitvec_read_field(vector, readIndex, 1)) - { - fExist = 0x01; - } - - *pui8 = fExist; - remaining_bits_len -= 1; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - ++bit_offset; - - if (fExist == 0) - { /* Skip 'i' entries */ - pDescr += pDescr->i; - } - - pDescr++; - break; - } - - case CSN_NEXT_EXIST_LH: - { - guint8 fExist; - pui8 = pui8DATA(data, pDescr->offset); - - /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */ - if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0)) - { /* no more bits to decode is fine here - end of message detected and allowed */ - - /* skip 'i' entries + this entry */ - pDescr += pDescr->i + 1; - - /* set the data member to "not exist" */ - *pui8 = 0; - break; - } - - /* the "regular" M_NEXT_EXIST_LH description element */ - fExist = get_masked_bits8(vector, readIndex, bit_offset, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)fExist); - *pui8++ = fExist; - remaining_bits_len -= 1; - - bit_offset++; - - if (fExist == 0) - { /* Skip 'i' entries */ - pDescr += pDescr->i; - } - pDescr++; - - break; - } - - case CSN_VARIABLE_BITMAP_1: - { /* Bitmap from here and to the end of message */ - - *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ - - /*no break - - * with a length set we have a regular variable length bitmap so we continue */ - } - /* FALL THROUGH */ - case CSN_VARIABLE_BITMAP: - { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * - * Bit array with length (in bits) specified in parameter (pDescr->descr) - * The result is right aligned! - */ - gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value); - - no_of_bits += pDescr->i; /* adjusted by offset */ - - if (no_of_bits > 0) - { - remaining_bits_len -= no_of_bits; - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - { /* extract bits */ - guint8* pui8 = pui8DATA(data, pDescr->offset); - gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ - - if (nB1 > 0) - { /* take care of the first byte - it will be right aligned */ - *pui8 = bitvec_read_field(vector, readIndex, nB1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= nB1; - bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ - } - - /* remaining no_of_bits is a multiple of 8 or 0 */ - while (no_of_bits > 0) - { - *pui8 = bitvec_read_field(vector, readIndex, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= 8; - } - } - } - pDescr++; - break; - } - - case CSN_LEFT_ALIGNED_VAR_BMP_1: - { /* Bitmap from here and to the end of message */ - - *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ - - /* no break - - * with a length set we have a regular left aligned variable length bitmap so we continue - */ - } - /* FALL THROUGH */ - case CSN_LEFT_ALIGNED_VAR_BMP: - { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * - * bit array with length (in bits) specified in parameter (pDescr->descr) - */ - gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */ - - no_of_bits += pDescr->i;/* size adjusted by offset */ - - if (no_of_bits > 0) - { - remaining_bits_len -= no_of_bits; - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - { /* extract bits */ - guint8* pui8 = pui8DATA(data, pDescr->offset); - - while (no_of_bits >= 8) - { - *pui8 = bitvec_read_field(vector, readIndex, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= 8; - } - if (no_of_bits > 0) - { - *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - bit_offset += no_of_bits; - no_of_bits = 0; - } - } - } - - /* bitmap was successfully extracted or it was empty */ - pDescr++; - break; - } - - case CSN_PADDING_BITS: - { /* Padding from here and to the end of message */ - LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz); - if (remaining_bits_len > 0) - { - while (remaining_bits_len > 0) - { - guint bits_to_handle = remaining_bits_len%8; - if (bits_to_handle > 0) - { - LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, bits_to_handle)); - remaining_bits_len -= bits_to_handle; - bit_offset += bits_to_handle; - } - else if (bits_to_handle == 0) - { - LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, 8)); - remaining_bits_len -= 8; - bit_offset += 8; - } - } - } - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - /* Padding was successfully extracted or it was empty */ - pDescr++; - break; - } - - case CSN_VARIABLE_ARRAY: - { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR; - * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * Array with length specified in parameter: - * - * - */ - gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value); - - count += pDescr->i; /* Adjusted by offset */ - - if (count > 0) - { - remaining_bits_len -= count * 8; - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pui8 = pui8DATA(data, pDescr->offset); - - while (count > 0) - { - *pui8 = bitvec_read_field(vector, readIndex, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%x | ", pDescr->sz , (unsigned)*pui8); - pui8++; - bit_offset += 8; - count--; - } - } - - pDescr++; - break; - } - - case CSN_RECURSIVE_ARRAY: - { /* Recursive way to specify an array: ::= {1 | 0} - * or more generally: ::= { | } - * where ::= bit(value) - * ::= 0 | 1 - * ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa - * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * REMARK: recursive way to specify an array but an iterative implementation! - */ - gint16 no_of_bits = pDescr->i; - guint8 ElementCount = 0; - - pui8 = pui8DATA(data, pDescr->offset); - - while (existNextElement(vector, readIndex, Tag)) - { /* tag control shows existence of next list elements */ - LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz); - bit_offset++; - remaining_bits_len--; - - /* extract and store no_of_bits long element from bitstream */ - *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - remaining_bits_len -= no_of_bits; - ElementCount++; - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - bit_offset += no_of_bits; - } - - LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1)); - /* existNextElement() returned FALSE, 1 bit consumed */ - bit_offset++; - remaining_bits_len--; - - /* Store the counted number of elements of the array */ - *pui8DATA(data, (gint16)pDescr->descr.value) = ElementCount; - - pDescr++; - break; - } - - case CSN_RECURSIVE_TARRAY: - { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; - * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) - * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)} - */ - gint16 nSizeElement = (gint16)(gint32)pDescr->value; - guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn); - guint8 ElementCount = 0; - pui8 = pui8DATA(data, pDescr->offset); - - while (existNextElement(vector, readIndex, Tag)) - { /* tag control shows existence of next list elements */ - LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz); - /* existNextElement() returned TRUE, 1 bit consumed */ - bit_offset++; - remaining_bits_len--; - ElementCount++; - - if (ElementCount > nSizeArray) - { - LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray); - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); - } - - { /* unpack the following data structure */ - csnStream_t arT = *ar; - gint16 Status; - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); - - if (Status >= 0) - { /* successful completion */ - pui8 += nSizeElement; /* -> to next data element */ - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { /* something went awry */ - return Status; - } - } - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - } - - LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1)); - - /* existNextElement() returned FALSE, 1 bit consumed */ - remaining_bits_len--; - bit_offset++; - - /* Store the counted number of elements of the array */ - *pui8DATA(data, (gint16)(gint32)pDescr->i) = ElementCount; - - pDescr++; - break; - } - - case CSN_RECURSIVE_TARRAY_2: - { /* Recursive way to specify an array of type: ::= { 0 } ** 1 ; */ - - Tag = REVERSED_TAG; - - /* NO break - - * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue - */ - } - /* FALL THROUGH */ - case CSN_RECURSIVE_TARRAY_1: - { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; - * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) - * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)} - */ - gint16 nSizeElement = (gint16)(gint32)pDescr->value; - guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn); - guint8 ElementCount = 0; - csnStream_t arT = *ar; - gboolean EndOfList = FALSE; - gint16 Status; - pui8 = pui8DATA(data, pDescr->offset); - - do - { /* get data element */ - ElementCount++; - - if (ElementCount > nSizeArray) - { - LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray); - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); - } - - LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz); - - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); - - if (Status >= 0) - { /* successful completion */ - pui8 += nSizeElement; /* -> to next */ - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { /* something went awry */ - return Status; - } - - if (remaining_bits_len < 0) - { - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - /* control of next element's tag */ - LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz); - EndOfList = !(existNextElement(vector, readIndex, Tag)); - - bit_offset++; - remaining_bits_len--; /* 1 bit consumed (tag) */ - } while (!EndOfList); - - - /* Store the count of the array */ - *pui8DATA(data, pDescr->i) = ElementCount; - Tag = STANDARD_TAG; /* in case it was set to "reversed" */ - pDescr++; - break; - } - - case CSN_FIXED: - { /* Verify the fixed bits */ - guint8 no_of_bits = (guint8) pDescr->i; - guint32 ui32; - - if (no_of_bits <= 32) - { - ui32 = bitvec_read_field(vector, readIndex, no_of_bits); - } - else - { - return ProcessError(readIndex,"no_of_bits > 32", -1, pDescr); - } - if (ui32 != (unsigned)(gint32)pDescr->offset) - { - return ProcessError(readIndex,"csnStreamDecoder FIXED value does not match", -1, pDescr); - } - - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)ui32); - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_CALLBACK: - { - guint16 no_of_bits; - DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn; - LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz); - no_of_bits = callback(vector, readIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset)); - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_TRAP_ERROR: - { - return ProcessError(readIndex,"csnStreamDecoder", pDescr->i, pDescr); - } - - case CSN_END: - { - ar->remaining_bits_len = remaining_bits_len; - ar->bit_offset = bit_offset; - return remaining_bits_len; - } - - default: - { - assert(0); - } - - - } - - } while (remaining_bits_len >= 0); - - return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); -} - - - - -gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *writeIndex, void* data) -{ - gint remaining_bits_len = ar->remaining_bits_len; - gint bit_offset = ar->bit_offset; - guint8* pui8; - guint16* pui16; - guint32* pui32; - guint64* pui64; - unsigned ib; - - guint8 Tag = STANDARD_TAG; - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - do - { - switch (pDescr->type) - { - case CSN_BIT: - { - if (remaining_bits_len > 0) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - /* end add the bit value to protocol tree */ - } - else if (pDescr->may_be_null) - { - LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pDescr++; - remaining_bits_len--; - bit_offset++; - break; - } - - case CSN_NULL: - { /* Empty member! */ - pDescr++; - break; - } - - case CSN_UINT: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui16, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - else if (pDescr->may_be_null) - { - LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pDescr++; - break; - } - - case CSN_UINT_OFFSET: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value)); - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value)); - } - else if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value)); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_LH: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - // TODO : Change get_masked_bits8() - *writeIndex -= no_of_bits; - guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits); - *writeIndex -= no_of_bits; - bitvec_write_field(vector, writeIndex, ui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - - } - else - {/* Maybe we should support more than 8 bits ? */ - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_ARRAY: - { - guint8 no_of_bits = (guint8) pDescr->i; - guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ - - if (pDescr->value != 0) - { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ - nCount = *pui16DATA(data, nCount); - } - - if (remaining_bits_len >= (no_of_bits * nCount)) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - do - { - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } while (--nCount > 0); - } - else if (no_of_bits <= 16) - { - return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); - } - else if (no_of_bits <= 32) - { - return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - pDescr++; - break; - } - - case CSN_VARIABLE_TARRAY_OFFSET: - case CSN_VARIABLE_TARRAY: - case CSN_TYPE_ARRAY: - { - gint16 Status; - csnStream_t arT = *ar; - gint16 nCount = pDescr->i; - guint16 nSize = (guint16)(gint32)pDescr->value; - - pui8 = pui8DATA(data, pDescr->offset); - if (pDescr->type == CSN_VARIABLE_TARRAY) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - } - else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ - } - - while (nCount > 0) - { /* resulting array of length 0 is possible - * but no bits shall be read from bitstream - */ - - LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); - if (Status >= 0) - { - pui8 += nSize; - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - - } - else - { - return Status; - } - nCount--; - } - - pDescr++; - break; - } - - case CSN_BITMAP: - { /* bitmap with given length. The result is left aligned! */ - guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ - - if (no_of_bits > 0) - { - if (no_of_bits > remaining_bits_len) - { - return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - if (no_of_bits <= 32) - { - for(ib = 0; ib < 4; ib++) - { - pui8 = pui8DATA(data, pDescr->offset+ib); - bitvec_write_field(vector, writeIndex, *pui8, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); - } - } - else if (no_of_bits <= 64) - { - for(ib = 0; ib < 8; ib++) - { - pui8 = pui8DATA(data, pDescr->offset+ib); - bitvec_write_field(vector, writeIndex, *pui8, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - /* bitmap was successfully extracted or it was empty */ - - pDescr++; - break; - } - - case CSN_TYPE: - { - gint16 Status; - csnStream_t arT = *ar; - LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset)); - LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); - if (Status >= 0) - { - - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - pDescr++; - } - else - { - /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */ - return Status; - } - - break; - } - - case CSN_CHOICE: - { - gint16 count = pDescr->i; - const CSN_ChoiceElement_t* pChoice = (const CSN_ChoiceElement_t*) pDescr->descr.ptr; - - /* Make sure that the list of choice items is not empty */ - if (!count) - return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); - else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */ - return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); - - /* Make sure that choice index is not out of range */ - pui8 = pui8DATA(data, pDescr->offset); - if (*pui8 >= count) - return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); - - pChoice += *pui8; - guint8 no_of_bits = pChoice->bits; - guint8 value = pChoice->value; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pChoice->descr.sz , (unsigned)value); - bitvec_write_field(vector, writeIndex, value, no_of_bits); - - CSN_DESCR descr[2]; - gint16 Status; - csnStream_t arT = *ar; - - descr[0] = pChoice->descr; - memset(&descr[1], 0x00, sizeof(CSN_DESCR)); - descr[1].type = CSN_END; - bit_offset += no_of_bits; - remaining_bits_len -= no_of_bits; - - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, descr, vector, writeIndex, data); - - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { - return Status; - } - - pDescr++; - break; - } - - case CSN_SERIALIZE: - { - StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn; - csnStream_t arT = *ar; - guint8 length_len = pDescr->i; - gint16 Status = -1; - unsigned lengthIndex; - - // store writeIndex for length value (7 bit) - lengthIndex = *writeIndex; - *writeIndex += length_len; - bit_offset += length_len; - remaining_bits_len -= length_len; - arT.direction = 0; - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = serialize(&arT, vector, writeIndex, pvDATA(data, pDescr->offset)); - - bitvec_write_field(vector, &lengthIndex, *writeIndex - lengthIndex - length_len, length_len); - LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , (unsigned)(*writeIndex - lengthIndex)); - - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - pDescr++; - } - else - { - // Has already been processed: - return Status; - } - - break; - } - - case CSN_UNION_LH: - case CSN_UNION: - { - gint16 Bits; - guint8 index; - gint16 count = pDescr->i; - const CSN_DESCR* pDescrNext = pDescr; - - pDescrNext += count + 1; /* now this is next after the union */ - if ((count <= 0) || (count > 16)) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); - } - - /* Now get the bits to extract the index */ - Bits = ixBitsTab[count]; - index = 0; - - /* Assign UnionType */ - pui8 = pui8DATA(data, pDescr->offset); - //read index from data and write to vector - bitvec_write_field(vector, writeIndex, *pui8, Bits); - - //decode index - *writeIndex -= Bits; - - while (Bits > 0) - { - index <<= 1; - - if (CSN_UNION_LH == pDescr->type) - { - index |= get_masked_bits8(vector, writeIndex, bit_offset, 1); - } - else - { - index |= bitvec_read_field(vector, writeIndex, 1); - } - - remaining_bits_len--; - bit_offset++; - Bits--; - } - - *writeIndex -= Bits; - bitvec_write_field(vector, writeIndex, index, Bits); - - - /* script index to continue on, limited in case we do not have a power of 2 */ - pDescr += (MIN(index + 1, count)); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)index); - - switch (pDescr->type) - { /* get the right element of the union based on computed index */ - - case CSN_BIT: - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - remaining_bits_len--; - bit_offset++; - pDescr++; - break; - } - - case CSN_NULL: - { /* Empty member! */ - pDescr++; - break; - } - - case CSN_UINT: - { - guint8 no_of_bits = (guint8) pDescr->i; - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui16, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); - } - else if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_OFFSET: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value)); - } - else if (no_of_bits <= 16) - { - pui16 = pui16DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value)); - } - else if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value)); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_LH: - { - guint8 no_of_bits = (guint8) pDescr->i; - - if (remaining_bits_len >= no_of_bits) - { - remaining_bits_len -= no_of_bits; - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - // TODO : Change get_masked_bits8() - *writeIndex -= no_of_bits; - guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits); - *writeIndex -= no_of_bits; - bitvec_write_field(vector, writeIndex, ui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - - } - else - {/* Maybe we should support more than 8 bits ? */ - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_UINT_ARRAY: - { - guint8 no_of_bits = (guint8) pDescr->i; - guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ - - if (pDescr->value != 0) - { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ - nCount = *pui16DATA(data, nCount); - } - - if (remaining_bits_len >= (no_of_bits * nCount)) - { - if (no_of_bits <= 8) - { - pui8 = pui8DATA(data, pDescr->offset); - do - { - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } while (--nCount > 0); - } - else if (no_of_bits <= 16) - { - return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); - } - else if (no_of_bits <= 32) - { - return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); - } - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - pDescr++; - break; - } - - case CSN_VARIABLE_TARRAY_OFFSET: - case CSN_VARIABLE_TARRAY: - case CSN_TYPE_ARRAY: - { - gint16 Status; - csnStream_t arT = *ar; - gint16 nCount = pDescr->i; - guint16 nSize = (guint16)(gint32)pDescr->value; - - pui8 = pui8DATA(data, pDescr->offset); - if (pDescr->type == CSN_VARIABLE_TARRAY) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - } - else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) - { /* Count specified in field */ - nCount = *pui8DATA(data, pDescr->i); - /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ - } - - while (nCount > 0) - { /* resulting array of length 0 is possible - * but no bits shall be read from bitstream - */ - - LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); - if (Status >= 0) - { - pui8 += nSize; - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { - return Status; - } - nCount--; - } - - pDescr++; - break; - } - - case CSN_BITMAP: - { /* bitmap with given length. The result is left aligned! */ - guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ - - if (no_of_bits > 0) - { - if (no_of_bits > remaining_bits_len) - { - return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - if (no_of_bits <= 32) - { - pui32 = pui32DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); - } - else if (no_of_bits <= 64) - { - pui64 = pui64DATA(data, pDescr->offset); - bitvec_write_field(vector, writeIndex, *pui64, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64); - } - else - { - return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr); - } - - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - } - /* bitmap was successfully extracted or it was empty */ - - pDescr++; - break; - } - - case CSN_TYPE: - { - gint16 Status; - csnStream_t arT = *ar; - LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset)); - LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); - if (Status >= 0) - { - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - pDescr++; - } - else - { - /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */ - return Status; - } - - break; - } - - default: - { /* descriptions of union elements other than above are illegal */ - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); - } - } - - pDescr = pDescrNext; - break; - } - - case CSN_EXIST: - case CSN_EXIST_LH: - { - guint8 fExist; - unsigned exist = 0; - pui8 = pui8DATA(data, pDescr->offset); - exist = *pui8; - bitvec_write_field(vector, writeIndex, *pui8, 1); - writeIndex--; - if (CSN_EXIST_LH == pDescr->type) - { - fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1); - } - else - { - fExist = bitvec_read_field(vector, writeIndex, 1); - } - writeIndex--; - bitvec_write_field(vector, writeIndex, fExist, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz, (unsigned)fExist); - remaining_bits_len--; - bit_offset++; - pDescr++; - - if (!exist) - { - ar->remaining_bits_len = remaining_bits_len; - ar->bit_offset = bit_offset; - return remaining_bits_len; - } - break; - } - - case CSN_NEXT_EXIST: - { - guint8 fExist; - - pui8 = pui8DATA(data, pDescr->offset); - - /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */ - if ((pDescr->may_be_null) && (remaining_bits_len == 0)) - { /* no more bits to decode is fine here - end of message detected and allowed */ - - /* Skip i entries + this entry */ - pDescr += pDescr->i + 1; - - break; - } - - bitvec_write_field(vector, writeIndex, *pui8, 1); - fExist = *pui8; - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - - remaining_bits_len--; - bit_offset++; - - if (fExist == 0) - { /* Skip 'i' entries */ - pDescr += pDescr->i; - } - - pDescr++; - break; - } - - case CSN_NEXT_EXIST_LH: - { - guint8 fExist; - pui8 = pui8DATA(data, pDescr->offset); - - /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */ - if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0)) - { /* no more bits to decode is fine here - end of message detected and allowed */ - - /* skip 'i' entries + this entry */ - pDescr += pDescr->i + 1; - - /* set the data member to "not exist" */ - //*pui8 = 0; - break; - } - - /* the "regular" M_NEXT_EXIST_LH description element */ - bitvec_write_field(vector, writeIndex, *pui8, 1); - writeIndex--; - fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1); - writeIndex--; - bitvec_write_field(vector, writeIndex, fExist, 1); - pui8++; - - remaining_bits_len--; - bit_offset++; - - if (fExist == 0) - { /* Skip 'i' entries */ - pDescr += pDescr->i; - } - pDescr++; - - break; - } - - case CSN_VARIABLE_BITMAP_1: - { /* Bitmap from here and to the end of message */ - - //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ - - /*no break - - * with a length set we have a regular variable length bitmap so we continue */ - } - /* FALL THROUGH */ - case CSN_VARIABLE_BITMAP: - { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * - * Bit array with length (in bits) specified in parameter (pDescr->descr) - * The result is right aligned! - */ - gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value); - - no_of_bits += pDescr->i; /* adjusted by offset */ - - if (no_of_bits > 0) - { - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - { /* extract bits */ - guint8* pui8 = pui8DATA(data, pDescr->offset); - gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ - - if (nB1 > 0) - { /* take care of the first byte - it will be right aligned */ - bitvec_write_field(vector, writeIndex, *pui8, nB1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= nB1; - bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ - remaining_bits_len -= nB1; - } - - /* remaining no_of_bits is a multiple of 8 or 0 */ - while (no_of_bits > 0) - { - bitvec_write_field(vector, writeIndex, *pui8, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= 8; - remaining_bits_len -= 8; - } - } - } - pDescr++; - break; - } - - case CSN_LEFT_ALIGNED_VAR_BMP_1: - { /* Bitmap from here and to the end of message */ - - //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ - - /* no break - - * with a length set we have a regular left aligned variable length bitmap so we continue - */ - } - /* FALL THROUGH */ - case CSN_LEFT_ALIGNED_VAR_BMP: - { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * - * bit array with length (in bits) specified in parameter (pDescr->descr) - */ - - gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */ - - no_of_bits += pDescr->i;/* size adjusted by offset */ - - if (no_of_bits > 0) - { - remaining_bits_len -= no_of_bits; - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - { /* extract bits */ - guint8* pui8 = pui8DATA(data, pDescr->offset); - gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ - - while (no_of_bits > 0) - { - bitvec_write_field(vector, writeIndex, *pui8, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= 8; - } - if (nB1 > 0) - { - bitvec_write_field(vector, writeIndex, *pui8, nB1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - no_of_bits -= nB1; - bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ - } - } - - } - - /* bitmap was successfully extracted or it was empty */ - pDescr++; - break; - } - - case CSN_PADDING_BITS: - { /* Padding from here and to the end of message */ - LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz); - guint8 filler = 0x2b; - if (remaining_bits_len > 0) - { - while (remaining_bits_len > 0) - { - guint8 bits_to_handle = remaining_bits_len%8; - if (bits_to_handle > 0) - { - /* section 11 of 44.060 - * The padding bits may be the 'null' string. Otherwise, the - * padding bits starts with bit '0', followed by 'spare padding' - * < padding bits > ::= { null | 0 < spare padding > ! < Ignore : 1 bit** = < no string > > } ; - */ - guint8 fl = filler&(0xff>>(8-bits_to_handle + 1)); - bitvec_write_field(vector, writeIndex, fl, bits_to_handle); - LOGPC(DCSN1, LOGL_DEBUG, "%u|", fl); - remaining_bits_len -= bits_to_handle; - bit_offset += bits_to_handle; - } - else if (bits_to_handle == 0) - { - bitvec_write_field(vector, writeIndex, filler, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%u|", filler); - remaining_bits_len -= 8; - bit_offset += 8; - } - } - } - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - /* Padding was successfully extracted or it was empty */ - pDescr++; - break; - } - - case CSN_VARIABLE_ARRAY: - { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR; - * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * Array with length specified in parameter: - * - * - */ - gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value); - - count += pDescr->i; /* Adjusted by offset */ - - if (count > 0) - { - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - pui8 = pui8DATA(data, pDescr->offset); - - while (count > 0) - { - bitvec_write_field(vector, writeIndex, *pui8, 8); - LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%x | ", pDescr->sz , (unsigned)*pui8); - pui8++; - bit_offset += 8; - remaining_bits_len -= 8; - count--; - } - } - - pDescr++; - break; - } - - case CSN_RECURSIVE_ARRAY: - { /* Recursive way to specify an array: ::= {1 | 0} - * or more generally: ::= { | } - * where ::= bit(value) - * ::= 0 | 1 - * ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa - * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} - * REMARK: recursive way to specify an array but an iterative implementation! - */ - gint16 no_of_bits = pDescr->i; - guint8 ElementCount = 0; - pui8 = pui8DATA(data, pDescr->offset); - ElementCount = *pui8DATA(data, (gint16)pDescr->descr.value); - while (ElementCount > 0) - { /* tag control shows existence of next list elements */ - bitvec_write_field(vector, writeIndex, Tag, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); - bit_offset++; - remaining_bits_len--; - - /* extract and store no_of_bits long element from bitstream */ - bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); - pui8++; - ElementCount--; - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - bit_offset += no_of_bits; - remaining_bits_len -= no_of_bits; - } - - bitvec_write_field(vector, writeIndex, !Tag, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag)); - bit_offset++; - remaining_bits_len--; - - pDescr++; - break; - } - - case CSN_RECURSIVE_TARRAY: - { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; - * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) - * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)} - */ - gint16 nSizeElement = (gint16)(gint32)pDescr->value; - guint8 ElementCount = 0; - pui8 = pui8DATA(data, pDescr->offset); - /* Store the counted number of elements of the array */ - ElementCount = *pui8DATA(data, (gint16)(gint32)pDescr->i); - - while (ElementCount > 0) - { /* tag control shows existence of next list elements */ - bitvec_write_field(vector, writeIndex, Tag, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); - bit_offset++; - - remaining_bits_len--; - ElementCount--; - - { /* unpack the following data structure */ - csnStream_t arT = *ar; - gint16 Status; - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); - - if (Status >= 0) - { /* successful completion */ - pui8 += nSizeElement; /* -> to next data element */ - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { /* something went awry */ - return Status; - } - } - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - } - - bitvec_write_field(vector, writeIndex, !Tag, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag)); - bit_offset++; - - pDescr++; - break; - } - - case CSN_RECURSIVE_TARRAY_2: - { /* Recursive way to specify an array of type: ::= { 0 } ** 1 ; */ - - Tag = REVERSED_TAG; - - /* NO break - - * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue - */ - } - /* FALL THROUGH */ - case CSN_RECURSIVE_TARRAY_1: - { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; - * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) - * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)} - */ - gint16 nSizeElement = (gint16)(gint32)pDescr->value; - guint8 ElementCount = 0; - guint8 ElementNum = 0; - csnStream_t arT = *ar; - gint16 Status; - - pui8 = pui8DATA(data, pDescr->offset); - /* Store the count of the array */ - ElementCount = *pui8DATA(data, pDescr->i); - ElementNum = ElementCount; - - while (ElementCount > 0) - { /* get data element */ - if (ElementCount != ElementNum) - { - bitvec_write_field(vector, writeIndex, Tag, 1); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); - bit_offset++; - remaining_bits_len--; - } - ElementCount--; - LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz); - csnStreamInit(&arT, bit_offset, remaining_bits_len); - Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); - LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz); - if (Status >= 0) - { /* successful completion */ - pui8 += nSizeElement; /* -> to next */ - remaining_bits_len = arT.remaining_bits_len; - bit_offset = arT.bit_offset; - } - else - { /* something went awry */ - return Status; - } - - if (remaining_bits_len < 0) - { - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); - } - - } - bitvec_write_field(vector, writeIndex, !Tag, 1); - bit_offset++; - remaining_bits_len--; - Tag = STANDARD_TAG; /* in case it was set to "reversed" */ - pDescr++; - break; - } - - case CSN_FIXED: - { /* Verify the fixed bits */ - guint8 no_of_bits = (guint8) pDescr->i; - bitvec_write_field(vector, writeIndex, pDescr->offset, no_of_bits); - LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)pDescr->offset); - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_CALLBACK: - { - guint16 no_of_bits; - DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn; - LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz); - no_of_bits = callback(vector, writeIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset)); - remaining_bits_len -= no_of_bits; - bit_offset += no_of_bits; - pDescr++; - break; - } - - case CSN_TRAP_ERROR: - { - return ProcessError(writeIndex,"csnStreamEncoder", pDescr->i, pDescr); - } - - case CSN_END: - { - ar->remaining_bits_len = remaining_bits_len; - ar->bit_offset = bit_offset; - return remaining_bits_len; - } - - default: - { - assert(0); - } - - } - - } while (remaining_bits_len >= 0); - - return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); -} diff --git a/src/csn1.h b/src/csn1.h index 761293d1..d470228d 100644 --- a/src/csn1.h +++ b/src/csn1.h @@ -592,4 +592,18 @@ typedef gint16 (*CsnCallBackFcn_t)(void* pv ,...); #define CSNDESCR(_FuncType) CSNDESCR_##_FuncType +#define pvDATA(_pv, _offset) ((void*) ((unsigned char*)_pv + _offset)) +#define pui8DATA(_pv, _offset) ((guint8*) pvDATA(_pv, _offset)) +#define pui16DATA(_pv, _offset) ((guint16*) pvDATA(_pv, _offset)) +#define pui32DATA(_pv, _offset) ((guint32*) pvDATA(_pv, _offset)) +#define pui64DATA(_pv, _offset) ((guint64*) pvDATA(_pv, _offset)) +/* used to tag existence of next element in variable length lists */ +#define STANDARD_TAG 1 +#define REVERSED_TAG 0 + +gint16 ProcessError_impl(const char *file, int line, unsigned *readIndex, + const char* sz, gint16 err, const CSN_DESCR* pDescr); +#define ProcessError(readIndex, sz, err, pDescr) \ + ProcessError_impl(__FILE__, __LINE__, readIndex, sz, err, pDescr) + #endif /*_PACKET_CSN1_H_*/ diff --git a/src/csn1_dec.c b/src/csn1_dec.c new file mode 100644 index 00000000..2d3f2421 --- /dev/null +++ b/src/csn1_dec.c @@ -0,0 +1,1390 @@ +/* csn1_dec.c + * Routines for CSN1 dissection in wireshark. + * + * Copyright (C) 2011 Ivan Klyuchnikov + * + * By Vincent Helfre, based on original code by Jari Sassi + * with the gracious authorization of STE + * Copyright (c) 2011 ST-Ericsson + * + * $Id: packet-csn1.c 39140 2011-09-25 22:01:50Z wmeier $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#define __STDC_FORMAT_MACROS +#include +#include "csn1.h" +#include + +#include +#include + +extern const unsigned char ixBitsTab[]; +guint8 get_masked_bits8(struct bitvec *vector, unsigned *readIndex, gint bit_offset, const gint no_of_bits); + +/** + * ================================================================================================ + * Return TRUE if tag in bit stream indicates existence of next list element, + * otherwise return FALSE. + * Will work for tag values equal to both 0 and 1. + * ================================================================================================ + */ + +static gboolean +existNextElement(struct bitvec *vector, unsigned *readIndex, guint8 Tag) +{ + int res = bitvec_get_bit_pos(vector, (*readIndex)++); + if (Tag == STANDARD_TAG) + { + return (res > 0); + } + return (res == 0); +} + + +gint16 +csnStreamDecoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *readIndex, void* data) +{ + gint remaining_bits_len = ar->remaining_bits_len; + gint bit_offset = ar->bit_offset; + guint8* pui8 = NULL; + guint16* pui16; + guint32* pui32; + guint64* pui64; + guint8 Tag = STANDARD_TAG; + unsigned ib; + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + do + { + switch (pDescr->type) + { + case CSN_BIT: + { + if (remaining_bits_len > 0) + { + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = bitvec_read_field(vector, readIndex, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + /* end add the bit value to protocol tree */ + } + else if (pDescr->may_be_null) + { + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = 0; + LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pDescr++; + remaining_bits_len--; + bit_offset++; + break; + } + + case CSN_NULL: + { /* Empty member! */ + bit_offset += pDescr->i; + pDescr++; + break; + } + + case CSN_UINT: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); + pui16 = pui16DATA(data, pDescr->offset); + *pui16 = ui16; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = ui32; + LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%08x | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + else if (pDescr->may_be_null) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = 0; + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + *pui16 = 0; + } + else if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = 0; + } + LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pDescr++; + break; + } + + case CSN_UINT_OFFSET: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8 + (guint8)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); + pui16 = pui16DATA(data, pDescr->offset); + *pui16 = ui16 + (guint16)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = ui32 + (guint16)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_LH: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else + {/* Maybe we should support more than 8 bits ? */ + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_ARRAY: + { + guint8 no_of_bits = (guint8) pDescr->i; + guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ + + if (pDescr->value != 0) + { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ + nCount = *pui16DATA(data, nCount); + } + + if (remaining_bits_len >= (no_of_bits * nCount)) + { + remaining_bits_len -= (no_of_bits*nCount); + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + do + { + *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + bit_offset += no_of_bits; + } while (--nCount > 0); + } + else if (no_of_bits <= 16) + { + return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr); + } + else if (no_of_bits <= 32) + { + return ProcessError(readIndex,"csnStreamDecoder NOTIMPLEMENTED", 999, pDescr); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + pDescr++; + break; + } + + case CSN_VARIABLE_TARRAY_OFFSET: + case CSN_VARIABLE_TARRAY: + case CSN_TYPE_ARRAY: + { + gint16 Status; + csnStream_t arT = *ar; + gint16 nCount = pDescr->i; + guint16 nSize = (guint16)(gint32)pDescr->value; + + pui8 = pui8DATA(data, pDescr->offset); + if (pDescr->type == CSN_VARIABLE_TARRAY) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + } + else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ + } + + while (nCount > 0) + { /* resulting array of length 0 is possible + * but no bits shall be read from bitstream + */ + + LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); + if (Status >= 0) + { + pui8 += nSize; + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { + return Status; + } + nCount--; + } + + pDescr++; + break; + } + + case CSN_BITMAP: + { /* bitmap with given length. The result is left aligned! */ + guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ + + if (no_of_bits > 0) + { + if (no_of_bits > remaining_bits_len) + { + return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + if (no_of_bits <= 32) + { + for(ib = 0; ib < 4; ib++) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, 8); + pui8 = pui8DATA(data, pDescr->offset+ib); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); + } + } + else if (no_of_bits <= 64) + { + for(ib = 0; ib < 8; ib++) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, 8); + pui8 = pui8DATA(data, pDescr->offset+ib); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + /* bitmap was successfully extracted or it was empty */ + + pDescr++; + break; + } + + case CSN_TYPE: + { + gint16 Status; + csnStream_t arT = *ar; + LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset)); + LOGPC(DCSN1, LOGL_DEBUG, ": End %s | ", pDescr->sz); + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + pDescr++; + } + else + { + /* Has already been processed: ProcessError("csnStreamDecoder", Status, pDescr); */ + return Status; + } + + break; + } + + case CSN_CHOICE: + { + gint16 count = pDescr->i; + guint8 i = 0; + CSN_ChoiceElement_t* pChoice = (CSN_ChoiceElement_t*) pDescr->descr.ptr; + + /* Make sure that the list of choice items is not empty */ + if (!count) + return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); + else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */ + return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); + + while (count > 0) + { + guint8 no_of_bits = pChoice->bits; + guint8 value = bitvec_read_field(vector, readIndex, no_of_bits); + if (value == pChoice->value) + { + CSN_DESCR descr[2]; + gint16 Status; + csnStream_t arT = *ar; + + descr[0] = pChoice->descr; + memset(&descr[1], 0x00, sizeof(CSN_DESCR)); + descr[1].type = CSN_END; + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = i; + LOGPC(DCSN1, LOGL_DEBUG, "Choice %s = %u | ", pDescr->sz , (unsigned)value); + if (!pChoice->keep_bits) { + bit_offset += no_of_bits; + remaining_bits_len -= no_of_bits; + } + + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, descr, vector, readIndex, data); + + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { + return Status; + } + break; + } + + *readIndex -= no_of_bits; + count--; + pChoice++; + i++; + } + + /* Neither of the choice items matched => unknown value */ + if (!count) + return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); + + pDescr++; + break; + } + + case CSN_SERIALIZE: + { + StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn; + csnStream_t arT = *ar; + guint8 length_len = pDescr->i; + gint16 Status = -1; + + guint8 length = bitvec_read_field(vector, readIndex, length_len); + + LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , length); + bit_offset += length_len; + remaining_bits_len -= length_len; + + csnStreamInit(&arT, bit_offset, length > 0 ? length : remaining_bits_len); + arT.direction = 1; + LOGPC(DCSN1, LOGL_DEBUG, "offset = %u | ", pDescr->offset); + Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset)); + + if (Status >= 0) + { + if (length > 0) { + remaining_bits_len -= length; + bit_offset += length; + } else { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + + /* Skip bits not handled by serialize(), if any */ + if (Status > 0) { + LOGPC(DCSN1, LOGL_DEBUG, "skipped = %d | ", Status); + *readIndex += Status; + } + + pDescr++; + } + else + { + /* Has already been processed: */ + return Status; + } + + break; + } + + case CSN_UNION_LH: + case CSN_UNION: + { + gint16 Bits; + guint8 index; + gint16 count = pDescr->i; + const CSN_DESCR* pDescrNext = pDescr; + + pDescrNext += count + 1; /* now this is next after the union */ + if ((count <= 0) || (count > 16)) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); + } + + /* Now get the bits to extract the index */ + Bits = ixBitsTab[count]; + index = 0; + + while (Bits > 0) + { + index <<= 1; + + if (CSN_UNION_LH == pDescr->type) + { + index |= get_masked_bits8(vector, readIndex, bit_offset, 1); + } + else + { + index |= bitvec_read_field(vector, readIndex, 1); + } + remaining_bits_len--; + bit_offset++; + Bits--; + } + + /* Assign UnionType */ + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = index; + + + /* script index to continue on, limited in case we do not have a power of 2 */ + pDescr += (MIN(index + 1, count)); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + + switch (pDescr->type) + { /* get the right element of the union based on computed index */ + + case CSN_BIT: + { + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = 0x00; + if (bitvec_read_field(vector, readIndex, 1) > 0) + { + *pui8 = 0x01; + } + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + remaining_bits_len -= 1; + bit_offset++; + pDescr++; + break; + } + + case CSN_NULL: + { /* Empty member! */ + bit_offset += pDescr->i; + pDescr++; + break; + } + + case CSN_UINT: + { + guint8 no_of_bits = (guint8) pDescr->i; + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); + pui16 = pui16DATA(data, pDescr->offset); + *pui16 = ui16; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = ui32; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_OFFSET: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8 + (guint8)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits); + pui16 = pui16DATA(data, pDescr->offset); + *pui16 = ui16 + (guint16)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = ui32 + (guint16)pDescr->descr.value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_LH: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits); + pui8 = pui8DATA(data, pDescr->offset); + *pui8 = ui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else + { /* Maybe we should support more than 8 bits ? */ + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_ARRAY: + { + guint8 no_of_bits = (guint8) pDescr->i; + guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ + + if (pDescr->value != 0) + { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ + nCount = *pui16DATA(data, nCount); + } + + if (remaining_bits_len >= (no_of_bits * nCount)) + { + remaining_bits_len -= (no_of_bits * nCount); + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + + while (nCount > 0) + { + *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + bit_offset += no_of_bits; + nCount--; + } + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + + while (nCount > 0) + { + *pui16 = bitvec_read_field(vector, readIndex, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + pui16++; + bit_offset += no_of_bits; + nCount--; + } + } + else if (no_of_bits <= 32) + { /* not supported */ + return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pDescr++; + break; + } + + case CSN_VARIABLE_TARRAY_OFFSET: + case CSN_VARIABLE_TARRAY: + case CSN_TYPE_ARRAY: + { + gint16 Status; + csnStream_t arT = *ar; + guint16 nCount = (guint16) pDescr->i; + guint16 nSize = (guint16)(guint32)pDescr->value; + + pui8 = pui8DATA(data, pDescr->offset); + + if (CSN_VARIABLE_TARRAY == pDescr->type) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + } + else if (CSN_VARIABLE_TARRAY_OFFSET == pDescr->type) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + nCount--; /* Offset 1 */ + } + + while (nCount--) /* Changed to handle length = 0. */ + { + LOGPC(DCSN1, LOGL_DEBUG, "%s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); + if (Status >= 0) + { + pui8 += nSize; + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { + return Status; + } + } + + pDescr++; + break; + } + + case CSN_BITMAP: + { /* bitmap with given length. The result is left aligned! */ + guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ + + if (no_of_bits > 0) + { + if (no_of_bits > remaining_bits_len) + { + return ProcessError(readIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + if (no_of_bits <= 32) + { + guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + pui32 = pui32DATA(data, pDescr->offset); + *pui32 = ui32; + } + else if (no_of_bits <= 64) + { + guint64 ui64 = bitvec_read_field(vector, readIndex, no_of_bits); + pui64 = pui64DATA(data, pDescr->offset); + *pui64 = ui64; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64); + } + else + { + return ProcessError(readIndex,"csnStreamDecoder NOT IMPLEMENTED", 999, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + /* bitmap was successfully extracted or it was empty */ + + pDescr++; + break; + } + + case CSN_TYPE: + { + gint16 Status; + csnStream_t arT = *ar; + LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset)); + LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + pDescr++; + } + else + { /* return error code Has already been processed: */ + return Status; + } + + break; + } + + default: + { /* descriptions of union elements other than above are illegal */ + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_IN_SCRIPT, pDescr); + } + } + + pDescr = pDescrNext; + break; + } + + case CSN_EXIST: + case CSN_EXIST_LH: + { + guint8 fExist; + + pui8 = pui8DATA(data, pDescr->offset); + + if (CSN_EXIST_LH == pDescr->type) + { + fExist = get_masked_bits8(vector, readIndex, bit_offset, 1); + } + else + { + fExist = bitvec_read_field(vector, readIndex, 1); + } + + *pui8 = fExist; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pDescr++; + bit_offset++; + remaining_bits_len -= 1; + + if (!fExist) + { + ar->remaining_bits_len = remaining_bits_len; + ar->bit_offset = bit_offset; + return remaining_bits_len; + } + + break; + } + + case CSN_NEXT_EXIST: + { + guint8 fExist; + + pui8 = pui8DATA(data, pDescr->offset); + + /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */ + if ((pDescr->may_be_null) && (remaining_bits_len == 0)) + { /* no more bits to decode is fine here - end of message detected and allowed */ + + /* Skip i entries + this entry */ + pDescr += pDescr->i + 1; + + /* Set the data member to "not exist" */ + *pui8 = 0; + break; + } + + /* the "regular" M_NEXT_EXIST description element */ + + fExist = 0x00; + if (bitvec_read_field(vector, readIndex, 1)) + { + fExist = 0x01; + } + + *pui8 = fExist; + remaining_bits_len -= 1; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + ++bit_offset; + + if (fExist == 0) + { /* Skip 'i' entries */ + pDescr += pDescr->i; + } + + pDescr++; + break; + } + + case CSN_NEXT_EXIST_LH: + { + guint8 fExist; + pui8 = pui8DATA(data, pDescr->offset); + + /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */ + if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0)) + { /* no more bits to decode is fine here - end of message detected and allowed */ + + /* skip 'i' entries + this entry */ + pDescr += pDescr->i + 1; + + /* set the data member to "not exist" */ + *pui8 = 0; + break; + } + + /* the "regular" M_NEXT_EXIST_LH description element */ + fExist = get_masked_bits8(vector, readIndex, bit_offset, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)fExist); + *pui8++ = fExist; + remaining_bits_len -= 1; + + bit_offset++; + + if (fExist == 0) + { /* Skip 'i' entries */ + pDescr += pDescr->i; + } + pDescr++; + + break; + } + + case CSN_VARIABLE_BITMAP_1: + { /* Bitmap from here and to the end of message */ + + *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ + + /*no break - + * with a length set we have a regular variable length bitmap so we continue */ + } + /* FALL THROUGH */ + case CSN_VARIABLE_BITMAP: + { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * + * Bit array with length (in bits) specified in parameter (pDescr->descr) + * The result is right aligned! + */ + gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value); + + no_of_bits += pDescr->i; /* adjusted by offset */ + + if (no_of_bits > 0) + { + remaining_bits_len -= no_of_bits; + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + { /* extract bits */ + guint8* pui8 = pui8DATA(data, pDescr->offset); + gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ + + if (nB1 > 0) + { /* take care of the first byte - it will be right aligned */ + *pui8 = bitvec_read_field(vector, readIndex, nB1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= nB1; + bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ + } + + /* remaining no_of_bits is a multiple of 8 or 0 */ + while (no_of_bits > 0) + { + *pui8 = bitvec_read_field(vector, readIndex, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= 8; + } + } + } + pDescr++; + break; + } + + case CSN_LEFT_ALIGNED_VAR_BMP_1: + { /* Bitmap from here and to the end of message */ + + *pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ + + /* no break - + * with a length set we have a regular left aligned variable length bitmap so we continue + */ + } + /* FALL THROUGH */ + case CSN_LEFT_ALIGNED_VAR_BMP: + { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * + * bit array with length (in bits) specified in parameter (pDescr->descr) + */ + gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */ + + no_of_bits += pDescr->i;/* size adjusted by offset */ + + if (no_of_bits > 0) + { + remaining_bits_len -= no_of_bits; + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + { /* extract bits */ + guint8* pui8 = pui8DATA(data, pDescr->offset); + + while (no_of_bits >= 8) + { + *pui8 = bitvec_read_field(vector, readIndex, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= 8; + } + if (no_of_bits > 0) + { + *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + bit_offset += no_of_bits; + no_of_bits = 0; + } + } + } + + /* bitmap was successfully extracted or it was empty */ + pDescr++; + break; + } + + case CSN_PADDING_BITS: + { /* Padding from here and to the end of message */ + LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz); + if (remaining_bits_len > 0) + { + while (remaining_bits_len > 0) + { + guint bits_to_handle = remaining_bits_len%8; + if (bits_to_handle > 0) + { + LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, bits_to_handle)); + remaining_bits_len -= bits_to_handle; + bit_offset += bits_to_handle; + } + else if (bits_to_handle == 0) + { + LOGPC(DCSN1, LOGL_DEBUG, "%d|", bitvec_get_uint(vector, 8)); + remaining_bits_len -= 8; + bit_offset += 8; + } + } + } + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + /* Padding was successfully extracted or it was empty */ + pDescr++; + break; + } + + case CSN_VARIABLE_ARRAY: + { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR; + * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * Array with length specified in parameter: + * + * + */ + gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value); + + count += pDescr->i; /* Adjusted by offset */ + + if (count > 0) + { + remaining_bits_len -= count * 8; + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pui8 = pui8DATA(data, pDescr->offset); + + while (count > 0) + { + *pui8 = bitvec_read_field(vector, readIndex, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%x | ", pDescr->sz , (unsigned)*pui8); + pui8++; + bit_offset += 8; + count--; + } + } + + pDescr++; + break; + } + + case CSN_RECURSIVE_ARRAY: + { /* Recursive way to specify an array: ::= {1 | 0} + * or more generally: ::= { | } + * where ::= bit(value) + * ::= 0 | 1 + * ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa + * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * REMARK: recursive way to specify an array but an iterative implementation! + */ + gint16 no_of_bits = pDescr->i; + guint8 ElementCount = 0; + + pui8 = pui8DATA(data, pDescr->offset); + + while (existNextElement(vector, readIndex, Tag)) + { /* tag control shows existence of next list elements */ + LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz); + bit_offset++; + remaining_bits_len--; + + /* extract and store no_of_bits long element from bitstream */ + *pui8 = bitvec_read_field(vector, readIndex, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + remaining_bits_len -= no_of_bits; + ElementCount++; + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + bit_offset += no_of_bits; + } + + LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1)); + /* existNextElement() returned FALSE, 1 bit consumed */ + bit_offset++; + remaining_bits_len--; + + /* Store the counted number of elements of the array */ + *pui8DATA(data, (gint16)pDescr->descr.value) = ElementCount; + + pDescr++; + break; + } + + case CSN_RECURSIVE_TARRAY: + { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; + * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) + * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)} + */ + gint16 nSizeElement = (gint16)(gint32)pDescr->value; + guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn); + guint8 ElementCount = 0; + pui8 = pui8DATA(data, pDescr->offset); + + while (existNextElement(vector, readIndex, Tag)) + { /* tag control shows existence of next list elements */ + LOGPC(DCSN1, LOGL_DEBUG, "%s = Exist | ", pDescr->sz); + /* existNextElement() returned TRUE, 1 bit consumed */ + bit_offset++; + remaining_bits_len--; + ElementCount++; + + if (ElementCount > nSizeArray) + { + LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray); + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); + } + + { /* unpack the following data structure */ + csnStream_t arT = *ar; + gint16 Status; + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); + + if (Status >= 0) + { /* successful completion */ + pui8 += nSizeElement; /* -> to next data element */ + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { /* something went awry */ + return Status; + } + } + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + } + + LOGPC(DCSN1, LOGL_DEBUG, "%s = %d | ", pDescr->sz , bitvec_get_uint(vector, 1)); + + /* existNextElement() returned FALSE, 1 bit consumed */ + remaining_bits_len--; + bit_offset++; + + /* Store the counted number of elements of the array */ + *pui8DATA(data, (gint16)(gint32)pDescr->i) = ElementCount; + + pDescr++; + break; + } + + case CSN_RECURSIVE_TARRAY_2: + { /* Recursive way to specify an array of type: ::= { 0 } ** 1 ; */ + + Tag = REVERSED_TAG; + + /* NO break - + * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue + */ + } + /* FALL THROUGH */ + case CSN_RECURSIVE_TARRAY_1: + { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; + * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) + * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE), (void_fn_t)ElementsOf(((_STRUCT*)0)->_MEMBER)} + */ + gint16 nSizeElement = (gint16)(gint32)pDescr->value; + guint32 nSizeArray = (guint32)((uintptr_t)pDescr->aux_fn); + guint8 ElementCount = 0; + csnStream_t arT = *ar; + gboolean EndOfList = FALSE; + gint16 Status; + pui8 = pui8DATA(data, pDescr->offset); + + do + { /* get data element */ + ElementCount++; + + if (ElementCount > nSizeArray) + { + LOGPC(DCSN1, LOGL_ERROR, "error: %s: too many elements (>%u) in recursive array. Increase its size! } |", pDescr->sz, nSizeArray); + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_STREAM_NOT_SUPPORTED, pDescr); + } + + LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz); + + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8); + + if (Status >= 0) + { /* successful completion */ + pui8 += nSizeElement; /* -> to next */ + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { /* something went awry */ + return Status; + } + + if (remaining_bits_len < 0) + { + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + /* control of next element's tag */ + LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz); + EndOfList = !(existNextElement(vector, readIndex, Tag)); + + bit_offset++; + remaining_bits_len--; /* 1 bit consumed (tag) */ + } while (!EndOfList); + + + /* Store the count of the array */ + *pui8DATA(data, pDescr->i) = ElementCount; + Tag = STANDARD_TAG; /* in case it was set to "reversed" */ + pDescr++; + break; + } + + case CSN_FIXED: + { /* Verify the fixed bits */ + guint8 no_of_bits = (guint8) pDescr->i; + guint32 ui32; + + if (no_of_bits <= 32) + { + ui32 = bitvec_read_field(vector, readIndex, no_of_bits); + } + else + { + return ProcessError(readIndex,"no_of_bits > 32", -1, pDescr); + } + if (ui32 != (unsigned)(gint32)pDescr->offset) + { + return ProcessError(readIndex,"csnStreamDecoder FIXED value does not match", -1, pDescr); + } + + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)ui32); + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_CALLBACK: + { + guint16 no_of_bits; + DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn; + LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz); + no_of_bits = callback(vector, readIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset)); + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_TRAP_ERROR: + { + return ProcessError(readIndex,"csnStreamDecoder", pDescr->i, pDescr); + } + + case CSN_END: + { + ar->remaining_bits_len = remaining_bits_len; + ar->bit_offset = bit_offset; + return remaining_bits_len; + } + + default: + { + assert(0); + } + + + } + + } while (remaining_bits_len >= 0); + + return ProcessError(readIndex,"csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); +} diff --git a/src/csn1_enc.c b/src/csn1_enc.c new file mode 100644 index 00000000..5518d063 --- /dev/null +++ b/src/csn1_enc.c @@ -0,0 +1,1305 @@ +/* csn1_enc.c + * Routines for CSN1 dissection in wireshark. + * + * Copyright (C) 2011 Ivan Klyuchnikov + * + * By Vincent Helfre, based on original code by Jari Sassi + * with the gracious authorization of STE + * Copyright (c) 2011 ST-Ericsson + * + * $Id: packet-csn1.c 39140 2011-09-25 22:01:50Z wmeier $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#define __STDC_FORMAT_MACROS +#include +#include "csn1.h" +#include + +#include +#include + +extern const unsigned char ixBitsTab[]; +guint8 get_masked_bits8(struct bitvec *vector, unsigned *readIndex, gint bit_offset, const gint no_of_bits); + +/** + * ================================================================================================ + * set initial/start values in help data structure used for packing/unpacking operation + * ================================================================================================ + */ + +gint16 csnStreamEncoder(csnStream_t* ar, const CSN_DESCR* pDescr, struct bitvec *vector, unsigned *writeIndex, void* data) +{ + gint remaining_bits_len = ar->remaining_bits_len; + gint bit_offset = ar->bit_offset; + guint8* pui8; + guint16* pui16; + guint32* pui32; + guint64* pui64; + unsigned ib; + + guint8 Tag = STANDARD_TAG; + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex, __func__, CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + do + { + switch (pDescr->type) + { + case CSN_BIT: + { + if (remaining_bits_len > 0) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + /* end add the bit value to protocol tree */ + } + else if (pDescr->may_be_null) + { + LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pDescr++; + remaining_bits_len--; + bit_offset++; + break; + } + + case CSN_NULL: + { /* Empty member! */ + pDescr++; + break; + } + + case CSN_UINT: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui16, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + else if (pDescr->may_be_null) + { + LOGPC(DCSN1, LOGL_DEBUG, "%s = NULL | ", pDescr->sz); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pDescr++; + break; + } + + case CSN_UINT_OFFSET: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value)); + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value)); + } + else if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value)); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_LH: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + // TODO : Change get_masked_bits8() + *writeIndex -= no_of_bits; + guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits); + *writeIndex -= no_of_bits; + bitvec_write_field(vector, writeIndex, ui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + + } + else + {/* Maybe we should support more than 8 bits ? */ + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_ARRAY: + { + guint8 no_of_bits = (guint8) pDescr->i; + guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ + + if (pDescr->value != 0) + { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ + nCount = *pui16DATA(data, nCount); + } + + if (remaining_bits_len >= (no_of_bits * nCount)) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + do + { + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } while (--nCount > 0); + } + else if (no_of_bits <= 16) + { + return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); + } + else if (no_of_bits <= 32) + { + return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + pDescr++; + break; + } + + case CSN_VARIABLE_TARRAY_OFFSET: + case CSN_VARIABLE_TARRAY: + case CSN_TYPE_ARRAY: + { + gint16 Status; + csnStream_t arT = *ar; + gint16 nCount = pDescr->i; + guint16 nSize = (guint16)(gint32)pDescr->value; + + pui8 = pui8DATA(data, pDescr->offset); + if (pDescr->type == CSN_VARIABLE_TARRAY) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + } + else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ + } + + while (nCount > 0) + { /* resulting array of length 0 is possible + * but no bits shall be read from bitstream + */ + + LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); + if (Status >= 0) + { + pui8 += nSize; + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + + } + else + { + return Status; + } + nCount--; + } + + pDescr++; + break; + } + + case CSN_BITMAP: + { /* bitmap with given length. The result is left aligned! */ + guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ + + if (no_of_bits > 0) + { + if (no_of_bits > remaining_bits_len) + { + return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + if (no_of_bits <= 32) + { + for(ib = 0; ib < 4; ib++) + { + pui8 = pui8DATA(data, pDescr->offset+ib); + bitvec_write_field(vector, writeIndex, *pui8, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); + } + } + else if (no_of_bits <= 64) + { + for(ib = 0; ib < 8; ib++) + { + pui8 = pui8DATA(data, pDescr->offset+ib); + bitvec_write_field(vector, writeIndex, *pui8, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + /* bitmap was successfully extracted or it was empty */ + + pDescr++; + break; + } + + case CSN_TYPE: + { + gint16 Status; + csnStream_t arT = *ar; + LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset)); + LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); + if (Status >= 0) + { + + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + pDescr++; + } + else + { + /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */ + return Status; + } + + break; + } + + case CSN_CHOICE: + { + gint16 count = pDescr->i; + const CSN_ChoiceElement_t* pChoice = (const CSN_ChoiceElement_t*) pDescr->descr.ptr; + + /* Make sure that the list of choice items is not empty */ + if (!count) + return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); + else if (count > 255) /* We can handle up to 256 (UCHAR_MAX) selectors */ + return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); + + /* Make sure that choice index is not out of range */ + pui8 = pui8DATA(data, pDescr->offset); + if (*pui8 >= count) + return ProcessError(writeIndex, "csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); + + pChoice += *pui8; + guint8 no_of_bits = pChoice->bits; + guint8 value = pChoice->value; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pChoice->descr.sz , (unsigned)value); + bitvec_write_field(vector, writeIndex, value, no_of_bits); + + CSN_DESCR descr[2]; + gint16 Status; + csnStream_t arT = *ar; + + descr[0] = pChoice->descr; + memset(&descr[1], 0x00, sizeof(CSN_DESCR)); + descr[1].type = CSN_END; + bit_offset += no_of_bits; + remaining_bits_len -= no_of_bits; + + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, descr, vector, writeIndex, data); + + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { + return Status; + } + + pDescr++; + break; + } + + case CSN_SERIALIZE: + { + StreamSerializeFcn_t serialize = (StreamSerializeFcn_t)pDescr->aux_fn; + csnStream_t arT = *ar; + guint8 length_len = pDescr->i; + gint16 Status = -1; + unsigned lengthIndex; + + // store writeIndex for length value (7 bit) + lengthIndex = *writeIndex; + *writeIndex += length_len; + bit_offset += length_len; + remaining_bits_len -= length_len; + arT.direction = 0; + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = serialize(&arT, vector, writeIndex, pvDATA(data, pDescr->offset)); + + bitvec_write_field(vector, &lengthIndex, *writeIndex - lengthIndex - length_len, length_len); + LOGPC(DCSN1, LOGL_DEBUG, "%s length = %u | ", pDescr->sz , (unsigned)(*writeIndex - lengthIndex)); + + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + pDescr++; + } + else + { + // Has already been processed: + return Status; + } + + break; + } + + case CSN_UNION_LH: + case CSN_UNION: + { + gint16 Bits; + guint8 index; + gint16 count = pDescr->i; + const CSN_DESCR* pDescrNext = pDescr; + + pDescrNext += count + 1; /* now this is next after the union */ + if ((count <= 0) || (count > 16)) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_INVALID_UNION_INDEX, pDescr); + } + + /* Now get the bits to extract the index */ + Bits = ixBitsTab[count]; + index = 0; + + /* Assign UnionType */ + pui8 = pui8DATA(data, pDescr->offset); + //read index from data and write to vector + bitvec_write_field(vector, writeIndex, *pui8, Bits); + + //decode index + *writeIndex -= Bits; + + while (Bits > 0) + { + index <<= 1; + + if (CSN_UNION_LH == pDescr->type) + { + index |= get_masked_bits8(vector, writeIndex, bit_offset, 1); + } + else + { + index |= bitvec_read_field(vector, writeIndex, 1); + } + + remaining_bits_len--; + bit_offset++; + Bits--; + } + + *writeIndex -= Bits; + bitvec_write_field(vector, writeIndex, index, Bits); + + + /* script index to continue on, limited in case we do not have a power of 2 */ + pDescr += (MIN(index + 1, count)); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)index); + + switch (pDescr->type) + { /* get the right element of the union based on computed index */ + + case CSN_BIT: + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + remaining_bits_len--; + bit_offset++; + pDescr++; + break; + } + + case CSN_NULL: + { /* Empty member! */ + pDescr++; + break; + } + + case CSN_UINT: + { + guint8 no_of_bits = (guint8) pDescr->i; + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui16, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui16); + } + else if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_OFFSET: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value)); + } + else if (no_of_bits <= 16) + { + pui16 = pui16DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value)); + } + else if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value)); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_LH: + { + guint8 no_of_bits = (guint8) pDescr->i; + + if (remaining_bits_len >= no_of_bits) + { + remaining_bits_len -= no_of_bits; + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + // TODO : Change get_masked_bits8() + *writeIndex -= no_of_bits; + guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits); + *writeIndex -= no_of_bits; + bitvec_write_field(vector, writeIndex, ui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + + } + else + {/* Maybe we should support more than 8 bits ? */ + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_UINT_ARRAY: + { + guint8 no_of_bits = (guint8) pDescr->i; + guint16 nCount = (guint16)pDescr->descr.value; /* nCount supplied by value i.e. M_UINT_ARRAY(...) */ + + if (pDescr->value != 0) + { /* nCount specified by a reference to field holding value i.e. M_VAR_UINT_ARRAY(...) */ + nCount = *pui16DATA(data, nCount); + } + + if (remaining_bits_len >= (no_of_bits * nCount)) + { + if (no_of_bits <= 8) + { + pui8 = pui8DATA(data, pDescr->offset); + do + { + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } while (--nCount > 0); + } + else if (no_of_bits <= 16) + { + return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); + } + else if (no_of_bits <= 32) + { + return ProcessError(writeIndex,"csnStreamEncoder NOTIMPLEMENTED", 999, pDescr); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_GENERAL, pDescr); + } + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + pDescr++; + break; + } + + case CSN_VARIABLE_TARRAY_OFFSET: + case CSN_VARIABLE_TARRAY: + case CSN_TYPE_ARRAY: + { + gint16 Status; + csnStream_t arT = *ar; + gint16 nCount = pDescr->i; + guint16 nSize = (guint16)(gint32)pDescr->value; + + pui8 = pui8DATA(data, pDescr->offset); + if (pDescr->type == CSN_VARIABLE_TARRAY) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + } + else if (pDescr->type == CSN_VARIABLE_TARRAY_OFFSET) + { /* Count specified in field */ + nCount = *pui8DATA(data, pDescr->i); + /* nCount--; the 1 offset is already taken into account in CSN_UINT_OFFSET */ + } + + while (nCount > 0) + { /* resulting array of length 0 is possible + * but no bits shall be read from bitstream + */ + + LOGPC(DCSN1, LOGL_DEBUG, "%s : | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); + if (Status >= 0) + { + pui8 += nSize; + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { + return Status; + } + nCount--; + } + + pDescr++; + break; + } + + case CSN_BITMAP: + { /* bitmap with given length. The result is left aligned! */ + guint8 no_of_bits = (guint8) pDescr->i; /* length of bitmap */ + + if (no_of_bits > 0) + { + if (no_of_bits > remaining_bits_len) + { + return ProcessError(writeIndex, "csnStreamDecoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + if (no_of_bits <= 32) + { + pui32 = pui32DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui32, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , *pui32); + } + else if (no_of_bits <= 64) + { + pui64 = pui64DATA(data, pDescr->offset); + bitvec_write_field(vector, writeIndex, *pui64, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %lu | ", pDescr->sz , *pui64); + } + else + { + return ProcessError(writeIndex,"csnStreamEncoder NOT IMPLEMENTED", 999, pDescr); + } + + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + } + /* bitmap was successfully extracted or it was empty */ + + pDescr++; + break; + } + + case CSN_TYPE: + { + gint16 Status; + csnStream_t arT = *ar; + LOGPC(DCSN1, LOGL_DEBUG, " : %s | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pvDATA(data, pDescr->offset)); + LOGPC(DCSN1, LOGL_DEBUG, " : End %s | ", pDescr->sz); + if (Status >= 0) + { + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + pDescr++; + } + else + { + /* Has already been processed: ProcessError("csnStreamEncoder", Status, pDescr); */ + return Status; + } + + break; + } + + default: + { /* descriptions of union elements other than above are illegal */ + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_IN_SCRIPT, pDescr); + } + } + + pDescr = pDescrNext; + break; + } + + case CSN_EXIST: + case CSN_EXIST_LH: + { + guint8 fExist; + unsigned exist = 0; + pui8 = pui8DATA(data, pDescr->offset); + exist = *pui8; + bitvec_write_field(vector, writeIndex, *pui8, 1); + writeIndex--; + if (CSN_EXIST_LH == pDescr->type) + { + fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1); + } + else + { + fExist = bitvec_read_field(vector, writeIndex, 1); + } + writeIndex--; + bitvec_write_field(vector, writeIndex, fExist, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz, (unsigned)fExist); + remaining_bits_len--; + bit_offset++; + pDescr++; + + if (!exist) + { + ar->remaining_bits_len = remaining_bits_len; + ar->bit_offset = bit_offset; + return remaining_bits_len; + } + break; + } + + case CSN_NEXT_EXIST: + { + guint8 fExist; + + pui8 = pui8DATA(data, pDescr->offset); + + /* this if-statement represents the M_NEXT_EXIST_OR_NULL description element */ + if ((pDescr->may_be_null) && (remaining_bits_len == 0)) + { /* no more bits to decode is fine here - end of message detected and allowed */ + + /* Skip i entries + this entry */ + pDescr += pDescr->i + 1; + + break; + } + + bitvec_write_field(vector, writeIndex, *pui8, 1); + fExist = *pui8; + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + + remaining_bits_len--; + bit_offset++; + + if (fExist == 0) + { /* Skip 'i' entries */ + pDescr += pDescr->i; + } + + pDescr++; + break; + } + + case CSN_NEXT_EXIST_LH: + { + guint8 fExist; + pui8 = pui8DATA(data, pDescr->offset); + + /* this if-statement represents the M_NEXT_EXIST_OR_NULL_LH description element */ + if ((pDescr->descr.ptr != NULL) && (remaining_bits_len == 0)) + { /* no more bits to decode is fine here - end of message detected and allowed */ + + /* skip 'i' entries + this entry */ + pDescr += pDescr->i + 1; + + /* set the data member to "not exist" */ + //*pui8 = 0; + break; + } + + /* the "regular" M_NEXT_EXIST_LH description element */ + bitvec_write_field(vector, writeIndex, *pui8, 1); + writeIndex--; + fExist = get_masked_bits8(vector, writeIndex, bit_offset, 1); + writeIndex--; + bitvec_write_field(vector, writeIndex, fExist, 1); + pui8++; + + remaining_bits_len--; + bit_offset++; + + if (fExist == 0) + { /* Skip 'i' entries */ + pDescr += pDescr->i; + } + pDescr++; + + break; + } + + case CSN_VARIABLE_BITMAP_1: + { /* Bitmap from here and to the end of message */ + + //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ + + /*no break - + * with a length set we have a regular variable length bitmap so we continue */ + } + /* FALL THROUGH */ + case CSN_VARIABLE_BITMAP: + { /* {CSN_VARIABLE_BITMAP, 0, offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * + * Bit array with length (in bits) specified in parameter (pDescr->descr) + * The result is right aligned! + */ + gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value); + + no_of_bits += pDescr->i; /* adjusted by offset */ + + if (no_of_bits > 0) + { + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + { /* extract bits */ + guint8* pui8 = pui8DATA(data, pDescr->offset); + gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ + + if (nB1 > 0) + { /* take care of the first byte - it will be right aligned */ + bitvec_write_field(vector, writeIndex, *pui8, nB1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= nB1; + bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ + remaining_bits_len -= nB1; + } + + /* remaining no_of_bits is a multiple of 8 or 0 */ + while (no_of_bits > 0) + { + bitvec_write_field(vector, writeIndex, *pui8, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= 8; + remaining_bits_len -= 8; + } + } + } + pDescr++; + break; + } + + case CSN_LEFT_ALIGNED_VAR_BMP_1: + { /* Bitmap from here and to the end of message */ + + //*pui8DATA(data, (gint16)pDescr->descr.value) = (guint8) remaining_bits_len; /* length of bitmap == remaining bits */ + + /* no break - + * with a length set we have a regular left aligned variable length bitmap so we continue + */ + } + /* FALL THROUGH */ + case CSN_LEFT_ALIGNED_VAR_BMP: + { /* {CSN_LEFT_ALIGNED_VAR_BMP, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * + * bit array with length (in bits) specified in parameter (pDescr->descr) + */ + + gint16 no_of_bits = *pui8DATA(data, (gint16)pDescr->descr.value);/* Size of bitmap */ + + no_of_bits += pDescr->i;/* size adjusted by offset */ + + if (no_of_bits > 0) + { + remaining_bits_len -= no_of_bits; + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + { /* extract bits */ + guint8* pui8 = pui8DATA(data, pDescr->offset); + gint16 nB1 = no_of_bits & 0x07;/* no_of_bits Mod 8 */ + + while (no_of_bits > 0) + { + bitvec_write_field(vector, writeIndex, *pui8, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= 8; + } + if (nB1 > 0) + { + bitvec_write_field(vector, writeIndex, *pui8, nB1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + no_of_bits -= nB1; + bit_offset += nB1; /* (nB1 is no_of_bits Mod 8) */ + } + } + + } + + /* bitmap was successfully extracted or it was empty */ + pDescr++; + break; + } + + case CSN_PADDING_BITS: + { /* Padding from here and to the end of message */ + LOGPC(DCSN1, LOGL_DEBUG, "%s = ", pDescr->sz); + guint8 filler = 0x2b; + if (remaining_bits_len > 0) + { + while (remaining_bits_len > 0) + { + guint8 bits_to_handle = remaining_bits_len%8; + if (bits_to_handle > 0) + { + /* section 11 of 44.060 + * The padding bits may be the 'null' string. Otherwise, the + * padding bits starts with bit '0', followed by 'spare padding' + * < padding bits > ::= { null | 0 < spare padding > ! < Ignore : 1 bit** = < no string > > } ; + */ + guint8 fl = filler&(0xff>>(8-bits_to_handle + 1)); + bitvec_write_field(vector, writeIndex, fl, bits_to_handle); + LOGPC(DCSN1, LOGL_DEBUG, "%u|", fl); + remaining_bits_len -= bits_to_handle; + bit_offset += bits_to_handle; + } + else if (bits_to_handle == 0) + { + bitvec_write_field(vector, writeIndex, filler, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%u|", filler); + remaining_bits_len -= 8; + bit_offset += 8; + } + } + } + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + /* Padding was successfully extracted or it was empty */ + pDescr++; + break; + } + + case CSN_VARIABLE_ARRAY: + { /* {int type; int i; void* descr; int offset; const char* sz; } CSN_DESCR; + * {CSN_VARIABLE_ARRAY, _OFFSET, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * Array with length specified in parameter: + * + * + */ + gint16 count = *pui8DATA(data, (gint16)pDescr->descr.value); + + count += pDescr->i; /* Adjusted by offset */ + + if (count > 0) + { + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + pui8 = pui8DATA(data, pDescr->offset); + + while (count > 0) + { + bitvec_write_field(vector, writeIndex, *pui8, 8); + LOGPC(DCSN1, LOGL_DEBUG, "%s = 0x%x | ", pDescr->sz , (unsigned)*pui8); + pui8++; + bit_offset += 8; + remaining_bits_len -= 8; + count--; + } + } + + pDescr++; + break; + } + + case CSN_RECURSIVE_ARRAY: + { /* Recursive way to specify an array: ::= {1 | 0} + * or more generally: ::= { | } + * where ::= bit(value) + * ::= 0 | 1 + * ::= reversed tag i.e. tag == 1 -> EndTag == 0 and vice versa + * {CSN_RECURSIVE_ARRAY, _BITS, (void*)offsetof(_STRUCT, _ElementCountField), offsetof(_STRUCT, _MEMBER), #_MEMBER} + * REMARK: recursive way to specify an array but an iterative implementation! + */ + gint16 no_of_bits = pDescr->i; + guint8 ElementCount = 0; + pui8 = pui8DATA(data, pDescr->offset); + ElementCount = *pui8DATA(data, (gint16)pDescr->descr.value); + while (ElementCount > 0) + { /* tag control shows existence of next list elements */ + bitvec_write_field(vector, writeIndex, Tag, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); + bit_offset++; + remaining_bits_len--; + + /* extract and store no_of_bits long element from bitstream */ + bitvec_write_field(vector, writeIndex, *pui8, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)*pui8); + pui8++; + ElementCount--; + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + bit_offset += no_of_bits; + remaining_bits_len -= no_of_bits; + } + + bitvec_write_field(vector, writeIndex, !Tag, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag)); + bit_offset++; + remaining_bits_len--; + + pDescr++; + break; + } + + case CSN_RECURSIVE_TARRAY: + { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; + * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) + * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)} + */ + gint16 nSizeElement = (gint16)(gint32)pDescr->value; + guint8 ElementCount = 0; + pui8 = pui8DATA(data, pDescr->offset); + /* Store the counted number of elements of the array */ + ElementCount = *pui8DATA(data, (gint16)(gint32)pDescr->i); + + while (ElementCount > 0) + { /* tag control shows existence of next list elements */ + bitvec_write_field(vector, writeIndex, Tag, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); + bit_offset++; + + remaining_bits_len--; + ElementCount--; + + { /* unpack the following data structure */ + csnStream_t arT = *ar; + gint16 Status; + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); + + if (Status >= 0) + { /* successful completion */ + pui8 += nSizeElement; /* -> to next data element */ + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { /* something went awry */ + return Status; + } + } + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + } + + bitvec_write_field(vector, writeIndex, !Tag, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)(!Tag)); + bit_offset++; + + pDescr++; + break; + } + + case CSN_RECURSIVE_TARRAY_2: + { /* Recursive way to specify an array of type: ::= { 0 } ** 1 ; */ + + Tag = REVERSED_TAG; + + /* NO break - + * handling is exactly the same as for CSN_RECURSIVE_TARRAY_1 so we continue + */ + } + /* FALL THROUGH */ + case CSN_RECURSIVE_TARRAY_1: + { /* Recursive way to specify an array of type: ::= { 1 } ** 0 ; + * M_REC_TARRAY(_STRUCT, _MEMBER, _MEMBER_TYPE, _ElementCountField) + * {t, offsetof(_STRUCT, _ElementCountField), (void*)CSNDESCR_##_MEMBER_TYPE, offsetof(_STRUCT, _MEMBER), #_MEMBER, (StreamSerializeFcn_t)sizeof(_MEMBER_TYPE)} + */ + gint16 nSizeElement = (gint16)(gint32)pDescr->value; + guint8 ElementCount = 0; + guint8 ElementNum = 0; + csnStream_t arT = *ar; + gint16 Status; + + pui8 = pui8DATA(data, pDescr->offset); + /* Store the count of the array */ + ElementCount = *pui8DATA(data, pDescr->i); + ElementNum = ElementCount; + + while (ElementCount > 0) + { /* get data element */ + if (ElementCount != ElementNum) + { + bitvec_write_field(vector, writeIndex, Tag, 1); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)Tag); + bit_offset++; + remaining_bits_len--; + } + ElementCount--; + LOGPC(DCSN1, LOGL_DEBUG, "%s { | ", pDescr->sz); + csnStreamInit(&arT, bit_offset, remaining_bits_len); + Status = csnStreamEncoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, writeIndex, pui8); + LOGPC(DCSN1, LOGL_DEBUG, "%s } | ", pDescr->sz); + if (Status >= 0) + { /* successful completion */ + pui8 += nSizeElement; /* -> to next */ + remaining_bits_len = arT.remaining_bits_len; + bit_offset = arT.bit_offset; + } + else + { /* something went awry */ + return Status; + } + + if (remaining_bits_len < 0) + { + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); + } + + } + bitvec_write_field(vector, writeIndex, !Tag, 1); + bit_offset++; + remaining_bits_len--; + Tag = STANDARD_TAG; /* in case it was set to "reversed" */ + pDescr++; + break; + } + + case CSN_FIXED: + { /* Verify the fixed bits */ + guint8 no_of_bits = (guint8) pDescr->i; + bitvec_write_field(vector, writeIndex, pDescr->offset, no_of_bits); + LOGPC(DCSN1, LOGL_DEBUG, "%s = %u | ", pDescr->sz , (unsigned)pDescr->offset); + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_CALLBACK: + { + guint16 no_of_bits; + DissectorCallbackFcn_t callback = (DissectorCallbackFcn_t)pDescr->aux_fn; + LOGPC(DCSN1, LOGL_DEBUG, "CSN_CALLBACK(%s) | ", pDescr->sz); + no_of_bits = callback(vector, writeIndex, pvDATA(data, pDescr->i), pvDATA(data, pDescr->offset)); + remaining_bits_len -= no_of_bits; + bit_offset += no_of_bits; + pDescr++; + break; + } + + case CSN_TRAP_ERROR: + { + return ProcessError(writeIndex,"csnStreamEncoder", pDescr->i, pDescr); + } + + case CSN_END: + { + ar->remaining_bits_len = remaining_bits_len; + ar->bit_offset = bit_offset; + return remaining_bits_len; + } + + default: + { + assert(0); + } + + } + + } while (remaining_bits_len >= 0); + + return ProcessError(writeIndex,"csnStreamEncoder", CSN_ERROR_NEED_MORE_BITS_TO_UNPACK, pDescr); +}