Initially implement the new osmo-mgw and libosmo-mgcp

Leave the old osmo-bsc_mgcp and libosmo-legacy-mgcp as it is; on a copy thereof
(added by a previous commit), apply changes to initially implement the new
osmo-mgw.

Adjust build system and debian packaging to accomodate the new libosmo-mgcp and
osmo-mgw.

The main differences:

*) use a list to manage rtp connections.

Aggregate all rtp related information inside a single struct.

Use a linked list to manage the both connections (net and bts).
The idea behind using a list is that we might support conference
calls at some later point.

Store the linked list in struct mgcp_endpoint, have a private linked
list for each endpoint. The list contains connection items which are
implemented in struct mgcp_conn. A connection is allocated and freed
using the functions in mgcp_conn.c. A connection is allocated on the
reception of a CRCX command and freed with the reception of a DLCX
command.

*) remove external transcoder feature

Fortunatelly the external transcoder feature is not needed
anymore. This patch removes the related code.

*) vty: get rid of CONN_BTS and CONN_NET

Since the new connection model does not make a difference
between BTS and NET connections the VTY should not use
the fixed CONN_BTS and CONN_NET constants.

- Handle the conns list inside the endpoint directly
- introduce function to dump basic rtp connection info
- introduce human readable names for connections

Parts of the code adjusted to use generalized connections instead of explicit
BTS/NET ones:

- teach mgcp_send_dummy() to send dummy packets to any RTP connection
- network: generalize mgcp_bind_net/bts_rtp_port()
- network: generalize mgcp_send()
- tap: generalize call tapping feature
- stat: generalize statistics
- Replace rtp_data_net() and rtp_data_bts() with generalized rtp_data_rx()

*) mgcp_protocol.c fixes:

- check ci string before it is converted:
  In case of missing ci, a nullpointer is delivered to strtoul().
  Add a function that takes ci, checks it and converts it to an
  uint32_t. Use the return code to react on missing ci.
- output error message on missing CI.
- when parsing the mode, print log message when mode is missing.
- use mode_orig when mode is missing.
- fix ptime formatstring to use %u rather than %d.
- cosmetic: log when connection is deleted on DLCX.
- change loglevels of CRCX, MDCX, DLCX events from DEBUG to NOTICE.

*) mgcp_test

- apply rename of strline_r() to mgcp_strline().
- MGCP command macros:
  - Add 'I: 1' parameters.
  - Use proper port numbers:
    from m=audio 0 RTP/AVP 126
    to   m=audio 16002 RTP/AVP 128
  - Change ptime to 'a=ptime:40' because this is what the MGW currently
    returns.  CRCX generally feed a ptime:40 and this is expected to be
    returned.
- struct mgcp_test: Use only one ptype, there are no explicit BTS and NET
  endpoints anymore.
  Hence remove one column from tests[].
- test_messages():
  - Enable: remove '#if 0'
  - Remove concept of BTS and NET endpoints: test only one conn, as they are
    now interchangeable anyway.
  - remove endpoint init, now done internally.
  - add false asserts in error cases.
- test_retransmission():
  - remove endpoint init, now done internally.
  - add false asserts in error cases.
- test_packet_error_detection():
  - Remove concept of BTS and NET endpoints: test only one conn, as they are
    now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
  - remove endpoint init, now done internally.
  - add false assert in error case.
  - Assert that a conn really vanishes on DLCX, previously the conn would
    remain and just be unused, now it is actually discarded.
- test_no_cycle()
  - Remove concept of BTS and NET endpoints: test only one conn, as they are
    now interchangeable anyway. Use arbitrary conn ids (e.g. 4711).
- test_no_name()
  - Enable: remove '#if 0'.
  - remove endpoint init, now done internally.
  - add false assert in error case.
- mgcp_test.ok: adjust expected results to status quo:
  - We now see two dummy packets instead of one, now sent to both sides because
    we don't know of BTS or NET side. (maybe drop dummy packets later...)
  - packet duration, conn mode: now sane defaults show instead of unset.
- various whitespace and formatting changes from lindent.

Change-Id: Ie008599136c7ed8a0dfbb0cf803188975a499fc5
diff --git a/include/Makefile.am b/include/Makefile.am
index 0027386..3cc4b1d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -8,4 +8,7 @@
 	osmocom/legacy_mgcp/osmux.h \
 	osmocom/mgcp_client/mgcp_client.h \
 	osmocom/mgcp_client/mgcp_common.h \
