diff options
author | Pablo Neira Ayuso <pablo@gnumonks.org> | 2012-10-15 18:16:21 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-10-15 23:07:12 +0200 |
commit | 4925acf2975f39a7ba3d6451f77eceae4b7fb203 (patch) | |
tree | 9f3203918e3b1e070e1d86bb93429ec9e6fd39b9 /examples | |
parent | 384bdf630a59f5611447675dfec962d15bc1eeaa (diff) |
examples: add osmux-test-input and osmux-test-output
You can use these utilities to test osmux:
1) in one console, run ./osmux-test-input
This listens in port UDP 20000 and convert RTP traffic to osmux
Then, it sends osmux traffic via port UDP 20001
2) in another console, run ./osmux-test-output
This listens in port UDP 20001 and convert osmux to RTP traffic
Then, it sends RTP traffic to UDP port 20002
3) in another console run, nc -u nc -u -l -p 20002
This is the sink, just to avoid ICMP destination unreachable messages
Now you can run replay UDP traffic from one pcap trace that contains
RTP traffic with this tool:
http://1984.lsi.us.es/git/pcap-inject/
Example of command line invocation:
./traffic-inject /home/pablo/rtp-nanobts-2-phones-amr.pcap udp 20000
You can run wireshark in the loopback to make sure osmux is getting back
the traces looking like the original.
The tests also generate output files in AMR that you can validate via
mplayer: /tmp/output.amr and /tmp/input.amr respectively. This is to
make sure there are no reordering or problems of any sort.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile.am | 12 | ||||
-rw-r--r-- | examples/osmux-test-input.c | 199 | ||||
-rw-r--r-- | examples/osmux-test-output.c | 185 |
3 files changed, 395 insertions, 1 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am index 1063245..e7742cd 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -13,7 +13,9 @@ noinst_PROGRAMS = ipa-stream-client \ rs232-read \ rs232-write \ rtp-udp-test-client \ - rtp-udp-test-server + rtp-udp-test-server \ + osmux-test-input \ + osmux-test-output ipa_stream_client_SOURCES = ipa-stream-client.c ipa_stream_client_LDADD = $(top_builddir)/src/libosmonetif.la \ @@ -54,3 +56,11 @@ rtp_udp_test_client_LDADD = $(top_builddir)/src/libosmonetif.la \ rtp_udp_test_server_SOURCES = rtp-udp-test-server.c rtp_udp_test_server_LDADD = $(top_builddir)/src/libosmonetif.la \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) + +osmux_test_input_SOURCES = osmux-test-input.c +osmux_test_input_LDADD = $(top_builddir)/src/libosmonetif.la \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) + +osmux_test_output_SOURCES = osmux-test-output.c +osmux_test_output_LDADD = $(top_builddir)/src/libosmonetif.la \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) diff --git a/examples/osmux-test-input.c b/examples/osmux-test-input.c new file mode 100644 index 0000000..3203b4d --- /dev/null +++ b/examples/osmux-test-input.c @@ -0,0 +1,199 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <signal.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/application.h> +#include <osmocom/core/select.h> + +#include <osmocom/netif/rtp.h> +#include <osmocom/netif/osmux.h> +#include <osmocom/netif/datagram.h> + +#define DOSMUX_TEST 0 + +struct log_info_cat osmux_test_cat[] = { + [DOSMUX_TEST] = { + .name = "DOSMUX_TEST", + .description = "osmux test input", + .color = "\033[1;35m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, +}; + +const struct log_info osmux_test_log_info = { + .filter_fn = NULL, + .cat = osmux_test_cat, + .num_cat = ARRAY_SIZE(osmux_test_cat), +}; + +static int fd; + +static void amr_open(void) +{ + fd = open("/tmp/input.amr", O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) { + perror("open"); + exit(EXIT_FAILURE); + } + write(fd, "#!AMR\n", strlen("#!AMR\n")); +} + +static void amr_close(void) +{ + close(fd); +} + +static void amr_write(struct msgb *msg) +{ + struct rtp_hdr *rtph; + void *amr; + unsigned int len; + + /* as described by rfc4867, see page 35 */ + rtph = osmo_rtp_get_hdr(msg); + amr = osmo_rtp_get_payload(rtph, msg, &len); + + write(fd, (uint8_t *)amr + 1, len - 1); +} + +static struct osmo_dgram *conn; +static struct osmo_rtp_handle *rtp; + +static void osmux_deliver(struct msgb *batch_msg) +{ + printf("sending batch (len=%d)\n", batch_msg->len); + osmo_dgram_send(conn, 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 = { + .osmux_seq = 0, /* sequence number to start OSmux message from */ + .batch_factor = 4, /* batch up to 4 RTP messages */ + .deliver = osmux_deliver, +}; + +int read_cb(struct osmo_dgram *conn) +{ + struct msgb *msg; + struct rtp_hdr *rtph; + int ret; + + LOGP(DOSMUX_TEST, LOGL_DEBUG, "received message from datagram\n"); + + msg = msgb_alloc(RTP_MSGB_SIZE, "OSMUX/test"); + if (msg == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot allocate message\n"); + return -1; + } + if (osmo_dgram_recv(conn, msg) < 0) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot receive message\n"); + return -1; + } + rtph = osmo_rtp_get_hdr(msg); + if (rtph == NULL) { + msgb_free(msg); + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot parse RTP message\n"); + return -1; + } + LOGP(DLINP, LOGL_DEBUG, "received message with RTP payload type: %d\n", + rtph->payload_type); + + if (rtph->payload_type == RTP_PT_AMR) + amr_write(msg); + + /* now build the osmux frame */ + if (osmux_xfrm_input_get_ccid(&h_input, rtph->ssrc) < 0) + osmux_xfrm_input_register_ccid(&h_input, rtph->ssrc); + + while ((ret = osmux_xfrm_input(&h_input, msg)) > 0) { + /* batch full, deliver it */ + osmux_xfrm_input_deliver(&h_input); + } + if (ret == -1) + printf("something is wrong\n"); + + return 0; +} + +void sighandler(int foo) +{ + LOGP(DLINP, LOGL_NOTICE, "closing test.\n"); + osmo_dgram_close(conn); + osmo_dgram_destroy(conn); + osmo_rtp_handle_free(rtp); + amr_close(); + exit(EXIT_SUCCESS); +} + +static void *tall_test; + +/* + * 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. + */ +int main(int argc, char *argv[]) +{ + amr_open(); + + signal(SIGINT, sighandler); + + tall_test = talloc_named_const(NULL, 1, "osmux_test"); + + osmo_init_logging(&osmux_test_log_info); + log_set_log_level(osmo_stderr_target, LOGL_DEBUG); + + /* + * initialize RTP handler. + */ + rtp = osmo_rtp_handle_create(tall_test); + if (rtp == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "Error init RTP handler\n"); + exit(EXIT_FAILURE); + } + osmo_rtp_handle_tx_set_sequence(rtp, random()); + osmo_rtp_handle_tx_set_ssrc(rtp, random()); + osmo_rtp_handle_tx_set_timestamp(rtp, time(NULL)); + + /* + * initialize OSMUX handlers. + */ + osmux_xfrm_input_init(&h_input); + + /* + * initialize datagram server. + */ + + conn = osmo_dgram_create(tall_test); + if (conn == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot create UDP socket\n"); + exit(EXIT_FAILURE); + } + osmo_dgram_set_local_addr(conn, "127.0.0.1"); + osmo_dgram_set_local_port(conn, 20000); + osmo_dgram_set_remote_addr(conn, "127.0.0.1"); + osmo_dgram_set_remote_port(conn, 20001); + osmo_dgram_set_read_cb(conn, read_cb); + + if (osmo_dgram_open(conn) < 0) { + fprintf(stderr, "cannot open client\n"); + exit(EXIT_FAILURE); + } + + LOGP(DOSMUX_TEST, LOGL_NOTICE, "Entering main loop\n"); + + while(1) { + osmo_select_main(0); + } +} diff --git a/examples/osmux-test-output.c b/examples/osmux-test-output.c new file mode 100644 index 0000000..f797f49 --- /dev/null +++ b/examples/osmux-test-output.c @@ -0,0 +1,185 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <signal.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/application.h> +#include <osmocom/core/select.h> + +#include <osmocom/netif/rtp.h> +#include <osmocom/netif/osmux.h> +#include <osmocom/netif/datagram.h> + +#define DOSMUX_TEST 0 + +struct log_info_cat osmux_test_cat[] = { + [DOSMUX_TEST] = { + .name = "DOSMUX_TEST", + .description = "osmux test output", + .color = "\033[1;35m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, +}; + +const struct log_info osmux_test_log_info = { + .filter_fn = NULL, + .cat = osmux_test_cat, + .num_cat = ARRAY_SIZE(osmux_test_cat), +}; + +static struct osmo_dgram *conn; +static struct osmo_rtp_handle *rtp; + +/* + * 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 int fd; + +static void amr_open(void) +{ + fd = open("/tmp/output.amr", O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) { + perror("open"); + exit(1); + } + write(fd, "#!AMR\n", strlen("#!AMR\n")); +} + +static void amr_close(void) +{ + close(fd); +} + +static void amr_write(struct msgb *msg) +{ + struct rtp_hdr *rtph; + void *amr; + unsigned int len; + + rtph = osmo_rtp_get_hdr(msg); + amr = osmo_rtp_get_payload(rtph, msg, &len); + + write(fd, (uint8_t *)amr + 1, len - 1); +} + +static void tx_cb(struct msgb *msg, void *data) +{ + char buf[4096]; + + osmo_rtp_snprintf(buf, sizeof(buf), msg); + printf("sending: %s\n", buf); + osmo_dgram_send(conn, msg); + + amr_write(msg); +} + +int read_cb(struct osmo_dgram *conn) +{ + struct msgb *msg; + struct osmux_hdr *osmuxh; + struct llist_head list; + + LOGP(DOSMUX_TEST, LOGL_DEBUG, "received message from datagram\n"); + + msg = msgb_alloc(RTP_MSGB_SIZE, "OSMUX/test"); + if (msg == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot allocate message\n"); + return -1; + } + if (osmo_dgram_recv(conn, msg) < 0) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot receive message\n"); + return -1; + } + + LOGP(DLINP, LOGL_DEBUG, "received OSMUX message (len=%d)\n", msg->len); + + while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) { + printf("tx_sched\n"); + osmux_xfrm_output(osmuxh, &h_output, &list); + osmux_tx_sched(&list, tx_cb, NULL); + } + + return 0; +} + +void sighandler(int foo) +{ + LOGP(DLINP, LOGL_NOTICE, "closing OSMUX.\n"); + osmo_dgram_close(conn); + osmo_dgram_destroy(conn); + osmo_rtp_handle_free(rtp); + amr_close(); + exit(EXIT_SUCCESS); +} + +static void *tall_test; + +/* + * 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. + */ +int main(int argc, char *argv[]) +{ + amr_open(); + + signal(SIGINT, sighandler); + + tall_test = talloc_named_const(NULL, 1, "osmux_test"); + + osmo_init_logging(&osmux_test_log_info); + log_set_log_level(osmo_stderr_target, LOGL_DEBUG); + + /* + * initialize RTP handler. + */ + rtp = osmo_rtp_handle_create(tall_test); + if (rtp == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "Error init OSMUX handler\n"); + exit(EXIT_FAILURE); + } + osmo_rtp_handle_tx_set_sequence(rtp, random()); + osmo_rtp_handle_tx_set_ssrc(rtp, random()); + osmo_rtp_handle_tx_set_timestamp(rtp, time(NULL)); + + /* + * initialize OSMUX handlers. + */ + osmux_xfrm_output_init(&h_output); + + /* + * initialize datagram server. + */ + + conn = osmo_dgram_create(tall_test); + if (conn == NULL) { + LOGP(DOSMUX_TEST, LOGL_ERROR, "cannot create UDP socket\n"); + exit(EXIT_FAILURE); + } + osmo_dgram_set_local_addr(conn, "127.0.0.1"); + osmo_dgram_set_local_port(conn, 20001); + osmo_dgram_set_remote_addr(conn, "127.0.0.1"); + osmo_dgram_set_remote_port(conn, 20002); + osmo_dgram_set_read_cb(conn, read_cb); + + if (osmo_dgram_open(conn) < 0) { + fprintf(stderr, "cannot open client\n"); + exit(EXIT_FAILURE); + } + + LOGP(DOSMUX_TEST, LOGL_NOTICE, "Entering main loop\n"); + + while(1) { + osmo_select_main(0); + } +} |