asterisk: Implement AMI Action DedicatedBearerStatus

Related: SYS#6879
Change-Id: I49c216f8874fe63480414096d9c03a1af00a0fc2
diff --git a/asterisk/AMI_Functions.ttcn b/asterisk/AMI_Functions.ttcn
index 16cf71f..d31d316 100644
--- a/asterisk/AMI_Functions.ttcn
+++ b/asterisk/AMI_Functions.ttcn
@@ -27,7 +27,9 @@
 
 const charstring AMI_FIELD_ACTION := "Action";
 const charstring AMI_FIELD_ACTION_ID := "ActionID";
+const charstring AMI_FIELD_CHANNEL := "Channel";
 const charstring AMI_FIELD_CHAN_TYPE := "ChannelType";
+const charstring AMI_FIELD_CONTEXT := "Context";
 const charstring AMI_FIELD_DOMAIN := "Domain";
 const charstring AMI_FIELD_EVENT := "Event";
 const charstring AMI_FIELD_INFO := "Info";
@@ -88,8 +90,12 @@
 template (value) AMI_Field
 ts_AMI_Field_ActionId(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION_ID, val);
 template (value) AMI_Field
+ts_AMI_Field_Channel(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_CHANNEL, val);
+template (value) AMI_Field
 ts_AMI_Field_ChannelType(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_CHAN_TYPE, val);
 template (value) AMI_Field
+ts_AMI_Field_Context(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_CONTEXT, val);
+template (value) AMI_Field
 ts_AMI_Field_Domain(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_DOMAIN, val);
 template (value) AMI_Field
 ts_AMI_Field_Event(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_EVENT, val);
@@ -124,8 +130,12 @@
 template (present) AMI_Field
 tr_AMI_Field_ActionId(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_ACTION_ID, val);
 template (present) AMI_Field
+tr_AMI_Field_Channel(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_CHANNEL, val);
+template (present) AMI_Field
 tr_AMI_Field_ChannelType(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_CHAN_TYPE, val);
 template (present) AMI_Field
+tr_AMI_Field_Context(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_CONTEXT, val);
+template (present) AMI_Field
 tr_AMI_Field_Domain(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_DOMAIN, val);
 template (present) AMI_Field
 tr_AMI_Field_Event(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_EVENT, val);
@@ -203,6 +213,21 @@
 	ts_AMI_Field_IK(ik)
 };
 
+/* Action: DedicatedBearerStatus
+ * ActionID: <value>
+ * Channel: <value>
+ * Status: <value>
+ */
+template (value) AMI_Msg
+ts_AMI_Action_DedicatedBearerStatus(template (value) charstring channel,
+				    template (value) charstring status,
+				    template (value) charstring action_id := "0001") := {
+	ts_AMI_Field_Action("DedicatedBearerStatus"),
+	ts_AMI_Field_ActionId(action_id),
+	ts_AMI_Field_Channel(channel),
+	ts_AMI_Field_Status(status)
+};
+
 /* Action: Login
  * Username: <value>
  * Secret: <value>
@@ -357,6 +382,44 @@
 	tr_AMI_Field_Status(status)
 );
 
+/* Event: Newchannel
+ * Privilege: call,all
+ * Channel: PJSIP/volte_ims-00000001
+ * ChannelState: 0
+ * ChannelStateDesc: Down
+ * CallerIDNum: <unknown>
+ * CallerIDName: <unknown>
+ * ConnectedLineNum: <unknown>
+ * ConnectedLineName: <unknown>
+ * Language: en
+ * AccountCode:
+ * Context: volte_ims
+ * Exten: s
+ * Priority: 1
+ * Uniqueid: 1718732522.1
+ * LinkEvent: Newstate
+ * Privilege: call,all
+ * Channel: PJSIP/volte_ims-00000001
+ * ChannelState: 5
+ * ChannelStateDesc: Ringing
+ * CallerIDNum: 90829
+ * CallerIDName: <unknown>
+ * ConnectedLineNum: 0501
+ * ConnectedLineName: <unknown>
+ * Language: en
+ * AccountCode:
+ * Context: volte_ims
+ * Exten: 90829
+ * Priority: 1
+ * Uniqueid: 1718732522.1
+ * Linkedid: 1718732522.0
+ */
+template (present) AMI_Msg
+tr_AMI_Event_Newchannel(template (present) charstring context := ?) := superset(
+	tr_AMI_Field_Event("Newchannel"),
+	tr_AMI_Field_Context(context)
+);
+
 /***********************
  * Adapter:
  ***********************/
