From c82eef458d6ae6cdb7290744607d61ca1e693983 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 24 Nov 2017 20:40:12 +0100 Subject: [PATCH] ipa: Further progress on the bsc-nat test suite --- ipa/BSC_MS_Simulation.ttcn | 5 +- ipa/MSC_ConnectionHandler.ttcn | 89 +++++++++++++++++++++++-- ipa/MSC_Simulation.ttcn | 3 + ipa/gen_links.sh | 14 +++- ipa/regen_makefile.sh | 2 +- library/BSSMAP_Emulation.ttcn | 116 ++++++++++++++++++++++++++++++++- library/IPA_CodecPort.ttcn | 7 ++ library/IPA_Emulation.ttcn | 84 +++++++++++++++++------- library/MGCP_Templates.ttcn | 10 +++ 9 files changed, 294 insertions(+), 36 deletions(-) diff --git a/ipa/BSC_MS_Simulation.ttcn b/ipa/BSC_MS_Simulation.ttcn index c33e84847..24ac4bcaa 100644 --- a/ipa/BSC_MS_Simulation.ttcn +++ b/ipa/BSC_MS_Simulation.ttcn @@ -43,9 +43,12 @@ function main(charstring remote_ip, PortNumber remote_port, /* connect MTP3 service provider (IPA) to lower side of SCCP */ connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT); - /* connect BSSNAP dispatcher to upper side of SCCP */ + /* connect BSSMAP dispatcher to upper side of SCCP */ connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT); + /* connect BSSMAP dispatcher to IPA_Emulation MGCP */ + connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT); + vc_IPA.start(IPA_Emulation.main_client(remote_ip, remote_port, local_ip, local_port)); vc_SCCP.start(SCCPStart(sccp_pars)); vc_BSSMAP.start(BSSMAP_Emulation.main(BSC_MS_BssmapOps)); diff --git a/ipa/MSC_ConnectionHandler.ttcn b/ipa/MSC_ConnectionHandler.ttcn index 641a832b3..53123fe83 100644 --- a/ipa/MSC_ConnectionHandler.ttcn +++ b/ipa/MSC_ConnectionHandler.ttcn @@ -7,6 +7,10 @@ import from BSSAP_Types all; import from BSSMAP_Emulation all; import from BSSMAP_Templates all; +import from MGCP_Types all; +import from MGCP_Templates all; +import from SDP_Types all; + /* this component represents a single subscriber connection at the MSC. * There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components. * We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */ @@ -15,6 +19,11 @@ type component MSC_ConnHdlr extends BSSAP_ConnHdlr { var uint5_t g_e1_timeslot; /* SCCP Connecction Identifier for the underlying SCCP connection */ var integer g_sccp_conn_id; + + var MSC_State g_state := MSC_STATE_NONE; + var MgcpEndpoint g_ep_name; + var MgcpCallId g_call_id; + var MgcpConnectionId g_mgcp_conn_id; } /* Callback function from general BSSMAP_Emulation whenever a new incoming @@ -49,30 +58,98 @@ const BssmapOps MSC_BssmapOps := { unitdata_cb := refers(UnitdataCallback) } +type enumerated MSC_State { + MSC_STATE_NONE, + MSC_STATE_WAIT_ASS_COMPL, + MSC_STATE_WAIT_CRCX_ACK, + MSC_STATE_WAIT_MDCX_ACK, + MSC_STATE_WAIT_CLEAR_COMPL, + MSC_STATE_WAIT_DLCX_ACK +} + +private function f_mgcp_alloc_tid() return MgcpTransId { + return int2str(float2int(rnd()*2147483647.0)); +} + +private function f_mgcp_alloc_call_id() return MgcpCallId { + return int2hex(float2int(rnd()*2147483647.0), 8); +} + +function extract_conn_id(MgcpResponse resp) return MgcpConnectionId { + var integer i; + for (i := 0; i < lengthof(resp.params); i := i + 1) { + var MgcpParameter par := resp.params[i]; + if (par.code == "I") { + return str2hex(par.val); + } + } + setverdict(fail); + return '00000000'H; +} + /* main function processing various incoming events */ function main(integer connection_id, integer timeslot) runs on MSC_ConnHdlr { - g_sccp_conn_id := connection_id; + var MgcpResponse mgcp_rsp; + g_e1_timeslot := 1; /* FIXME */ + g_sccp_conn_id := connection_id; + g_call_id := f_mgcp_alloc_call_id(); + g_ep_name := hex2str(int2hex(g_e1_timeslot, 1)) & "@mgw"; + while (true) { var PDU_BSSAP bssap; alt { /* new SCCP-level connection indication from BSC */ - [] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap { + [g_state == MSC_STATE_NONE] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap { /* respond with ASSIGNMENT CMD */ + g_state := MSC_STATE_WAIT_ASS_COMPL; BSSAP.send(ts_BSSMAP_AssignmentReq(0, g_e1_timeslot)); - /* FIXME: Send MGCP */ + } + [g_state == MSC_STATE_WAIT_ASS_COMPL] BSSAP.receive(tr_BSSMAP_AssignmentComplete) { + /* FIXME: Send MGCP CRCX */ + g_state := MSC_STATE_WAIT_CRCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + //template SDP_Message sdp := omit; + BSSAP.send(ts_CRCX(trans_id, g_ep_name, "recvonly", g_call_id)); //, sdp)); } /* - [] BSSAP.receive(tr_BSSMAP_AssignmentCompl) { - } [] BSSAP.receive(tr_BSSMAP_AssignmentFail) { } */ + + /* receive CRCX ACK: transmit MDCX */ + [g_state == MSC_STATE_WAIT_CRCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp { + /* extract connection ID */ + g_mgcp_conn_id := extract_conn_id(mgcp_rsp); + g_state := MSC_STATE_WAIT_MDCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + BSSAP.send(ts_MDCX(trans_id, g_ep_name, "sendrecv", g_call_id, g_mgcp_conn_id)); + } + + /* receive MDCX ACK: wait + transmit CLEAR COMMAND */ + [g_state == MSC_STATE_WAIT_MDCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp { + g_state := MSC_STATE_WAIT_CLEAR_COMPL + BSSAP.send(ts_BSSMAP_ClearCommand(0)); + } + + /* CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */ + [g_state == MSC_STATE_WAIT_CLEAR_COMPL] BSSAP.receive(ts_BSSMAP_ClearComplete) { + /* send DLCX */ + g_state := MSC_STATE_WAIT_DLCX_ACK; + var MgcpTransId trans_id := f_mgcp_alloc_tid(); + BSSAP.send(ts_DLCX(trans_id, g_ep_name, g_call_id)); + } + + [g_state == MSC_STATE_WAIT_DLCX_ACK] BSSAP.receive(tr_DLCX_ACK) { + setverdict(pass); + self.stop; + } + /* TODO: CLEAR REQUEST from BSS */ - /* TODO: CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */ [] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) { + setverdict(fail); self.stop; } diff --git a/ipa/MSC_Simulation.ttcn b/ipa/MSC_Simulation.ttcn index 8c9418845..0198350ce 100755 --- a/ipa/MSC_Simulation.ttcn +++ b/ipa/MSC_Simulation.ttcn @@ -46,6 +46,9 @@ function main(charstring local_ip, PortNumber local_port, /* connect BSSNAP dispatcher to upper side of SCCP */ connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT); + /* connect BSSMAP dispatcher to IPA_Emulation MGCP */ + connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT); + vc_IPA.start(IPA_Emulation.main_server(local_ip, local_port)); vc_SCCP.start(SCCPStart(sccp_pars)); vc_BSSMAP.start(BSSMAP_Emulation.main(MSC_BssmapOps)); diff --git a/ipa/gen_links.sh b/ipa/gen_links.sh index be11ec053..7dd5ed2be 100755 --- a/ipa/gen_links.sh +++ b/ipa/gen_links.sh @@ -16,7 +16,7 @@ gen_links() { #gen_links $DIR $FILES DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src -FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h" +FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h SDP_EncDec.cc" gen_links $DIR $FILES DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src @@ -35,7 +35,7 @@ gen_links $DIR $FILES DIR=../SCCP_CNL113341/src FILES="SCCP_Emulation.ttcn SCCP_EncDec.cc SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn" gen_links $DIR $FILES -ln -s SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn +ln -sf SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src FILES="BSSAP_Types.ttcn" @@ -45,7 +45,15 @@ DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn" gen_links $DIR $FILES +DIR=$BASEDIR/titan.ProtocolModules.SDP/src +FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l +SDP_parser.y lex.SDP_parse_.c" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.RTP/src +FILES="RTP_EncDec.cc RTP_Types.ttcn" +gen_links $DIR $FILES DIR=../library -FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn" +FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn" gen_links $DIR $FILES diff --git a/ipa/regen_makefile.sh b/ipa/regen_makefile.sh index 1acda328b..be79a351f 100755 --- a/ipa/regen_makefile.sh +++ b/ipa/regen_makefile.sh @@ -2,7 +2,7 @@ MAIN=IPA_Test.ttcn -FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc" +FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc SDP_EncDec *.c" ttcn3_makefilegen -l -f $MAIN $FILES sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile diff --git a/library/BSSMAP_Emulation.ttcn b/library/BSSMAP_Emulation.ttcn index 5cf534236..7a8413386 100644 --- a/library/BSSMAP_Emulation.ttcn +++ b/library/BSSMAP_Emulation.ttcn @@ -4,7 +4,9 @@ import from SCCP_Emulation all; import from SCCPasp_Types all; import from BSSAP_Types all; import from BSSMAP_Templates all; -//import from MSC_ConnectionHandler all; +import from MGCP_Types all; +import from MGCP_Templates all; +import from IPA_Emulation all; /* General "base class" component definition, of which specific implementations * derive themselves by means of the "extends" feature */ @@ -29,7 +31,7 @@ type record BSSAP_Conn_Req { /* port between individual per-connection components and this dispatcher */ type port BSSAP_Conn_PT message { - inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req; + inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req, MgcpCommand, MgcpResponse; } with { extension "internal" }; @@ -37,7 +39,11 @@ type port BSSAP_Conn_PT message { type record ConnectionData { /* reference to the instance of the per-connection component */ BSSAP_ConnHdlr comp_ref, - integer sccp_conn_id + integer sccp_conn_id, + /* most recent MGCP transaction ID (Used on MSC side) */ + MgcpTransId mgcp_trans_id optional, + /* CIC that has been used for voice of this channel (BSC side) */ + integer cic optional } type component BSSMAP_Emulation_CT { @@ -45,6 +51,8 @@ type component BSSMAP_Emulation_CT { port SCCPasp_PT SCCP; /* BSSAP port to the per-connection clients */ port BSSAP_Conn_PT CLIENT; + /* MGCP port */ + port IPA_MGCP_PT MGCP; /* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */ var ConnectionData ConnectionTable[16]; @@ -85,6 +93,56 @@ runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr { self.stop; } +/* resolve component reference by CIC */ +private function f_comp_by_mgcp_tid(MgcpTransId tid) +runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].mgcp_trans_id == tid) { + return ConnectionTable[i].comp_ref; + } + } + log("BSSMAP Connection table not found by MGCP Transaction ID ", tid); + self.stop; +} + +private function f_comp_store_mgcp_tid(BSSAP_ConnHdlr client, MgcpTransId tid) +runs on BSSMAP_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].comp_ref == client) { + ConnectionTable[i].mgcp_trans_id := tid; + return; + } + } + log("BSSMAP Connection table not found by component ", client); + self.stop; +} + +private function f_comp_by_cic(integer cic) +runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].cic == cic) { + return ConnectionTable[i].comp_ref; + } + } + log("BSSMAP Connection table not found by CIC ", cic); + self.stop; +} + +private function f_comp_store_cic(BSSAP_ConnHdlr client, integer cic) +runs on BSSMAP_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(ConnectionTable); i := i+1) { + if (ConnectionTable[i].comp_ref == client) { + ConnectionTable[i].cic := cic; + return; + } + } + log("BSSMAP Connection table not found by component ", client); +} + /* resolve connection ID by component reference */ private function f_conn_id_by_comp(BSSAP_ConnHdlr client) runs on BSSMAP_Emulation_CT return integer { @@ -113,6 +171,8 @@ runs on BSSMAP_Emulation_CT { for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) { ConnectionTable[i].comp_ref := null; ConnectionTable[i].sccp_conn_id := -1; + ConnectionTable[i].mgcp_trans_id := omit; + ConnectionTable[i].cic := omit; } } @@ -178,6 +238,8 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT { var BSSAP_Conn_Req creq; var BSSAP_ConnHdlr vc_conn; var PDU_BSSAP bssap; + var MgcpCommand mgcp_req; + var MgcpResponse mgcp_resp; alt { /* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */ @@ -266,14 +328,62 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT { [] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn { var integer conn_id := f_conn_id_by_comp(vc_conn); + /* MSC Side: If this is an assignment command, store CIC */ + if (ischosen(bssap.pdu.bssmap.assignmentRequest) and + ispresent(bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode)) { + var BSSMAP_IE_CircuitIdentityCode cic_ie := + bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode; + var integer cic := (oct2int(cic_ie.cicHigh) * 256) + oct2int(cic_ie.cicLow); + f_comp_store_cic(vc_conn, cic); + } /* encode + send it to dispatcher */ var octetstring userdata := enc_PDU_BSSAP(bssap); SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit)); } + /* Handling of MGCP in IPA SCCPLite case. This predates 3GPP AoIP + * and uses a MGCP session in parallel to BSSAP. BSSAP uses CIC + * as usual, and MGCP uses "CIC@mgw" endpoint naming, where CIC + * is printed as hex string, e.g. a@mgw for CIC 10 */ + + /* CLIENT -> MGCP */ + [] CLIENT.receive(MgcpCommand:?) -> value mgcp_req sender vc_conn { + /* MGCP request from Handler (we're MSC) */ + /* store the transaction ID we've seen */ + f_comp_store_mgcp_tid(vc_conn, mgcp_req.line.trans_id); + /* simply forward any MGCP from the client to the port */ + MGCP.send(mgcp_req); + } + [] CLIENT.receive(MgcpResponse:?) -> value mgcp_resp sender vc_conn { + /* MGCP response from Handler (we're BSC/MGW) */ + /* simply forward any MGCP from the client to the port */ + MGCP.send(mgcp_resp); + } + + /* MGCP -> CLIENT */ + [] MGCP.receive(MgcpCommand:?) -> value mgcp_req { + /* MGCP request from network side (we're BSC/MGW) */ + /* Extract CIC from local part of endpoint name */ + var integer cic := f_mgcp_ep_extract_cic(mgcp_req.line.ep); + /* Resolve the vc_conn by the CIC */ + vc_conn := f_comp_by_cic(cic); + CLIENT.send(mgcp_req) to vc_conn; + } + [] MGCP.receive(MgcpResponse:?) -> value mgcp_resp { + /* MGCP response from network side (we're MSC) */ + /* Resolve the vc_conn by the transaction ID */ + vc_conn := f_comp_by_mgcp_tid(mgcp_resp.line.trans_id); + CLIENT.send(mgcp_resp) to vc_conn; + } + } } } +private function f_mgcp_ep_extract_cic(charstring inp) return integer { + var charstring local_part := regexp(inp, "(.*)@(.*)", 0); + return hex2int(str2hex(local_part)); + +} } diff --git a/library/IPA_CodecPort.ttcn b/library/IPA_CodecPort.ttcn index de47a16fb..3c68e2279 100644 --- a/library/IPA_CodecPort.ttcn +++ b/library/IPA_CodecPort.ttcn @@ -18,6 +18,13 @@ module IPA_CodecPort { octetstring msg } + template IPA_Send t_IPA_Send(ConnectionId conn_id, IpaStreamId stream_id, + octetstring msg, template IpaExtStreamId stream_id_ext := omit) := { + connId := conn_id, + streamId := stream_id, + streamIdExt := stream_id_ext, + msg := msg + } /* 'stream' contains the octets received so far, we must return the total length */ function f_IPA_getMsgLen(in octetstring stream, inout ro_integer args) return integer { diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn index 57edb0080..3b8d931f6 100644 --- a/library/IPA_Emulation.ttcn +++ b/library/IPA_Emulation.ttcn @@ -7,6 +7,8 @@ import from IPL4asp_Types all; import from MTP3asp_Types all; import from MTP3asp_PortType all; +import from MGCP_Types all; + /* modulepar { } @@ -19,7 +21,7 @@ type enumerated IpaMode { type record ASP_IPA_Unitdata { IpaStreamId streamId, - IpaStreamIdExt streamIdExt optional, + IpaExtStreamId streamIdExt optional, octetstring payload } @@ -27,16 +29,24 @@ type port IPA_SP_PT message { inout ASP_IPA_Unitdata; } with { extension "internal" } +type port IPA_MGCP_PT message { + inout MgcpCommand, MgcpResponse; +} with { extension "internal" } + type component IPA_Emulation_CT { /* down-facing port to IPA codec port */ port IPA_CODEC_PT IPA_PORT; /* up-facing port to SCCP */ port MTP3asp_SP_PT MTP3_SP_PORT; + /* up-facing port for MGCP */ + port IPA_MGCP_PT IPA_MGCP_PORT; /* up-facing port for other streams */ port IPA_SP_PT IPA_SP_PORT; var boolean g_initialized := false; var ConnectionId g_ipa_conn_id := -1; + /* Are we a BSC/MGW (truel) or MSC (false) */ + var boolean g_is_bsc_mgw; var IpaMode g_mode; } @@ -47,6 +57,7 @@ function f_connect(charstring remote_host, PortNumber remote_port, res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port, local_host, local_port, 0, { tcp:={} }); g_ipa_conn_id := res.connId; + g_is_bsc_mgw := true; } function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT { @@ -54,6 +65,7 @@ function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulat res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT, local_host, local_port, { tcp:={} }); g_ipa_conn_id := res.connId; + g_is_bsc_mgw := false; } template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := { @@ -103,12 +115,7 @@ private function f_ccm_make_id_resp(PDU_IPA_CCM get) return PDU_IPA_CCM { /* transmit IPA CCM message */ private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT { - var IPA_Send ipa_tx := { - connId := g_ipa_conn_id, - streamId := IPAC_PROTO_CCM, - streamIdExt := omit, - msg := enc_PDU_IPA_CCM(ccm) - } + var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm))); log("CCM Tx:", ccm); IPA_PORT.send(ipa_tx); } @@ -160,12 +167,8 @@ private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata { } private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send { - var IPA_Send ret := { - connId := connId, - streamId := ipa_tx.streamId, - streamIdExt := ipa_tx.streamIdExt, - msg := ipa_tx.payload - } + var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload, + ipa_tx.streamIdExt)); return ret; } @@ -182,11 +185,24 @@ function main_server(charstring local_host, PortNumber local_port) runs on IPA_E ScanEvents(); } +private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT { + var charstring msg_ch := oct2char(msg); + if (g_is_bsc_mgw) { + log("============"); + log(msg_ch); + IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch)); + } else { + IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch)); + } +} + 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; var ASP_Event asp_evt; + var MgcpCommand mgcp_cmd; + var MgcpResponse mgcp_rsp; while (true) { alt { @@ -197,13 +213,21 @@ private function ScanEvents() runs on IPA_Emulation_CT { var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg); log("CCM Rx:", ccm); f_ccm_rx(ccm); - } - case (IPAC_PROTO_SCCP) { + } case (IPAC_PROTO_SCCP) { var ASP_MTP3_TRANSFERind mtp; mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg)); MTP3_SP_PORT.send(mtp); + } case (IPAC_PROTO_MGCP_OLD) { + f_mgcp_to_user(ipa_rx.msg); + } case (IPAC_PROTO_OSMO) { + select (ipa_rx.streamIdExt) { + case (IPAC_PROTO_EXT_MGCP) { + f_mgcp_to_user(ipa_rx.msg); + } case else { + IPA_SP_PORT.send(f_to_asp(ipa_rx)); + } } - case else { + } case else { IPA_SP_PORT.send(f_to_asp(ipa_rx)); } } @@ -226,15 +250,31 @@ private function ScanEvents() runs on IPA_Emulation_CT { /* Received SCCP -> down into IPA */ [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req { - var IPA_Send ipa_tx := { - connId := g_ipa_conn_id, - streamId := IPAC_PROTO_SCCP, - msg := mtp_req.data - } + var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_SCCP, + mtp_req.data)); IPA_PORT.send(ipa_tx); } - /* Received MISC (RSL/OML/CTRL/MGCP) -> down into IPA */ + /* Received MGCP -> down into IPA */ + [] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd { + ipa_ud := { + streamId := IPAC_PROTO_OSMO, + streamIdExt := IPAC_PROTO_EXT_MGCP, + payload := char2oct(enc_MgcpCommand(mgcp_cmd)) + } + IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud)); + } + [] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp { + ipa_ud := { + streamId := IPAC_PROTO_OSMO, + streamIdExt := IPAC_PROTO_EXT_MGCP, + payload := char2oct(enc_MgcpResponse(mgcp_rsp)) + } + IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud)); + } + + + /* Received MISC (RSL/OML/CTRL) -> down into IPA */ [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud { IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud)); } diff --git a/library/MGCP_Templates.ttcn b/library/MGCP_Templates.ttcn index f78bfc7f2..30a5c8ed2 100644 --- a/library/MGCP_Templates.ttcn +++ b/library/MGCP_Templates.ttcn @@ -102,6 +102,16 @@ module MGCP_Templates { return cmd; } + template MgcpResponse tr_DLCX_ACK := { + line := { + code := "200", + trans_id := ?, + string := "OK" + }, + params:= *, + sdp := * + } + /* SDP Templates */ template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id, charstring session_version := "1",