Ejemplo n.º 1
0
/**
 * @brief Test the ROHC library with the given ROHC feedback packet
 *
 * @param rohc_feedback  The ROHC feedback data
 * @return               0 in case of success,
 *                       1 in case of failure
 */
static int test_decomp(const struct rohc_buf rohc_feedback)
{
	struct rohc_decomp *decomp;

	uint8_t ip_buffer[MAX_ROHC_SIZE];
	struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, MAX_ROHC_SIZE);

	uint8_t feedback_buffer[MAX_ROHC_SIZE];
	struct rohc_buf feedback_packet =
		rohc_buf_init_empty(feedback_buffer, MAX_ROHC_SIZE);

	int is_failure = 1;
	rohc_status_t status;

	/* create the ROHC decompressor in bi-directional mode */
	decomp = rohc_decomp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, ROHC_O_MODE);
	if(decomp == NULL)
	{
		fprintf(stderr, "failed to create the ROHC decompressor\n");
		goto error;
	}

	/* set the callback for traces on decompressor */
	if(!rohc_decomp_set_traces_cb2(decomp, print_rohc_traces, NULL))
	{
		fprintf(stderr, "cannot set trace callback for decompressor\n");
		goto destroy_decomp;
	}

	/* decompress the ROHC feedback with the ROHC decompressor */
	status = rohc_decompress3(decomp, rohc_feedback, &ip_packet,
	                          &feedback_packet, NULL);
	if(status != ROHC_STATUS_OK)
	{
		fprintf(stderr, "failed to decompress ROHC feedback\n");
		goto destroy_decomp;
	}
	if(!rohc_buf_is_empty(ip_packet))
	{
		fprintf(stderr, "ROHC packet was not a feedback-only packet\n");
	}
	if(rohc_buf_is_empty(feedback_packet))
	{
		fprintf(stderr, "ROHC packet contained no feedback data\n");
	}
	fprintf(stderr, "decompression is successful\n");

	/* everything went fine */
	is_failure = 0;

destroy_decomp:
	rohc_decomp_free(decomp);
error:
	return is_failure;
}
Ejemplo n.º 2
0
/**
 * @brief Create and configure a ROHC decompressor
 *
 * @param cid_type      The type of CIDs the compressor shall use
 * @param max_contexts  The maximum number of ROHC contexts to use
 * @return              The new ROHC decompressor
 */
static struct rohc_decomp * create_decompressor(const rohc_cid_type_t cid_type,
                                                const size_t max_contexts)
{
	struct rohc_decomp *decomp;

	/* create the decompressor */
	decomp = rohc_decomp_new2(cid_type, max_contexts - 1, ROHC_U_MODE);
	if(decomp == NULL)
	{
		printf("failed to create decompressor\n");
		goto error;
	}

	/* set the callback for traces */
	if(!rohc_decomp_set_traces_cb2(decomp, print_rohc_traces, NULL))
	{
		printf("failed to set trace callback\n");
		goto destroy_decomp;
	}

	/* enable decompression profiles */
	if(!rohc_decomp_enable_profiles(decomp, ROHC_PROFILE_UNCOMPRESSED,
	                                ROHC_PROFILE_UDP, ROHC_PROFILE_IP,
	                                ROHC_PROFILE_UDPLITE, ROHC_PROFILE_RTP,
	                                ROHC_PROFILE_ESP, ROHC_PROFILE_TCP, -1))
	{
		printf("failed to enable the profiles\n");
		goto destroy_decomp;
	}

	return decomp;

destroy_decomp:
	rohc_decomp_free(decomp);
error:
	return NULL;
}
Ejemplo n.º 3
0
/**
 * @brief Test the ROHC library with a flow of ROHC packets
 *
 * @param filename       The name of the PCAP file that contains the ROHC packets
 * @param failure_start  The first packet that shall fail to be decompressed
 * @return               0 in case of success,
 *                       1 in case of failure
 */