@@ -625,34 +688,39 @@
 	[fail_others] as_ami_rx_fail(pt, msg_expect);
 }
 
+function f_ami_wait_rx_msg(AMI_Msg_PT pt,
+			   template (present) AMI_Msg msg_expect := ?,
+			   boolean fail_others := true,
+			   float rx_timeout := 10.0) return AMI_Msg {
+	var AMI_Msg ami_msg;
+	timer tAMI;
+
+	tAMI.start(rx_timeout);
+	alt {
+	[] pt.receive(msg_expect) -> value ami_msg;
+	[not fail_others] as_ami_rx_ignore(pt);
+	[fail_others] as_ami_rx_fail(pt, msg_expect);
+	[] tAMI.timeout {
+		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+					log2str("AMI msg timeout: ", msg_expect));
+		}
+	}
+	tAMI.stop;
+	return ami_msg;
+}
+
 function f_ami_transceive_match(AMI_Msg_PT pt,
 				template (value) AMI_Msg tx_msg,
 				template (present) AMI_Msg exp_ret := ?,
 				boolean fail_others := true,
 				float rx_timeout := 10.0) return AMI_Msg {
-	var AMI_Msg rx_msg;
-	timer T;
-
-	T.start(rx_timeout);
 	pt.send(tx_msg);
-	alt {
-	[] pt.receive(exp_ret) -> value rx_msg;
-	[not fail_others] pt.receive(AMI_Msg:?) -> value rx_msg {
-		log("AMI: Ignoring Rx msg ", rx_msg);
-		repeat;
-	}
-	[fail_others] as_ami_rx_fail(pt, exp_ret);
-	[] T.timeout {
-		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
-					log2str("AMI Response timeout: ", tx_msg));
-		}
-	}
-	T.stop;
-	return rx_msg;
+	return f_ami_wait_rx_msg(pt, exp_ret, fail_others, rx_timeout);
 }
 
 function f_ami_transceive_match_response_success(AMI_Msg_PT pt,
-						 template (value) AMI_Msg tx_msg) {
+						 template (value) AMI_Msg tx_msg,
+						 boolean fail_others := true) {
 	var template (present) AMI_Msg exp_resp;
 	var template (omit) charstring action_id := f_ami_msg_get_value(valueof(tx_msg), AMI_FIELD_ACTION_ID);
 	if (isvalue(action_id)) {
@@ -660,7 +728,7 @@
 	} else {
 		exp_resp := tr_AMI_Response_Success;
 	}
-	f_ami_transceive_match(pt, tx_msg, exp_resp);
+	f_ami_transceive_match(pt, tx_msg, exp_resp, fail_others := fail_others);
 }
 
 function f_ami_action_login(AMI_Msg_PT pt, charstring username, charstring secret) {
@@ -675,6 +743,15 @@
 	f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPAccessNetworkInfo(registration, info, reg_action_id));
 }
 
+function f_ami_action_DedicatedBearerStatus(AMI_Msg_PT pt,
+					    template (value) charstring channel,
+					    template (value) charstring status,
+					    boolean fail_others := true) {
+	var charstring reg_action_id := f_gen_action_id();
+	f_ami_transceive_match_response_success(pt, ts_AMI_Action_DedicatedBearerStatus(channel, status, reg_action_id),
+						fail_others := fail_others);
+}
+
 function f_ami_action_PJSIPRegister(AMI_Msg_PT pt, charstring register) {
 	var charstring reg_action_id := f_gen_action_id();
 	f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPRegister(register, reg_action_id));
