split off osmo-mgw: remove files, apply build, rename

Add vty and logging previously used from libcommon

Rename libmgcp to libosmo-legacy-mgcp and install.

Use DLMGCP, not DMGCP.

Slim down the public mgcpgw_client API, move all elements not actually used by
current callers to private headers / static c.

Depends: libosmocore I09c587e2d59472cbde852d467d457254746d9e67
Change-Id: I71a0a16ebaaef881c34235849601fc40aa12cfd7
diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am
new file mode 100644
index 0000000..6514436
--- /dev/null
+++ b/include/osmocom/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+	legacy_mgcp \
+	$(NULL)
diff --git a/include/osmocom/legacy_mgcp/Makefile.am b/include/osmocom/legacy_mgcp/Makefile.am
new file mode 100644
index 0000000..52f0b5b
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/Makefile.am
@@ -0,0 +1,5 @@
+noinst_HEADERS = \
+	mgcpgw_client_internal.h \
+	mgcp_transcode.h \
+	vty.h \
+	$(NULL)
diff --git a/include/osmocom/legacy_mgcp/mgcp.h b/include/osmocom/legacy_mgcp/mgcp.h
new file mode 100644
index 0000000..c017faf
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcp.h
@@ -0,0 +1,299 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 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_H
+#define OPENBSC_MGCP_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/logging.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
+
+/**
+ * Calculate the RTP audio port for the given multiplex
+ * and the direction. This allows a semi static endpoint
+ * to port calculation removing the need for the BSC
+ * and the MediaGateway to communicate.
+ *
+ * Port usage explained:
+ *       base + (multiplex * 2) + 0 == local port to wait for network packets
+ *       base + (multiplex * 2) + 1 == local port for rtcp
+ *
+ * The above port will receive packets from the BTS that need
+ * to be patched and forwarded to the network.
+ * The above port will receive packets from the network that
+ * need to be patched and forwarded to the BTS.
+ *
+ * We assume to have a static BTS IP address so we can differentiate
+ * network and BTS.
+ *
+ */
+static inline int rtp_calculate_port(int multiplex, int base)
+{
+	return base + (multiplex * 2);
+}
+
+
+/*
+ * Handling of MGCP Endpoints and the MGCP Config
+ */
+struct mgcp_endpoint;
+struct mgcp_config;
+struct mgcp_trunk_config;
+struct mgcp_rtp_end;
+
+#define MGCP_ENDP_CRCX 1
+#define MGCP_ENDP_DLCX 2
+#define MGCP_ENDP_MDCX 3
+
+/*
+ * what to do with the msg?
+ *	- continue as usual?
+ *	- reject and send a failure code?
+ *	- defer? do not send anything
+ */
+#define MGCP_POLICY_CONT	4
+#define MGCP_POLICY_REJECT	5
+#define MGCP_POLICY_DEFER	6
+
+typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
+typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
+typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
+typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
+
+/**
+ * Return:
+ *   <  0 in case no audio was processed
+ *   >= 0 in case audio was processed. The remaining payload
+ *   length will be returned.
+ */
+typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
+			       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);
+
+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
+
+/**
+ * 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;
+	int last_port;
+};
+
+#define MGCP_KEEPALIVE_ONCE (-1)
+
+struct mgcp_trunk_config {
+	struct llist_head entry;
+
+	struct mgcp_config *cfg;
+
+	int trunk_nr;
+	int trunk_type;
+
+	char *audio_fmtp_extra;
+	char *audio_name;
+	int audio_payload;
+	int audio_send_ptime;
+	int audio_send_name;
+	int audio_loop;
+
+	int no_audio_transcoding;
+
+	int omit_rtcp;
+	int keepalive_interval;
+
+	/* RTP patching */
+	int force_constant_ssrc; /* 0: don't, 1: once */
+	int force_aligned_timing;
+
+	/* spec handling */
+	int force_realloc;
+
+	/* timer */
+	struct osmo_timer_list keepalive_timer;
+
+	unsigned int number_endpoints;
+	struct mgcp_endpoint *endpoints;
+};
+
+enum mgcp_role {
+	MGCP_BSC = 0,
+	MGCP_BSC_NAT,
+};
+
+enum mgcp_connection_mode {
+	MGCP_CONN_NONE = 0,
+	MGCP_CONN_RECV_ONLY = 1,
+	MGCP_CONN_SEND_ONLY = 2,
+	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
+	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
+};
+
+extern const struct value_string mgcp_connection_mode_strs[];
+
+static inline const char *mgcp_cmode_name(enum mgcp_connection_mode mode)
+{
+	return get_value_string(mgcp_connection_mode_strs, mode);
+}
+
+struct mgcp_config {
+	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;
+
+	mgcp_get_format get_net_downlink_format_cb;
+
+	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;
+
+	mgcp_change change_cb;
+	mgcp_policy policy_cb;
+	mgcp_reset reset_cb;
+	mgcp_realloc realloc_cb;
+	mgcp_rqnt rqnt_cb;
+	void *data;
+
+	uint32_t last_call_id;
+
+	/* trunk handling */
+	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 */
+	int osmux;
+	/* addr to bind the server to */
+	char *osmux_addr;
+	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
+	 * the osmux socket is already initialized.
+	 */
+	int osmux_init;
+	/* osmux batch factor: from 1 to 4 maximum */
+	int osmux_batch;
+	/* osmux batch size (in bytes) */
+	int osmux_batch_size;
+	/* osmux port */
+	uint16_t osmux_port;
+	/* Pad circuit with dummy messages until we see the first voice
+	 * message.
+	 */
+	uint16_t osmux_dummy;
+};
+
+/* config management */
+struct mgcp_config *mgcp_config_alloc(void);
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
+		      enum mgcp_role role);
+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);
+
+/*
+ * format helper functions
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
+
+/* adc helper */
+static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
+{
+	if (timeslot == 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
+		timeslot = 255;
+	}
+
+	return timeslot + (32 * multiplex);
+}
+
+static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
+{
+	*multiplex = endpoint / 32;
+	*timeslot = endpoint % 32;
+}
+
+int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
+int mgcp_send_reset_all(struct mgcp_config *cfg);
+
+
+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/legacy_mgcp/mgcp_internal.h b/include/osmocom/legacy_mgcp/mgcp_internal.h
new file mode 100644
index 0000000..dcc75f1
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcp_internal.h
@@ -0,0 +1,337 @@
+/* MGCP Private Data */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 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/>.
+ *
+ */
+
+#pragma once
+
+#include <string.h>
+
+#include <osmocom/core/select.h>
+
+#define CI_UNUSED 0
+
+enum mgcp_trunk_type {
+	MGCP_TRUNK_VIRTUAL,
+	MGCP_TRUNK_E1,
+};
+
+struct mgcp_rtp_stream_state {
+	uint32_t ssrc;
+	uint16_t last_seq;
+	uint32_t last_timestamp;
+	uint32_t err_ts_counter;
+	int32_t last_tsdelta;
+	uint32_t last_arrival_time;
+};
+
+struct mgcp_rtp_state {
+	int initialized;
+	int patch_ssrc;
+
+	uint32_t orig_ssrc;
+
+	int seq_offset;
+
+	int32_t  timestamp_offset;
+	uint32_t packet_duration;
+
+	struct mgcp_rtp_stream_state in_stream;
+	struct mgcp_rtp_stream_state out_stream;
+
+	/* jitter and packet loss calculation */
+	int stats_initialized;
+	uint16_t stats_base_seq;
+	uint16_t stats_max_seq;
+	uint32_t stats_ssrc;
+	uint32_t stats_jitter;
+	int32_t stats_transit;
+	int stats_cycles;
+	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
+};
+
+struct mgcp_rtp_codec {
+	uint32_t rate;
+	int channels;
+	uint32_t frame_duration_num;
+	uint32_t frame_duration_den;
+
+	int payload_type;
+	char *audio_name;
+	char *subtype_name;
+};
+
+struct mgcp_rtp_end {
+	/* statistics */
+	unsigned int packets;
+	unsigned int octets;
+	unsigned int dropped_packets;
+	struct in_addr addr;
+
+	/* in network byte order */
+	int rtp_port, rtcp_port;
+
+	/* audio codec information */
+	struct mgcp_rtp_codec codec;
+	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
+
+	/* per endpoint data */
+	int  frames_per_packet;
+	uint32_t packet_duration_ms;
+	char *fmtp_extra;
+	int output_enabled;
+	int force_output_ptime;
+
+	/* 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...
+	 */
+	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 {
+	int enabled;
+	struct sockaddr_in forward;
+};
+
+struct mgcp_lco {
+	char *string;
+	char *codec;
+	int pkt_period_min; /* time in ms */
+	int pkt_period_max; /* time in ms */
+};
+
+enum mgcp_type {
+	MGCP_RTP_DEFAULT	= 0,
+	MGCP_RTP_TRANSCODED,
+	MGCP_OSMUX_BSC,
+	MGCP_OSMUX_BSC_NAT,
+};
+
+#include <osmocom/legacy_mgcp/osmux.h>
+
+struct mgcp_endpoint {
+	int allocated;
+	uint32_t ci;
+	char *callid;
+	struct mgcp_lco local_options;
+	int conn_mode;
+	int orig_mode;
+
+	/* backpointer */
+	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
+
+	/* port status for bts/net */
+	struct mgcp_rtp_end bts_end;
+	struct mgcp_rtp_end net_end;
+
+	/*
+	 * 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;
+
+	/* sequence bits */
+	struct mgcp_rtp_state net_state;
+	struct mgcp_rtp_state bts_state;
+
+	/* fields for re-transmission */
+	char *last_trans;
+	char *last_response;
+
+	/* tap for the endpoint */
+	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+
+	struct {
+		/* Osmux state: disabled, activating, active */
+		enum osmux_state state;
+		/* Allocated Osmux circuit ID for this endpoint */
+		int allocated_cid;
+		/* Used Osmux circuit ID for this endpoint */
+		uint8_t cid;
+		/* handle to batch messages */
+		struct osmux_in_handle *in;
+		/* handle to unbatch messages */
+		struct osmux_out_handle out;
+		/* statistics */
+		struct {
+			uint32_t chunks;
+			uint32_t octets;
+		} stats;
+	} osmux;
+};
+
+#define for_each_line(line, save)			\
+	for (line = strline_r(NULL, &save); line;\
+	     line = strline_r(NULL, &save))
+
+static inline char *strline_r(char *str, char **saveptr)
+{
+	char *result;
+
+	if (str)
+		*saveptr = str;
+
+	result = *saveptr;
+
+	if (*saveptr != NULL) {
+		*saveptr = strpbrk(*saveptr, "\r\n");
+
+		if (*saveptr != NULL) {
+			char *eos = *saveptr;
+
+			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
+				(*saveptr)++;
+			(*saveptr)++;
+			if ((*saveptr)[0] == '\0')
+				*saveptr = NULL;
+
+			*eos = '\0';
+		}
+	}
+
+	return result;
+}
+
+
+
+#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
+
+/**
+ * Internal structure while parsing a request
+ */
+struct mgcp_parse_data {
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+	char *trans;
+	char *save;
+	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);
+
+/* For transcoding we need to manage an in and an output that are connected */
+static inline int endp_back_channel(int endpoint)
+{
+	return endpoint + 60;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
+struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+			 struct mgcp_rtp_end *rtp);
+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);
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_end *dst_end,
+				      struct mgcp_rtp_end *src_end);
+
+void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
+					  int *payload_type,
+					  const char**subtype_name,
+					  const char**fmtp_extra);
+
+/* internal RTP Annex A counting */
+void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+			const uint16_t seq, const int32_t transit,
+			const uint32_t ssrc);
+
+int mgcp_set_ip_tos(int fd, int tos);
+
+enum {
+	MGCP_DEST_NET = 0,
+	MGCP_DEST_BTS,
+};
+
+
+#define MGCP_DUMMY_LOAD 0x23
+
+
+/**
+ * SDP related information
+ */
+/* Assume audio frame length of 20ms */
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
+#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
+#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
+
+#define PTYPE_UNDEFINED (-1)
+int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
+int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
+			int payload_type, const char *audio_name);
+
+
+/**
+ * Internal network related
+ */
+static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
+{
+	if (endp->cfg->net_ports.bind_addr)
+		return endp->cfg->net_ports.bind_addr;
+	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/legacy_mgcp/mgcp_transcode.h b/include/osmocom/legacy_mgcp/mgcp_transcode.h
new file mode 100644
index 0000000..147e48b
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcp_transcode.h
@@ -0,0 +1,90 @@
+/*
+ * (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/legacy_mgcp/mgcpgw_client.h b/include/osmocom/legacy_mgcp/mgcpgw_client.h
new file mode 100644
index 0000000..09db816
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcpgw_client.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <stdint.h>
+
+#define MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
+#define MGCPGW_CLIENT_LOCAL_PORT_DEFAULT 0
+#define MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
+#define MGCPGW_CLIENT_REMOTE_PORT_DEFAULT 2427
+
+struct msgb;
+struct vty;
+struct mgcpgw_client;
+
+struct mgcpgw_client_conf {
+	const char *local_addr;
+	int local_port;
+	const char *remote_addr;
+	int remote_port;
+	uint16_t first_endpoint;
+	uint16_t last_endpoint;
+	uint16_t bts_base;
+};
+
+typedef unsigned int mgcp_trans_id_t;
+
+struct mgcp_response_head {
+       int response_code;
+       mgcp_trans_id_t trans_id;
+       const char *comment;
+};
+
+struct mgcp_response {
+	char *body;
+	struct mgcp_response_head head;
+	uint16_t audio_port;
+};
+
+void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf);
+void mgcpgw_client_vty_init(void *talloc_ctx, int node, struct mgcpgw_client_conf *conf);
+int mgcpgw_client_config_write(struct vty *vty, const char *indent);
+struct mgcpgw_client_conf *mgcpgw_client_conf_actual(struct mgcpgw_client *mgcp);
+
+struct mgcpgw_client *mgcpgw_client_init(void *ctx,
+					 struct mgcpgw_client_conf *conf);
+int mgcpgw_client_connect(struct mgcpgw_client *mgcp);
+
+const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp);
+uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp);
+uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp);
+
+int mgcpgw_client_next_endpoint(struct mgcpgw_client *client);
+void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client);
+
+/* Invoked when an MGCP response is received or sending failed.  When the
+ * response is passed as NULL, this indicates failure during transmission. */
+typedef void (* mgcp_response_cb_t )(struct mgcp_response *response, void *priv);
+int mgcp_response_parse_params(struct mgcp_response *r);
+
+int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
+		     mgcp_response_cb_t response_cb, void *priv);
+
+enum mgcp_connection_mode;
+
+struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, unsigned int call_id,
+			   enum mgcp_connection_mode mode);
+
+struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
+			   uint16_t rtp_port, enum mgcp_connection_mode mode);
+
+struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint,
+			   unsigned int call_id);
diff --git a/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h b/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h
new file mode 100644
index 0000000..d3a7849
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#define MSGB_CB_MGCP_TRANS_ID 0
+
+struct mgcpgw_client {
+	struct mgcpgw_client_conf actual;
+	uint32_t remote_addr;
+	struct osmo_wqueue wq;
+	mgcp_trans_id_t next_trans_id;
+	struct llist_head responses_pending;
+	struct llist_head inuse_endpoints;
+};
+
+struct mgcp_inuse_endpoint {
+	struct llist_head entry;
+	uint16_t id;
+};
+
+struct mgcp_response_pending {
+	struct llist_head entry;
+
+	mgcp_trans_id_t trans_id;
+	mgcp_response_cb_t response_cb;
+	void *priv;
+};
+
+int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg);
+
+struct mgcp_response_pending * mgcpgw_client_pending_add(
+					struct mgcpgw_client *mgcp,
+					mgcp_trans_id_t trans_id,
+					mgcp_response_cb_t response_cb,
+					void *priv);
diff --git a/include/osmocom/legacy_mgcp/osmux.h b/include/osmocom/legacy_mgcp/osmux.h
new file mode 100644
index 0000000..f3ea72a
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/osmux.h
@@ -0,0 +1,41 @@
+#ifndef _OPENBSC_OSMUX_H_
+#define _OPENBSC_OSMUX_H_
+
+#include <osmocom/netif/osmux.h>
+
+#define OSMUX_PORT	1984
+
+enum {
+	OSMUX_ROLE_BSC = 0,
+	OSMUX_ROLE_BSC_NAT,
+};
+
+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_get_cid(void);
+void osmux_put_cid(uint8_t osmux_cid);
+int osmux_used_cid(void);
+
+enum osmux_state {
+	OSMUX_STATE_DISABLED = 0,
+	OSMUX_STATE_NEGOTIATING,
+	OSMUX_STATE_ACTIVATING,
+	OSMUX_STATE_ENABLED,
+};
+
+enum osmux_usage {
+	OSMUX_USAGE_OFF = 0,
+	OSMUX_USAGE_ON = 1,
+	OSMUX_USAGE_ONLY = 2,
+};
+
+#endif
diff --git a/include/osmocom/legacy_mgcp/vty.h b/include/osmocom/legacy_mgcp/vty.h
new file mode 100644
index 0000000..c277c0a
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/vty.h
@@ -0,0 +1,31 @@
+#ifndef OPENBSC_VTY_H
+#define OPENBSC_VTY_H
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
+struct gsm_network;
+struct vty;
+
+void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
+
+struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
+
+extern struct cmd_element cfg_description_cmd;
+extern struct cmd_element cfg_no_description_cmd;
+
+enum mgcp_vty_node {
+	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
+	TRUNK_NODE,
+};
+
+struct log_info;
+int bsc_vty_init(struct gsm_network *network);
+int bsc_vty_init_extra(void);
+
+void msc_vty_init(struct gsm_network *msc_network);
+
+struct gsm_network *gsmnet_from_vty(struct vty *vty);
+
+#endif