+	osmocom/mgcp/mgcp.h \
+	osmocom/mgcp/mgcp_internal.h \
+	osmocom/mgcp/osmux.h \
 	$(NULL)
diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am
index be9f1ca..c752c40 100644
--- a/include/osmocom/Makefile.am
+++ b/include/osmocom/Makefile.am
@@ -1,4 +1,5 @@
 SUBDIRS = \
 	legacy_mgcp \
 	mgcp_client \
+	mgcp \
 	$(NULL)
diff --git a/include/osmocom/mgcp/Makefile.am b/include/osmocom/mgcp/Makefile.am
index 4a9550c..646b887 100644
--- a/include/osmocom/mgcp/Makefile.am
+++ b/include/osmocom/mgcp/Makefile.am
@@ -1,4 +1,7 @@
 noinst_HEADERS = \
-	mgcp_transcode.h \
 	vty.h \
+	mgcp_msg.h \
+	mgcp_conn.h \
+	mgcp_stat.h \
+	mgcp_ep.h \
 	$(NULL)
diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h
index c017faf..67c499b 100644
--- a/include/osmocom/mgcp/mgcp.h
+++ b/include/osmocom/mgcp/mgcp.h
@@ -20,21 +20,21 @@
  *
  */
 
-#ifndef OPENBSC_MGCP_H
-#define OPENBSC_MGCP_H
+#pragma once
 
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/write_queue.h>
 #include <osmocom/core/timer.h>
 #include <osmocom/core/logging.h>
+#include <osmocom/mgcp/mgcp_ep.h>
 
 #include <arpa/inet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 
-#define RTP_PORT_DEFAULT 4000
-#define RTP_PORT_NET_DEFAULT 16000
+#define RTP_PORT_DEFAULT_RANGE_START 16002
+#define RTP_PORT_DEFAULT_RANGE_END RTP_PORT_DEFAULT_RANGE_START + 64
 
 /**
  * Calculate the RTP audio port for the given multiplex
@@ -102,26 +102,20 @@
 				     struct mgcp_rtp_end *dst_end,
 				     struct mgcp_rtp_end *src_end);
 
+struct mgcp_conn_rtp;
 typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
 				int *payload_type,
 				const char**subtype_name,
-				const char**fmtp_extra);
-
-#define PORT_ALLOC_STATIC	0
-#define PORT_ALLOC_DYNAMIC	1
+				const char**fmtp_extra,
+				struct mgcp_conn_rtp *conn);
 
 /**
  * This holds information on how to allocate ports
  */
 struct mgcp_port_range {
-	int mode;
-
 	/* addr or NULL to fall-back to default */
 	char *bind_addr;
 
-	/* pre-allocated from a base? */
-	int base_port;
-
 	/* dynamically allocated */
 	int range_start;
 	int range_end;
@@ -160,6 +154,10 @@
 	/* timer */
 	struct osmo_timer_list keepalive_timer;
 
+	/* When set, incoming RTP packets are not filtered
+	 * when ports and ip-address do not match (debug) */
+	int rtp_accept_all;
+
 	unsigned int number_endpoints;
 	struct mgcp_endpoint *endpoints;
 };
@@ -188,16 +186,8 @@
 	int source_port;
 	char *local_ip;
 	char *source_addr;
-	char *bts_ip;
 	char *call_agent_addr;
 
-	struct in_addr bts_in;
-
-	/* transcoder handling */
-	char *transcoder_ip;
-	struct in_addr transcoder_in;
-	int transcoder_remote_base;
-
 	/* RTP processing */
 	mgcp_processing rtp_processing_cb;
 	mgcp_processing_setup setup_rtp_processing_cb;
@@ -206,12 +196,10 @@
 
 	struct osmo_wqueue gw_fd;
 
-	struct mgcp_port_range bts_ports;
 	struct mgcp_port_range net_ports;
-	struct mgcp_port_range transcoder_ports;
 	int endp_dscp;
 
-	int bts_force_ptime;
+	int force_ptime;
 
 	mgcp_change change_cb;
 	mgcp_policy policy_cb;
