asterisk: Validate precondition in SDP of MO calls

Change-Id: If37aa4146e02279120bc4856255fb845086fa5a8
diff --git a/asterisk/IMS_ConnectionHandler.ttcn b/asterisk/IMS_ConnectionHandler.ttcn
index 7a9f11f..32a35f4 100644
--- a/asterisk/IMS_ConnectionHandler.ttcn
+++ b/asterisk/IMS_ConnectionHandler.ttcn
@@ -544,7 +544,13 @@
 	[fail_others] as_SIP_fail_resp(sip_expect_str);
 }
 
-private function f_gen_sdp() runs on IMS_ConnHdlr return charstring {
+type enumerated IMS_gen_sdp_state {
+	IMS_GEN_SDP_None,
+	IMS_GEN_SDP_MT_Session_Progress,
+	IMS_GEN_SDP_MT_UPDATE_200OK
+}
+
+private function f_gen_sdp(IMS_gen_sdp_state st := IMS_GEN_SDP_None) runs on IMS_ConnHdlr return charstring {
 	var charstring sdp :=
 		"v=0\r\n" &
 		"o=0502 2390 1824 IN IP4 " & g_pars.subscr.cp.local_rtp_addr & "\r\n" &
@@ -568,6 +574,25 @@
 		"a=rtcp:" & int2str(g_pars.subscr.cp.local_rtp_port + 1) & "\r\n" &
 		"a=rtcp-fb:* trr-int 1000\r\n" &
 		"a=rtcp-fb:* ccm tmmbr\r\n";
+	select (st) {
+	case (IMS_GEN_SDP_None) {
+	}
+	case (IMS_GEN_SDP_MT_Session_Progress) {
+		sdp := sdp &
+			"a=curr:qos local none\r\n" &
+			"a=curr:qos remote none\r\n" &
+			"a=des:qos mandatory local sendrecv\r\n" &
+			"a=des:qos mandatory remote sendrecv\r\n" &
+			"a=conf:qos remote sendrecv\r\n";
+	}
+	case (IMS_GEN_SDP_MT_UPDATE_200OK) {
+		sdp := sdp &
+			"a=curr:qos local sendrecv\r\n" &
+			"a=curr:qos remote sendrecv\r\n" &
+			"a=des:qos mandatory local sendrecv\r\n" &
+			"a=des:qos mandatory remote sendrecv\r\n";
+	}
+	}
 	return sdp;
 }
 
@@ -1200,7 +1225,7 @@
 	[] SIP.receive(exp_req) -> value g_rx_sip_req {
 		var template (value) PDU_SIP_Response tx_resp;
 		var Via via;
-		var charstring tx_sdp;
+		var template (omit) charstring tx_sdp;
 		var boolean peer_support_precondition := match(g_rx_sip_req.msgHeader.supported.optionsTags,
 							       superset("100rel", "precondition"));
 
@@ -1232,13 +1257,30 @@
 			COORD.send(IMS_COORD_CMD_CALL_TRYING);
 		}
 
-		tx_sdp := f_gen_sdp();
-
 		/* Use precondition ? */
 		if (g_pars.subscr.cp.require_precondition_ext or
 		    (g_pars.subscr.cp.support_precondition_ext and peer_support_precondition)) {
+			var template (present) SDP_attribute_list preconds;
+			/* Validate SDP in INVITE contains the preconditions:
+			 * a=curr:qos local none
+			 * a=curr:qos remote none
+			 * a=des:qos mandatory local sendrecv
+			 * a=des:qos optional remote sendrecv
+			 */
+			preconds := superset(
+				tr_SDP_curr(c_SDP_PRECON_STATUS_TYPE_local,  c_SDP_PRECON_DIR_TAG_none),
+				tr_SDP_curr(c_SDP_PRECON_STATUS_TYPE_remote, c_SDP_PRECON_DIR_TAG_none),
+				tr_SDP_des(c_SDP_PRECON_STRENGTH_TAG_mandatory, c_SDP_PRECON_STATUS_TYPE_local, c_SDP_PRECON_DIR_TAG_sendrecv),
+				tr_SDP_des(c_SDP_PRECON_STRENGTH_TAG_optional,  c_SDP_PRECON_STATUS_TYPE_remote, c_SDP_PRECON_DIR_TAG_sendrecv));
+			if (not ispresent(g_pars.subscr.cp.peer_sdp.attributes) or
+			    not match(g_pars.subscr.cp.peer_sdp.attributes, preconds)) {
+				Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+							log2str(g_name & ": Unexpected precondition attrs in INVITE : ",
+								g_pars.subscr.cp.peer_sdp.attributes));
+			}
+
 			/* Tx 183 Session Progress */
-			/* TODO: add a=curr:qos, a=des:qos and a=conf:qos fields to SDP */
+			tx_sdp := f_gen_sdp(IMS_GEN_SDP_MT_Session_Progress);
 			tx_resp := ts_SIP_Response_SessionProgress(g_pars.subscr.cp.sip_call_id,
 							g_pars.subscr.cp.from_addr,
 							g_pars.subscr.cp.to_addr,
@@ -1281,8 +1323,26 @@
 					body := ?);
 			as_SIP_expect_req(exp_req);
 
+			/* Validate SDP in UPDATE contains the preconditions:
+			 * a=curr:qos local sendrecv
+			 * a=curr:qos remote none
+			 * a=des:qos mandatory local sendrecv
+			 * a=des:qos mandatory remote sendrecv
+			 */
+			preconds := superset(
+				tr_SDP_curr(c_SDP_PRECON_STATUS_TYPE_local,  c_SDP_PRECON_DIR_TAG_sendrecv),
+				tr_SDP_curr(c_SDP_PRECON_STATUS_TYPE_remote, c_SDP_PRECON_DIR_TAG_none),
+				tr_SDP_des(c_SDP_PRECON_STRENGTH_TAG_mandatory, c_SDP_PRECON_STATUS_TYPE_local, c_SDP_PRECON_DIR_TAG_sendrecv),
+				tr_SDP_des(c_SDP_PRECON_STRENGTH_TAG_mandatory,  c_SDP_PRECON_STATUS_TYPE_remote, c_SDP_PRECON_DIR_TAG_sendrecv));
+			if (not ispresent(g_pars.subscr.cp.peer_sdp.attributes) or
+			    not match(g_pars.subscr.cp.peer_sdp.attributes, preconds)) {
+				Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+							log2str(g_name & ": Unexpected precondition attrs in UPDATE: ",
+								g_pars.subscr.cp.peer_sdp.attributes));
+			}
+
 			/* Tx 200 OK (UPDATE) */
