mgcp: Merge OpenBSC MGCP code and update the structure to match it

* Upstream has a separation of BTS and NET side for RTP ports and
  can allocate them dynamically.
* Upstream has gained the concept of trunks. We will now have various
  trunks to connect audio things.

* We will now be able to utilize multiple trunks and have the endpoints
  used properly.
diff --git a/include/mgcp/mgcp.h b/include/mgcp/mgcp.h
index 71e45f3..675db0c 100644
--- a/include/mgcp/mgcp.h
+++ b/include/mgcp/mgcp.h
@@ -1,13 +1,13 @@
 /* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
- * This program is free software: you can redistribute it and/or modify
+ * 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
+ * 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,
@@ -23,11 +23,15 @@
 #ifndef OPENBSC_MGCP_H
 #define OPENBSC_MGCP_H
 
+#include "cellmgr_debug.h"
+
 #include <osmocore/msgb.h>
+#include <osmocore/write_queue.h>
 
 #include <arpa/inet.h>
 
 #define RTP_PORT_DEFAULT 4000
+#define RTP_PORT_NET_DEFAULT 16000
 
 /**
  * Calculate the RTP audio port for the given multiplex
@@ -59,6 +63,7 @@
  */
 struct mgcp_endpoint;
 struct mgcp_config;
+struct mgcp_trunk_config;
 
 #define MGCP_ENDP_CRCX 1
 #define MGCP_ENDP_DLCX 2
@@ -74,51 +79,113 @@
 #define MGCP_POLICY_REJECT	5
 #define MGCP_POLICY_DEFER	6
 
-typedef int (*mgcp_realloc)(struct mgcp_config *cfg, int endpoint);
-typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state, int local_rtp);
-typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
+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_config *cfg);
 
+#define PORT_ALLOC_STATIC	0
+#define PORT_ALLOC_DYNAMIC	1
+
+/**
+ * This holds information on how to allocate ports
+ */
+struct mgcp_port_range {
+	int mode;
+
+	/* pre-allocated from a base? */
+	int base_port;
+
+	/* dynamically allocated */
+	int range_start;
+	int range_end;
+	int last_port;
+};
+
+struct mgcp_trunk_config {
+	struct llist_head entry;
+
+	struct mgcp_config *cfg;
+
+	int trunk_nr;
+	int trunk_type;
+
+	char *audio_name;
+	int audio_payload;
+	int audio_loop;
+
+	/* spec handling */
+	int force_realloc;
+
+	unsigned int number_endpoints;
+	struct mgcp_endpoint *endpoints;
+
+	/* Special MGW handling */
+	int target_trunk_start;
+	int trunk_base;
+	int endp_offset;
+	int vad_enabled;
+
+	int digital_inp_gain;
+	int digital_out_gain;
+	int upstr_agc_enbl;
+	int upstr_adp_rate;
+	int upstr_max_gain;
+	int upstr_target_lvl;
+	int dwnstr_agc_enbl;
+	int dwnstr_adp_rate;
+	int dwnstr_max_gain;
+	int dwnstr_target_lvl;
+};
+
 struct mgcp_config {
 	int source_port;
 	char *local_ip;
 	char *source_addr;
-	unsigned int number_endpoints;
 	char *bts_ip;
 	char *call_agent_addr;
 
 	struct in_addr bts_in;
-	char *audio_name;
-	int audio_payload;
-	int audio_loop;
-	int early_bind;
-	int rtp_base_port;
+
+	/* transcoder handling */
+	char *transcoder_ip;
+	struct in_addr transcoder_in;
+	int transcoder_remote_base;
+
+	struct write_queue gw_fd;
+
+	struct mgcp_port_range bts_ports;
+	struct mgcp_port_range net_ports;
+	struct mgcp_port_range transcoder_ports;
 	int endp_dscp;
 
-	char *forward_ip;
-	int forward_port;
-
-	/* spec handling */
-	int force_realloc;
-
 	mgcp_change change_cb;
 	mgcp_policy policy_cb;
 	mgcp_reset reset_cb;
 	mgcp_realloc realloc_cb;
 	void *data;
 
-	struct mgcp_endpoint *endpoints;
 	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;
+
+	/* MGW handling */
+	int configure_trunks;
 };
 
 /* config management */
 struct mgcp_config *mgcp_config_alloc(void);
 int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
 int mgcp_vty_init(void);
-void mgcp_vty_set_config(struct mgcp_config *cfg);
-int mgcp_endpoints_allocate(struct mgcp_config *cfg);
-int mgcp_bind_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
 void mgcp_free_endp(struct mgcp_endpoint *endp);