@@ -226,10 +214,6 @@
 	struct mgcp_trunk_config trunk;
 	struct llist_head trunks;
 
-	/* only used for start with a static configuration */
-	int last_net_port;
-	int last_bts_port;
-
 	enum mgcp_role role;
 
 	/* osmux translator: 0 means disabled, 1 means enabled */
@@ -259,11 +243,6 @@
 int mgcp_vty_init(void);
 int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 void mgcp_release_endp(struct mgcp_endpoint *endp);
-void mgcp_initialize_endp(struct mgcp_endpoint *endp);
-int mgcp_reset_transcoder(struct mgcp_config *cfg);
-void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
-int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
-
 void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
 
 /*
@@ -293,7 +272,4 @@
 
 
 int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
-int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
 int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
-
-#endif
diff --git a/include/osmocom/mgcp/mgcp_conn.h b/include/osmocom/mgcp/mgcp_conn.h
new file mode 100644
index 0000000..e0ae021
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_conn.h
@@ -0,0 +1,40 @@
+/* Message connection list handling */
+
+/*
+ * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/mgcp/mgcp_internal.h>
+#include <osmocom/core/linuxlist.h>
+#include <inttypes.h>
+
+struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
+				  uint32_t id, enum mgcp_conn_type type,
+				  char *name);
+struct mgcp_conn *mgcp_conn_get(struct mgcp_endpoint *endp, uint32_t id);
+struct mgcp_conn_rtp *mgcp_conn_get_rtp(struct mgcp_endpoint *endp,
+					uint32_t id);
+void mgcp_conn_free(struct mgcp_endpoint *endp, uint32_t id);
+void mgcp_conn_free_oldest(struct mgcp_endpoint *endp);
+void mgcp_conn_free_all(struct mgcp_endpoint *endp);
+char *mgcp_conn_dump(struct mgcp_conn *conn);
+struct mgcp_conn *mgcp_find_dst_conn(struct mgcp_conn *conn);
diff --git a/include/osmocom/mgcp/mgcp_ep.h b/include/osmocom/mgcp/mgcp_ep.h
new file mode 100644
index 0000000..e477a47
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_ep.h
@@ -0,0 +1,50 @@
+/* Endpoint types */
+
+/*
+ * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+struct sockaddr_in;
+struct mgcp_conn;
+
+/* Callback type for RTP dispatcher functions
+   (e.g mgcp_dispatch_rtp_bridge_cb, see below) */
+typedef int (*mgcp_dispatch_rtp_cb) (int proto, struct sockaddr_in * addr,
+				     char *buf, unsigned int buf_size,
+				     struct mgcp_conn * conn);
+
+/*! MGCP endpoint properties */
+struct mgcp_endpoint_type {
+	/*!< maximum number of connections */
+	int max_conns;
+
+	/*!< callback that defines how to dispatch incoming RTP data */
+	mgcp_dispatch_rtp_cb dispatch_rtp_cb;
+};
+
+/*! MGCP endpoint typeset */
+struct mgcp_endpoint_typeset {
+	struct mgcp_endpoint_type rtp;
+};
+
+/*! static MGCP endpoint typeset (pre-initalized, read-only) */
+extern const struct mgcp_endpoint_typeset ep_typeset;
diff --git a/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h
index dcc75f1..3a22d51 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -23,11 +23,16 @@
 #pragma once
 
 #include <string.h>
-
+#include <inttypes.h>
 #include <osmocom/core/select.h>
+#include <osmocom/mgcp/mgcp.h>
+#include <osmocom/core/linuxlist.h>
 
 #define CI_UNUSED 0
 
