ASCI: Support conference briding with 1..n connections

For each RTP packet that is received from a connection, the mode is
checked whether receiving is allowed or not. If not it is discarded.

In case of "confecho" mode, the RTP is also sent by the receiving
connection.

Then a loop is used to send RTP to all sending endpoints except the one
that received the packet.

Because we have a loop that allows to have 1..n connections, we have no
maximum number of allowed connections anymore.

Change-Id: Ic99a55ab5a3a6170e940403fadd52697e99f2f3a
Related: OS#4853
diff --git a/src/libosmo-mgcp/mgcp_conn.c b/src/libosmo-mgcp/mgcp_conn.c
index b97c161..0ba10e5 100644
--- a/src/libosmo-mgcp/mgcp_conn.c
+++ b/src/libosmo-mgcp/mgcp_conn.c
@@ -173,8 +173,8 @@
 	struct mgcp_conn *conn;
 	int rc;
 
-	/* Do not allow more then two connections */
-	if (llist_count(&endp->conns) >= endp->type->max_conns)
+	/* Do not allow more than the maximum number of connections */
+	if (endp->type->max_conns > 0 && llist_count(&endp->conns) >= endp->type->max_conns)
 		return NULL;
 
 	/* Create new connection and add it to the list */
diff --git a/src/libosmo-mgcp/mgcp_endp.c b/src/libosmo-mgcp/mgcp_endp.c
index 20088b7..4c870ec 100644
--- a/src/libosmo-mgcp/mgcp_endp.c
+++ b/src/libosmo-mgcp/mgcp_endp.c
@@ -38,7 +38,6 @@
 const struct mgcp_endpoint_typeset ep_typeset = {
 	/* Specify endpoint properties for RTP endpoint */
 	.rtp = {
-		.max_conns = 2,
 		.dispatch_rtp_cb = mgcp_dispatch_rtp_bridge_cb,
 		.cleanup_cb = mgcp_cleanup_rtp_bridge_cb,
 	},
diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c
index 33cd8af..46d0cb4 100644
--- a/src/libosmo-mgcp/mgcp_network.c
+++ b/src/libosmo-mgcp/mgcp_network.c
@@ -1290,8 +1290,10 @@
 	struct mgcp_conn_rtp *conn_src = mc->conn_src;
 	struct mgcp_conn *conn = conn_src->conn;
 	struct mgcp_conn *conn_dst;
+	struct mgcp_endpoint *endp = conn->endp;
 	struct osmo_sockaddr *from_addr = mc->from_addr;
 	char ipbuf[INET6_ADDRSTRLEN];
+	int rc = 0;
 
 	/*! NOTE: This callback function implements the endpoint specific
 	 *  dispatch behaviour of an rtp bridge/proxy endpoint. It is assumed
@@ -1323,36 +1325,35 @@
 		return mgcp_conn_rtp_dispatch_rtp(conn_src, msg);
 	}
 
-	/* Find a destination connection. */
-	/* NOTE: This code path runs every time an RTP packet is received. The
-	 * function mgcp_find_dst_conn() we use to determine the detination
-	 * connection will iterate the connection list inside the endpoint.
-	 * Since list iterations are quite costly, we will figure out the
-	 * destination only once and use the optional private data pointer of
-	 * the connection to cache the destination connection pointer. */
-	if (!conn->priv) {
-		conn_dst = mgcp_find_dst_conn(conn);
-		conn->priv = conn_dst;
-	} else {
-		conn_dst = (struct mgcp_conn *)conn->priv;
+	/* If the mode does not allow receiving RTP, we are done. */
+	switch (conn->mode) {
+	case MGCP_CONN_RECV_ONLY:
+	case MGCP_CONN_RECV_SEND:
+	case MGCP_CONN_CONFECHO:
+		break;
+	default:
+		return rc;
 	}
 
-	/* There is no destination conn, stop here */
-	if (!conn_dst) {
-		LOGPCONN(conn, DRTP, LOGL_DEBUG,
-			 "no connection to forward an incoming RTP packet to\n");
-		return -1;
-	}
+	/* If the mode is "confecho", send RTP back to the sender. */
+	if (conn->mode == MGCP_CONN_CONFECHO)
+		rc = mgcp_conn_rtp_dispatch_rtp(conn_src, msg);
 
-	/* The destination conn is not an RTP connection */
-	if (conn_dst->type != MGCP_CONN_TYPE_RTP) {
-		LOGPCONN(conn, DRTP, LOGL_ERROR,
-			 "unable to find suitable destination conn\n");
-		return -1;
+	/* Dispatch RTP packet to all other connection(s) that send audio. */
+	llist_for_each_entry(conn_dst, &endp->conns, entry) {
+		if (conn_dst == conn)
+			continue;
+		switch (conn_dst->mode) {
+		case MGCP_CONN_SEND_ONLY:
+		case MGCP_CONN_RECV_SEND:
+		case MGCP_CONN_CONFECHO:
+			rc = mgcp_conn_rtp_dispatch_rtp(&conn_dst->u.rtp, msg);
+			break;
+		default:
+			break;
+		}
 	}
-
-	/* Dispatch RTP packet to destination RTP connection */
-	return mgcp_conn_rtp_dispatch_rtp(&conn_dst->u.rtp, msg);
+	return rc;
 }
 
 /*! dispatch incoming RTP packet to E1 subslot, handle RTCP packets locally.
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index 978af42..7795734 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -967,7 +967,7 @@
 	}
 
 	/* Check if we are able to accept the creation of another connection */
-	if (llist_count(&endp->conns) >= endp->type->max_conns) {
+	if (endp->type->max_conns > 0 && llist_count(&endp->conns) >= endp->type->max_conns) {
 		LOGPENDP(endp, DLMGCP, LOGL_ERROR,
 			"CRCX: endpoint full, max. %i connections allowed!\n",
 			endp->type->max_conns);