From b0d9360aac5b47387371d4654cf9e1b496700d46 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 20 Mar 2018 18:09:34 +0100 Subject: More progress on osmo-sip-connector tests Change-Id: I34a5d7929264c7f5f21d3868a5f919874ffa106c --- sip/SIP_Tests.ttcn | 299 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 260 insertions(+), 39 deletions(-) (limited to 'sip/SIP_Tests.ttcn') diff --git a/sip/SIP_Tests.ttcn b/sip/SIP_Tests.ttcn index de2f4987..f690dc70 100644 --- a/sip/SIP_Tests.ttcn +++ b/sip/SIP_Tests.ttcn @@ -17,9 +17,10 @@ import from SDP_Types all; import from SIP_Emulation all; import from SIPmsg_Types all; +import from SIP_Templates all; modulepar { - //charstring mp_local_host := "127.0.0.2; + charstring mp_local_host := "127.0.0.2"; charstring mp_osmosip_host := "127.0.0.1"; integer mp_osmosip_port_ctrl := -1; /* RFU */ charstring mp_mncc := "/tmp/mncc"; @@ -38,7 +39,48 @@ type component ConnHdlr extends SIP_ConnHdlr, MNCC_ConnHdlr { } type record ConnHdlrPars { - float t_guard + float t_guard, + CallPars g_cp optional +} + +type record CallPars { + boolean is_mo, + charstring calling, + charstring called, + + uint32_t mncc_call_id optional, + + CallParsComputed comp optional +} + +type record CallParsComputed { + CallidString sip_call_id, + SipAddr sip_url_ext, + SipAddr sip_url_gsm, + charstring sip_body, + integer sip_seq_nr +} + +private template (value) CallPars t_CallPars(boolean is_mo) := { + is_mo := is_mo, + calling := "12345", + called := "98766", + mncc_call_id := omit, + comp := omit +} + +private function f_CallPars_compute(inout CallPars cp) { + if (cp.is_mo) { + cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.called, mp_local_host, 5060)); + cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.calling, mp_osmosip_host, 5060)); + cp.mncc_call_id := f_rnd_int(429496725); + } else { + cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.calling, mp_local_host, 5060)); + cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.called, mp_osmosip_host, 5060)); + cp.comp.sip_call_id := hex2str(f_rnd_hexstring(15)); + } + cp.comp.sip_seq_nr := f_rnd_int(4294967295); + cp.comp.sip_body := ""; } @@ -105,67 +147,246 @@ runs on ConnHdlr { template (value) ConnHdlrPars t_Pars := { - t_guard := 30.0 + t_guard := 30.0, + g_cp := omit } -private function f_TC_mo_setup(charstring id) runs on ConnHdlr { +/* Establish a mobile terminated call described in 'cp' */ +function f_establish_mt(inout CallPars cp) runs on ConnHdlr { + var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm); + var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext); var PDU_SIP_Request sip_req; + var MNCC_PDU mncc; + + /* Ask MNCC_Emulation to "expect" a call to the given called number */ + f_create_mncc_expect(cp.called); + + /* OSC <- SIP: A party sends SIP invite for a MT-call into OSC */ + SIP.send(ts_SIP_INVITE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm, + cp.comp.sip_seq_nr, cp.comp.sip_body)); + /* MSC <- OSC: OSC generates MNCC_SETUP_REQ from INVITE */ + MNCC.receive(tr_MNCC_SETUP_req) -> value mncc { + cp.mncc_call_id := mncc.u.signal.callref; + } + /* OSC -> SIP */ + SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *, + "INVITE", 100, ?, "Trying", *)); + + /* MSC -> OSC: After MS sends CALL CONF in response to SETUP */ + MNCC.send(ts_MNCC_CALL_CONF_ind(cp.mncc_call_id)); + /* MSC <- OSC: OSC asks MSC to create RTP socket */ + MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)); + MNCC.send(ts_MNCC_RTP_CREATE(cp.mncc_call_id)); + + /* MSC -> OSC: After MS is ringing and sent CC ALERTING */ + MNCC.send(ts_MNCC_ALERT_ind(cp.mncc_call_id)); + SIP.clear; + SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *, + "INVITE", 180, ?, "Ringing", *)); + + /* MSC -> OSC: After MT user has picked up and sent CC CONNECT */ + MNCC.send(ts_MNCC_SETUP_CNF(cp.mncc_call_id)); + + SIP.clear; + interleave { + /* MSC <- OSC: OSC asks MSC to connect its RTP stream to remote end */ + [] MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id)) {} + /* OSC -> SIP: OSC confirms call establishment to SIP side */ + [] SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, ?, + "INVITE", 200, ?, "OK", ?)) {} + } + /* OSC <- SIP: SIP world acknowledges "200 OK" */ + SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm, + cp.comp.sip_seq_nr, omit)); + /* MSC <- OSC: OSC sends SETUP COMPL to MNCC (which triggers CC CONNECT ACK */ + MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id)); +} - var MNCC_number dst := valueof(ts_MNCC_number("01234567")); - var MNCC_number src := valueof(ts_MNCC_number("112")); - - f_create_sip_expect(valueof(ts_SIP_Url("+01234567"))); - - log("sending mncc setup"); - MNCC.send(ts_MNCC_SETUP_ind(2342, dst, src, "262420123456789")); - - MNCC.receive(tr_MNCC_RTP_CREATE(2342)); - MNCC.send(ts_MNCC_RTP_CREATE(2342)); +/* Establish a mobile originated call described in 'cp' */ +function f_establish_mo(inout CallPars cp) runs on ConnHdlr { + var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN)); + var MNCC_number src := valueof(ts_MNCC_number(cp.calling, GSM48_TON_UNKNOWN)); + var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm); + var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext); + var PDU_SIP_Request sip_req; + var integer seq_nr; + + f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec); + + /* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */ + MNCC.send(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789")); + /* MSC <- OSC: Create GSM side RTP socket */ + MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) { + var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id)); + mncc.u.rtp.payload_msg_type := oct2int('0300'O); + MNCC.send(mncc); /* FIXME: port/ip */ + } + /* OSC -> SIP: Send INVITE with GSM side IP/Port in SDP */ + SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) -> value sip_req { + cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams; + cp.comp.sip_call_id := sip_req.msgHeader.callId.callid; + seq_nr := sip_req.msgHeader.cSeq.seqNumber; + } + /* OSC <- SIP: Notify call is proceeding */ + SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext, + "INVITE", 100, seq_nr, "Trying", sip_req.msgHeader.via)); + /* MSC <- OSC: "100 Trying" translated to MNCC_CALL_PROC_REQ */ + MNCC.receive(tr_MNCC_CALL_PROC_req(cp.mncc_call_id)); + + /* OSC <- SIP: SIP-terminated user is ringing now */ + SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext, + "INVITE", 180, seq_nr, "Ringing", sip_req.msgHeader.via)); + + /* MSC <- OSC: "180 Ringing" translated to MNCC_ALERT_REQ */ + MNCC.receive(tr_MNCC_ALERT_req(cp.mncc_call_id)) {} + + /* OSC <- SIP: SIP-terminated user has accepted the call */ + SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext, + "INVITE", 200, seq_nr, "OK", sip_req.msgHeader.via, + cp.comp.sip_body)); + MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id)); + /* MSC <- OSC: "200 OK" translated to MNCC_SETUP_RSP */ + MNCC.receive(tr_MNCC_SETUP_rsp(cp.mncc_call_id)); + + /* MSC -> OSC: CC CONNECT ACK was received from MS */ + MNCC.send(ts_MNCC_SETUP_COMPL_ind(cp.mncc_call_id)); + /* OSC -> SIP: Acknowledge the call */ + SIP.receive(tr_SIP_ACK(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, omit)); +} - SIP.receive(PDU_SIP_Request:?) -> value sip_req { - log(sip_req); +/* Release call from the mobile side */ +function f_release_mobile(inout CallPars cp) runs on ConnHdlr { + var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm); + var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext); + var PDU_SIP_Request sip_req; + SIP.clear; + /* MSC -> OSC: Simulate a CC DISCONNET from the MT user */ + MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0))); + /* OSC -> SIP: Expect BYE from OSC to SIP side */ + SIP.receive(tr_SIP_BYE(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, *)) -> value sip_req { + cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams; } + /* OSC <- SIP: Acknowledge the BYE */ + SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext, + "BYE", 200, sip_req.msgHeader.cSeq.seqNumber, "OK", + sip_req.msgHeader.via)); + /* MSC <- OSC: Send REL_REQ to MSC, triggers CC RELEASE REQ to MS */ + MNCC.receive(tr_MNCC_REL_req(cp.mncc_call_id)); // CAUSE? + /* MSC -> OSC: MS has responded with CC CLEAR COMPL, triggers MNCC_REL_CNF */ + MNCC.send(ts_MNCC_REL_cnf(cp.mncc_call_id, ts_MNCC_cause(0))); +} + +/* Release call from the SIP side */ +function f_release_sip(inout CallPars cp) runs on ConnHdlr { + var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm); + var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext); + /* OSC <- SIP: SIP-side sends a BYE to OSC */ + SIP.send(ts_SIP_BYE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm, + cp.comp.sip_seq_nr, omit)); + /* MSC <- OSC: Expect OSC to cause MNCC Disconnect Request */ + MNCC.receive(tr_MNCC_DISC_req(cp.mncc_call_id)); + /* MSC -> OSC: Indicate GSM side release */ + MNCC.send(ts_MNCC_REL_ind(cp.mncc_call_id, ts_MNCC_cause(0))); + /* OSC -> SIP: Confirmation to SIP side */ + SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *, + "BYE", 200, cp.comp.sip_seq_nr, "OK", omit)); } -testcase TC_mo_setup() runs on test_CT { +/* Successful MT Call, which is subsequently released by GSM side */ +private function f_TC_mt_success_rel_gsm(charstring id) runs on ConnHdlr { + var CallPars cp := valueof(t_CallPars(false)); + f_CallPars_compute(cp); + cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n"; + f_sleep(3.0) + + f_establish_mt(cp); + /* now call is fully established */ + f_sleep(2.0); + f_release_mobile(cp); + setverdict(pass); +} +testcase TC_mt_success_rel_gsm() runs on test_CT { var ConnHdlrPars pars; var ConnHdlr vc_conn; - f_init(); - pars := valueof(t_Pars); - vc_conn := f_start_handler(refers(f_TC_mo_setup), pars); + vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars); vc_conn.done; } +/* Successful MT Call, which is subsequently released by SIP side */ +private function f_TC_mt_success_rel_sip(charstring id) runs on ConnHdlr { + var CallPars cp := valueof(t_CallPars(false)); + f_CallPars_compute(cp); + cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n"; + f_sleep(3.0) + + f_establish_mt(cp); + /* now call is fully established */ + f_sleep(2.0); + f_release_sip(cp); + setverdict(pass); +} +testcase TC_mt_success_rel_sip() runs on test_CT { + var ConnHdlrPars pars; + var ConnHdlr vc_conn; + f_init(); + pars := valueof(t_Pars); + vc_conn := f_start_handler(refers(f_TC_mt_success_rel_sip), pars); + vc_conn.done; +} +/* Successful MO Call, which is subsequently released by GSM side */ +private function f_TC_mo_success_rel_gsm(charstring id) runs on ConnHdlr { + var CallPars cp := valueof(t_CallPars(true)); + f_CallPars_compute(cp); + cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n"; + f_sleep(3.0) - -/* SIP specifics */ - -const integer c_SIP_PORT := 5060; - -template (value) SIP_comm_adress ts_SipAddr(charstring rhost, - template (omit) charstring lhost := omit, - integer rport := c_SIP_PORT, - integer lport := c_SIP_PORT, - SIP_com_prot prot := UDP_E) := { - remote_host := rhost, - remote_port := rport, - local_host := lhost, - local_port := lport, - protocol := prot + f_establish_mo(cp); + /* now call is fully established */ + f_sleep(2.0); + f_release_mobile(cp); + setverdict(pass); } - -template (value) ASP_SIP_open ts_SIP_open(SIP_comm_adress addr) := { - addr := addr +testcase TC_mo_success_rel_gsm() runs on test_CT { + var ConnHdlrPars pars; + var ConnHdlr vc_conn; + f_init(); + pars := valueof(t_Pars); + vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars); + vc_conn.done; } +/* Successful MO Call, which is subsequently released by SIP side */ +private function f_TC_mo_success_rel_sip(charstring id) runs on ConnHdlr { + var CallPars cp := valueof(t_CallPars(true)); + f_CallPars_compute(cp); + cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n"; + f_sleep(3.0) + + f_establish_mo(cp); + /* now call is fully established */ + f_sleep(2.0); + f_release_sip(cp); + setverdict(pass); +} +testcase TC_mo_success_rel_sip() runs on test_CT { + var ConnHdlrPars pars; + var ConnHdlr vc_conn; + f_init(); + pars := valueof(t_Pars); + vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars); + vc_conn.done; +} control { - execute( TC_mo_setup() ); + execute( TC_mt_success_rel_gsm() ); + execute( TC_mt_success_rel_sip() ); + execute( TC_mo_success_rel_gsm() ); + execute( TC_mo_success_rel_sip() ); } -- cgit v1.2.3