+#define CONN_ID_BTS 0
+#define CONN_ID_NET 1
+
 enum mgcp_trunk_type {
 	MGCP_TRUNK_VIRTUAL,
 	MGCP_TRUNK_E1,
@@ -80,8 +85,10 @@
 
 struct mgcp_rtp_end {
 	/* statistics */
-	unsigned int packets;
-	unsigned int octets;
+	unsigned int packets_rx;
+	unsigned int octets_rx;
+	unsigned int packets_tx;
+	unsigned int octets_tx;
 	unsigned int dropped_packets;
 	struct in_addr addr;
 
@@ -104,24 +111,11 @@
 	int force_aligned_timing;
 	void *rtp_process_data;
 
-	/*
-	 * Each end has a socket...
-	 */
+	/* Each end has a separate socket for RTP and RTCP */
 	struct osmo_fd rtp;
 	struct osmo_fd rtcp;
 
 	int local_port;
-	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 {
@@ -136,51 +130,36 @@
 	int pkt_period_max; /* time in ms */
 };
 
-enum mgcp_type {
+/* Specific rtp connection type (see struct mgcp_conn_rtp) */
+enum mgcp_conn_rtp_type {
 	MGCP_RTP_DEFAULT	= 0,
-	MGCP_RTP_TRANSCODED,
 	MGCP_OSMUX_BSC,
 	MGCP_OSMUX_BSC_NAT,
 };
 
-#include <osmocom/legacy_mgcp/osmux.h>
+#include <osmocom/mgcp/osmux.h>
+struct mgcp_conn;
 
-struct mgcp_endpoint {
-	int allocated;
-	uint32_t ci;
-	char *callid;
-	struct mgcp_lco local_options;
-	int conn_mode;
-	int orig_mode;
+/* MGCP connection (RTP) */
+struct mgcp_conn_rtp {
 
-	/* backpointer */
-	struct mgcp_config *cfg;
-	struct mgcp_trunk_config *tcfg;
+	/* Backpointer to conn struct */
+	struct mgcp_conn *conn;
 
-	/* port status for bts/net */
-	struct mgcp_rtp_end bts_end;
-	struct mgcp_rtp_end net_end;
+	/* Specific connection type */
+	enum mgcp_conn_rtp_type type;
 
-	/*
-	 * For transcoding we will send from the local_port
-	 * of trans_bts and it will arrive at trans_net from
-	 * where we will forward it to the network.
-	 */
-	struct mgcp_rtp_end trans_bts;
-	struct mgcp_rtp_end trans_net;
-	enum mgcp_type type;
+	/* Port status */
+	struct mgcp_rtp_end end;
 
-	/* sequence bits */
-	struct mgcp_rtp_state net_state;
-	struct mgcp_rtp_state bts_state;
+	/* Sequence bits */
+	struct mgcp_rtp_state state;
 
-	/* fields for re-transmission */
-	char *last_trans;
-	char *last_response;
+	/* taps for the rtp connection */
+	struct mgcp_rtp_tap tap_in;
+	struct mgcp_rtp_tap tap_out;
 
-	/* tap for the endpoint */
-	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
-
+	/* Osmux states (optional) */
 	struct {
 		/* Osmux state: disabled, activating, active */
 		enum osmux_state state;
@@ -200,38 +179,64 @@
 	} osmux;
 };
 
-#define for_each_line(line, save)			\
-	for (line = strline_r(NULL, &save); line;\
-	     line = strline_r(NULL, &save))
+/*! Connection type, specifies which member of the union "u" in mgcp_conn
+ *  contains a useful connection description (currently only RTP) */
+enum mgcp_conn_type {
+	MGCP_CONN_TYPE_RTP,
+};
 
-static inline char *strline_r(char *str, char **saveptr)
-{
-	char *result;
+/*! MGCP connection (untyped) */
+struct mgcp_conn {
+	/*!< list head */
+	struct llist_head entry;
 
-	if (str)
-		*saveptr = str;
+	/*!< Backpointer to the endpoint where the conn belongs to */
+	struct mgcp_endpoint *endp;
 
-	result = *saveptr;
+	/*!< type of the connection (union) */
+	enum mgcp_conn_type type;
 
-	if (*saveptr != NULL) {
-		*saveptr = strpbrk(*saveptr, "\r\n");
+	/*!< mode of the connection */
+	enum mgcp_connection_mode mode;
 
-		if (*saveptr != NULL) {
-			char *eos = *saveptr;
+	/*!< copy of the mode to restore the original setting (VTY) */
+	enum mgcp_connection_mode mode_orig;
 
-			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
-				(*saveptr)++;
-			(*saveptr)++;
-			if ((*saveptr)[0] == '\0')
-				*saveptr = NULL;
+	/*!< connection id to identify the conntion */
+	uint32_t id;
 
-			*eos = '\0';
-		}
-	}
+	/*!< human readable name (vty, logging) */
+	char name[256];
 
-	return result;
-}
+	/*!< union with connection description */
+	union {
+		struct mgcp_conn_rtp rtp;
+	} u;
 
+	/*!< pointer to optional private data */
+	void *priv;
+};
+
+#include <osmocom/mgcp/mgcp_conn.h>
+
+struct mgcp_endpoint_type;
+
+struct mgcp_endpoint {
+	char *callid;
+	struct mgcp_lco local_options;
+
+	struct llist_head conns;
+
+	/* backpointer */
+	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
+
+	const struct mgcp_endpoint_type *type;
+
+	/* fields for re-transmission */
+	char *last_trans;
+	char *last_response;
+};
 
 
 #define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
@@ -247,12 +252,15 @@
 	int found;
 };
 
-int mgcp_send_dummy(struct mgcp_endpoint *endp);
-int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
+int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
+	      char *buf, int rc, struct mgcp_conn_rtp *conn_src,
+	      struct mgcp_conn_rtp *conn_dst);
+int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
+int mgcp_dispatch_rtp_bridge_cb(int proto, struct sockaddr_in *addr, char *buf,
+				unsigned int buf_size, struct mgcp_conn *conn);
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
+			   struct mgcp_conn_rtp *conn);
+void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
 
 /* For transcoding we need to manage an in and an output that are connected */
 static inline int endp_back_channel(int endpoint)
@@ -268,10 +276,6 @@
 uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
 				  struct mgcp_rtp_end *rtp);
 
-void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
-			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_endpoint *endp, struct mgcp_rtp_end *dst_end,
 				char *data, int *len, int buf_size);
@@ -282,8 +286,9 @@
 
 void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
 					  int *payload_type,
-					  const char**subtype_name,
-					  const char**fmtp_extra);
+					  const char**audio_name,
+					  const char**fmtp_extra,
+					  struct mgcp_conn_rtp *conn);
 
 /* internal RTP Annex A counting */
 void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
@@ -316,10 +321,9 @@
 int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
 			int payload_type, const char *audio_name);
 
-
-/**
- * Internal network related
- */
+/*! get the ip-address where the mgw application is bound on.
+ *  \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters
+ *  \returns pointer to a string that contains the source ip-address */
 static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
 {
 	if (endp->cfg->net_ports.bind_addr)
@@ -327,11 +331,4 @@
 	return endp->cfg->source_addr;
 }
 
-static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
-{
-	if (endp->cfg->bts_ports.bind_addr)
-		return endp->cfg->bts_ports.bind_addr;
-	return endp->cfg->source_addr;
-}
-
 int mgcp_msg_terminate_nul(struct msgb *msg);
diff --git a/include/osmocom/mgcp/mgcp_msg.h b/include/osmocom/mgcp/mgcp_msg.h
new file mode 100644
index 0000000..b7d52bb
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_msg.h
@@ -0,0 +1,58 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* Message parser/generator utilities */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
+ * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+struct mgcp_conn;
+struct mgcp_parse_data;
+struct mgcp_endpoint;
+
+void mgcp_disp_msg(unsigned char *message, unsigned int len, char *preamble);
+
+int mgcp_parse_conn_mode(const char *msg, struct mgcp_endpoint *endp,
+			 struct mgcp_conn *conn);
+
+int mgcp_parse_header(struct mgcp_parse_data *pdata, char *data);
+
+int mgcp_parse_osmux_cid(const char *line);
+
+int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line);
+
+int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid);
+
+int mgcp_verify_ci(struct mgcp_endpoint *endp, const char *ci);
+
+char *mgcp_strline(char *str, char **saveptr);
+
+#define for_each_line(line, save)\
+	for (line = mgcp_strline(NULL, &save); line;\
+	     line = mgcp_strline(NULL, &save))
+
+#define for_each_non_empty_line(line, save)\
+	for (line = strtok_r(NULL, "\r\n", &save); line;\
+	     line = strtok_r(NULL, "\r\n", &save))
+
+int mgcp_parse_ci(uint32_t *conn_id, const char *ci);
diff --git a/include/osmocom/mgcp/mgcp_stat.h b/include/osmocom/mgcp/mgcp_stat.h
new file mode 100644
index 0000000..b6c73fa
--- /dev/null
+++ b/include/osmocom/mgcp/mgcp_stat.h
@@ -0,0 +1,37 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* The statistics generator */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
+ * (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/mgcp/mgcp_internal.h>
+#include <inttypes.h>
+
+void mgcp_format_stats(char *str, size_t str_len,  struct mgcp_conn *conn);
+
+/* Exposed for test purposes only, do not use actively */
+void calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
+			uint32_t *expected, int *loss);
+
+/* Exposed for test purposes only, do not use actively */
+uint32_t calc_jitter(struct mgcp_rtp_state *);
diff --git a/include/osmocom/mgcp/mgcp_transcode.h b/include/osmocom/mgcp/mgcp_transcode.h
deleted file mode 100644
index 147e48b..0000000
--- a/include/osmocom/mgcp/mgcp_transcode.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * (C) 2014 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#ifndef OPENBSC_MGCP_TRANSCODE_H
-#define OPENBSC_MGCP_TRANSCODE_H
-
-#include "bscconfig.h"
-
-#include <gsm.h>
-#ifdef HAVE_BCG729
-#include <bcg729/decoder.h>
-#include <bcg729/encoder.h>
-#endif
-
-enum audio_format {
-	AF_INVALID,
-	AF_S16,
-	AF_L16,
-	AF_GSM,
-	AF_G729,
-	AF_PCMA,
-	AF_PCMU
-};
-
-
-struct mgcp_process_rtp_state {
-	/* decoding */
-	enum audio_format src_fmt;
-	union {
-		gsm gsm_handle;
-#ifdef HAVE_BCG729
-		bcg729DecoderChannelContextStruct *g729_dec;
-#endif
-	} src;
-	size_t src_frame_size;
-	size_t src_samples_per_frame;
-
-	/* processing */
-
-	/* encoding */
-	enum audio_format dst_fmt;
-	union {
-		gsm gsm_handle;
-#ifdef HAVE_BCG729
-		bcg729EncoderChannelContextStruct *g729_enc;
-#endif
-	} dst;
-	size_t dst_frame_size;
-	size_t dst_samples_per_frame;
-	int dst_packet_duration;
-
-	int is_running;
-	uint16_t next_seq;
-	uint32_t next_time;
-	int16_t samples[10*160];
-	size_t sample_cnt;
-	size_t sample_offs;
-};
-
-
-int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
-			   struct mgcp_rtp_end *dst_end,
-			   struct mgcp_rtp_end *src_end);
-
-void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
-					  int *payload_type,
-					  const char**audio_name,
-					  const char**fmtp_extra);
-
-int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
-				 struct mgcp_rtp_end *dst_end,
-				 char *data, int *len, int buf_size);
-
-int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst);
-#endif /* OPENBSC_MGCP_TRANSCODE_H */
diff --git a/include/osmocom/mgcp/osmux.h b/include/osmocom/mgcp/osmux.h
index f3ea72a..ea849c8 100644
--- a/include/osmocom/mgcp/osmux.h
+++ b/include/osmocom/mgcp/osmux.h
@@ -1,7 +1,8 @@
-#ifndef _OPENBSC_OSMUX_H_
-#define _OPENBSC_OSMUX_H_
+#pragma once
+
 
 #include <osmocom/netif/osmux.h>
+struct mgcp_conn_rtp;
 
 #define OSMUX_PORT	1984
 
@@ -11,16 +12,13 @@
 };
 
 int osmux_init(int role, struct mgcp_config *cfg);
-int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port);
-void osmux_disable_endpoint(struct mgcp_endpoint *endp);
-void osmux_allocate_cid(struct mgcp_endpoint *endp);
-void osmux_release_cid(struct mgcp_endpoint *endp);
-
-int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc);
-int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp);
-
-int osmux_send_dummy(struct mgcp_endpoint *endp);
-
+int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
+		      struct in_addr *addr, uint16_t port);
+void osmux_disable_conn(struct mgcp_conn_rtp *conn);
+void osmux_allocate_cid(struct mgcp_conn_rtp *conn);
+void osmux_release_cid(struct mgcp_conn_rtp *conn);
+int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn);
+int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
 int osmux_get_cid(void);
 void osmux_put_cid(uint8_t osmux_cid);
 int osmux_used_cid(void);
@@ -38,4 +36,3 @@
 	OSMUX_USAGE_ONLY = 2,
 };
 
-#endif