module BSSAP_Adapter { /* This module implements a 'dumb' BSSAP adapter. It creates the M3UA and SCCP components and stacks a BSSAP * codec port on top. As a result, it provides the ability to transceive SCCP-User-SAP primitives with * deoded BSSAP payload. Use this if you want to have full control about what you transmit or receive, * without any automatisms in place. Allows you to refuse connections or other abnormal behavior. */ import from General_Types all; import from Osmocom_Types all; import from M3UA_Types all; import from M3UA_Emulation all; import from MTP3asp_Types all; import from MTP3asp_PortType all; import from SCCP_Types all; import from SCCPasp_Types all; import from SCCP_Emulation all; import from SCTPasp_Types all; import from SCTPasp_PortType all; import from BSSAP_CodecPort all; import from BSSMAP_Templates all; import from BSSMAP_Emulation all; import from MSC_ConnectionHandler all; type component BSSAP_Adapter_CT { /* component references */ var M3UA_CT vc_M3UA; var SCCP_CT vc_SCCP; /* test port to SCCP emulation */ port BSSAP_CODEC_PT BSSAP; var octetstring g_sio; var MSC_SCCP_MTP3_parameters g_sccp_pars; var SCCP_PAR_Address g_sccp_addr_own, g_sccp_addr_peer; /* handler mode */ var BSSMAP_Emulation_CT vc_BSSMAP; } modulepar { charstring mp_sccp_service_type := "mtp3_itu"; SCTP_Association_Address mp_sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" }; integer mp_own_pc := 185; /* 0.23.1 */ integer mp_own_ssn := 254; integer mp_peer_pc := 187; integer mp_peer_ssn := 254; } /* construct a SCCP_PAR_Address with just PC + SSN and no GT */ template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn) := { addressIndicator := { pointCodeIndic := '1'B, ssnIndicator := '1'B, globalTitleIndic := '0000'B, routingIndicator := '1'B }, signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, '83'O), //signPointCode := SCCP_SPC_int2bit(pc, mp_sccp_service_type, g_sio), subsystemNumber := ssn, globalTitle := omit } private function init_pars() runs on BSSAP_Adapter_CT { g_sio := '83'O; g_sccp_pars := { sio := { ni := substr(oct2bit(g_sio),0,2), prio := substr(oct2bit(g_sio),2,2), si := substr(oct2bit(g_sio),4,4) }, opc := mp_own_pc, dpc := mp_peer_pc, sls := 0, sccp_serviceType := mp_sccp_service_type, ssn := mp_own_ssn }; g_sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(mp_own_pc, mp_own_ssn)); g_sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(mp_peer_pc, mp_peer_ssn)); } function f_bssap_init(charstring id, boolean handler_mode := false) runs on BSSAP_Adapter_CT { init_pars(); /* create components */ vc_M3UA := M3UA_CT.create(id & "-M3UA"); vc_SCCP := SCCP_CT.create(id & "-SCCP"); if (handler_mode) { vc_BSSMAP := BSSMAP_Emulation_CT.create(id & "-BSSMAP"); } map(vc_M3UA:SCTP_PORT, system:sctp); /* connect MTP3 service provider (M3UA) to lower side of SCCP */ connect(vc_M3UA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT); if (handler_mode) { connect(vc_BSSMAP:BSSAP, vc_SCCP:SCCP_SP_PORT); } else { /* connect BSSNAP dispatcher to upper side of SCCP */ connect(self:BSSAP, vc_SCCP:SCCP_SP_PORT); } vc_M3UA.start(f_M3UA_Emulation(mp_sctp_addr)); vc_SCCP.start(SCCPStart(g_sccp_pars)); if (handler_mode) { vc_BSSMAP.start(BSSMAP_Emulation.main(MSC_BssmapOps, "")); } } private altstep as_reset_ack() runs on BSSAP_Adapter_CT { var BSSAP_N_UNITDATA_ind ud_ind; [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) -> value ud_ind { log("Respoding to inbound RESET with RESET-ACK"); BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress, ts_BSSMAP_ResetAck)); repeat; } } function f_bssap_wait_for_reset() runs on BSSAP_Adapter_CT { var BSSAP_N_UNITDATA_ind ud_ind; timer T := 20.0; T.start; alt { [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset)) -> value ud_ind { BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress, ts_BSSMAP_ResetAck)); } [] as_reset_ack(); [] BSSAP.receive { repeat; } [] T.timeout { setverdict(fail); } } } function f_bssap_reset() runs on BSSAP_Adapter_CT { timer T := 5.0; BSSAP.send(ts_BSSAP_UNITDATA_req(g_sccp_addr_peer, g_sccp_addr_own, ts_BSSMAP_Reset(0))); T.start; alt { [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_sccp_addr_own, g_sccp_addr_peer, tr_BSSMAP_ResetAck)) { log("Received RESET-ACK in response to RESET, we're ready to go!"); } [] as_reset_ack(); [] BSSAP.receive { repeat }; [] T.timeout { setverdict(fail, "Waiting for RESET-ACK after sending RESET"); } } } }