WIP: asterisk: Initial IMS registration
Change-Id: I30261472587e2386a5cd8ffce2aee6e5e3ada6ff
This commit is contained in:
parent
915580ef91
commit
c6b09407cd
|
@ -25,10 +25,14 @@ modulepar {
|
|||
}
|
||||
|
||||
const charstring AMI_FIELD_ACTION := "Action";
|
||||
const charstring AMI_FIELD_ACTION_ID := "ActionId";
|
||||
const charstring AMI_FIELD_USERNAME := "Username";
|
||||
const charstring AMI_FIELD_SECRET := "Secret";
|
||||
const charstring AMI_FIELD_RESPONSE := "Response";
|
||||
|
||||
/* Extensions: */
|
||||
const charstring AMI_FIELD_REGISTRATION := "Registration";
|
||||
|
||||
type record AMI_Field {
|
||||
charstring key,
|
||||
charstring val
|
||||
|
@ -69,28 +73,46 @@ tr_AMI_Field(template (present) charstring key := ?,
|
|||
template (value) AMI_Field
|
||||
ts_AMI_Field_Action(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION, val);
|
||||
template (value) AMI_Field
|
||||
ts_AMI_Field_ActionId(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION_ID, val);
|
||||
template (value) AMI_Field
|
||||
ts_AMI_Field_Username(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_USERNAME, val);
|
||||
template (value) AMI_Field
|
||||
ts_AMI_Field_Secret(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_SECRET, val);
|
||||
/* Extensions: */
|
||||
template (value) AMI_Field
|
||||
ts_AMI_Field_Registration(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_REGISTRATION, val);
|
||||
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_Action(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_ACTION, val);
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_ActionId(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_ACTION_ID, val);
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_Username(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_USERNAME, val);
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_Secret(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_SECRET, val);
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_Response(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_RESPONSE, val);
|
||||
/* Extensions: */
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_Registration(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_REGISTRATION, val);
|
||||
|
||||
|
||||
template (present) AMI_Field
|
||||
tr_AMI_Field_ResponseSuccess := tr_AMI_Field(AMI_FIELD_RESPONSE, "Success");
|
||||
|
||||
|
||||
/*
|
||||
/***********************
|
||||
* Message Templates:
|
||||
***********************/
|
||||
|
||||
/*
|
||||
* ACTIONS
|
||||
*/
|
||||
|
||||
/* Action: Login
|
||||
* Username: <value>
|
||||
* Secret: <value>
|
||||
*/
|
||||
template (value) AMI_Msg
|
||||
ts_AMI_Action_Login(charstring username, charstring secret) := {
|
||||
ts_AMI_Field_Action("Login"),
|
||||
|
@ -106,15 +128,101 @@ tr_AMI_Action_Login(template(present) charstring username := ?,
|
|||
tr_AMI_Field_Secret(secret)
|
||||
);
|
||||
|
||||
/* Action: PJSIPRegister
|
||||
* ActionID: <value>
|
||||
* Registration: volte_ims
|
||||
*/
|
||||
template (value) AMI_Msg
|
||||
ts_AMI_Action_PJSIPRegister(template (value) charstring registration := "volte_ims",
|
||||
template (value) charstring action_id := "0001") := {
|
||||
ts_AMI_Field_Action("PJSIPRegister"),
|
||||
ts_AMI_Field_ActionId(action_id),
|
||||
ts_AMI_Field_Registration(registration)
|
||||
};
|
||||
template (present) AMI_Msg
|
||||
tr_AMI_Action_PJSIPRegister(template (present) charstring registration := ?,
|
||||
template (present) charstring action_id := ?) := {
|
||||
tr_AMI_Field_Action("PJSIPRegister"),
|
||||
tr_AMI_Field_ActionId(action_id),
|
||||
tr_AMI_Field_Registration(registration)
|
||||
};
|
||||
|
||||
/*
|
||||
* RESPONSES
|
||||
*/
|
||||
|
||||
/* Response: Success
|
||||
*/
|
||||
template (present) AMI_Msg
|
||||
tr_AMI_Response_Success := superset(
|
||||
tr_AMI_Field_ResponseSuccess
|
||||
);
|
||||
|
||||
/* Response: Success
|
||||
* ActionId: <value>
|
||||
*/
|
||||
template (present) AMI_Msg
|
||||
tr_AMI_Response_Success_ActionId(template (present) charstring action_id := ?) := superset(
|
||||
tr_AMI_Field_ResponseSuccess,
|
||||
tr_AMI_Field_ActionId(action_id)
|
||||
);
|
||||
|
||||
/*
|
||||
* Functions:
|
||||
*/
|
||||
|
||||
/* Generate a random "ActionId" value: */
|
||||
function f_gen_action_id() return charstring {
|
||||
return hex2str(f_rnd_hexstring(16));
|
||||
}
|
||||
|
||||
function f_ami_msg_find(AMI_Msg msg,
|
||||
template (present) charstring key := ?)
|
||||
return template (omit) AMI_Field {
|
||||
var integer i;
|
||||
|
||||
for (i := 0; i < lengthof(msg); i := i + 1) {
|
||||
if (not ispresent(msg[i])) {
|
||||
continue;
|
||||
}
|
||||
if (match(msg[i].key, key)) {
|
||||
return msg[i];
|
||||
}
|
||||
}
|
||||
return omit;
|
||||
}
|
||||
|
||||
function f_ami_msg_find_or_fail(AMI_Msg msg,
|
||||
template (present) charstring key := ?)
|
||||
return AMI_Field {
|
||||
var template (omit) AMI_Field field;
|
||||
field := f_ami_msg_find(msg, key);
|
||||
if (istemplatekind(field, "omit")) {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
log2str("Key ", key, " not found in ", msg));
|
||||
}
|
||||
return valueof(field);
|
||||
}
|
||||
|
||||
function f_ami_msg_get_value(AMI_Msg msg,
|
||||
template (present) charstring key := ?)
|
||||
return template (omit) charstring {
|
||||
var template (omit) AMI_Field field;
|
||||
field := f_ami_msg_find(msg, key);
|
||||
if (istemplatekind(field, "omit")) {
|
||||
return omit;
|
||||
}
|
||||
return field.val;
|
||||
}
|
||||
|
||||
function f_ami_msg_get_value_or_fail(AMI_Msg msg,
|
||||
template (present) charstring key := ?)
|
||||
return template charstring {
|
||||
var AMI_Field field;
|
||||
field := f_ami_msg_find_or_fail(msg, key);
|
||||
return field.val;
|
||||
}
|
||||
|
||||
private function f_ami_wait_for_prompt_str(TELNETasp_PT pt, charstring log_label := "(?)")
|
||||
return charstring {
|
||||
var charstring rx, buf := "";
|
||||
|
@ -172,11 +280,23 @@ function f_ami_transceive_match(TELNETasp_PT pt,
|
|||
|
||||
function f_ami_transceive_match_response_success(TELNETasp_PT pt,
|
||||
template (value) AMI_Msg tx_msg) {
|
||||
f_ami_transceive_match(pt, tx_msg, tr_AMI_Response_Success);
|
||||
var template (present) AMI_Msg exp_resp;
|
||||
var template (omit) charstring action_id := f_ami_msg_get_value(valueof(tx_msg), AMI_FIELD_ACTION_ID);
|
||||
if (isvalue(action_id)) {
|
||||
exp_resp := tr_AMI_Response_Success_ActionId(action_id);
|
||||
} else {
|
||||
exp_resp := tr_AMI_Response_Success;
|
||||
}
|
||||
f_ami_transceive_match(pt, tx_msg, exp_resp);
|
||||
}
|
||||
|
||||
function f_ami_action_login(TELNETasp_PT pt, charstring username, charstring secret) {
|
||||
f_ami_transceive_match_response_success(pt, ts_AMI_Action_Login(username, secret));
|
||||
}
|
||||
|
||||
function f_ami_action_PJSIPRegister(TELNETasp_PT pt, charstring register) {
|
||||
var charstring reg_action_id := f_gen_action_id();
|
||||
f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPRegister(register, reg_action_id));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ modulepar {
|
|||
|
||||
charstring mp_local_ims_host := "127.0.0.3";
|
||||
integer mp_local_ims_port := 5060;
|
||||
charstring mp_ims_imsi := "001010000000002";
|
||||
|
||||
/* Asterisk AMI: */
|
||||
charstring mp_ami_user := "test_user";
|
||||
|
@ -68,6 +69,15 @@ function f_init_ConnHdlrPars(integer idx := 1) runs on test_CT return SIPConnHdl
|
|||
return valueof(pars);
|
||||
}
|
||||
|
||||
function f_init_IMS_ConnHdlrPars(integer idx := 1) runs on test_CT return IMS_ConnHdlrPars {
|
||||
var template (value) IMS_CallPars cp := t_IMS_CallPars(mp_local_sip_host, 1234 + 2*idx);
|
||||
var template (value) IMS_ConnHdlrPars pars := t_IMS_Pars(mp_local_ims_host,
|
||||
mp_local_ims_port,
|
||||
mp_ims_imsi,
|
||||
cp := cp);
|
||||
return valueof(pars);
|
||||
}
|
||||
|
||||
/* Initialize connection towards Asterisk AMI */
|
||||
private function f_init_ami() runs on test_CT {
|
||||
map(self:AMI, system:AMI);
|
||||
|
@ -111,6 +121,22 @@ runs on test_CT return SIPConnHdlr {
|
|||
return vc_conn;
|
||||
}
|
||||
|
||||
function f_start_handler_IMS(ims_void_fn fn, IMS_ConnHdlrPars pars)
|
||||
runs on test_CT return IMS_ConnHdlr {
|
||||
var IMS_ConnHdlr vc_conn;
|
||||
var charstring id := testcasename() & "-IMS_ConnHdlr-" & pars.user;
|
||||
|
||||
vc_conn := IMS_ConnHdlr.create(id) alive;
|
||||
|
||||
connect(vc_conn:SIP, vc_SIP:CLIENT);
|
||||
connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
|
||||
|
||||
connect(vc_conn:COORD, self:IMS_COORD);
|
||||
|
||||
vc_conn.start(f_ims_handler_init(fn, id, pars));
|
||||
return vc_conn;
|
||||
}
|
||||
|
||||
/* Test SIP registration of local clients */
|
||||
private function f_TC_internal_registration(charstring id) runs on SIPConnHdlr {
|
||||
|
||||
|
@ -290,12 +316,46 @@ testcase TC_selftest() runs on test_CT {
|
|||
setverdict(pass);
|
||||
}
|
||||
|
||||
/* Test SIP registration of local clients */
|
||||
private function f_TC_ims_registration(charstring id) runs on IMS_ConnHdlr {
|
||||
|
||||
as_IMS_register();
|
||||
setverdict(pass);
|
||||
}
|
||||
testcase TC_ims_registration() 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(refers(f_TC_ims_registration), pars);
|
||||
|
||||
/* Trigger registration: */
|
||||
f_ami_action_PJSIPRegister(AMI, "volte_ims");
|
||||
/* TODO: Rx "Event: AuthRequest" */
|
||||
/* TODO: Tx "Action: AuthResponse" */
|
||||
/* TODO: Rx "Response: Success" */
|
||||
/* TODO: once registration is successful, rx:
|
||||
* Event: Registry
|
||||
* ChannelType: pjsip
|
||||
* Username: <value>
|
||||
* Domain: <value>
|
||||
* Status: <value>
|
||||
* Cause: <value> */
|
||||
|
||||
/* TODO: test "Action: PJSIPUnregister" */
|
||||
|
||||
/* TODO: in another test emulating a call, test "Action: DedicatedBearerStatus" */
|
||||
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
control {
|
||||
execute( TC_internal_registration() );
|
||||
execute( TC_internal_call_momt() );
|
||||
execute( TC_internal_call_all_2registered() );
|
||||
execute( TC_internal_call_all_3registered() );
|
||||
execute( TC_internal_call_all_4registered() );
|
||||
execute( TC_ims_registration() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ type record of IMS_ConnHdlr IMS_ConnHdlrList;
|
|||
|
||||
type record IMS_ConnHdlrPars {
|
||||
float t_guard,
|
||||
charstring remote_sip_host,
|
||||
uint16_t remote_sip_port,
|
||||
charstring remote_sip_host optional,
|
||||
uint16_t remote_sip_port optional,
|
||||
charstring user,
|
||||
charstring display_name,
|
||||
charstring password,
|
||||
|
@ -66,6 +66,10 @@ type record IMS_CallParsMT {
|
|||
/* Whether to expect CANCEL instead of ACK as answer to our OK */
|
||||
boolean exp_cancel
|
||||
}
|
||||
template (value) IMS_CallParsMT t_IMS_CallParsMT := {
|
||||
wait_coord_cmd_pickup := false,
|
||||
exp_cancel := false
|
||||
}
|
||||
|
||||
type record IMS_CallPars {
|
||||
SipAddr calling optional,
|
||||
|
@ -85,4 +89,127 @@ type record IMS_CallPars {
|
|||
IMS_CallParsMT mt
|
||||
}
|
||||
|
||||
template (value) IMS_CallPars t_IMS_CallPars(charstring local_rtp_addr,
|
||||
uint16_t local_rtp_port := 0,
|
||||
template (omit) SipAddr calling := omit,
|
||||
template (omit) SipAddr called := omit) := {
|
||||
calling := calling,
|
||||
called := called,
|
||||
from_addr := omit,
|
||||
to_addr := omit,
|
||||
sip_call_id := hex2str(f_rnd_hexstring(15)),
|
||||
sip_seq_nr := f_sip_rand_seq_nr(),
|
||||
sip_body := omit,
|
||||
local_rtp_addr := local_rtp_addr,
|
||||
local_rtp_port := local_rtp_port,
|
||||
peer_sdp := omit,
|
||||
mt := t_IMS_CallParsMT
|
||||
}
|
||||
|
||||
template (value) IMS_ConnHdlrPars t_IMS_Pars(charstring local_sip_host,
|
||||
uint16_t local_sip_port,
|
||||
charstring user,
|
||||
charstring display_name := "Anonymous",
|
||||
charstring password := "secret",
|
||||
template (omit) IMS_CallPars cp := omit) := {
|
||||
t_guard := 30.0,
|
||||
remote_sip_host := omit,
|
||||
remote_sip_port := omit,
|
||||
user := user,
|
||||
display_name := f_sip_str_quote(display_name),
|
||||
password := password,
|
||||
registrar_sip_req_uri := valueof(ts_SipUrlHost(local_sip_host)),
|
||||
registrar_sip_record := ts_SipAddr(ts_HostPort(local_sip_host),
|
||||
ts_UserInfo(user),
|
||||
f_sip_str_quote(display_name)),
|
||||
registrar_sip_call_id := hex2str(f_rnd_hexstring(15)) & "@" & local_sip_host,
|
||||
registrar_sip_seq_nr := f_sip_rand_seq_nr(),
|
||||
local_via := ts_Via_from(ts_HostPort(local_sip_host, local_sip_port)),
|
||||
local_sip_url_ext := ts_SipUrl(ts_HostPort(local_sip_host, local_sip_port),
|
||||
ts_UserInfo(user)),
|
||||
local_sip_record := ts_SipAddr(ts_HostPort(local_sip_host),
|
||||
ts_UserInfo(user)),
|
||||
local_contact := valueof(ts_Contact({
|
||||
ts_ContactAddress(
|
||||
ts_Addr_Union_SipUrl(ts_SipUrl(ts_HostPort(
|
||||
local_sip_host,
|
||||
local_sip_port),
|
||||
ts_UserInfo(user))),
|
||||
omit)
|
||||
})),
|
||||
cp := cp
|
||||
}
|
||||
|
||||
private altstep as_Tguard() runs on IMS_ConnHdlr {
|
||||
[] g_Tguard.timeout {
|
||||
setverdict(fail, "Tguard timeout");
|
||||
mtc.stop;
|
||||
}
|
||||
}
|
||||
|
||||
type function ims_void_fn(charstring id) runs on IMS_ConnHdlr;
|
||||
function f_ims_handler_init(ims_void_fn fn, charstring id, IMS_ConnHdlrPars pars)
|
||||
runs on IMS_ConnHdlr {
|
||||
g_name := id;
|
||||
g_pars := pars;
|
||||
g_Tguard.start(pars.t_guard);
|
||||
activate(as_Tguard());
|
||||
|
||||
/* call the user-supied test case function */
|
||||
fn.apply(id);
|
||||
}
|
||||
|
||||
private 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 {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
log2str(g_name & ": Received unexpected SIP Req message := ", sip_req, "\nvs exp := ", exp_msg_str));
|
||||
}
|
||||
}
|
||||
|
||||
private 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 {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
log2str(g_name & ": Received unexpected SIP Resp message := ", sip_resp, "\nvs exp := ", exp_msg_str));
|
||||
}
|
||||
}
|
||||
|
||||
/* Peer is calling us, accept it: */
|
||||
altstep as_IMS_register(boolean exp_update_to_direct_rtp := true,
|
||||
boolean fail_others := true) runs on IMS_ConnHdlr
|
||||
{
|
||||
var template (present) PDU_SIP_Request exp_req :=
|
||||
tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
|
||||
?,
|
||||
tr_SipAddr(),
|
||||
tr_SipAddr(),
|
||||
tr_Via_from(?));
|
||||
var charstring sip_expect_str := log2str(exp_req);
|
||||
|
||||
[] SIP.receive(exp_req) -> value g_rx_sip_req {
|
||||
var template (value) PDU_SIP_Response tx_resp;
|
||||
var Via via;
|
||||
var charstring tx_sdp;
|
||||
|
||||
via := g_rx_sip_req.msgHeader.via;
|
||||
|
||||
/* Tx 200 OK
|
||||
* TODO: Tx Unauthorized instead, with IMS params */
|
||||
tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
|
||||
g_pars.cp.from_addr,
|
||||
g_pars.cp.to_addr,
|
||||
"REGISTER", 200,
|
||||
g_pars.cp.sip_seq_nr,
|
||||
"OK",
|
||||
via);
|
||||
SIP.send(tx_resp);
|
||||
}
|
||||
[fail_others] as_SIP_fail_resp(sip_expect_str);
|
||||
[fail_others] as_SIP_fail_req(sip_expect_str);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue