209 lines
4.9 KiB
C
209 lines
4.9 KiB
C
/*
|
|
* (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
|
|
* (C) 2012 by On Waves ehf <http://www.on-waves.com>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <pcap.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <netinet/ip.h>
|
|
#include <arpa/inet.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <unistd.h>
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
#include <osmocom/core/timer.h>
|
|
#include <osmocom/core/select.h>
|
|
#include <osmocom/core/logging.h>
|
|
#include <osmocom/core/application.h>
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/netif/rtp.h>
|
|
#include <osmocom/netif/osmux.h>
|
|
|
|
#include "osmo_pcap.h"
|
|
|
|
#define DOSMUXTEST 0
|
|
|
|
/*
|
|
* This is the output handle for osmux, it stores last RTP sequence and
|
|
* timestamp that has been used. There should be one per circuit ID.
|
|
*/
|
|
static struct osmux_out_handle *h_output;
|
|
|
|
static void tx_cb(struct msgb *msg, void *data)
|
|
{
|
|
printf("now sending message scheduled [emulated], msg=%p\n", msg);
|
|
/*
|
|
* Here we should call the real function that sends the message
|
|
* instead of releasing it.
|
|
*/
|
|
msgb_free(msg);
|
|
}
|
|
|
|
static void deliver(struct msgb *batch_msg)
|
|
{
|
|
struct osmux_hdr *osmuxh;
|
|
|
|
printf("sending batch (len=%d) [emulated]\n", batch_msg->len);
|
|
|
|
/* This code below belongs to the osmux receiver */
|
|
while((osmuxh = osmux_xfrm_output_pull(batch_msg)) != NULL)
|
|
osmux_xfrm_output_sched(h_output, osmuxh);
|
|
msgb_free(batch_msg);
|
|
}
|
|
|
|
/*
|
|
* This is the input handle for osmux. It stores the last osmux sequence that
|
|
* has been used and the deliver function that sends the osmux batch.
|
|
*/
|
|
struct osmux_in_handle *h_input;
|
|
|
|
#define MAX_CONCURRENT_CALLS 8
|
|
|
|
static int ccid[MAX_CONCURRENT_CALLS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
|
|
|
|
static void register_ccid(uint32_t ssrc)
|
|
{
|
|
int i, found = 0;
|
|
|
|
for (i=0; i<MAX_CONCURRENT_CALLS; i++) {
|
|
if (ccid[i] == ssrc)
|
|
continue;
|
|
if (ccid[i] < 0) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
ccid[i] = ssrc;
|
|
LOGP(DOSMUXTEST, LOGL_DEBUG, "mapping ssrc=%u to ccid=%d\n",
|
|
ntohl(ssrc), i);
|
|
} else {
|
|
LOGP(DOSMUXTEST, LOGL_ERROR, "cannot map ssrc to ccid!\n");
|
|
}
|
|
}
|
|
|
|
static int get_ccid(uint32_t ssrc)
|
|
{
|
|
int i, found = 0;
|
|
|
|
for (i=0; i<MAX_CONCURRENT_CALLS; i++) {
|
|
if (ccid[i] == ssrc) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return found ? i : -1;
|
|
}
|
|
|
|
static int pcap_test_run(struct msgb *msg)
|
|
{
|
|
int ret, ccid;
|
|
struct rtp_hdr *rtph;
|
|
|
|
rtph = osmo_rtp_get_hdr(msg);
|
|
if (rtph == NULL)
|
|
return 0;
|
|
|
|
ccid = get_ccid(rtph->ssrc);
|
|
if (ccid < 0)
|
|
register_ccid(rtph->ssrc);
|
|
|
|
while ((ret = osmux_xfrm_input(h_input, msg, ccid)) > 0) {
|
|
/* batch full, deliver it */
|
|
osmux_xfrm_input_deliver(h_input);
|
|
}
|
|
if (ret == -1)
|
|
printf("something is wrong\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct osmo_pcap osmo_pcap;
|
|
|
|
static void osmo_pcap_pkt_timer_cb(void *data)
|
|
{
|
|
if (osmo_pcap_test_run(&osmo_pcap, IPPROTO_UDP, pcap_test_run) < 0) {
|
|
osmo_pcap_stats_printf();
|
|
printf("\e[1;34mDone.\e[0m\n");
|
|
osmo_pcap_test_close(osmo_pcap.h);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
struct log_info_cat osmux_test_cat[] = {
|
|
[DOSMUXTEST] = {
|
|
.name = "DOSMUXTEST",
|
|
.description = "osmux test",
|
|
.color = "\033[1;35m",
|
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
|
},
|
|
};
|
|
|
|
const struct log_info osmux_log_info = {
|
|
.filter_fn = NULL,
|
|
.cat = osmux_test_cat,
|
|
.num_cat = ARRAY_SIZE(osmux_test_cat),
|
|
};
|
|
|
|
static void *tall_test;
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret;
|
|
|
|
if (argc != 2) {
|
|
fprintf(stderr, "Wrong usage:\n");
|
|
fprintf(stderr, "%s <pcap_file>\n", argv[0]);
|
|
fprintf(stderr, "example: %s file.pcap\n", argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
tall_test = talloc_named_const(NULL, 1, "osmux_pcap_test");
|
|
osmo_init_logging(&osmux_log_info);
|
|
log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
|
|
log_set_use_color(osmo_stderr_target, 0);
|
|
|
|
osmo_pcap_init();
|
|
|
|
printf("\e[1;34mStarting test...\e[0m\n");
|
|
|
|
osmo_pcap.h = osmo_pcap_test_open(argv[1]);
|
|
if (osmo_pcap.h == NULL)
|
|
exit(EXIT_FAILURE);
|
|
|
|
osmo_pcap.timer.cb = osmo_pcap_pkt_timer_cb;
|
|
|
|
h_input = osmux_xfrm_input_alloc(tall_test);
|
|
osmux_xfrm_input_set_initial_seqnum(h_input, 0);
|
|
osmux_xfrm_input_set_batch_factor(h_input, 4);
|
|
osmux_xfrm_input_set_deliver_cb(h_input, deliver, NULL);
|
|
|
|
h_output = osmux_xfrm_output_alloc(tall_test);
|
|
osmux_xfrm_output_set_rtp_ssrc(h_output, 0);
|
|
osmux_xfrm_output_set_rtp_pl_type(h_output, 98);
|
|
osmux_xfrm_output_set_tx_cb(h_output, tx_cb, NULL);
|
|
|
|
/* first run */
|
|
osmo_pcap_pkt_timer_cb(NULL);
|
|
|
|
while(1) {
|
|
osmo_select_main(0);
|
|
}
|
|
|
|
talloc_free(h_output);
|
|
|
|
return ret;
|
|
}
|