示例#1
0
/**
 * @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;
}
示例#2
0
/**
 * @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;
}
示例#3
0
/**
 * @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;
}
示例#4
0
/**
 * @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;
}