+int mgcp_reset_transcoder(struct mgcp_config *cfg);
 
 /*
  * format helper functions
@@ -129,9 +196,18 @@
 /* adc helper */
 static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
 {
-	if (timeslot == 0)
-		timeslot = 1;
-	return timeslot + (31 * multiplex);
+	if (timeslot == 0) {
+		LOGP(DMGCP, 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;
 }
 
 
diff --git a/include/mgcp/mgcp_internal.h b/include/mgcp/mgcp_internal.h
index b156aea..3197543 100644
--- a/include/mgcp/mgcp_internal.h
+++ b/include/mgcp/mgcp_internal.h
@@ -1,13 +1,13 @@
 /* MGCP Private Data */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
- * This program is free software: you can redistribute it and/or modify
+ * 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
+ * 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,
@@ -35,6 +35,11 @@
 	MGCP_CONN_LOOPBACK  = 4,
 };
 
+enum mgcp_trunk_type {
+	MGCP_TRUNK_VIRTUAL,
+	MGCP_TRUNK_E1,
+};
+
 struct mgcp_rtp_state {
 	int initialized;
 	int patch;
@@ -48,47 +53,82 @@
 	int32_t  timestamp_offset;
 };
 
+struct mgcp_rtp_end {
+	/* statistics */
+	unsigned int packets;
+	struct in_addr addr;
+
+	/* in network byte order */
+	int rtp_port, rtcp_port;
+
+	int payload_type;
+
+	/*
+	 * Each end has a socket...
+	 */
+	struct bsc_fd rtp;
+	struct bsc_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_endpoint {
+	int allocated;
 	uint32_t ci;
 	char *callid;
 	char *local_options;
 	int conn_mode;
 	int orig_mode;
 
-	int bts_payload_type;
-	int net_payload_type;
-
-	/* the local rtp port we are binding to */
-	int rtp_port;
-
-	/*
-	 * RTP mangling:
-	 *  - we get RTP and RTCP to us and need to forward to the BTS
-	 *  - we get RTP and RTCP from the BTS and forward to the network
-	 */
-	struct bsc_fd local_rtp;
-	struct bsc_fd local_rtcp;
-
-	struct in_addr remote;
-	struct in_addr bts;
-
-	/* in network byte order */
-	int net_rtp, net_rtcp;
-	int bts_rtp, bts_rtcp;
-
 	/* backpointer */
 	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
 
-	/* statistics */
-	unsigned int in_bts;
-	unsigned int in_remote;
+	/* 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;
+	int is_transcoded;
 
 	/* sequence bits */
 	struct mgcp_rtp_state net_state;
 	struct mgcp_rtp_state bts_state;
+
+	/* SSRC/seq/ts patching for loop */
+	int allow_patch;
+
+	/* tap for the endpoint */
+	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+
+	/* Special MGW handling */
+	unsigned int audio_port;
+	int block_processing;
 };
 
-#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
+#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
 
 struct mgcp_msg_ptr {
 	unsigned int start;
@@ -99,5 +139,20 @@
 			struct mgcp_msg_ptr *ptr, int size,
 			const char **transaction_id, struct mgcp_endpoint **endp);
 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);
+
 
 #endif
diff --git a/include/mgcp_ss7.h b/include/mgcp_ss7.h
index ff0973b..45828e8 100644
--- a/include/mgcp_ss7.h
+++ b/include/mgcp_ss7.h
@@ -1,7 +1,7 @@
 /* mgcp_ss7 helper coder */
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software: you can redistribute it and/or modify
@@ -29,19 +29,11 @@
 
 #include "thread.h"
 
-enum cellmgr_node {
-	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
-};
-
-
-struct mgcp_ss7_endpoint;
 struct mgcp_ss7 {
 	struct mgcp_config *cfg;
 	struct write_queue mgcp_fd;
 	struct msgb *mgcp_msg;
 
-	struct mgcp_ss7_endpoint *mgw_end;
-
 	/* timer */
 	struct timer_list poll_timer;
 
@@ -54,19 +46,17 @@
 	MGCP_SS7_MUTE_STATUS,
 	MGCP_SS7_ALLOCATE,
 	MGCP_SS7_DELETE,
-	MGCP_SS7_SHUTDOWN,
 };
 
 struct mgcp_ss7_cmd {
 	struct llist_head entry;
 	uint8_t type;
-	uint32_t port;
+	struct mgcp_endpoint *endp;
 	uint32_t param;
 };
 
-void mgcp_ss7_exec(struct mgcp_ss7 *mgcp, uint8_t type, uint32_t port, uint32_t param);
-
 void mgcp_ss7_reset(struct mgcp_ss7 *mgcp);
-void mgcp_ss7_free(struct mgcp_ss7 *mgcp);
+
+void mgcp_mgw_vty_init();
 
 #endif
diff --git a/include/ss7_vty.h b/include/ss7_vty.h
index 48dbb48..a0368bd 100644
--- a/include/ss7_vty.h
+++ b/include/ss7_vty.h
@@ -27,6 +27,7 @@
 
 enum ss7_vty_node {
 	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
+	TRUNK_NODE,
 	CELLMGR_NODE,
 	SS7_NODE,
 	LINKSETS_NODE,