[MERGED] osmo-ttcn3-hacks[master]: MGCP_Emulation: More complete implementation

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Fri Jan 26 09:44:44 UTC 2018


Harald Welte has submitted this change and it was merged.

Change subject: MGCP_Emulation: More complete implementation
......................................................................


MGCP_Emulation: More complete implementation

* re-introduce connection table
* introduce unitdata_cb for connectionless MGCP messages (like AUEP)
* rename MGCP_Emulation_CT members to avoid clashes with other similar
  component names when using "multiple inheritance"
* Use HostName/PortNumber types on MGCP_conn_parameters
* allow "bind to local UDP port only, permit any UDP source port" behavior
* implement expect matching criteria + expect matching only on CRCX
* add helper function f_create_mgcp_expect() like in other Emulations

Change-Id: I953a91e663648715fa4fe98acacca393c8747001
---
M library/MGCP_Emulation.ttcn
M library/MGCP_Templates.ttcn
2 files changed, 191 insertions(+), 44 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/library/MGCP_Emulation.ttcn b/library/MGCP_Emulation.ttcn
index beef9e8..5bd4e50 100644
--- a/library/MGCP_Emulation.ttcn
+++ b/library/MGCP_Emulation.ttcn
@@ -36,6 +36,8 @@
 
 type component MGCP_ConnHdlr {
 	port MGCP_Conn_PT MGCP;
+	/* procedure based port to register for incoming connections */
+	port MGCPEM_PROC_PT MGCP_PROC;
 	var MgcpConnectionId mgcp_conn_id;
 }
 
@@ -44,6 +46,11 @@
 	inout MgcpCommand, MgcpResponse;
 } with { extension "internal" };
 
+/* represents a single MGCP Connection */
+type record ConnectionData {
+	MGCP_ConnHdlr	comp_ref,
+	MgcpConnectionId conn_id optional
+};
 
 type component MGCP_Emulation_CT {
 	/* Port facing to the UDP SUT */
@@ -51,13 +58,13 @@
 	/* All MGCP_ConnHdlr MGCP ports connect here
 	 * MGCP_Emulation_CT.main needs to figure out what messages
 	 * to send where with CLIENT.send() to vc_conn */
-	port MGCP_Conn_PT CLIENT;
+	port MGCP_Conn_PT MGCP_CLIENT;
 	/* currently tracked connections */
-//	var ConnectionData ConnectionTable[16];
+	var ConnectionData MgcpConnectionTable[16];
 	/* pending expected CRCX */
-	var ExpectData ExpectTable[8];
+	var ExpectData MgcpExpectTable[8];
 	/* procedure based port to register for incoming connections */
-	port MGCPEM_PROC_PT PROC;
+	port MGCPEM_PROC_PT MGCP_PROC;
 
 	var charstring g_mgcp_id;
 	var integer g_mgcp_conn_id := -1;
@@ -66,15 +73,19 @@
 type function MGCPCreateCallback(MgcpCommand cmd, charstring id)
 runs on MGCP_Emulation_CT return MGCP_ConnHdlr;
 
+type function MGCPUnitdataCallback(MgcpMessage msg)
+runs on MGCP_Emulation_CT return template MgcpMessage;
+
 type record MGCPOps {
-	MGCPCreateCallback create_cb
+	MGCPCreateCallback create_cb,
+	MGCPUnitdataCallback unitdata_cb
 }
 
 type record MGCP_conn_parameters {
-	charstring callagent_ip,
-	uint16_t callagent_udp_port,
-	charstring mgw_ip,
-	uint16_t mgw_udp_port
+	HostName callagent_ip,
+	PortNumber callagent_udp_port,
+	HostName mgw_ip,
+	PortNumber mgw_udp_port
 }
 
 function tr_MGCP_RecvFrom_R(template MgcpMessage msg)
@@ -90,19 +101,94 @@
 	return mrf;
 }
 
