ipa: First version that emulates both MSC and BSC up to ASSIGNMENT REQ
diff --git a/library/BSSMAP_Emulation.ttcn b/library/BSSMAP_Emulation.ttcn
index bcc0e11..9e4d5c3 100644
--- a/library/BSSMAP_Emulation.ttcn
+++ b/library/BSSMAP_Emulation.ttcn
@@ -1,5 +1,6 @@
module BSSMAP_Emulation {
+import from SCCP_Emulation all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from BSSMAP_Templates all;
@@ -20,10 +21,15 @@
MSC_CONN_PRIM_DISC_REQ
}
+type record BSSAP_Conn_Req {
+ SCCP_PAR_Address addr_peer,
+ SCCP_PAR_Address addr_own,
+ PDU_BSSAP bssap
+}
+
/* port between individual per-connection components and this dispatcher */
type port BSSAP_Conn_PT message {
- inout PDU_BSSAP;
- inout BSSAP_Conn_Prim;
+ inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req;
} with { extension "internal" };
@@ -44,6 +50,27 @@
var ConnectionData ConnectionTable[16];
};
+private function f_conn_id_known(integer sccp_conn_id)
+runs on BSSMAP_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].sccp_conn_id == sccp_conn_id){
+ return true;
+ }
+ }
+ return false;
+}
+
+private function f_comp_known(BSSAP_ConnHdlr client)
+runs on BSSMAP_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return true;
+ }
+ }
+ return false;
+}
/* resolve component reference by connection ID */
private function f_comp_by_conn_id(integer sccp_conn_id)
@@ -70,6 +97,17 @@
self.stop;
}
+private function f_gen_conn_id()
+runs on BSSMAP_Emulation_CT return integer {
+ var integer conn_id;
+
+ do {
+ conn_id := float2int(rnd()*SCCP_Emulation.tsp_max_ConnectionId);
+ } while (f_conn_id_known(conn_id) == true);
+
+ return conn_id;
+}
+
private function f_conn_table_init()
runs on BSSMAP_Emulation_CT {
for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
@@ -84,6 +122,7 @@
if (ConnectionTable[i].sccp_conn_id == -1) {
ConnectionTable[i].comp_ref := comp_ref;
ConnectionTable[i].sccp_conn_id := sccp_conn_id;
+ log("Added conn table entry ", i, comp_ref, sccp_conn_id);
return;
}
}
@@ -95,6 +134,8 @@
runs on BSSMAP_Emulation_CT {
for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
if (ConnectionTable[i].sccp_conn_id == sccp_conn_id) {
+ log("Deleted conn table entry ", i,
+ ConnectionTable[i].comp_ref, sccp_conn_id);
ConnectionTable[i].sccp_conn_id := -1;
ConnectionTable[i].comp_ref := null;
}
@@ -135,8 +176,10 @@
while (true) {
var ASP_SCCP_N_UNITDATA_ind ud_ind;
var ASP_SCCP_N_CONNECT_ind conn_ind;
+ var ASP_SCCP_N_CONNECT_cfm conn_cfm;
var ASP_SCCP_N_DATA_ind data_ind;
var ASP_SCCP_N_DISCONNECT_ind disc_ind;
+ var BSSAP_Conn_Req creq;
var BSSAP_ConnHdlr vc_conn;
var PDU_BSSAP bssap;
@@ -183,6 +226,12 @@
/* TOOD: return confirm to other side? */
}
+ /* SCCP -> Client: connection confirm for outbound connection */
+ [] SCCP.receive(ASP_SCCP_N_CONNECT_cfm:?) -> value conn_cfm {
+ /* handle user payload */
+ f_handle_userData(vc_conn, conn_cfm.userData);
+ }
+
/* Disconnect request client -> SCCP */
[] CLIENT.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_REQ) -> sender vc_conn {
var integer conn_id := f_conn_id_by_comp(vc_conn);
@@ -191,9 +240,31 @@
}
/* BSSAP from client -> SCCP */
+ [] CLIENT.receive(BSSAP_Conn_Req:?) -> value creq sender vc_conn {
+ var integer conn_id;
+ /* encode + send to dispatcher */
+ var octetstring userdata := enc_PDU_BSSAP(creq.bssap);
+
+ if (f_comp_known(vc_conn) == false) {
+ /* unknown client, create new connection */
+ conn_id := f_gen_conn_id();
+
+ /* store mapping between client components and SCCP connectionId */
+ f_conn_table_add(vc_conn, conn_id);
+
+ SCCP.send(t_ASP_N_CONNECT_req(creq.addr_peer, creq.addr_own, omit, omit,
+ userdata, conn_id, omit));
+ } else {
+ /* known client, send via existing connection */
+ conn_id := f_conn_id_by_comp(vc_conn);
+ SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit));
+ }
+
+ }
+
[] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn {
var integer conn_id := f_conn_id_by_comp(vc_conn);
- /* encode + send to dispatcher */
+ /* encode + send it to dispatcher */
var octetstring userdata := enc_PDU_BSSAP(bssap);
SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit));
}
diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index b030072..274f42e 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -11,7 +11,9 @@
spare := '0000000'B,
dlci := omit,
lengthIndicator := 0, /* overwritten by codec */
- pdu := ?
+ pdu := {
+ bssmap := ?
+ }
}
template PDU_BSSAP tr_BSSAP_BSSMAP := {
@@ -24,6 +26,27 @@
}
}
+template PDU_BSSAP ts_BSSAP_DTAP := {
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := omit,
+ lengthIndicator := 0, /* overwritten by codec */
+ pdu := {
+ dtap := ?
+ }
+}
+
+template PDU_BSSAP tr_BSSAP_DTAP := {
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := omit,
+ lengthIndicator := ?,
+ pdu := {
+ dtap := ?
+ }
+}
+
+
template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
elementIdentifier := '04'O,
lengthIndicator := 0,
@@ -238,4 +261,119 @@
}
}
+template PDU_BSSAP tr_BSSMAP_AssignmentCmd modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ assignmentRequest := {
+ messageType :='01'O, /* overwritten */
+ channelType := ?,
+ layer3HeaderInfo := *,
+ priority := *,
+ circuitIdentityCode := ?,
+ downLinkDTX_Flag := *,
+ interferenceBandToBeUsed := *,
+ classmarkInformationType2 := *,
+ groupCallReference := *,
+ talkerFlag := *,
+ configurationEvolutionIndication := *,
+ lsaAccesControlSuppression := *,
+ serviceHandover := *,
+ encryptionInformation := *,
+ talkerPriority := *,
+ aoIPTransportLayer := *,
+ codecList := *,
+ callIdentifier := *,
+ kC128 := *,
+ globalCallReference := *,
+ lCLS_Configuration := *,
+ lCLS_ConnectionStatusControl := *,
+ lCLS_CorrelationNotNeeded := *
+ }
+ }
+ }
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_AssignmentComplete(BSSMAP_IE_CircuitIdentityCode cic)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ assignmentComplete := {
+ messageType :='02'O, /* overwritten */
+ circuitIdentityCode := cic,
+ cellIdentifier := omit,
+ chosenChannel := omit,
+ chosenEncryptionAlgorithm := omit,
+ circuitPool := omit,
+ speechVersion := omit,
+ lSAIdentifier := omit,
+ talkerPriority := omit,
+ aoIPTransportLayer := omit,
+ speechCodec := omit,
+ codecList := omit,
+ lCLS_BSS_Status := omit
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_AssignmentComplete modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ assignmentComplete := {
+ messageType := '02'O, /* overwritten */
+ circuitIdentityCode := ?,
+ cellIdentifier := *,
+ chosenChannel := *,
+ chosenEncryptionAlgorithm := *,
+ circuitPool := *,
+ speechVersion := *,
+ lSAIdentifier := *,
+ talkerPriority := *,
+ aoIPTransportLayer := *,
+ speechCodec := *,
+ codecList := *,
+ lCLS_BSS_Status := *
+ }
+ }
+ }
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_ClearCommand(BssmapCause cause)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ clearCommand := {
+ messageType := '20'O, /* overwritten */
+ layer3HeaderInfo := omit,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ cSFB_Indication := omit
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_ClearCommand modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ clearCommand := {
+ messageType := '20'O, /* overwritten */
+ layer3HeaderInfo := *,
+ cause := ?,
+ cSFB_Indication := *
+ }
+ }
+ }
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_ClearComplete
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ clearComplete := {
+ messageType := '21'O /* overwritten */
+ }
+ }
+ }
+}
+
}
diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn
index 4d21bb4..ed51110 100644
--- a/library/IPA_Emulation.ttcn
+++ b/library/IPA_Emulation.ttcn
@@ -12,6 +12,11 @@
}
*/
+type enumerated IpaMode {
+ IPA_MODE_CLIENT,
+ IPA_MODE_SERVER
+}
+
type record ASP_IPA_Unitdata {
IpaStreamId streamId,
octetstring payload
@@ -31,6 +36,8 @@
var boolean g_initialized := false;
var ConnectionId g_ipa_conn_id := -1;
+
+ var IpaMode g_mode;
}
function f_connect(charstring remote_host, PortNumber remote_port,
@@ -41,6 +48,13 @@
g_ipa_conn_id := res.connId;
}
+function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
+ var Result res;
+ res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
+ local_host, local_port, { tcp:={} });
+ g_ipa_conn_id := res.connId;
+}
+
template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
sio := { '10'B, '00'B, '0011'B },
opc := opc,
@@ -107,6 +121,15 @@
u := omit
}
+template PDU_IPA_CCM ts_IPA_ID_GET := {
+ msg_type := IPAC_MSGT_ID_GET,
+ u := {
+ get := {
+ { 1, IPAC_IDTAG_UNITNAME }
+ }
+ }
+}
+
/* receive IPA CCM message */
private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
select (ccm.msg_type) {
@@ -142,12 +165,24 @@
return ret;
}
-function ScanEvents() runs on IPA_Emulation_CT {
+function main_client(charstring remote_host, PortNumber remote_port,
+ charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
+ g_mode := IPA_MODE_CLIENT;
+ f_connect(remote_host, remote_port, local_host, local_port);
+ ScanEvents();
+}
+
+function main_server(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
+ g_mode := IPA_MODE_SERVER;
+ f_bind(local_host, local_port);
+ ScanEvents();
+}
+
+private function ScanEvents() runs on IPA_Emulation_CT {
var IPA_RecvFrom ipa_rx;
var ASP_IPA_Unitdata ipa_ud;
var ASP_MTP3_TRANSFERreq mtp_req;
-
- f_connect("127.0.0.1", 5000, "127.0.0.1", 49999);
+ var ASP_Event asp_evt;
while (true) {
alt {
@@ -170,6 +205,21 @@
}
}
+ /* server only */
+ [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
+ log("IPA: Connected");
+ g_ipa_conn_id := asp_evt.connOpened.connId;
+ if (g_mode == IPA_MODE_SERVER) {
+ f_ccm_tx(valueof(ts_IPA_ID_GET));
+ }
+ }
+
+ [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
+ log("IPA: Closed");
+ g_ipa_conn_id := -1;
+ self.stop;
+ }
+
/* Received SCCP -> down into IPA */
[] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
var IPA_Send ipa_tx := {