blob: 1f3dc5e0f10dc2fed67d3859c36cab8126ca9298 [file] [log] [blame]
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +02001/* Asterisk's AMI interface functions in TTCN-3
2 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
3 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
4 * All rights reserved.
5 *
6 * Released under the terms of GNU General Public License, Version 2 or
7 * (at your option) any later version.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12/*
13 * https://docs.asterisk.org/Configuration/Interfaces/Asterisk-Manager-Interface-AMI/AMI-v2-Specification/
14 */
15module AMI_Functions {
16
17import from Misc_Helpers all;
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020018import from Osmocom_Types all;
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +020019import from IPL4asp_Types all;
20import from IPL4asp_PortType all;
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020021import from Socket_API_Definitions all;
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +020022import from TCCConversion_Functions all;
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020023
24modulepar {
25 float mp_ami_prompt_timeout := 10.0;
26}
27
28const charstring AMI_FIELD_ACTION := "Action";
Pau Espin Pedrol941ca3c2024-05-09 16:46:58 +020029const charstring AMI_FIELD_ACTION_ID := "ActionID";
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020030const charstring AMI_FIELD_USERNAME := "Username";
31const charstring AMI_FIELD_SECRET := "Secret";
32const charstring AMI_FIELD_RESPONSE := "Response";
33
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +020034/* Extensions: */
35const charstring AMI_FIELD_REGISTRATION := "Registration";
36
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020037type record AMI_Field {
38 charstring key,
39 charstring val
Pau Espin Pedrolde7a4852024-04-19 16:20:45 +020040} with {
41 encode "TEXT"
42 variant "SEPARATOR(': ', ':\s+')"
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020043};
Pau Espin Pedrolde7a4852024-04-19 16:20:45 +020044
45type set of AMI_Field AMI_Msg with {
46 encode "TEXT"
47 variant "SEPARATOR('\r\n', '(\r\n)|[\n]')"
48 variant "END('\r\n', '(\r\n)|[\n]')"
49};
50
51external function enc_AMI_Msg(in AMI_Msg msg) return charstring
52 with { extension "prototype(convert) encode(TEXT)" }
53external function dec_AMI_Msg(in charstring stream) return AMI_Msg
54 with { extension "prototype(convert) decode(TEXT)" }
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020055
56template (value) AMI_Field
57ts_AMI_Field(template (value) charstring key,
58 template (value) charstring val) := {
59 key := key,
60 val := val
61};
62
63template (present) AMI_Field
64tr_AMI_Field(template (present) charstring key := ?,
65 template (present) charstring val := ?) := {
66 key := key,
67 val := val
68};
69
70/*
71 * Field Templates:
72 */
73
74template (value) AMI_Field
75ts_AMI_Field_Action(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION, val);
76template (value) AMI_Field
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +020077ts_AMI_Field_ActionId(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION_ID, val);
78template (value) AMI_Field
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020079ts_AMI_Field_Username(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_USERNAME, val);
80template (value) AMI_Field
81ts_AMI_Field_Secret(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_SECRET, val);
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +020082/* Extensions: */
83template (value) AMI_Field
84ts_AMI_Field_Registration(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_REGISTRATION, val);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020085
86template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020087tr_AMI_Field_Action(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_ACTION, val);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020088template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020089tr_AMI_Field_ActionId(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_ACTION_ID, val);
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +020090template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020091tr_AMI_Field_Username(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_USERNAME, val);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020092template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020093tr_AMI_Field_Secret(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_SECRET, val);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020094template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020095tr_AMI_Field_Response(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_RESPONSE, val);
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +020096/* Extensions: */
97template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +020098tr_AMI_Field_Registration(template (present) charstring val := ?) := tr_AMI_Field(pattern @nocase AMI_FIELD_REGISTRATION, val);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +020099
100
101template (present) AMI_Field
Pau Espin Pedrol21c084f2024-05-09 16:42:16 +0200102tr_AMI_Field_ResponseSuccess := tr_AMI_Field(pattern @nocase AMI_FIELD_RESPONSE, "Success");
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200103
104
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200105/***********************
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200106 * Message Templates:
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200107 ***********************/
108
109/*
110 * ACTIONS
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200111 */
112
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200113/* Action: Login
114 * Username: <value>
115 * Secret: <value>
116 */
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200117template (value) AMI_Msg
Pau Espin Pedrol77976a62024-05-08 21:17:38 +0200118ts_AMI_Action_Login(charstring username,
119 charstring secret,
120 template (value) charstring action_id := "0001") := {
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200121 ts_AMI_Field_Action("Login"),
Pau Espin Pedrol77976a62024-05-08 21:17:38 +0200122 ts_AMI_Field_ActionId(action_id),
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200123 ts_AMI_Field_Username(username),
124 ts_AMI_Field_Secret(secret)
125};
126
127template (present) AMI_Msg
128tr_AMI_Action_Login(template(present) charstring username := ?,
Pau Espin Pedrol77976a62024-05-08 21:17:38 +0200129 template(present) charstring secret := ?,
130 template (present) charstring action_id := ?) := superset(
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200131 tr_AMI_Field_Action("Login"),
Pau Espin Pedrol77976a62024-05-08 21:17:38 +0200132 tr_AMI_Field_ActionId(action_id),
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200133 tr_AMI_Field_Username(username),
134 tr_AMI_Field_Secret(secret)
135);
136
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200137/* Action: PJSIPRegister
138 * ActionID: <value>
139 * Registration: volte_ims
140 */
141template (value) AMI_Msg
142ts_AMI_Action_PJSIPRegister(template (value) charstring registration := "volte_ims",
143 template (value) charstring action_id := "0001") := {
144 ts_AMI_Field_Action("PJSIPRegister"),
145 ts_AMI_Field_ActionId(action_id),
146 ts_AMI_Field_Registration(registration)
147};
148template (present) AMI_Msg
149tr_AMI_Action_PJSIPRegister(template (present) charstring registration := ?,
150 template (present) charstring action_id := ?) := {
151 tr_AMI_Field_Action("PJSIPRegister"),
152 tr_AMI_Field_ActionId(action_id),
153 tr_AMI_Field_Registration(registration)
154};
155
156/*
157 * RESPONSES
158 */
159
160/* Response: Success
161 */
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200162template (present) AMI_Msg
163tr_AMI_Response_Success := superset(
164 tr_AMI_Field_ResponseSuccess
165);
166
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200167/* Response: Success
168 * ActionId: <value>
169 */
170template (present) AMI_Msg
171tr_AMI_Response_Success_ActionId(template (present) charstring action_id := ?) := superset(
172 tr_AMI_Field_ResponseSuccess,
173 tr_AMI_Field_ActionId(action_id)
174);
175
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200176
177/***********************
178 * Adapter:
179 ***********************/
180
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200181type record AMI_Adapter_Parameters {
182 charstring remote_host,
183 IPL4asp_Types.PortNumber remote_port,
184 charstring local_host,
185 IPL4asp_Types.PortNumber local_port,
186 charstring welcome_str
187}
188
189const AMI_Adapter_Parameters c_default_AMI_Adapter_pars := {
190 remote_host := "127.0.0.1",
191 remote_port := 5038,
192 local_host := "0.0.0.0",
193 local_port := 0,
194 welcome_str := "Asterisk Call Manager/9.0.0\r\n"
195};
196
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200197type port AMI_Msg_PT message {
198 inout AMI_Msg;
199} with { extension "internal" };
200
201type component AMI_Adapter_CT {
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200202 port IPL4asp_PT IPL4;
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200203 port AMI_Msg_PT CLIENT;
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200204 var AMI_Adapter_Parameters g_pars;
205
206 /* Connection identifier of the client itself */
207 var IPL4asp_Types.ConnectionId g_self_conn_id := -1;
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200208}
209
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200210/* Function to use to connect as client to a remote IPA Server */
211private function f_AMI_Adapter_connect() runs on AMI_Adapter_CT {
212 var IPL4asp_Types.Result res;
213 map(self:IPL4, system:IPL4);
214 res := IPL4asp_PortType.f_IPL4_connect(IPL4, g_pars.remote_host, g_pars.remote_port,
215 g_pars.local_host, g_pars.local_port, 0, { tcp:={} });
216 if (not ispresent(res.connId)) {
217 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
218 log2str("Could not connect AMI socket from ", g_pars.local_host, " port ",
219 g_pars.local_port, " to ", g_pars.remote_host, " port ", g_pars.remote_port,
220 "; check your configuration"));
221 }
222 g_self_conn_id := res.connId;
223 log("AMI connected, ConnId=", g_self_conn_id)
224}
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200225
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200226private function f_ASP_RecvFrom_msg_to_charstring(ASP_RecvFrom rx_rf) return charstring {
227 return oct2char(rx_rf.msg);
228}
229
230/* Function to use to connect as client to a remote IPA Server */
231private function f_AMI_Adapter_wait_rx_welcome_str() runs on AMI_Adapter_CT {
232 var ASP_RecvFrom rx_rf;
233 var charstring rx_str;
234 timer Twelcome := 3.0;
235
236 Twelcome.start;
237 alt {
238 [] IPL4.receive(ASP_RecvFrom:?) -> value rx_rf {
239 rx_str := f_ASP_RecvFrom_msg_to_charstring(rx_rf);
240 if (g_pars.welcome_str != rx_str) {
241 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
242 log2str("AMI Welcome message mismatch: '", rx_str,
243 "' vs exp '", g_pars.welcome_str, "'"));
244 }
245 }
246 [] Twelcome.timeout {
247 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
248 log2str("AMI Welcome timeout"));
249 }
250 }
251 Twelcome.stop;
252 log("AMI Welcome message received: '", rx_str, "'");
253}
254
255private function dec_AMI_Msg_ext(charstring txt) return AMI_Msg {
256 log("AMI dec: '", txt, "'");
257 /* TEXT Enc/dec is not happy with empty values, workaround it: */
258 var charstring patched_txt := f_str_replace(txt, "Challenge: \r\n", "");
259 patched_txt := f_str_replace(patched_txt, "AccountCode: \r\n", "");
260 patched_txt := f_str_replace(patched_txt, "Value: \r\n", "");
261 patched_txt := f_str_replace(patched_txt, "DestExten: \r\n", "");
262 patched_txt := f_str_replace(patched_txt, "Exten: \r\n", "");
263 patched_txt := f_str_replace(patched_txt, "Extension: \r\n", "");
264
265 /* "AppData" field sometimes has a value containing separator ": ", which makes
266 * TEXT dec not happy. Workaround it for now by removing the whole field line:
267 * "AppData: 5,0502: Call pjsip endpoint from 0501\r\n"
268 */
269 var integer pos := f_strstr(patched_txt, "AppData: ", 0);
270 if (pos >= 0) {
271 var integer pos_end := f_strstr(patched_txt, "\r\n", pos) + lengthof("\r\n");
272 var charstring to_remove := substr(patched_txt, pos, pos_end - pos);
273 patched_txt := f_str_replace(patched_txt, to_remove, "");
274 }
275
276 log("AMI patched dec: '", patched_txt, "'");
277 return dec_AMI_Msg(patched_txt);
278}
279
280function f_AMI_Adapter_main(AMI_Adapter_Parameters pars := c_default_AMI_Adapter_pars)
281 runs on AMI_Adapter_CT {
282 var AMI_Msg msg;
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200283 var charstring rx, buf := "";
284 var integer fd;
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200285 var ASP_RecvFrom rx_rf;
286 var ASP_Event rx_ev;
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200287
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200288 g_pars := pars;
289
290 f_AMI_Adapter_connect();
291
292 f_AMI_Adapter_wait_rx_welcome_str();
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200293
294 while (true) {
295
296 alt {
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200297 [] IPL4.receive(ASP_RecvFrom:?) -> value rx_rf {
298 var charstring rx_str := f_ASP_RecvFrom_msg_to_charstring(rx_rf);
299 log("AMI rx: '", rx_str, "'");
300 buf := buf & rx_str;
301 log("AMI buf: '", buf, "'");
302
303 /* If several messages come together */
304 var boolean last_is_complete := f_str_endswith(buf, "\r\n\r\n");
305 var Misc_Helpers.ro_charstring msgs := f_str_split(buf, "\r\n\r\n");
306 log("AMI split: ", msgs);
307 if (lengthof(msgs) > 0) {
308 for (var integer i := 0; i < lengthof(msgs) - 1; i := i + 1) {
309 var charstring txt := msgs[i] & "\r\n";
310 msg := dec_AMI_Msg_ext(txt);
311 CLIENT.send(msg);
312 }
313 if (last_is_complete) {
314 var charstring txt := msgs[lengthof(msgs) - 1] & "\r\n";
315 msg := dec_AMI_Msg_ext(txt);
316 CLIENT.send(msg);
317 buf := "";
318 } else {
319 buf := msgs[lengthof(msgs) - 1];
320 }
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200321 }
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200322 log("AMI remain buf: '", buf, "'");
323 }
324 [] IPL4.receive(ASP_ConnId_ReadyToRelease:?) {
325 }
326
327 [] IPL4.receive(ASP_Event:?) -> value rx_ev {
328 log("Rx AMI ASP_Event: ", rx_ev);
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200329 }
330 [] CLIENT.receive(AMI_Msg:?) -> value msg {
331 /* TODO: in the future, queue Action if there's already one Action in transit, to fullfill AMI requirements. */
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200332 var charstring tx_txt := enc_AMI_Msg(msg) & "\r\n";
333
334 var ASP_SendTo tx := {
335 connId := g_self_conn_id,
336 remName := g_pars.remote_host,
337 remPort := g_pars.remote_port,
338 proto := { tcp := {} },
339 msg := char2oct(tx_txt)
340 };
341 IPL4.send(tx);
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200342 }
343 }
344 }
345}
346
347
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200348/*
349 * Functions:
350 */
351
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200352/* Generate a random "ActionId" value: */
353function f_gen_action_id() return charstring {
354 return hex2str(f_rnd_hexstring(16));
355}
356
357function f_ami_msg_find(AMI_Msg msg,
358 template (present) charstring key := ?)
359return template (omit) AMI_Field {
360 var integer i;
361
362 for (i := 0; i < lengthof(msg); i := i + 1) {
363 if (not ispresent(msg[i])) {
364 continue;
365 }
366 if (match(msg[i].key, key)) {
367 return msg[i];
368 }
369 }
370 return omit;
371}
372
373function f_ami_msg_find_or_fail(AMI_Msg msg,
374 template (present) charstring key := ?)
375return AMI_Field {
376 var template (omit) AMI_Field field;
377 field := f_ami_msg_find(msg, key);
378 if (istemplatekind(field, "omit")) {
379 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
380 log2str("Key ", key, " not found in ", msg));
381 }
382 return valueof(field);
383}
384
385function f_ami_msg_get_value(AMI_Msg msg,
386 template (present) charstring key := ?)
387return template (omit) charstring {
388 var template (omit) AMI_Field field;
389 field := f_ami_msg_find(msg, key);
390 if (istemplatekind(field, "omit")) {
391 return omit;
392 }
393 return field.val;
394}
395
396function f_ami_msg_get_value_or_fail(AMI_Msg msg,
397 template (present) charstring key := ?)
398return template charstring {
399 var AMI_Field field;
400 field := f_ami_msg_find_or_fail(msg, key);
401 return field.val;
402}
403
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200404function f_ami_transceive_ret(AMI_Msg_PT pt, template (value) AMI_Msg tx_msg, float rx_timeout := 10.0) return AMI_Msg {
405 var AMI_Msg rx_msg;
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200406 timer T;
407
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200408 T.start(rx_timeout);
409 pt.send(tx_msg);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200410 alt {
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200411 [] pt.receive(AMI_Msg:?) -> value rx_msg;
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200412 [] T.timeout {
413 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200414 log2str("AMI Response timeout: ", tx_msg));
415 }
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200416 }
417 T.stop;
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200418 return rx_msg;
419
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200420}
421
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200422private altstep as_ami_rx_fail(AMI_Msg_PT pt, template AMI_Msg exp_msg := *)
423{
424 var AMI_Msg msg;
425 [] pt.receive(AMI_Msg:?) -> value msg {
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200426 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200427 log2str("Received unexpected AMI message := ", msg, "\nvs exp := ", exp_msg));
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200428 }
429}
430
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200431altstep as_ami_expect_msg(AMI_Msg_PT pt, template (present) AMI_Msg msg_expect, boolean fail_others := true)
432{
433 [] pt.receive(msg_expect);
434 [fail_others] as_ami_rx_fail(pt, msg_expect);
435}
436
437function f_ami_transceive_match(AMI_Msg_PT pt,
438 template (value) AMI_Msg tx_msg,
439 template (present) AMI_Msg exp_ret := ?,
440 boolean fail_others := true,
441 float rx_timeout := 10.0) return AMI_Msg {
442 var AMI_Msg rx_msg;
443 timer T;
444
445 T.start(rx_timeout);
446 pt.send(tx_msg);
447 alt {
448 [] pt.receive(exp_ret) -> value rx_msg;
449 [not fail_others] pt.receive(AMI_Msg:?) -> value rx_msg {
450 log("AMI: Ignoring Rx msg ", rx_msg);
451 repeat;
452 }
453 [fail_others] as_ami_rx_fail(pt, exp_ret);
454 [] T.timeout {
455 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
456 log2str("AMI Response timeout: ", tx_msg));
457 }
458 }
459 T.stop;
460 return rx_msg;
461}
462
463function f_ami_transceive_match_response_success(AMI_Msg_PT pt,
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200464 template (value) AMI_Msg tx_msg) {
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200465 var template (present) AMI_Msg exp_resp;
466 var template (omit) charstring action_id := f_ami_msg_get_value(valueof(tx_msg), AMI_FIELD_ACTION_ID);
467 if (isvalue(action_id)) {
468 exp_resp := tr_AMI_Response_Success_ActionId(action_id);
469 } else {
470 exp_resp := tr_AMI_Response_Success;
471 }
472 f_ami_transceive_match(pt, tx_msg, exp_resp);
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200473}
474
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200475function f_ami_action_login(AMI_Msg_PT pt, charstring username, charstring secret) {
Pau Espin Pedrol77976a62024-05-08 21:17:38 +0200476 var charstring reg_action_id := f_gen_action_id();
477 f_ami_transceive_match_response_success(pt, ts_AMI_Action_Login(username, secret, reg_action_id));
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200478}
479
Pau Espin Pedrolbcb4e822024-04-26 20:16:47 +0200480function f_ami_action_PJSIPRegister(AMI_Msg_PT pt, charstring register) {
Pau Espin Pedrol4362dbd2024-04-26 19:31:27 +0200481 var charstring reg_action_id := f_gen_action_id();
482 f_ami_transceive_match_response_success(pt, ts_AMI_Action_PJSIPRegister(register, reg_action_id));
483}
484
Pau Espin Pedrol01f1df82024-05-08 16:55:55 +0200485private function f_ami_selftest_decode(charstring txt) {
486 log("Text to decode: '", txt, "'");
487 var AMI_Msg msg := dec_AMI_Msg(txt);
488 log("AMI_Msg decoded: ", msg);
489}
490
491function f_ami_selftest() {
492 f_ami_selftest_decode("AppData: 5,0502: Call pjsip endpoint from 0501\r\n");
493}
494
Pau Espin Pedrol54b614a2024-04-17 18:58:36 +0200495}