mgcp: Add callbacks for payload processing

This patch adds the callbacks rtp_processing_cb and
setup_rtp_processing_cb to mgcp_config to support arbitrary RTP
payload processing.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 939e7ee..34eb429 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -65,6 +65,7 @@
 struct mgcp_endpoint;
 struct mgcp_config;
 struct mgcp_trunk_config;
+struct mgcp_rtp_end;
 
 #define MGCP_ENDP_CRCX 1
 #define MGCP_ENDP_DLCX 2
@@ -86,6 +87,11 @@
 typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
 typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
 
+typedef int (*mgcp_processing)(struct mgcp_rtp_end *dst_end,
+			       char *data, int *len, int buf_size);
+typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
+				     struct mgcp_rtp_end *dst_end,
+				     struct mgcp_rtp_end *src_end);
 #define PORT_ALLOC_STATIC	0
 #define PORT_ALLOC_DYNAMIC	1
 
@@ -156,6 +162,10 @@
 	struct in_addr transcoder_in;
 	int transcoder_remote_base;
 
+	/* RTP processing */
+	mgcp_processing rtp_processing_cb;
+	mgcp_processing_setup setup_rtp_processing_cb;
+
 	struct osmo_wqueue gw_fd;
 
 	struct mgcp_port_range bts_ports;
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index 52bf558..d281813 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -90,6 +90,7 @@
 	/* RTP patching */
 	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
 	int force_aligned_timing;
+	void *rtp_process_data;
 
 	/*
 	 * Each end has a socket...
@@ -205,6 +206,14 @@
 			uint32_t *expected, int *loss);
 uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
 
+/* payload processing default functions */
+int mgcp_rtp_processing_default(struct mgcp_rtp_end *dst_end,
+				char *data, int *len, int buf_size);
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_end *dst_end,
+				      struct mgcp_rtp_end *src_end);
+
 enum {
 	MGCP_DEST_NET = 0,
 	MGCP_DEST_BTS,
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index 5e8284d..393a9e5 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -79,6 +79,7 @@
 #define RTP_SEQ_MOD		(1 << 16)
 #define RTP_MAX_DROPOUT		3000
 #define RTP_MAX_MISORDER	100
+#define RTP_BUF_SIZE		4096
 
 enum {
 	MGCP_PROTO_RTP,
@@ -339,6 +340,18 @@
 	return timestamp_error;
 }
 
+int mgcp_rtp_processing_default(struct mgcp_rtp_end *dst_end,
+				char *data, int *len, int buf_size)
+{
+	return 0;
+}
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_end *dst_end,
+				      struct mgcp_rtp_end *src_end)
+{
+	return 0;
+}
 
 /**
  * The RFC 3550 Appendix A assumes there are multiple sources but
@@ -589,6 +602,7 @@
 		rtp_end->dropped_packets += 1;
 	else if (is_rtp) {
 		mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, buf, rc);
+		endp->cfg->rtp_processing_cb(rtp_end, buf, &rc, RTP_BUF_SIZE);
 		forward_data(rtp_end->rtp.fd, &endp->taps[tap_idx], buf, rc);
 		return mgcp_udp_send(rtp_end->rtp.fd,
 				     &rtp_end->addr,
@@ -627,7 +641,7 @@
 
 static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
 {
-	char buf[4096];
+	char buf[RTP_BUF_SIZE];
 	struct sockaddr_in addr;
 	struct mgcp_endpoint *endp;
 	int rc, proto;
@@ -723,7 +737,7 @@
 
 static int rtp_data_bts(struct osmo_fd *fd, unsigned int what)
 {
-	char buf[4096];
+	char buf[RTP_BUF_SIZE];
 	struct sockaddr_in addr;
 	struct mgcp_endpoint *endp;
 	int rc, proto;
@@ -790,7 +804,7 @@
 static int rtp_data_transcoder(struct mgcp_rtp_end *end, struct mgcp_endpoint *_endp,
 			      int dest, struct osmo_fd *fd)
 {
-	char buf[4096];
+	char buf[RTP_BUF_SIZE];
 	struct sockaddr_in addr;
 	struct mgcp_config *cfg;
 	int rc, proto;
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 1a88a84..964971b 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -107,6 +107,8 @@
 static void create_transcoder(struct mgcp_endpoint *endp);
 static void delete_transcoder(struct mgcp_endpoint *endp);
 
+static void setup_rtp_processing(struct mgcp_endpoint *endp);
+
 static int mgcp_analyze_header(struct mgcp_parse_data *parse, char *data);
 
 static int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line)
@@ -852,8 +854,10 @@
 	endp->bts_end.payload_type = tcfg->audio_payload;
 	endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
 						tcfg->audio_fmtp_extra);
-	if (have_sdp)
+	if (have_sdp) {
 		parse_sdp_data(&endp->net_end, p);
+		setup_rtp_processing(endp);
+	}
 
 	/* policy CB */
 	if (p->cfg->policy_cb) {
@@ -980,6 +984,8 @@
 	set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
 			     local_options);
 
+	setup_rtp_processing(endp);
+
 	/* policy CB */
 	if (p->cfg->policy_cb) {
 		int rc;
@@ -1223,6 +1229,9 @@
 	cfg->bts_ports.base_port = RTP_PORT_DEFAULT;
 	cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT;
 
+	cfg->rtp_processing_cb = &mgcp_rtp_processing_default;
+	cfg->setup_rtp_processing_cb = &mgcp_setup_rtp_processing_default;
+
 	/* default trunk handling */
 	cfg->trunk.cfg = cfg;
 	cfg->trunk.trunk_nr = 0;
@@ -1288,6 +1297,8 @@
 	end->local_alloc = -1;
 	talloc_free(end->fmtp_extra);
 	end->fmtp_extra = NULL;
+	talloc_free(end->rtp_process_data);
+	end->rtp_process_data = NULL;
 
 	/* Set default values */
 	end->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
@@ -1442,6 +1453,27 @@
 	return send_agent(endp->cfg, buf, len);
 }
 
+static void setup_rtp_processing(struct mgcp_endpoint *endp)
+{
+	struct mgcp_config *cfg = endp->cfg;
+
+	if (endp->type != MGCP_RTP_DEFAULT)
+		return;
+
+	if (endp->conn_mode == MGCP_CONN_LOOPBACK)
+		return;
+
+	if (endp->conn_mode & MGCP_CONN_SEND_ONLY)
+		cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
+	else
+		cfg->setup_rtp_processing_cb(endp, &endp->net_end, NULL);
+
+	if (endp->conn_mode & MGCP_CONN_RECV_ONLY)
+		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
+	else
+		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, NULL);
+}
+
 static void create_transcoder(struct mgcp_endpoint *endp)
 {
 	int port;