asterisk: Introduce AMI_Adapter_CT
This allows to keep string handling totally internal to the AMI_Adapter component, which also means now the CLIENT port acts asynchronously on full AMI messages. This allows for instance using activated altsteps to ignore events or answer to them. Change-Id: Ibf230d2302fecf443f34e1c4d4acfd4802f4cc79
This commit is contained in:
parent
9c83471a5b
commit
bcb4e82d16
|
@ -167,6 +167,58 @@ tr_AMI_Response_Success_ActionId(template (present) charstring action_id := ?) :
|
|||
tr_AMI_Field_ActionId(action_id)
|
||||
);
|
||||
|
||||
|
||||
/***********************
|
||||
* Adapter:
|
||||
***********************/
|
||||
|
||||
type port AMI_Msg_PT message {
|
||||
inout AMI_Msg;
|
||||
} with { extension "internal" };
|
||||
|
||||
type component AMI_Adapter_CT {
|
||||
port TELNETasp_PT AMI;
|
||||
port AMI_Msg_PT CLIENT;
|
||||
}
|
||||
|
||||
function f_AMI_Adapter_main() runs on AMI_Adapter_CT {
|
||||
var AMI_Msg msg;
|
||||
|
||||
var charstring rx, buf := "";
|
||||
var integer fd;
|
||||
|
||||
map(self:AMI, system:AMI);
|
||||
|
||||
while (true) {
|
||||
|
||||
alt {
|
||||
[] AMI.receive(pattern "\n") {
|
||||
buf := buf & "\n";
|
||||
msg := dec_AMI_Msg(buf);
|
||||
buf := "";
|
||||
CLIENT.send(msg);
|
||||
};
|
||||
[] AMI.receive(charstring:?) -> value rx {
|
||||
buf := buf & rx;
|
||||
};
|
||||
[] AMI.receive(integer:?) -> value fd {
|
||||
if (fd == -1) {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
"AMI Telnet Connection Failure: " & int2str(fd));
|
||||
} else {
|
||||
/* telnet connection succeeded */
|
||||
}
|
||||
}
|
||||
[] CLIENT.receive(AMI_Msg:?) -> value msg {
|
||||
/* TODO: in the future, queue Action if there's already one Action in transit, to fullfill AMI requirements. */
|
||||
var charstring tx_txt := enc_AMI_Msg(msg);
|
||||
AMI.send(tx_txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Functions:
|
||||
*/
|
||||
|
@ -223,62 +275,66 @@ return template charstring {
|
|||
return field.val;
|
||||
}
|
||||
|
||||
private function f_ami_wait_for_prompt_str(TELNETasp_PT pt, charstring log_label := "(?)")
|
||||
return charstring {
|
||||
var charstring rx, buf := "";
|
||||
var integer fd;
|
||||
function f_ami_transceive_ret(AMI_Msg_PT pt, template (value) AMI_Msg tx_msg, float rx_timeout := 10.0) return AMI_Msg {
|
||||
var AMI_Msg rx_msg;
|
||||
timer T;
|
||||
|
||||
T.start(mp_ami_prompt_timeout);
|
||||
T.start(rx_timeout);
|
||||
pt.send(tx_msg);
|
||||
alt {
|
||||
[] pt.receive(pattern "\n") { buf := buf & "\n" };
|
||||
[] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
|
||||
[] pt.receive(integer:?) -> value fd {
|
||||
if (fd == -1) {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
"AMI Telnet Connection Failure: " & log_label);
|
||||
} else {
|
||||
repeat; /* telnet connection succeeded */
|
||||
}
|
||||
}
|
||||
[] pt.receive(AMI_Msg:?) -> value rx_msg;
|
||||
[] T.timeout {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
"AMI Timeout for prompt: " & log_label);
|
||||
};
|
||||
log2str("AMI Response timeout: ", tx_msg));
|
||||
}
|
||||
}
|
||||
T.stop;
|
||||
return buf;
|
||||
return rx_msg;
|
||||
|
||||
}
|
||||
|
||||
function f_ami_wait_for_prompt(TELNETasp_PT pt, charstring log_label := "(?)") return AMI_Msg {
|
||||
var charstring buf := f_ami_wait_for_prompt_str(pt, log_label);
|
||||
var AMI_Msg msg := dec_AMI_Msg(buf);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* send a AMI command and obtain response until prompt is received */
|
||||
private function f_ami_transceive_ret_str(TELNETasp_PT pt, charstring tx) return charstring {
|
||||
pt.send(tx);
|
||||
return f_ami_wait_for_prompt_str(pt, tx);
|
||||
}
|
||||
|
||||
function f_ami_transceive_ret(TELNETasp_PT pt, template (value) AMI_Msg tx_msg) return AMI_Msg {
|
||||
var charstring tx_txt := enc_AMI_Msg(valueof(tx_msg));
|
||||
var charstring resp_txt := f_ami_transceive_ret_str(pt, tx_txt);
|
||||
return dec_AMI_Msg(resp_txt);
|
||||
}
|
||||
|
||||
function f_ami_transceive_match(TELNETasp_PT pt,
|
||||
template (value) AMI_Msg tx_msg,
|
||||
template (present) AMI_Msg exp_ret := ?) {
|
||||
var AMI_Msg ret := f_ami_transceive_ret(pt, tx_msg);
|
||||
if (not match(ret, exp_ret)) {
|
||||
private altstep as_ami_rx_fail(AMI_Msg_PT pt, template AMI_Msg exp_msg := *)
|
||||
{
|
||||
var AMI_Msg msg;
|
||||
[] pt.receive(AMI_Msg:?) -> value msg {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
log2str("Non-matching AMI response: ", ret, " vs exp: ", exp_ret));
|
||||
log2str("Received unexpected AMI message := ", msg, "\nvs exp := ", exp_msg));
|
||||
}
|
||||
}
|
||||
|
||||
function f_ami_transceive_match_response_success(TELNETasp_PT pt,
|
||||
altstep as_ami_expect_msg(AMI_Msg_PT pt, template (present) AMI_Msg msg_expect, boolean fail_others := true)
|
||||
{
|
||||
[] pt.receive(msg_expect);
|
||||
[fail_others] as_ami_rx_fail(pt, msg_expect);
|
||||
}
|
||||
|
||||
function f_ami_transceive_match(AMI_Msg_PT pt,
|
||||
template (value) AMI_Msg tx_msg,
|
||||
template (present) AMI_Msg exp_ret := ?,
|
||||
boolean fail_others := true,
|
||||
float rx_timeout := 10.0) return AMI_Msg {
|
||||
var AMI_Msg rx_msg;
|
||||
timer T;
|
||||
|
||||
T.start(rx_timeout);
|
||||
pt.send(tx_msg);
|
||||
alt {
|
||||
[] pt.receive(exp_ret) -> value rx_msg;
|
||||
[not fail_others] pt.receive(AMI_Msg:?) -> value rx_msg {
|
||||
log("AMI: Ignoring Rx msg ", rx_msg);
|
||||
repeat;
|
||||
}
|
||||
[fail_others] as_ami_rx_fail(pt, exp_ret);
|
||||
[] T.timeout {
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
||||
log2str("AMI Response timeout: ", tx_msg));
|
||||
}
|
||||
}
|
||||
T.stop;
|
||||
return rx_msg;
|
||||
}
|
||||
|
||||
function f_ami_transceive_match_response_success(AMI_Msg_PT pt,
|
||||
template (value) AMI_Msg tx_msg) {
|
||||
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);
|
||||
|
@ -290,11 +346,11 @@ function f_ami_transceive_match_response_success(TELNETasp_PT pt,
|
|||
f_ami_transceive_match(pt, tx_msg, exp_resp);
|
||||
}
|
||||
|
||||
function f_ami_action_login(TELNETasp_PT pt, charstring username, charstring secret) {
|
||||
function f_ami_action_login(AMI_Msg_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) {
|
||||
function f_ami_action_PJSIPRegister(AMI_Msg_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));
|
||||
}
|
||||
|
|
|
@ -49,7 +49,9 @@ type component test_CT {
|
|||
/* Manages the IMS server Asterisk connects to: */
|
||||
var SIP_Emulation_CT vc_IMS;
|
||||
|
||||
port TELNETasp_PT AMI;
|
||||
/* Connection towards Asterisk AMI iface: */
|
||||
var AMI_Adapter_CT vc_AMI;
|
||||
port AMI_Msg_PT AMI_CLIENT;
|
||||
|
||||
port Coord_PT COORD;
|
||||
port IMSCoord_PT IMS_COORD;
|
||||
|
@ -70,8 +72,13 @@ function f_init_ConnHdlrPars(integer idx := 1) runs on test_CT return SIPConnHdl
|
|||
|
||||
/* Initialize connection towards Asterisk AMI */
|
||||
private function f_init_ami() runs on test_CT {
|
||||
map(self:AMI, system:AMI);
|
||||
f_ami_action_login(AMI, mp_ami_user, mp_ami_secret);
|
||||
var charstring id := "Asterisk_Tests_AMI_EMU";
|
||||
vc_AMI := AMI_Adapter_CT.create(id);
|
||||
connect(self:AMI_CLIENT, vc_AMI:CLIENT);
|
||||
vc_AMI.start(f_AMI_Adapter_main());
|
||||
|
||||
|
||||
f_ami_action_login(AMI_CLIENT, mp_ami_user, mp_ami_secret);
|
||||
}
|
||||
|
||||
/* Local SIP UAs */
|
||||
|
|
Loading…
Reference in New Issue