static int test_decomp(const char *const filename,
                       const size_t failure_start)
{
	char errbuf[PCAP_ERRBUF_SIZE];
	pcap_t *handle;
	int link_layer_type;
	int link_len;
	struct pcap_pkthdr header;
	unsigned char *packet;
	struct rohc_decomp *decomp;
	unsigned int counter;
	int is_failure = 1;

	/* open the source dump file */
	handle = pcap_open_offline(filename, errbuf);
	if(handle == NULL)
	{
		fprintf(stderr, "failed to open the source pcap file: %s\n", errbuf);
		goto error;
	}

	/* link layer in the source dump must be Ethernet */
	link_layer_type = pcap_datalink(handle);
	if(link_layer_type != DLT_EN10MB &&
	   link_layer_type != DLT_LINUX_SLL &&
	   link_layer_type != DLT_RAW)
	{
		fprintf(stderr, "link layer type %d not supported in source dump (supported = "
		       "%d, %d, %d)\n", link_layer_type, DLT_EN10MB, DLT_LINUX_SLL,
		       DLT_RAW);
		goto close_input;
	}

	if(link_layer_type == DLT_EN10MB)
	{
		link_len = ETHER_HDR_LEN;
	}
	else if(link_layer_type == DLT_LINUX_SLL)
	{
		link_len = LINUX_COOKED_HDR_LEN;
	}
	else /* DLT_RAW */
	{
		link_len = 0;
	}

	/* create the decompressor */
	decomp = rohc_decomp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX, ROHC_O_MODE);
	if(decomp == NULL)
	{
		fprintf(stderr, "cannot create the decompressor\n");
		goto close_input;
	}

	/* set the callback for traces */
	if(!rohc_decomp_set_traces_cb2(decomp, print_rohc_traces, NULL))
	{
		fprintf(stderr, "failed to set trace callback\n");
		goto destroy_decomp;
	}

	/* enable decompression profiles */
	if(!rohc_decomp_enable_profiles(decomp, ROHC_PROFILE_UNCOMPRESSED,
	                                ROHC_PROFILE_UDP, ROHC_PROFILE_IP,
	                                ROHC_PROFILE_UDPLITE, ROHC_PROFILE_RTP,
	                                ROHC_PROFILE_ESP, ROHC_PROFILE_TCP, -1))
	{
		fprintf(stderr, "failed to enable the decompression profiles\n");
		goto destroy_decomp;
	}

	/* for each packet in the dump */
	counter = 0;
	while((packet = (unsigned char *) pcap_next(handle, &header)) != NULL)
	{
		const struct rohc_ts arrival_time = { .sec = 0, .nsec = 0 };
		struct rohc_buf rohc_packet =
			rohc_buf_init_full(packet, header.caplen, arrival_time);
		uint8_t ip_buffer[MAX_ROHC_SIZE];
		struct rohc_buf ip_packet =
			rohc_buf_init_empty(ip_buffer, MAX_ROHC_SIZE);
		uint8_t rcvd_feedback_buf[6];
		struct rohc_buf rcvd_feedback = rohc_buf_init_empty(rcvd_feedback_buf, 6);
		uint8_t send_feedback_buf[6];
		struct rohc_buf send_feedback = rohc_buf_init_empty(send_feedback_buf, 6);
		rohc_status_t status;

		counter++;

		/* check Ethernet frame length */
		if(header.len < link_len || header.len != header.caplen)
		{
			fprintf(stderr, "bad PCAP packet (len = %d, caplen = %d)\n",
			       header.len, header.caplen);
			goto destroy_decomp;
		}

		/* skip the link layer header */
		rohc_buf_pull(&rohc_packet, link_len);

		fprintf(stderr, "decompress malformed packet #%u:\n", counter);

		/* decompress the ROHC packet */
		status = rohc_decompress3(decomp, rohc_packet, &ip_packet, &rcvd_feedback,
		                          &send_feedback);
		fprintf(stderr, "\tdecompression status: %s\n", rohc_strerror(status));
		if(status == ROHC_STATUS_OK)
		{
			if(counter >= failure_start)
			{
				fprintf(stderr, "\tunexpected successful decompression\n");
				goto destroy_decomp;
			}
			else
			{
				fprintf(stderr, "\texpected successful decompression\n");
			}
		}
		else
		{
			if(counter >= failure_start)
			{
				fprintf(stderr, "\texpected decompression failure\n");
			}
			else
			{
				fprintf(stderr, "\tunexpected decompression failure\n");
				goto destroy_decomp;
			}
		}

		/* be ready to get the next feedback to send */
		rohc_buf_reset(&send_feedback);
	}

	is_failure = 0;

destroy_decomp:
	rohc_decomp_free(decomp);
close_input:
	pcap_close(handle);
error:
	return is_failure;
}


/**
 * @brief Callback to print traces of the ROHC library
 *
 * @param priv_ctxt  An optional private context, may be NULL
 * @param level      The priority level of the trace
 * @param entity     The entity that emitted the trace among:
 *                    \li ROHC_TRACE_COMP
 *                    \li ROHC_TRACE_DECOMP
 * @param profile    The ID of the ROHC compression/decompression profile
 *                   the trace is related to
 * @param format     The format string of the trace
 */
static void print_rohc_traces(void *const priv_ctxt,
                              const rohc_trace_level_t level,
                              const rohc_trace_entity_t entity,
                              const int profile,
                              const char *const format,
                              ...)
{
	const char *level_descrs[] =
	{
		[ROHC_TRACE_DEBUG]   = "DEBUG",
		[ROHC_TRACE_INFO]    = "INFO",
		[ROHC_TRACE_WARNING] = "WARNING",
		[ROHC_TRACE_ERROR]   = "ERROR"
	};

	if(level >= ROHC_TRACE_WARNING || is_verbose)
	{
		va_list args;
		fprintf(stdout, "[%s] ", level_descrs[level]);
		va_start(args, format);
		vfprintf(stdout, format, args);
		va_end(args);
	}
}