diff --git a/asterisk/Asterisk_Tests.ttcn b/asterisk/Asterisk_Tests.ttcn
index 596848b..cee7adc 100644
--- a/asterisk/Asterisk_Tests.ttcn
+++ b/asterisk/Asterisk_Tests.ttcn
@@ -581,6 +581,7 @@
 	var IMS_ConnHdlrPars ims_pars;
 	var SIPConnHdlr vc_conn_sip;
 	var IMS_ConnHdlr vc_conn_ims;
+	var AMI_Msg ami_msg;
 	const charstring c_ext_msisdn := "90829";
 
 	f_init();
@@ -597,6 +598,7 @@
 							ts_UserInfo(c_ext_msisdn)));
 	ims_pars.subscr.cp.support_precondition_ext := use_precondition_ext;
 	ims_pars.subscr.cp.require_precondition_ext := use_precondition_ext;
+	ims_pars.subscr.cp.mo.tx_coord_cmd_invite_trying := true;
 
 	vc_conn_ims := f_start_handler_IMS(refers(f_TC_ims_call_mo_IMS_ConnHdlr), ims_pars);
 	vc_conn_sip := f_start_handler(refers(f_TC_internal_call_mo), sip_pars);
@@ -606,11 +608,18 @@
 	f_AMI_IMS_register(ims_pars);
 
 	COORD.send(COORD_CMD_START) to vc_conn_sip;
+
+	IMS_COORD.receive(IMS_COORD_CMD_CALL_TRYING) from vc_conn_ims;
+	ami_msg := f_ami_wait_rx_msg(AMI_CLIENT,
+				     tr_AMI_Event_Newchannel(mp_volte_ims_outbound_registration),
+				     fail_others := false);
+	f_ami_action_DedicatedBearerStatus(AMI_CLIENT,
+					   f_ami_msg_get_value(ami_msg, AMI_FIELD_CHANNEL),
+					   "Up", fail_others := false);
+
 	COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_sip;
 	IMS_COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_ims;
 
-	/* TODO: "Action: DedicatedBearerStatus" */
-
 	/* Call on-going */
 	f_sleep(1.0);
 
@@ -655,6 +664,7 @@
 	var IMS_ConnHdlrPars ims_pars;
 	var SIPConnHdlr vc_conn_sip;
 	var IMS_ConnHdlr vc_conn_ims;
+	var AMI_Msg ami_msg;
 	const charstring c_ext_msisdn := "90829";
 
 	f_init();
@@ -672,6 +682,7 @@
 							 ts_UserInfo(ims_pars.subscr.msisdn)));
 	ims_pars.subscr.cp.support_precondition_ext := use_precondition_ext;
 	ims_pars.subscr.cp.require_precondition_ext := use_precondition_ext;
+	ims_pars.subscr.cp.mt.tx_coord_cmd_session_progress := use_precondition_ext;
 
 	vc_conn_ims := f_start_handler_IMS(refers(f_TC_ims_call_mt_IMS_ConnHdlr), ims_pars);
 	vc_conn_sip := f_start_handler(refers(f_TC_internal_call_mt), sip_pars);
@@ -682,11 +693,20 @@
 	IMS_COORD.receive(IMS_COORD_CMD_REGISTERED) from vc_conn_ims;
 
 	IMS_COORD.send(IMS_COORD_CMD_START) to vc_conn_ims;
+
+	ami_msg := f_ami_wait_rx_msg(AMI_CLIENT,
+				     tr_AMI_Event_Newchannel(mp_volte_ims_outbound_registration),
+				     fail_others := false);
+	if (ims_pars.subscr.cp.mt.tx_coord_cmd_session_progress) {
+		IMS_COORD.receive(IMS_COORD_CMD_CALL_SESSION_PROGRESS) from vc_conn_ims;
+	}
+	f_ami_action_DedicatedBearerStatus(AMI_CLIENT,
+					   f_ami_msg_get_value(ami_msg, AMI_FIELD_CHANNEL),
+					   "Up", fail_others := false);
+
 	IMS_COORD.receive(IMS_COORD_CMD_CALL_ESTABLISHED) from vc_conn_ims;
 	COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_sip;
 
