/* * (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; }