module REMSIM_Tests { /* Implementation of RSPRO Client in TTCN-3. * (C) 2019 by Harald Welte * All rights reserved. * * Released under the terms of GNU General Public License, Version 2 or * (at your option) any later version. * * SPDX-License-Identifier: GPL-2.0-or-later */ import from IPL4asp_Types all; import from RSPRO all; import from RSPRO_Types all; import from IPA_Types all; import from IPA_Emulation all; modulepar { charstring mp_bankd_ip := "127.0.0.1"; integer mp_bankd_port := 9999; charstring mp_server_ip := "127.0.0.1"; integer mp_server_port := 9998; integer mp_rsres_port := 9997; } const integer NUM_CLIENT := 3; type record RSPRO_Client { IPA_Emulation_CT vc_IPA, IPA_CCM_Parameters ccm_pars, charstring id, ComponentIdentity rspro_id, ClientSlot rspro_client_slot optional, BankId rspro_bank_id optional, SlotNumber rspro_bank_nslots optional }; type component rspro_client_CT { var RSPRO_Client rspro[NUM_CLIENT]; port IPA_RSPRO_PT RSPRO[NUM_CLIENT]; }; private altstep as_ignore_id_ack(integer i := 0) runs on rspro_client_CT { [] RSPRO[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) { repeat; } } function f_rspro_init(inout RSPRO_Client clnt, charstring dst_host, integer dst_port, ComponentIdentity rspro_id, integer i) runs on rspro_client_CT { timer T := 4.0; clnt.id := "RSPRO" & int2str(i); clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id); clnt.ccm_pars := c_IPA_default_ccm_pars; clnt.ccm_pars.name := "Osmocom TTCN-3 RSPRO client simulator"; clnt.rspro_id := rspro_id; /* leave it up to the caller to set those */ clnt.rspro_client_slot := omit; clnt.rspro_bank_id := omit; clnt.rspro_bank_nslots := omit; map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT); connect(clnt.vc_IPA:IPA_RSPRO_PORT, self:RSPRO[i]); clnt.vc_IPA.start(IPA_Emulation.main_client(dst_host, dst_port, "", 10000+i, clnt.ccm_pars)); T.start; alt { [] RSPRO[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { } [] T.timeout { setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_UP"); mtc.stop; } } T.start; alt { [] RSPRO[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) { } [] T.timeout { setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_ID_ACK"); mtc.stop; } } activate(as_ignore_id_ack(i)); } function f_rspro_fini(inout RSPRO_Client clnt, integer i) runs on rspro_client_CT { clnt.vc_IPA.stop; disconnect(clnt.vc_IPA:IPA_RSPRO_PORT, self:RSPRO[i]); unmap(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT); } function f_rspro_exp(template RsproPDU exp, integer i := 0) runs on rspro_client_CT return RsproPDU { var RsproPDU pdu; timer T := 10.0; T.start; alt { [] RSPRO[i].receive(exp) -> value pdu { setverdict(pass); } [] RSPRO[i].receive(RsproPDU:?) -> value pdu { setverdict(fail, "Received unexpected RPSRO", pdu); mtc.stop; } [] RSPRO[i].receive { setverdict(fail, "Received unexpected != RPSRO"); mtc.stop; } [] T.timeout { setverdict(fail, "Timeout waiting for ", exp); mtc.stop; } } return pdu; } function f_rspro_exp_disconnect(integer i := 0) runs on rspro_client_CT { timer T := 10.0; T.start; alt { [] RSPRO[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) { setverdict(pass); } [] T.timeout { setverdict(fail, "Timeout expecting disconnect"); mtc.stop; } } } function f_rspro_connect_client(integer i, template ResultCode exp_res := ok) runs on rspro_client_CT { select (rspro[i].rspro_id.type_) { case (remsimClient) { RSPRO[i].send(ts_RSPRO_ConnectClientReq(rspro[i].rspro_id, rspro[i].rspro_client_slot)); f_rspro_exp(tr_RSPRO_ConnectClientRes(?, exp_res), i); } case (remsimBankd) { var template IpAddress ip := ts_IPv4(mp_bankd_ip); RSPRO[i].send(ts_RSPRO_ConnectBankReq(rspro[i].rspro_id, rspro[i].rspro_bank_id, rspro[i].rspro_bank_nslots, ts_IpPort(ip, mp_bankd_port))); f_rspro_exp(tr_RSPRO_ConnectBankRes(?, exp_res), i); } case else { setverdict(fail, "Unsupported type ", rspro[i].rspro_id.type_); mtc.stop; } } } function f_rspro_connect_clients() runs on rspro_client_CT { var integer i; for (i := 0; i < NUM_CLIENT; i := i+1) { select (rspro[i].rspro_id.type_) { case (remsimClient) { RSPRO[i].send(ts_RSPRO_ConnectClientReq(rspro[i].rspro_id, rspro[i].rspro_client_slot)); } case (remsimBankd) { var template IpAddress ip := ts_IPv4(mp_bankd_ip); RSPRO[i].send(ts_RSPRO_ConnectBankReq(rspro[i].rspro_id, rspro[i].rspro_bank_id, rspro[i].rspro_bank_nslots, ts_IpPort(ip, mp_bankd_port))); } } } for (i := 0; i < NUM_CLIENT; i := i+1) { select (rspro[i].rspro_id.type_) { case (remsimClient) { f_rspro_exp(tr_RSPRO_ConnectClientRes(?, ResultCode:ok), i); } case (remsimBankd) { f_rspro_exp(tr_RSPRO_ConnectBankRes(?, ResultCode:ok), i); } } } } /* transceive a TPDU from modem to card (and back) */ function f_rspro_xceive_mdm2card(integer idx, BankSlot bs, template (value) octetstring data, template (value) TpduFlags flags) runs on rspro_client_CT return octetstring { var RsproPDU rx; RSPRO[idx].send(ts_RSPRO_TpduModemToCard(rspro[idx].rspro_client_slot, bs, flags, data)); rx := f_rspro_exp(tr_RSPRO_TpduCardToModem(bs, rspro[idx].rspro_client_slot, ?, ?)); return rx.msg.tpduCardToModem.data; } /* handle an incoming CreateMapping + ACK it */ altstep as_rspro_create_mapping(integer i, template ClientSlot cslot := ?, template BankSlot bslot := ?, template ResultCode res := ok) runs on rspro_client_CT { var RsproPDU rx; [] RSPRO[i].receive(tr_RSPRO_CreateMappingReq(cslot, bslot)) -> value rx { RSPRO[i].send(ts_RSPRO_CreateMappingRes(res)); } } /* handle an incoming RemoveMapping + ACK it */ altstep as_rspro_remove_mapping(integer i, template ClientSlot cslot := ?, template BankSlot bslot := ?, template ResultCode res := ok) runs on rspro_client_CT { var RsproPDU rx; [] RSPRO[i].receive(tr_RSPRO_RemoveMappingReq(cslot, bslot)) -> value rx { RSPRO[i].send(ts_RSPRO_RemoveMappingRes(res)); } } altstep as_rspro_cfg_client_id(integer i, template ClientSlot cslot := ?, template (value) ResultCode res := ok) runs on rspro_client_CT { var RsproPDU rx; [] RSPRO[i].receive(tr_RSPRO_ConfigClientIdReq(cslot)) -> value rx { RSPRO[i].send(ts_RSPRO_ConfigClientIdRes(res)); } } altstep as_rspro_cfg_client_bank(integer i, template BankSlot bslot := ?, template IpPort ip_port := ?, template (value) ResultCode res := ok) runs on rspro_client_CT { var RsproPDU rx; [] RSPRO[i].receive(tr_RSPRO_ConfigClientBankReq(bslot, ip_port)) -> value rx { RSPRO[i].send(ts_RSPRO_ConfigClientBankRes(res)); } } }