aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-08-06 01:12:21 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-08-06 01:12:21 +0800
commit260d6ed02c12ccde6d8eec5a34118b71207757b6 (patch)
treec4741888236f20e1b3752a07e72de4efcae9b6ed
parent6357a8e3110a6cdecb5ee8fdbe59d806f257c1ba (diff)
mgcp: Add a call tap feature to forward audio to another forward port
For debugging it is useful to forward (tee) UDP packets to another system and use gstreamer to inspect the rtp stream. This is untested code and might contain bugs.... and of course only tap your own calls.
-rw-r--r--openbsc/include/openbsc/mgcp_internal.h18
-rw-r--r--openbsc/src/mgcp/mgcp_network.c15
-rw-r--r--openbsc/src/mgcp/mgcp_protocol.c2
-rw-r--r--openbsc/src/mgcp/mgcp_vty.c45
4 files changed, 80 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index bdcd03030..19e8e3f2b 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -69,6 +69,21 @@ struct mgcp_rtp_end {
int local_alloc;
};
+enum {
+ MGCP_TAP_BTS_IN,
+ MGCP_TAP_BTS_OUT,
+ MGCP_TAP_NET_IN,
+ MGCP_TAP_NET_OUT,
+
+ /* last element */
+ MGCP_TAP_COUNT
+};
+
+struct mgcp_rtp_tap {
+ int enabled;
+ struct sockaddr_in forward;
+};
+
struct mgcp_endpoint {
int ci;
char *callid;
@@ -89,6 +104,9 @@ struct mgcp_endpoint {
/* SSRC/seq/ts patching for loop */
int allow_patch;
+
+ /* tap for the endpoint */
+ struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
};
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c
index 387711298..bbc46f418 100644
--- a/openbsc/src/mgcp/mgcp_network.c
+++ b/openbsc/src/mgcp/mgcp_network.c
@@ -151,6 +151,14 @@ static void patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *s
* The below code is for dispatching. We have a dedicated port for
* the data coming from the net and one to discover the BTS.
*/
+static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int len)
+{
+ if (!tap->enabled)
+ return 0;
+
+ return sendto(fd, buf, len, 0,
+ (struct sockaddr *)&tap->forward, sizeof(tap->forward));
+}
static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
struct sockaddr_in *addr, char *buf, int rc)
{
@@ -168,6 +176,8 @@ static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
patch_and_count(endp, &endp->bts_state,
endp->net_end.payload_type,
addr, buf, rc);
+ forward_data(endp->net_end.rtp.fd,
+ &endp->taps[MGCP_TAP_NET_OUT], buf, rc);
return udp_send(endp->net_end.rtp.fd, &endp->net_end.addr,
endp->net_end.rtp_port, buf, rc);
} else {
@@ -179,6 +189,8 @@ static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
patch_and_count(endp, &endp->net_state,
endp->bts_end.payload_type,
addr, buf, rc);
+ forward_data(endp->bts_end.rtp.fd,
+ &endp->taps[MGCP_TAP_BTS_OUT], buf, rc);
return udp_send(endp->bts_end.rtp.fd, &endp->bts_end.addr,
endp->bts_end.rtp_port, buf, rc);
} else {
@@ -248,6 +260,8 @@ static int rtp_data_net(struct bsc_fd *fd, unsigned int what)
proto = fd == &endp->net_end.rtp ? PROTO_RTP : PROTO_RTCP;
endp->net_end.packets += 1;
+
+ forward_data(fd->fd, &endp->taps[MGCP_TAP_NET_IN], buf, rc);
return send_to(endp, DEST_BTS, proto == PROTO_RTP, &addr, &buf[0], rc);
}
@@ -310,6 +324,7 @@ static int rtp_data_bts(struct bsc_fd *fd, unsigned int what)
/* do this before the loop handling */
endp->bts_end.packets += 1;
+ forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc);
return send_to(endp, DEST_NETWORK, proto == PROTO_RTP, &addr, &buf[0], rc);
}
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c
index 036ddf02a..9916b4086 100644
--- a/openbsc/src/mgcp/mgcp_protocol.c
+++ b/openbsc/src/mgcp/mgcp_protocol.c
@@ -826,4 +826,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
endp->allow_patch = 0;
+
+ memset(&endp->taps, 0, sizeof(endp->taps));
}
diff --git a/openbsc/src/mgcp/mgcp_vty.c b/openbsc/src/mgcp/mgcp_vty.c
index 040e8ff2a..0faa674d4 100644
--- a/openbsc/src/mgcp/mgcp_vty.c
+++ b/openbsc/src/mgcp/mgcp_vty.c
@@ -310,10 +310,55 @@ DEFUN(loop_endp,
return CMD_SUCCESS;
}
+DEFUN(tap_call,
+ tap_call_cmd,
+ "tap-call ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
+ "Forward data on endpoint to a different system\n"
+ "The endpoint in hex\n"
+ "Forward the data coming from the bts\n"
+ "Forward the data coming from the bts leaving to the network\n"
+ "Forward the data coming from the net\n"
+ "Forward the data coming from the net leaving to the bts\n"
+ "destination IP of the data\n" "destination port\n")
+{
+ struct mgcp_rtp_tap *tap;
+ struct mgcp_endpoint *endp;
+ int port = 0;
+
+ int endp_no = strtoul(argv[0], NULL, 16);
+ if (endp_no < 1 || endp_no >= g_cfg->number_endpoints) {
+ vty_out(vty, "Endpoint number %s/%d is invalid.%s",
+ argv[0], endp_no, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ endp = &g_cfg->endpoints[endp_no];
+
+ if (strcmp(argv[1], "bts-in") == 0) {
+ port = MGCP_TAP_BTS_IN;
+ } else if (strcmp(argv[1], "bts-out") == 0) {
+ port = MGCP_TAP_BTS_OUT;
+ } else if (strcmp(argv[1], "net-in") == 0) {
+ port = MGCP_TAP_NET_IN;
+ } else if (strcmp(argv[1], "net-out") == 0) {
+ port = MGCP_TAP_NET_OUT;
+ } else {
+ vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ tap = &endp->taps[port];
+ memset(&tap->forward, 0, sizeof(tap->forward));
+ inet_aton(argv[2], &tap->forward.sin_addr);
+ tap->forward.sin_port = htons(atoi(argv[3]));
+ return CMD_SUCCESS;
+}
+
int mgcp_vty_init(void)
{
install_element_ve(&show_mgcp_cmd);
install_element(ENABLE_NODE, &loop_endp_cmd);
+ install_element(ENABLE_NODE, &tap_call_cmd);
install_element(CONFIG_NODE, &cfg_mgcp_cmd);
install_node(&mgcp_node, config_write_mgcp);