in ran_msg, return gsm0808_speech_codec (intra-MSC)

Do not convert to enum mgcp_codecs, but directly pass the
gsm0808_speech_codec IE from the A interface to codecs handling.

For Iu:
- RAN side: use ran_infra.force_mgw_codecs_to_ran to keep the MGW
  endpoint towards RAN on IUFP.
- CN side: introduce flag ran_msg.assignment_complete.codec_with_iuup,
  so to decide whether to forward IUFP towards CN, we don't need to test
  the RAN type, but use the flag from the ran_msg implementation.

In msc_vlr_tests, use the SDP codec string instead of enum
mgcp_codecs.

So far limit to intra-MSC related messaging, adjusting inter-MSC
handover follows in a separate patch.

Change-Id: Ia666cb697fbd140d7239089628faed93860ce671
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index e9f1840..f1e365f 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -1325,8 +1325,8 @@
 {
 	struct gsm_trans *cc_trans = msc_a->cc.active_trans;
 	struct rtp_stream *rtps_to_ran = msc_a->cc.call_leg ? msc_a->cc.call_leg->rtp[RTP_TO_RAN] : NULL;
-	const enum mgcp_codecs *codec_if_known = ac->assignment_complete.codec_present ?
-							&ac->assignment_complete.codec : NULL;
+	const struct gsm0808_speech_codec *codec_if_known = ac->assignment_complete.codec_present ?
+							    &ac->assignment_complete.codec : NULL;
 	const struct codec_mapping *codec_cn = NULL;
 
 	if (!rtps_to_ran) {
@@ -1346,16 +1346,33 @@
 	}
 
 	if (codec_if_known) {
-		codec_cn = codec_mapping_by_mgcp_codec(*codec_if_known);
-		if (!codec_cn) {
-			LOG_TRANS(cc_trans, LOGL_ERROR, "Unknown codec in Assignment Complete: %s\n",
-				  osmo_mgcpc_codec_name(*codec_if_known));
-			call_leg_release(msc_a->cc.call_leg);
-			return;
+		if (ac->assignment_complete.codec_with_iuup) {
+			/* FUTURE: soon, we want to tell the MGW to decapsulate IuUP to plain AMR-FR/RTP. So far,
+			 * continue to forward IuUP to the CN.
+			 *
+			 * ran_msg_iu now returns AMR-FR as the assigned codec. If we use that directly, that will
+			 * instruct the MGW to decapsulate IuUP into plain RTP. Let's keep this change to an explicit
+			 * patch, while various codecs patches are still being applied.
+			 *
+			 * So instruct MGW to forward IuUP to CN:
+			 */
+			codec_cn = codec_mapping_by_subtype_name("VND.3GPP.IUFP");
+			OSMO_ASSERT(codec_cn);
+		} else {
+			codec_cn = codec_mapping_by_gsm0808_speech_codec_type(codec_if_known->type);
+			/* TODO: use codec_mapping_by_gsm0808_speech_codec() to also match on codec_if_known->cfg */
+			if (!codec_cn) {
+				LOG_TRANS(cc_trans, LOGL_ERROR, "Unknown codec in Assignment Complete: %s\n",
+					  gsm0808_speech_codec_type_name(codec_if_known->type));
+				call_leg_release(msc_a->cc.call_leg);
+				return;
+			}
 		}
 
-		/* Update RAN-side endpoint CI from Assignment result */
-		rtp_stream_set_one_codec(rtps_to_ran, &codec_cn->sdp);
+		/* Update RAN-side endpoint CI from Assignment result -- unless it is forced by the ran_infra, in which
+		 * case it remains unchanged as passed to the earlier call of call_leg_ensure_ci(). */
+		if (msc_a->c.ran->force_mgw_codecs_to_ran.count == 0)
+			rtp_stream_set_one_codec(rtps_to_ran, &codec_cn->sdp);
 
 		/* Update codec filter with Assignment result, for the CN side */
 		cc_trans->cc.codecs.assignment = codec_cn->sdp;
diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c
index c9a13a2..56252f1 100644
--- a/src/libmsc/ran_msg_a.c
+++ b/src/libmsc/ran_msg_a.c
@@ -276,7 +276,6 @@
 	struct tlv_p_entry *ie_codec_list_bss_supported = TLVP_GET(tp, GSM0808_IE_SPEECH_CODEC_LIST);
 	struct tlv_p_entry *ie_osmux_cid = TLVP_GET(tp, GSM0808_IE_OSMO_OSMUX_CID);
 	struct sockaddr_storage rtp_addr;
-	struct gsm0808_speech_codec sc;
 	struct gsm0808_speech_codec_list codec_list_bss_supported;
 	int rc;
 	struct ran_msg ran_dec_msg = {
@@ -309,14 +308,14 @@
 
 	if (ie_speech_codec) {
 		/* Decode Speech Codec (Chosen) element */
-		rc = gsm0808_dec_speech_codec(&sc, ie_speech_codec->val, ie_speech_codec->len);
+		rc = gsm0808_dec_speech_codec(&ran_dec_msg.assignment_complete.codec,
+					      ie_speech_codec->val, ie_speech_codec->len);
 		if (rc < 0) {
 			LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Assignment Complete: unable to decode IE Speech Codec (Chosen)"
 					  " (rc=%d).\n", rc);
 			return -EINVAL;
 		}
 		ran_dec_msg.assignment_complete.codec_present = true;
-		ran_dec_msg.assignment_complete.codec = ran_a_mgcp_codec_from_sc(&sc);
 	}
 
 	if (ie_codec_list_bss_supported) {
diff --git a/src/libmsc/ran_msg_iu.c b/src/libmsc/ran_msg_iu.c
index ee1d0a5..eb7fc93 100644
--- a/src/libmsc/ran_msg_iu.c
+++ b/src/libmsc/ran_msg_iu.c
@@ -153,8 +153,16 @@
 		.msg_type = RAN_MSG_ASSIGNMENT_COMPLETE,
 		.msg_name = "RANAP RAB Assignment Response",
 		.assignment_complete = {
+			/* For codec compatibility resolution, indicate AMR-FR */
 			.codec_present = true,
-			.codec = CODEC_IUFP,
+			.codec = {
+				.fi = true,
+				.type = GSM0808_SCT_FR3,
+				.cfg = GSM0808_SC_CFG_DEFAULT_FR_AMR,
+			},
+			/* Indicate that (at least) the first MGW endpoint towards RAN needs to expect VND.3GPP.IUFP
+			 * that encapsulates the AMR-FR RTP payload. */
+			.codec_with_iuup = true,
 		},
 	};
 	if (osmo_sockaddr_str_from_str(&ran_dec_msg->assignment_complete.remote_rtp, addr, port)) {