-	/* TODO: "Action: DedicatedBearerStatus" */
-
 	/* Call on-going */
 	f_sleep(1.0);
 
diff --git a/asterisk/IMS_ConnectionHandler.ttcn b/asterisk/IMS_ConnectionHandler.ttcn
index dd3223c..7a9f11f 100644
--- a/asterisk/IMS_ConnectionHandler.ttcn
+++ b/asterisk/IMS_ConnectionHandler.ttcn
@@ -47,6 +47,8 @@
 const charstring IMS_COORD_CMD_START := "IMS_COORD_CMD_START";
 const charstring IMS_COORD_CMD_CALL_ESTABLISHED := "IMS_COORD_CMD_CALL_ESTABLISHED";
 const charstring IMS_COORD_CMD_HANGUP := "IMS_COORD_CMD_HANGUP";
+const charstring IMS_COORD_CMD_CALL_TRYING := "IMS_COORD_CMD_CALL_TRYING";
+const charstring IMS_COORD_CMD_CALL_SESSION_PROGRESS := "IMS_COORD_CMD_CALL_SESSION_PROGRESS";
 
 type component IMS_ConnHdlr extends SIP_ConnHdlr {
 	var charstring g_name;
@@ -113,15 +115,20 @@
 }
 type record of IMS_ConnHdlrPars IMS_ConnHdlrParsList;
 
+type record IMS_CallParsMO {
+	/* Whether to COORD.send(IMS_COORD_CMD_CALL_TRYING) when receiving an INVITE from UE. */
+	boolean tx_coord_cmd_invite_trying
+}
+template (value) IMS_CallParsMO t_IMS_CallParsMO := {
+	tx_coord_cmd_invite_trying := false
+}
+
 type record IMS_CallParsMT {
-	/* Whether to wait for COORD.receive(COORD_CMD_PICKUP) before accepting the call. */
-	boolean wait_coord_cmd_pickup,
-	/* Whether to expect CANCEL instead of ACK as answer to our OK */
-	boolean exp_cancel
+	/* Whether to COORD.send(IMS_COORD_CMD_CALL_SESSION_PROGRESS) when receiving an 183 Session Progress from UE. */
+	boolean tx_coord_cmd_session_progress
 }
 template (value) IMS_CallParsMT t_IMS_CallParsMT := {
-	wait_coord_cmd_pickup := false,
-	exp_cancel := false
+	tx_coord_cmd_session_progress := false
 }
 
 type record IMS_CallPars {
@@ -141,6 +148,7 @@
 	boolean support_precondition_ext,
 	boolean require_precondition_ext,
 	SDP_Message peer_sdp optional,
+	IMS_CallParsMO mo,
 	IMS_CallParsMT mt
 }
 
@@ -160,6 +168,7 @@
 	support_precondition_ext := true,
 	require_precondition_ext := false,
 	peer_sdp := omit,
+	mo := t_IMS_CallParsMO,
 	mt := t_IMS_CallParsMT
 }
 
@@ -1043,6 +1052,11 @@
 				    body := omit);
 		SIP.send(req);
 
+		if (g_pars.subscr.cp.mt.tx_coord_cmd_session_progress) {
+			/* Signal used to inform that Dedicated bearer can be established: */
+			COORD.send(IMS_COORD_CMD_CALL_SESSION_PROGRESS);
+		}
+
 		/* Rx 200 OK (PRACK) */
 		exp := tr_SIP_Response(g_pars.subscr.cp.sip_call_id,
 				       from_addr_exp,
@@ -1213,6 +1227,11 @@
 						   userAgent := omit);
 		SIP.send(tx_resp);
 
+		if (g_pars.subscr.cp.mo.tx_coord_cmd_invite_trying) {
+			/* Signal used to inform that Dedicated bearer can be established: */
+			COORD.send(IMS_COORD_CMD_CALL_TRYING);
+		}
+
 		tx_sdp := f_gen_sdp();
 
 		/* Use precondition ? */