pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/37194?usp=email )
Change subject: asterisk: Test initial IMS REGISTER timeout ......................................................................
asterisk: Test initial IMS REGISTER timeout
Add several tests emulating response timeouts at several point in time during IMS REGISTER procedure.
Related: SYS#6971 Change-Id: If59d43b2779dfbd14890a88d664077c194f843a1 --- M asterisk/Asterisk_Tests.ttcn M asterisk/IMS_ConnectionHandler.ttcn M asterisk/expected-results.xml 3 files changed, 143 insertions(+), 9 deletions(-)
Approvals: Jenkins Builder: Verified jolly: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/asterisk/Asterisk_Tests.ttcn b/asterisk/Asterisk_Tests.ttcn index 7126118..30f04fd 100644 --- a/asterisk/Asterisk_Tests.ttcn +++ b/asterisk/Asterisk_Tests.ttcn @@ -48,6 +48,8 @@ charstring mp_ami_user := "test_user"; charstring mp_ami_secret := "1234"; charstring mp_volte_ims_outbound_registration := "volte_ims"; + /* Current default by pjproject (timeout_timer_val) to 32s, and not changed by Asterisk */ + integer mp_volte_ims_outbound_register_timeout := 32; }
type component test_CT { @@ -386,7 +388,9 @@ f_ami_action_PJSIPRegister(AMI_CLIENT, mp_volte_ims_outbound_registration); }
-private altstep as_AMI_IMS_register_Auth(IMS_ConnHdlrPars pars, boolean resync := false) runs on test_CT +private altstep as_AMI_IMS_register_Auth(IMS_ConnHdlrPars pars, + boolean resync := false, + boolean exp_ami_ev_registered := true) runs on test_CT { var charstring rand_str := oct2str(pars.subscr.auth.rand); var charstring autn_str := oct2str(pars.subscr.auth.autn); @@ -399,9 +403,11 @@ f_str_tolower(oct2str(pars.subscr.auth.ck)), f_str_tolower(oct2str(pars.subscr.auth.ik)));
- AMI_CLIENT.receive(tr_AMI_Event_Registry(f_sip_SipAddr_to_str(pars.subscr.local_sip_record), - "sip:" & mp_ims_domain, - "Registered")); + if (exp_ami_ev_registered) { + AMI_CLIENT.receive(tr_AMI_Event_Registry(f_sip_SipAddr_to_str(pars.subscr.local_sip_record), + "sip:" & mp_ims_domain, + "Registered")); + } } [resync] AMI_CLIENT.receive(tr_AMI_Event_AuthRequest(mp_volte_ims_outbound_registration, rand := pattern @nocase rand_str, @@ -480,6 +486,79 @@ f_shutdown(); }
+private function f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_register_early_return early_ret, boolean exp_auth_resync := false) runs on IMS_ConnHdlr { + f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.subscr.registrar_sip_record.addr))); + + as_IMS_register(exp_auth_resync := exp_auth_resync, early_ret := early_ret); + + timer Tout; + /* 1.0: Give some margin. */ + Tout.start(int2float(mp_volte_ims_outbound_register_timeout) + 1.0); + /* Make sure no new REGISTER is attempted unless directed by AMI: */ + alt { + [] as_SIP_fail_req("nothing"); + [] as_SIP_fail_resp("nothing"); + [] Tout.timeout { /* Done */ } + } + setverdict(pass); +} +/* Test initial REGISTER against IMS core timing out. */ +private function f_TC_ims_registration_timeout_initial_100Trying(charstring id) runs on IMS_ConnHdlr { + f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_REG_EARLY_RET_BEFORE_Initial_100Trying); +} +private function f_TC_ims_registration_timeout_initial_401Unauthorized(charstring id) runs on IMS_ConnHdlr { + f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_REG_EARLY_RET_BEFORE_Initial_401Unauthorized); +} +private function f_TC_ims_registration_timeout_resync_401Unauthorized(charstring id) runs on IMS_ConnHdlr { + f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_REG_EARLY_RET_BEFORE_Resync_401Unauthorized, exp_auth_resync := true); +} +private function f_TC_ims_registration_timeout_protected_100Trying(charstring id) runs on IMS_ConnHdlr { + f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_REG_EARLY_RET_BEFORE_Protected_100Trying); +} +private function f_TC_ims_registration_timeout_protected_200OK(charstring id) runs on IMS_ConnHdlr { + f_TC_ims_registration_timeout_IMS_ConnHdlr(IMS_REG_EARLY_RET_BEFORE_Protected_200OK); +} +private function f_TC_ims_registration_timeout_initial(ims_void_fn fn, + boolean answer_register := false, + boolean resync := false) runs on test_CT { + var IMS_ConnHdlrPars pars; + var IMS_ConnHdlr vc_conn; + f_init(); + pars := f_init_IMS_ConnHdlrPars(); + vc_conn := f_start_handler_IMS(fn, pars); + + f_AMI_IMS_start_register(pars); + + if (answer_register) { + as_AMI_IMS_register_Auth(pars, resync := resync, exp_ami_ev_registered := false); + } + + AMI_CLIENT.receive(tr_AMI_Event_Registry(f_sip_SipAddr_to_str(pars.subscr.local_sip_record), + "sip:" & mp_ims_domain, + "Rejected")); + + vc_conn.done; + f_shutdown(); +} +testcase TC_ims_registration_timeout_initial_100Trying() runs on test_CT { + f_TC_ims_registration_timeout_initial(refers(f_TC_ims_registration_timeout_initial_100Trying)); +} +testcase TC_ims_registration_timeout_initial_401Unauthorized() runs on test_CT { + f_TC_ims_registration_timeout_initial(refers(f_TC_ims_registration_timeout_initial_401Unauthorized)); +} +testcase TC_ims_registration_timeout_resync_401Unauthorized() runs on test_CT { + f_TC_ims_registration_timeout_initial(refers(f_TC_ims_registration_timeout_resync_401Unauthorized), + true, true); +} +testcase TC_ims_registration_timeout_protected_100Trying() runs on test_CT { + f_TC_ims_registration_timeout_initial(refers(f_TC_ims_registration_timeout_protected_100Trying), + true, false); +} +testcase TC_ims_registration_timeout_protected_200OK() runs on test_CT { + f_TC_ims_registration_timeout_initial(refers(f_TC_ims_registration_timeout_protected_200OK), + true, false); +} + /* Test SIP registration of local clients */ private function f_TC_ims_call_mo(charstring id) runs on IMS_ConnHdlr { f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.subscr.registrar_sip_record.addr))); @@ -619,6 +698,11 @@ execute( TC_internal_call_all_4registered() ); execute( TC_ims_registration() ); execute( TC_ims_registration_resync() ); + execute( TC_ims_registration_timeout_initial_100Trying() ); + execute( TC_ims_registration_timeout_initial_401Unauthorized() ); + execute( TC_ims_registration_timeout_resync_401Unauthorized() ); + execute( TC_ims_registration_timeout_protected_100Trying() ); + execute( TC_ims_registration_timeout_protected_200OK() ); execute( TC_ims_call_mo() ); execute( TC_ims_call_mt() ); } diff --git a/asterisk/IMS_ConnectionHandler.ttcn b/asterisk/IMS_ConnectionHandler.ttcn index 7b26980..d396268 100644 --- a/asterisk/IMS_ConnectionHandler.ttcn +++ b/asterisk/IMS_ConnectionHandler.ttcn @@ -208,7 +208,7 @@ charstring domain, charstring imsi, template (omit) IMS_CallPars cp := omit) := { - t_guard := 30.0, + t_guard := 60.0, realm := domain, local_sip_host := local_sip_host, local_sip_port := local_sip_port, @@ -237,7 +237,7 @@ fn.apply(id); }
-private altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on IMS_ConnHdlr +altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on IMS_ConnHdlr { var PDU_SIP_Request sip_req; [] SIP.receive(PDU_SIP_Request:?) -> value sip_req { @@ -246,7 +246,7 @@ } }
-private altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on IMS_ConnHdlr +altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on IMS_ConnHdlr { var PDU_SIP_Response sip_resp; [] SIP.receive(PDU_SIP_Response:?) -> value sip_resp { @@ -533,8 +533,18 @@ return valueof(wwwAuthenticate); }
+type enumerated IMS_register_early_return { + IMS_REG_EARLY_RET_BEFORE_None, + IMS_REG_EARLY_RET_BEFORE_Initial_100Trying, + IMS_REG_EARLY_RET_BEFORE_Initial_401Unauthorized, + IMS_REG_EARLY_RET_BEFORE_Resync_401Unauthorized, + IMS_REG_EARLY_RET_BEFORE_Protected_100Trying, + IMS_REG_EARLY_RET_BEFORE_Protected_200OK +} + /* Peer is issuing 1st register, accept it: */ altstep as_IMS_register(boolean exp_auth_resync := false, + IMS_register_early_return early_ret := IMS_REG_EARLY_RET_BEFORE_None, boolean fail_others := true) runs on IMS_ConnHdlr { var template (present) PDU_SIP_Request exp_req := @@ -562,6 +572,10 @@ var template (value) Supported supported := ts_Supported({"sec-agree"}); var integer sip_seq_nr;
+ if (early_ret == IMS_REG_EARLY_RET_BEFORE_Initial_100Trying) { + return; /* Done */ + } + sip_call_id := g_rx_sip_req.msgHeader.callId.callid; via := g_rx_sip_req.msgHeader.via; via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "rport", "1234"); /* TODO: set remote src port of the REGISTER */ @@ -595,6 +609,10 @@ f_ims_parse_register_contact(g_rx_sip_req.msgHeader.contact); f_ims_parse_security_client(g_rx_sip_req.msgHeader.security_client);
+ if (early_ret == IMS_REG_EARLY_RET_BEFORE_Initial_401Unauthorized) { + return; /* Done */ + } + if (not exp_auth_resync) { /* Delay ipsec setup in ip xfrm, since there will be another * 1st REGISTER with potentially new ports coming in later. */ @@ -636,6 +654,10 @@ authorization := authorization); SIP.receive(exp_req) -> value g_rx_sip_req;
+ if (early_ret == IMS_REG_EARLY_RET_BEFORE_Resync_401Unauthorized) { + return; /* Done */ + } + via := g_rx_sip_req.msgHeader.via; from_addr := g_rx_sip_req.msgHeader.fromField; to_addr := g_rx_sip_req.msgHeader.toField; @@ -680,7 +702,7 @@ }
/* Now we should receive a new REGISTER over ipsec: */ - as_IMS_2nd_register(wwwAuthenticate); + as_IMS_2nd_register(wwwAuthenticate, early_ret := early_ret); } [fail_others] as_SIP_fail_resp(sip_expect_str); [fail_others] as_SIP_fail_req(sip_expect_str); @@ -688,7 +710,9 @@ }
/* Peer is issuing 2nd register, accept it: */ -altstep as_IMS_2nd_register(WwwAuthenticate wwwAuthenticate, boolean fail_others := true) runs on IMS_ConnHdlr +altstep as_IMS_2nd_register(WwwAuthenticate wwwAuthenticate, + IMS_register_early_return early_ret := IMS_REG_EARLY_RET_BEFORE_None, + boolean fail_others := true) runs on IMS_ConnHdlr { var template (present) Authorization authorization := f_tr_Authorization_AKAv1MD5(wwwAuthenticate, @@ -713,6 +737,10 @@ var template (value) Supported supported := ts_Supported({"sec-agree"}); var integer sip_seq_nr;
+ if (early_ret == IMS_REG_EARLY_RET_BEFORE_Protected_100Trying) { + return; /* Done */ + } + sip_call_id := g_rx_sip_req.msgHeader.callId.callid; via := g_rx_sip_req.msgHeader.via; from_addr := g_rx_sip_req.msgHeader.fromField; @@ -737,6 +765,10 @@ /* Validate P-Access-Network-Info: */ f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := true);
+ if (early_ret == IMS_REG_EARLY_RET_BEFORE_Protected_200OK) { + return; /* Done */ + } + g_pars.subscr.p_associated_uri := valueof(ts_P_Associated_Uri({ ts_P_Assoc_uri_spec(ts_NameAddr(ts_SipUrl(ts_HostPort(g_pars.realm), ts_UserInfo(g_pars.subscr.msisdn), diff --git a/asterisk/expected-results.xml b/asterisk/expected-results.xml index 0c9cdd8..6b5def5 100644 --- a/asterisk/expected-results.xml +++ b/asterisk/expected-results.xml @@ -7,6 +7,11 @@ <testcase classname='Asterisk_Tests' name='TC_internal_call_all_4registered' time='MASKED'/> <testcase classname='Asterisk_Tests' name='TC_ims_registration' time='MASKED'/> <testcase classname='Asterisk_Tests' name='TC_ims_registration_resync' time='MASKED'/> + <testcase classname='Asterisk_Tests' name='TC_ims_registration_timeout_initial_100Trying' time='MASKED'/> + <testcase classname='Asterisk_Tests' name='TC_ims_registration_timeout_initial_401Unauthorized' time='MASKED'/> + <testcase classname='Asterisk_Tests' name='TC_ims_registration_timeout_resync_401Unauthorized' time='MASKED'/> + <testcase classname='Asterisk_Tests' name='TC_ims_registration_timeout_protected_100Trying' time='MASKED'/> + <testcase classname='Asterisk_Tests' name='TC_ims_registration_timeout_protected_200OK' time='MASKED'/> <testcase classname='Asterisk_Tests' name='TC_ims_call_mo' time='MASKED'/> <testcase classname='Asterisk_Tests' name='TC_ims_call_mt' time='MASKED'/> </testsuite>