/** * @brief Get the XI information, ie. the X bit and the index value * * @param ps The PS bit * @param xi_index The index of the XI * @param xi_1 The XI 1 field if PS = 1 (4-bit XI) * @param data The data to parse * @param[out] is_item_present Whether the XI item shall be present or not * @return The value of the XI index */ static uint8_t rohc_list_get_xi_type_2or3(const int ps, const size_t xi_index, const uint8_t xi_1, const uint8_t *const data, bool *const is_item_present) { uint8_t xi_value; /* extract the value of the XI index */ if(ps == 1) { /* ROHC header contains 8-bit XIs */ *is_item_present = GET_BOOL(GET_BIT_7(data + xi_index)); xi_value = GET_BIT_0_6(data + xi_index); } else { /* ROHC header contains 4-bit XIs: encoding type 2 and 3 store XI #1 * in their first byte, so next XIs are shifted by 4 bits */ /* which type of XI do we parse ? first one, odd one or even one ? */ if(xi_index == 0) { /* first XI is stored in the first byte of the header */ *is_item_present = GET_BOOL(GET_BIT_3(&xi_1)); xi_value = GET_BIT_0_2(&xi_1); } else if((xi_index % 2) != 0) { /* handle odd XI, ie. XI stored in MSB */ *is_item_present = GET_BOOL(GET_BIT_7(data + (xi_index - 1) / 2)); xi_value = GET_BIT_4_6(data + (xi_index - 1) / 2); } else { /* handle even XI, ie. XI stored in LSB */ *is_item_present = GET_BOOL(GET_BIT_3(data + (xi_index - 1) / 2)); xi_value = GET_BIT_0_2(data + (xi_index - 1) / 2); } } return xi_value; }
/** * @brief Get the XI information, ie. the X bit and the index value * * @param ps The PS bit * @param xi_index The index of the XI * @param data The data to parse * @param[out] is_item_present Whether the XI item shall be present or not * @return The value of the XI index */ static uint8_t rohc_list_get_xi_type_0(const int ps, const size_t xi_index, const uint8_t *const data, bool *const is_item_present) { uint8_t xi_value; /* extract the value of the XI index */ if(ps == 1) { /* ROHC header contains 8-bit XIs */ *is_item_present = GET_BOOL(GET_BIT_7(data + xi_index)); xi_value = GET_BIT_0_6(data + xi_index); } else { /* ROHC header contains 4-bit XIs: encoding type 0 stores XI #1 * with all other XIs */ /* which type of XI do we parse ? even or odd one ? */ if((xi_index % 2) == 0) { /* handle even XI, ie. XI stored in MSB */ *is_item_present = GET_BOOL(GET_BIT_7(data + xi_index / 2)); xi_value = GET_BIT_4_6(data + xi_index / 2); } else { /* handle odd XI, ie. XI stored in LSB */ *is_item_present = GET_BOOL(GET_BIT_3(data + xi_index / 2)); xi_value = GET_BIT_0_2(data + xi_index / 2); } } return xi_value; }
/** * @brief Process the insertion scheme of the list compression * * @param decomp The list decompressor * @param packet The ROHC packet to decompress * @param packet_len The length (in bytes) of the packet to decompress * @param ps The PS bit * @param xi_1 The XI 1 field if PS = 1 (4-bit XI) * @param items_nr The number of items in the initial list * @param ref_list The list to use as reference * @param[out] ins_list The list with new items added * @return \li In case of success, the number of bytes read in the * given packet, ie. the length of the insertion mask * \li -1 in case of failure */ static int rohc_list_parse_insertion_scheme(struct list_decomp *const decomp, const uint8_t *packet, size_t packet_len, const int ps, const int xi_1, const size_t items_nr, const struct rohc_list *const ref_list, struct rohc_list *const ins_list) { size_t packet_read_len = 0; uint8_t mask[2]; /* removal bit mask on 1-2 bytes */ size_t mask_len; /* length (in bits) of the removal mask */ size_t item_read_len; /* the amount of bytes currently read in the item field */ size_t ref_list_cur_pos; /* current position in reference list */ size_t xi_index; /* the index of the current XI in XI list */ size_t xi_len; /* the length (in bytes) of the XI list */ size_t k; /* the number of ones in insertion mask and the number of elements in XI list */ size_t i; int ret; assert(ps == 0 || ps == 1); /* parse the insertion bit mask */ ret = rohc_list_decode_mask(decomp, "insertion", packet, packet_len, mask, &mask_len); if(ret < 0) { rd_list_warn(decomp, "failed to parse the insertion bit mask"); goto error; } packet += ret; packet_read_len += ret; packet_len -= ret; /* determine the number of indexes in the XI list */ k = rohc_list_get_xi_nr(mask, mask_len); /* determine the length (in bytes) of the XI list */ xi_len = rohc_list_get_xi_len(k, ps); if(packet_len < xi_len) { rd_list_warn(decomp, "packet too small for k = %zu XI items (only %zu " "bytes while at least %zu bytes are required)", k, packet_len, xi_len); goto error; } /* will the decompressed list contain too many items? */ if((items_nr + k) > ROHC_LIST_ITEMS_MAX) { rd_list_warn(decomp, "failed to decompress list based on reference list " "with %zu existing items and %zu additional new items: too " "many items for list (%u items max)", items_nr, k, ROHC_LIST_ITEMS_MAX); goto error; } /* create current list with reference list and new provided items */ xi_index = 0; item_read_len = 0; ref_list_cur_pos = 0; for(i = 0; i < mask_len; i++) { uint8_t new_item_to_insert; /* retrieve the corresponding bit in the insertion mask */ if(i < 7) { /* bit is located in first byte of insertion mask */ new_item_to_insert = rohc_get_bit(mask[0], 6 - i); } else { /* bit is located in 2nd byte of insertion mask */ new_item_to_insert = rohc_get_bit(mask[1], 14 - i); } /* insert item if required */ if(!new_item_to_insert) { /* take the next item from reference list (if there no more item in reference list, do nothing) */ if(ref_list_cur_pos < ref_list->items_nr) { /* new list, insert the item from reference list */ rd_list_debug(decomp, "use item from reference list (index %zu) into " "current list (index %zu)", ref_list_cur_pos, i); /* use next item from reference list */ ins_list->items[i] = ref_list->items[ref_list_cur_pos]; ins_list->items_nr++; /* skip item in removal list */ ref_list_cur_pos++; } } else { unsigned int xi_x_value; /* the value of the X field in one XI field */ unsigned int xi_index_value; /* the value of the Index field in one XI field */ /* new item to insert in list, parse the related XI field */ if(!ps) { /* ROHC header contains 4-bit XIs */ /* which type of XI do we parse ? first one, odd one or even one ? */ if(xi_index == 0) { /* first XI is stored in the first byte of the header */ xi_x_value = GET_BIT_3(&xi_1); xi_index_value = GET_BIT_0_2(&xi_1); } else if((xi_index % 2) != 0) { /* handle odd XI, ie. XI stored in MSB */ xi_x_value = GET_BIT_7(packet + (xi_index - 1) / 2); xi_index_value = GET_BIT_4_6(packet + (xi_index - 1) / 2); } else { /* handle even XI, ie. XI stored in LSB */ xi_x_value = GET_BIT_3(packet + (xi_index - 1) / 2); xi_index_value = GET_BIT_0_2(packet + (xi_index - 1) / 2); } } else { /* ROHC header contains 8-bit XIs */ xi_x_value = GET_BIT_7(packet + xi_index); xi_index_value = GET_BIT_0_6(packet + xi_index); } /* is the XI index valid? */ if(!decomp->check_item(decomp, xi_index_value)) { rd_list_warn(decomp, "XI #%zu got invalid index %u", xi_index, xi_index_value); goto error; } /* parse the corresponding item if present */ if(xi_x_value) { const uint8_t *const xi_item = packet + xi_len + item_read_len; const size_t xi_item_max_len = packet_len - xi_len - item_read_len; size_t item_len; rd_list_debug(decomp, "handle XI item #%zu", xi_index); /* create (or update if it already exists) the corresponding * item with the item transmitted in the ROHC header */ if(!rohc_decomp_list_create_item(decomp, xi_index, xi_index_value, xi_item, xi_item_max_len, &item_len)) { rd_list_warn(decomp, "failed to create XI item #%zu from " "packet", xi_index); goto error; } /* skip the item in ROHC header */ item_read_len += item_len; } else { /* X bit not set in XI, so item is not provided in ROHC header, * it must already be known by decompressor */ if(!decomp->trans_table[xi_index_value].known) { rd_list_warn(decomp, "list item with index #%u referenced by " "XI #%zu is not known yet", xi_index_value, xi_index); goto error; } } /* use new item from packet */ rd_list_debug(decomp, "use new item #%zu into current list (index " "%zu)", xi_index, i); ins_list->items[i] = &(decomp->trans_table[xi_index_value]); ins_list->items_nr++; /* skip the XI we have just parsed */ xi_index++; } } /* ensure that in case of an even number of 4-bit XIs, the 4 bits of * padding are set to 0 */ if(ps == 0 && (k % 2) == 0) { const uint8_t xi_padding = GET_BIT_0_3(packet + xi_len - 1); if(xi_padding != 0) { rd_list_warn(decomp, "sender does not conform to ROHC standards: " "when an even number of 4-bit XIs is used, the last 4 " "bits of the XI list should be set to 0, not 0x%x", xi_padding); #ifdef ROHC_RFC_STRICT_DECOMPRESSOR goto error; #endif } } /* skip the XI list and the item list */ packet_read_len += xi_len + item_read_len; #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ packet_len -= xi_len + item_read_len; #endif return packet_read_len; error: return -1; }
/** * @brief Decode an extension list type 0 * * @param decomp The list decompressor * @param packet The ROHC packet to decompress * @param packet_len The length (in bytes) of the packet to decompress * @param gen_id The id of the current list, * maybe ROHC_LIST_GEN_ID_ANON if not defined * @param ps The ps field * @param m The m field * @return \li In case of success, the number of bytes read in the given * packet, ie. the length of the compressed list * \li -1 in case of failure */ static int rohc_list_decode_type_0(struct list_decomp *const decomp, const unsigned char *packet, size_t packet_len, const unsigned int gen_id, const int ps, const uint8_t m) { size_t packet_read_len = 0; size_t xi_len; /* the length (in bytes) of the XI list */ unsigned int xi_index; /* the index of the current XI in XI list */ size_t item_read_len; /* the amount of bytes currently read in the item field */ assert(decomp != NULL); assert(packet != NULL); assert(gen_id != ROHC_LIST_GEN_ID_NONE); assert(ps == 0 || ps == 1); assert(m <= ROHC_LIST_ITEMS_MAX); /* determine the length (in bytes) of the XI list */ if(!ps) { /* 4-bit XIs */ if((m % 2) == 0) { /* even number of XI fields */ xi_len = m / 2; } else { /* odd number of XI fields, there are 4 bits of padding */ xi_len = (m + 1) / 2; } } else { /* 8-bit XIs */ xi_len = m; } /* is there enough room in packet for all the XI list ? */ if(packet_len < xi_len) { rd_list_warn(decomp, "packet too small for m = %d XI items (only %zu " "bytes while at least %zu bytes are required)", m, packet_len, xi_len); goto error; } /* creation of the list from the m XI items */ item_read_len = 0; for(xi_index = 0; xi_index < m; xi_index++) { unsigned int xi_x_value; /* the value of the X field in one XI field */ unsigned int xi_index_value; /* the value of the Index field in one XI field */ /* extract the value of the XI index */ if(!ps) { /* 4-bit XI */ if((xi_index % 2) == 0) { /* 4-bit XI is stored in MSB */ xi_x_value = GET_BIT_7(packet + xi_index / 2); xi_index_value = GET_BIT_4_6(packet + xi_index / 2); } else { /* 4-bit XI is stored in LSB */ xi_x_value = GET_BIT_3(packet + xi_index / 2); xi_index_value = GET_BIT_0_2(packet + xi_index / 2); } rd_list_debug(decomp, "0x%02x: XI #%u got index %u", packet[xi_index / 2], xi_index, xi_index_value); } else { /* 8-bit XI */ xi_x_value = GET_BIT_7(packet + xi_index); xi_index_value = GET_BIT_0_6(packet + xi_index); rd_list_debug(decomp, "0x%02x: XI #%u got index %u", packet[xi_index], xi_index, xi_index_value); } /* is the XI index valid? */ if(!decomp->check_item(decomp, xi_index_value)) { rd_list_warn(decomp, "XI #%u got invalid index %u", xi_index, xi_index_value); goto error; } /* is there a corresponding item in packet after the XI list? */ if(xi_x_value) { const uint8_t *const xi_item = packet + xi_len + item_read_len; const size_t xi_item_max_len = packet_len - xi_len - item_read_len; size_t item_len; rd_list_debug(decomp, "handle XI item #%u", xi_index); /* create (or update if it already exists) the corresponding item * with the item transmitted in the ROHC header */ if(!rohc_decomp_list_create_item(decomp, xi_index, xi_index_value, xi_item, xi_item_max_len, &item_len)) { rd_list_warn(decomp, "failed to create XI item #%u from packet", xi_index); goto error; } /* skip the item in ROHC header */ item_read_len += item_len; } else { /* X bit not set in XI, so item is not provided in ROHC header, * it must already be known by decompressor */ if(!decomp->trans_table[xi_index_value].known) { rd_list_warn(decomp, "list item with index #%u referenced by XI " "#%d is not known yet", xi_index_value, xi_index); goto error; } } /* record the structure of the list of the current packet */ assert(decomp->pkt_list.items_nr < ROHC_LIST_ITEMS_MAX); decomp->pkt_list.items[decomp->pkt_list.items_nr] = &decomp->trans_table[xi_index_value]; decomp->pkt_list.items_nr++; rd_list_debug(decomp, " XI #%u: use item of type 0x%02x (index %u in " "translation table) in list", xi_index, decomp->trans_table[xi_index_value].type, xi_index_value); } /* ensure that in case of an odd number of 4-bit XIs, the 4 bits of padding are set to 0 */ if(ps == 0 && (m % 2) != 0) { const uint8_t xi_padding = GET_BIT_0_3(packet + xi_len - 1); if(xi_padding != 0) { rd_list_warn(decomp, "sender does not conform to ROHC standards: " "when an odd number of 4-bit XIs is used, the last 4 " "bits of the XI list should be set to 0, not 0x%x", xi_padding); #ifdef ROHC_RFC_STRICT_DECOMPRESSOR goto error; #endif } } /* skip the XI list and the item list */ packet_read_len += xi_len + item_read_len; #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ packet_len -= xi_len + item_read_len; #endif return packet_read_len; error: return -1; }
// Return the size of the feedback // In: Bytes of a feedback header // Out: Size int d_feedback_size(const unsigned char *data) { if(GET_BIT_0_2(data)!=(0x0 >> 1)) return GET_BIT_0_2(data); else{