+private function f_conn_id_known(MgcpConnectionId conn_id)
+runs on MGCP_Emulation_CT return boolean {
+	var integer i;
+	for (i := 0; i < sizeof(MgcpConnectionTable); i := i+1) {
+		if (MgcpConnectionTable[i].conn_id == conn_id) {
+			return true;
+		}
+	}
+	return false;
+}
+
+private function f_comp_known(MGCP_ConnHdlr client)
+runs on MGCP_Emulation_CT return boolean {
+	var integer i;
+	for (i := 0; i < sizeof(MgcpConnectionTable); i := i+1) {
+		if (MgcpConnectionTable[i].comp_ref == client) {
+			return true;
+		}
+	}
+	return false;
+}
+
+private function f_comp_by_conn_id(MgcpConnectionId conn_id)
+runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
+	var integer i;
+	for (i := 0; i < sizeof(MgcpConnectionTable); i := i+1) {
+		if (MgcpConnectionTable[i].conn_id == conn_id) {
+			return MgcpConnectionTable[i].comp_ref;
+		}
+	}
+	log("MGCP Connection Table not found by Connection Id", conn_id);
+	setverdict(fail);
+	self.stop;
+}
+
+private function f_conn_id_by_comp(MGCP_ConnHdlr client)
+runs on MGCP_Emulation_CT return MgcpConnectionId {
+	var integer i;
+	for (i := 0; i < sizeof(MgcpConnectionTable); i := i+1) {
+		if (MgcpConnectionTable[i].comp_ref == client) {
+			return MgcpConnectionTable[i].conn_id;
+		}
+	}
+	log("MGCP Connection Table not found by component ", client);
+	setverdict(fail);
+	self.stop;
+}
+
+/* TODO: move this to MGCP_Types? */
+function f_mgcp_conn_id(MgcpMessage msg) return hexstring {
+	var MgcpParameterList params;
+	var integer i;
+	if (ischosen(msg.command)) {
+		params := msg.command.params;
+	} else {
+		params := msg.response.params;
+	}
+	for (i := 0; i < lengthof(params); i := i+1) {
+		if (params[i].code == "I") {
+			return str2hex(params[i].val);
+		}
+	}
+	return ''H;
+}
+
+private function f_conn_table_init()
+runs on MGCP_Emulation_CT {
+	for (var integer i := 0; i < sizeof(MgcpConnectionTable); i := i+1) {
+		MgcpConnectionTable[i].comp_ref := null;
+		MgcpConnectionTable[i].conn_id := omit;
+	}
+}
+
 function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_Emulation_CT {
 	var Result res;
 	g_mgcp_id := id;
-	//f_conn_table_init();
+	f_conn_table_init();
 	f_expect_table_init();
 
 	map(self:MGCP, system:MGCP_CODEC_PT);
-	res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.mgw_ip,
-p.mgw_udp_port,
-		p.callagent_ip, p.callagent_udp_port, 0, { udp:={} });
-	
+	if (p.callagent_udp_port == -1) {
+		res := MGCP_CodecPort_CtrlFunct.f_IPL4_listen(MGCP, p.mgw_ip, p.mgw_udp_port, { udp:={} });
+	} else {
+		res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, -1, { udp:={} });
+	}
+
 	g_mgcp_conn_id := res.connId;
-	
+
 	while (true) {
 		var MGCP_ConnHdlr vc_conn;
 		var ExpectCriteria crit;
@@ -113,32 +199,48 @@
 
 		alt {
 		/* MGCP from client */
-		[] CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
+		[] MGCP_CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
 			/* Pass message through */
 			msg.response := resp;
+			/* TODO: check which ConnectionID client has allocated + store in table? */
 			MGCP.send(t_MGCP_Send(g_mgcp_conn_id, msg));
 			}
 		[] MGCP.receive(tr_MGCP_RecvFrom_R(?)) -> value mrf {
+			if (p.callagent_udp_port == -1) {
+				/* we aren't yet connected to the remote side port, let's fix this */
+				p.callagent_udp_port := mrf.remPort;
+				MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, g_mgcp_conn_id, { udp:={} });
+			}
 			if (ischosen(mrf.msg.command)) {
 				cmd := mrf.msg.command;
-				vc_conn := ops.create_cb.apply(cmd, id);
-				f_handle_userData(vc_conn, cmd);
+				if (match(cmd, tr_MgcpCommand_CO)) {
+					/* connection-oriented MGCP */
+					if (cmd.line.verb == "CRCX") {
+						/* TODO: allocate ConnectionID here + store in Table? */
+						vc_conn := ops.create_cb.apply(cmd, id);
+					} else {
+						var MgcpConnectionId conn_id := f_mgcp_conn_id(mrf.msg);
+						vc_conn := f_comp_by_conn_id(conn_id);
+					}
+					MGCP_CLIENT.send(cmd) to vc_conn;
+				} else {
+					/* connectionless MGCP, i.e. messages without ConnectionId */
+					var template MgcpMessage r := ops.unitdata_cb.apply(mrf.msg);
+					if (isvalue(r)) {
+						MGCP.send(t_MGCP_Send(g_mgcp_conn_id, r));
+					}
+				}
 			} else {
 				setverdict(fail, "Received unexpected MGCP response: ", mrf.msg.response);
 				self.stop;
 			}
 			}
-		[] PROC.getcall(MGCPEM_register:{?,?}) -> param(crit, vc_conn) {
+		[] MGCP_PROC.getcall(MGCPEM_register:{?,?}) -> param(crit, vc_conn) {
 			f_create_expect(crit, vc_conn);
-			PROC.reply(MGCPEM_register:{crit, vc_conn});
+			MGCP_PROC.reply(MGCPEM_register:{crit, vc_conn});
 			}
 		}
 	}
-}
-
-private function f_handle_userData(MGCP_ConnHdlr conn, MgcpCommand cmd)
-runs on MGCP_Emulation_CT {
-	CLIENT.send(cmd) to conn;
 }
 
 /* "Expect" Handling */
