Implement IuCS (large refactoring and addition)

osmo-nitb becomes osmo-msc
add DIUCS debug log constant
add iucs.[hc]
add msc vty, remove nitb vty
add libiudummy, to avoid linking Iu deps in tests
Use new msc_tx_dtap() instead of gsm0808_submit_dtap()
libmgcp: add mgcpgw client API
bridge calls via mgcpgw

Enable MSC specific CTRL commands, bsc_base_ctrl_cmds_install() still needs to
be split up.

Change-Id: I5b5b6a9678b458affa86800afb1ec726e66eed88
diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c
index c847b78..ddc3836 100644
--- a/src/libmsc/osmo_msc.c
+++ b/src/libmsc/osmo_msc.c
@@ -28,6 +28,7 @@
 #include <openbsc/db.h>
 #include <openbsc/vlr.h>
 #include <openbsc/osmo_msc.h>
+#include <openbsc/iu.h>
 
 #include <openbsc/gsm_04_11.h>
 
@@ -40,24 +41,6 @@
 		gsm411_sapi_n_reject(conn);
 }
 
-static bool keep_conn(struct gsm_subscriber_connection *conn)
-{
-	/* TODO: what about a silent call? */
-
-	if (!conn->conn_fsm) {
-		DEBUGP(DMM, "No conn_fsm, release conn\n");
-		return false;
-	}
-
-	switch (conn->conn_fsm->state) {
-	case SUBSCR_CONN_S_NEW:
-	case SUBSCR_CONN_S_ACCEPTED:
-		return true;
-	default:
-		return false;
-	}
-}
-
 static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
 {
 	if (!conn)
@@ -65,39 +48,32 @@
 	if (!conn->conn_fsm)
 		return;
 	if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
-	      || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING))
+	      || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING)) {
+		DEBUGP(DMM, "%s: bump: conn still being established (%s)\n",
+		       vlr_subscr_name(conn->vsub),
+		       osmo_fsm_inst_state_name(conn->conn_fsm));
 		return;
+	}
 	osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
 }
 
 /* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
  * MSC_CONN_REJECT */
-static int msc_compl_l3(struct gsm_subscriber_connection *conn,
-			struct msgb *msg, uint16_t chosen_channel)
+int msc_compl_l3(struct gsm_subscriber_connection *conn,
+		 struct msgb *msg, uint16_t chosen_channel)
 {
-	/* Ownership of the gsm_subscriber_connection is still a bit mucky
-	 * between libbsc and libmsc. In libmsc, we use ref counting, but not
-	 * in libbsc. This will become simpler with the MSCSPLIT. */
-
-	/* reserve for the duration of this function */
 	msc_subscr_conn_get(conn);
-
 	gsm0408_dispatch(conn, msg);
 
-	if (!keep_conn(conn)) {
-		DEBUGP(DMM, "compl_l3: Discarding conn\n");
-		/* keep the use_count reserved, libbsc will discard. If we
-		 * released the ref count and discarded here, libbsc would
-		 * double-free. And we will not change bsc_api semantics. */
-		return MSC_CONN_REJECT;
-	}
-	DEBUGP(DMM, "compl_l3: Keeping conn\n");
-
 	/* Bump whether the conn wants to be closed */
 	subscr_conn_bump(conn);
 
 	/* If this should be kept, the conn->conn_fsm has placed a use_count */
 	msc_subscr_conn_put(conn);
+
+	/* Always return acceptance, because even if the conn was not accepted,
+	 * we assumed ownership of it and the caller shall not interfere with
+	 * that. We may even already have discarded the conn. */
 	return MSC_CONN_ACCEPT;
 
 #if 0
@@ -119,7 +95,7 @@
 }
 
 /* Receive a DTAP message from BSC */
-static void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
+void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
 {
 	msc_subscr_conn_get(conn);
 	gsm0408_dispatch(conn, msg);
@@ -170,8 +146,8 @@
 }
 
 /* Receive a CIPHERING MODE COMPLETE from BSC */
-static void msc_ciph_m_compl(struct gsm_subscriber_connection *conn,
-			     struct msgb *msg, uint8_t alg_id)
+void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
+			   struct msgb *msg, uint8_t alg_id)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
@@ -289,7 +265,7 @@
 	.assign_compl = msc_assign_compl,
 	.assign_fail = msc_assign_fail,
 	.classmark_chg = msc_classmark_chg,
-	.cipher_mode_compl = msc_ciph_m_compl,
+	.cipher_mode_compl = msc_cipher_mode_compl,
 	.conn_cleanup = msc_subscr_con_cleanup,
 };
 
@@ -308,7 +284,10 @@
 
 	switch (conn->via_ran) {
 	case RAN_UTRAN_IU:
-		/* future: iu_tx_release(conn->iu.ue_ctx, NULL); */
+		iu_tx_release(conn->iu.ue_ctx, NULL);
+		/* FIXME: keep the conn until the Iu Release Outcome is
+		 * received from the UE, or a timeout expires. For now, the log
+		 * says "unknown UE" for each release outcome. */
 		break;
 	case RAN_GERAN_A:
 		/* future: a_iface_tx_clear_cmd(conn); */
@@ -390,8 +369,12 @@
 		"%s: MSC conn use - 1 == %u\n",
 		vlr_subscr_name(conn->vsub), conn->use_count);
 
-	if (conn->use_count == 0) {
-		gsm0808_clear(conn);
-		bsc_subscr_con_free(conn);
-	}
+	if (conn->use_count == 0)
+		msc_subscr_con_free(conn);
+}
+
+void msc_stop_paging(struct vlr_subscr *vsub)
+{
+	DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
+	/* tell BSCs and RNCs to stop paging? How? */
 }