-			/* TODO: add a=curr:qos, a=des:qos and a=conf:qos fields to SDP */
+			tx_sdp := f_gen_sdp(IMS_GEN_SDP_MT_UPDATE_200OK);
 			tx_resp := ts_SIP_Response(g_pars.subscr.cp.sip_call_id,
 						g_pars.subscr.cp.from_addr,
 						g_pars.subscr.cp.to_addr,
@@ -1294,6 +1354,20 @@
 			SIP.send(tx_resp);
 
 			g_pars.subscr.cp.sip_seq_nr := g_pars.subscr.cp.sip_seq_nr + 1;
+			/* 200 OK (INVITE) has no SDP if we use precondition: */
+			tx_sdp := omit;
+		} else {
+			/* Check no precondition is sent in SDP */
+			if (ispresent(g_pars.subscr.cp.peer_sdp.attributes) and
+			    match (g_pars.subscr.cp.peer_sdp.attributes, superset(tr_SDP_curr_present,
+										  tr_SDP_des_present,
+										  tr_SDP_conf_present))) {
+				Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+							log2str(g_name & ": Unexpected precondition attrs in INVITE: ",
+								g_pars.subscr.cp.peer_sdp.attributes));
+			}
+			/* 200 OK (INVITE) has SDP if no precondition is used: */
+			tx_sdp := f_gen_sdp();
 		}
 
 		/* Tx 180 Ringing */
@@ -1306,6 +1380,7 @@
 
 
 		/* Tx 200 OK */
+		tx_sdp := f_gen_sdp();
 		tx_resp := ts_SIP_Response(g_pars.subscr.cp.sip_call_id,
 					   g_pars.subscr.cp.from_addr,
 					   g_pars.subscr.cp.to_addr,