@@ -163,8 +265,25 @@
 
 function f_get_mgcp_by_crit(ExpectCriteria crit)
 return template MgcpCommand {
-	template MgcpCommand ret := {
-	};
+	var template MgcpCommand ret := {
+		line := {
+			verb := ?,
+			trans_id := ?,
+			ep := ?,
+			ver := ?
+		},
+		params := *,
+		sdp := *
+	}
+	if (ispresent(crit.connid)) {
+		ret.params := { *, ts_MgcpParConnectionId(crit.connid), * };
+	}
+	if (ispresent(crit.endpoint)) {
+		ret.line.ep := crit.endpoint;
+	}
+	if (ispresent(crit.transid)) {
+		ret.line.trans_id := crit.transid;
+	}
 
 	return ret;
 }
@@ -178,20 +297,20 @@
 
 	/* Ensure cmd is a CRCX? */
 
-	for (i := 0; i < sizeof(ExpectTable); i := i+1) {
-		if (not ispresent(ExpectTable[i].crit)) {
+	for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
+		if (not ispresent(MgcpExpectTable[i].crit)) {
 			continue;
 		}
 		/* FIXME: Ignore criteria for now */
-//		mgcpcmd := f_get_mgcp_by_crit(ExpectTable[i].crit);
-//		if (match(cmd, mgcpcmd)) {
-			ret := ExpectTable[i].vc_conn;
+		mgcpcmd := f_get_mgcp_by_crit(MgcpExpectTable[i].crit);
+		if (match(cmd, mgcpcmd)) {
+			ret := MgcpExpectTable[i].vc_conn;
 			/* Release this entry */
-			ExpectTable[i].crit := omit;
-			ExpectTable[i].vc_conn := null;
+			MgcpExpectTable[i].crit := omit;
+			MgcpExpectTable[i].vc_conn := null;
 			log("Found Expect[", i, "] for ", cmd, " handled at ", ret);
 			return ret;
-//		}
+		}
 	}
 	setverdict(fail, "Couldn't find Expect for CRCX", cmd);
 	return ret;
@@ -202,29 +321,43 @@
 	var integer i;
 
 	/* Check an entry like this is not already presnt */
-	for (i := 0; i < sizeof(ExpectTable); i := i+1) {
-		if (crit == ExpectTable[i].crit) {
+	for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
+		if (crit == MgcpExpectTable[i].crit) {
 			setverdict(fail, "Crit already present", crit);
 			self.stop;
 		}
 	}
-	for (i := 0; i < sizeof(ExpectTable); i := i+1) {
-		if (not ispresent(ExpectTable[i].crit)) {
-			ExpectTable[i].crit := crit;
-			ExpectTable[i].vc_conn := hdlr;
+	for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
+		if (not ispresent(MgcpExpectTable[i].crit)) {
+			MgcpExpectTable[i].crit := crit;
+			MgcpExpectTable[i].vc_conn := hdlr;
 			log("Created Expect[", i, "] for ", crit, " to be handled at ", hdlr);
 			return;
 		}
 	}
-	setverdict(fail, "No space left in ExpectTable")
+	setverdict(fail, "No space left in MgcpExpectTable")
+}
+
+/* client/conn_hdlr side function to use procedure port to create expect in emulation */
+function f_create_mgcp_expect(ExpectCriteria dest_number) runs on MGCP_ConnHdlr {
+	MGCP_PROC.call(MGCPEM_register:{dest_number, self}) {
+		[] MGCP_PROC.getreply(MGCPEM_register:{?,?}) {};
+	}
 }
 
 private function f_expect_table_init()
 runs on MGCP_Emulation_CT {
 	var integer i;
-	for (i := 0; i < sizeof(ExpectTable); i := i + 1) {
-		ExpectTable[i].crit := omit;
+	for (i := 0; i < sizeof(MgcpExpectTable); i := i + 1) {
+		MgcpExpectTable[i].crit := omit;
 	}
 }
 
+function DummyUnitdataCallback(MgcpMessage msg)
+runs on MGCP_Emulation_CT return template MgcpMessage {
+	log("Ignoring MGCP ", msg);
+	return omit;
+}
+
+
 }
diff --git a/library/MGCP_Templates.ttcn b/library/MGCP_Templates.ttcn
index f4c6e0f..c0c827f 100644
--- a/library/MGCP_Templates.ttcn
+++ b/library/MGCP_Templates.ttcn
@@ -268,4 +268,18 @@
 		return int2hex(float2int(rnd()*2147483647.0), 8);
 	}
 
+	/* those verbs that related to a connection (and hence have ConnectionId) */
+	template MgcpVerb tr_MgcpVerb_ConnectionOriented := ("CRCX", "MDCX", "DLCX", "AUCX");
+	/* entire command template matching only connection oriented verbs */
+	template MgcpCommand tr_MgcpCommand_CO := {
+		line := {
+			verb := tr_MgcpVerb_ConnectionOriented,
+			trans_id := ?,
+			ep := ?,
+			ver := ?
+		},
+		params := *,
+		sdp := *
+	}
+
 }

-- 
To view, visit https://gerrit.osmocom.org/6089
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I953a91e663648715fa4fe98acacca393c8747001
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list