From fcf0a963bef40721e54d2a51ba123e52ec5305ed Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Thu, 24 Oct 2024 15:22:35 +0200 Subject: [PATCH 1/9] TEL-6201 Add new functions for setting and getting dialplan function. --- src/include/switch_channel.h | 2 ++ src/switch_channel.c | 12 ++++++++++++ src/switch_core_state_machine.c | 14 +++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 7fbbce968e2..5c04fc62a4a 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -720,6 +720,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_bind_device_state_handler(switch_ SWITCH_DECLARE(switch_status_t) switch_channel_unbind_device_state_handler(switch_device_state_function_t function); SWITCH_DECLARE(const char *) switch_channel_device_state2str(switch_device_state_t device_state); SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp); +SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_application_function_t function); +SWITCH_DECLARE(switch_application_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel); SWITCH_END_EXTERN_C #endif diff --git a/src/switch_channel.c b/src/switch_channel.c index 96e79f21c53..5f31072b245 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -189,6 +189,7 @@ struct switch_channel { switch_device_node_t *device_node; char *device_id; switch_event_t *log_tags; + switch_application_function_t post_dialplan_function; }; static void process_device_hup(switch_channel_t *channel); @@ -5846,6 +5847,17 @@ SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_c return status; } +SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_application_function_t function) +{ + assert(function != NULL); + channel->post_dialplan_function = function; +} + +SWITCH_DECLARE(switch_application_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel) +{ + return channel->post_dialplan_function; +} + /* For Emacs: * Local Variables: * mode:c diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 28185a89350..24115b07255 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -333,6 +333,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) const char *uuid; const char *next_application_on_execute = NULL; const char *next_application_data_on_execute = NULL; + const char *post_dialplan_execute = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel)); @@ -370,9 +371,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) switch_channel_set_variable(session->channel, "next_application_on_execute", ""); switch_channel_set_variable(session->channel, "next_application_data_on_execute", ""); } - - - + while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) { switch_caller_application_t *current_application = extension->current_application; @@ -390,6 +389,15 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) } + post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); + + if (!zstr(post_dialplan_execute)) { + switch_application_function_t func = switch_channel_get_post_dialplan_function(session->channel); + if (func) { + func(session, post_dialplan_execute); + } + } + if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE && switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER) && (uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) { From fd0b66ef1527f9ca732d134bca3c2cbe5a8ccb1b Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Wed, 4 Dec 2024 11:48:05 +0100 Subject: [PATCH 2/9] TEL-6201: Add checks for NULL. --- src/switch_channel.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 5f31072b245..b1be3dd79fb 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -5850,12 +5850,17 @@ SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_c SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_application_function_t function) { assert(function != NULL); - channel->post_dialplan_function = function; + if (channel) { + channel->post_dialplan_function = function; + } } SWITCH_DECLARE(switch_application_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel) { - return channel->post_dialplan_function; + if (channel) { + return channel->post_dialplan_function; + } + return NULL; } /* For Emacs: From 9a206e8f0fbd536ac668e2c662ce507c7f8f60e6 Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Thu, 5 Dec 2024 10:01:17 +0100 Subject: [PATCH 3/9] TEL-6201: Move this to on_routing. --- src/switch_core_state_machine.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 24115b07255..c06fc0f620d 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -238,6 +238,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) switch_caller_extension_t *extension = NULL; char *expanded = NULL; char *dpstr = NULL; + const char *post_dialplan_execute = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard ROUTING\n", switch_channel_get_name(session->channel)); @@ -297,6 +298,14 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } } + post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); + if (!zstr(post_dialplan_execute)) { + switch_application_function_t func = switch_channel_get_post_dialplan_function(session->channel); + if (func) { + func(session, post_dialplan_execute); + } + } + if (!count) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { @@ -333,7 +342,6 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) const char *uuid; const char *next_application_on_execute = NULL; const char *next_application_data_on_execute = NULL; - const char *post_dialplan_execute = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel)); @@ -389,15 +397,6 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) } - post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); - - if (!zstr(post_dialplan_execute)) { - switch_application_function_t func = switch_channel_get_post_dialplan_function(session->channel); - if (func) { - func(session, post_dialplan_execute); - } - } - if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE && switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER) && (uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) { From 9133236b684048865376091dbdc74331dc422404 Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Thu, 5 Dec 2024 14:33:19 +0100 Subject: [PATCH 4/9] TEL-6201: Update logic for post dialplans. --- src/include/switch_channel.h | 4 ++-- src/include/switch_types.h | 2 ++ src/switch_channel.c | 6 +++--- src/switch_core_state_machine.c | 16 ++++++++-------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 5c04fc62a4a..aad0d7d8b6b 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -720,8 +720,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_bind_device_state_handler(switch_ SWITCH_DECLARE(switch_status_t) switch_channel_unbind_device_state_handler(switch_device_state_function_t function); SWITCH_DECLARE(const char *) switch_channel_device_state2str(switch_device_state_t device_state); SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp); -SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_application_function_t function); -SWITCH_DECLARE(switch_application_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_post_dialplan_function_t function); +SWITCH_DECLARE(switch_post_dialplan_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index bc773ebe425..8ba35725ba7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -2571,6 +2571,8 @@ typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session typedef switch_status_t (*switch_read_frame_callback_function_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data); typedef struct switch_say_interface switch_say_interface_t; +typedef void (*switch_post_dialplan_function_t) (switch_core_session_t *, switch_caller_extension_t *, const char *); + #define DMACHINE_MAX_DIGIT_LEN 512 typedef enum { diff --git a/src/switch_channel.c b/src/switch_channel.c index b1be3dd79fb..129678ed7de 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -189,7 +189,7 @@ struct switch_channel { switch_device_node_t *device_node; char *device_id; switch_event_t *log_tags; - switch_application_function_t post_dialplan_function; + switch_post_dialplan_function_t post_dialplan_function; }; static void process_device_hup(switch_channel_t *channel); @@ -5847,7 +5847,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_c return status; } -SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_application_function_t function) +SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t *channel, switch_post_dialplan_function_t function) { assert(function != NULL); if (channel) { @@ -5855,7 +5855,7 @@ SWITCH_DECLARE(void) switch_channel_set_post_dialplan_function(switch_channel_t } } -SWITCH_DECLARE(switch_application_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel) +SWITCH_DECLARE(switch_post_dialplan_function_t) switch_channel_get_post_dialplan_function(switch_channel_t *channel) { if (channel) { return channel->post_dialplan_function; diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index c06fc0f620d..db18dfa0f33 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -290,6 +290,14 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) UNPROTECT_INTERFACE(dialplan_interface); if (extension) { + post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); + if (!zstr(post_dialplan_execute)) { + switch_post_dialplan_function_t func = switch_channel_get_post_dialplan_function(session->channel); + if (func) { + func(session, extension, post_dialplan_execute); + } + } + switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; @@ -298,14 +306,6 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) } } - post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); - if (!zstr(post_dialplan_execute)) { - switch_application_function_t func = switch_channel_get_post_dialplan_function(session->channel); - if (func) { - func(session, post_dialplan_execute); - } - } - if (!count) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { From 6265c0c29aa3ea0161ac6240bed1d9b292024db7 Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Fri, 6 Dec 2024 15:17:53 +0100 Subject: [PATCH 5/9] TEL-6201 Use `sofia_profile_name` to select a post dial plan profile. --- src/switch_core_state_machine.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index db18dfa0f33..32d3d933d30 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -238,7 +238,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) switch_caller_extension_t *extension = NULL; char *expanded = NULL; char *dpstr = NULL; - const char *post_dialplan_execute = NULL; + const char *profile_name = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard ROUTING\n", switch_channel_get_name(session->channel)); @@ -290,11 +290,11 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) UNPROTECT_INTERFACE(dialplan_interface); if (extension) { - post_dialplan_execute = switch_channel_get_variable(session->channel, "post_dialplan_execute"); - if (!zstr(post_dialplan_execute)) { + profile_name = switch_channel_get_variable(session->channel, "sofia_profile_name"); + if (!zstr(profile_name)) { switch_post_dialplan_function_t func = switch_channel_get_post_dialplan_function(session->channel); if (func) { - func(session, extension, post_dialplan_execute); + func(session, extension, profile_name); } } From 8252396f5a200304fe4c71909571229ae4a86a7f Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Mon, 9 Dec 2024 12:29:15 +0100 Subject: [PATCH 6/9] TEL-6201: Add unit test for lite dialplans. Add new function 'switch_caller_extension_insert_application'. --- src/include/switch_caller.h | 14 ++ src/switch_caller.c | 61 +++++++- tests/unit/Makefile.am | 2 +- tests/unit/conf_telnyx/freeswitch.xml | 211 ++++++++++++++++++++++++++ tests/unit/switch_mod_telnyx.c | 46 ++++++ 5 files changed, 331 insertions(+), 3 deletions(-) create mode 100644 tests/unit/conf_telnyx/freeswitch.xml create mode 100644 tests/unit/switch_mod_telnyx.c diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index 3f702fae084..72e602cc2b0 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -185,6 +185,20 @@ SWITCH_DECLARE(void) switch_caller_extension_add_application(_In_ switch_core_se _In_ switch_caller_extension_t *caller_extension, _In_z_ const char *application_name, _In_z_ const char *extra_data); +/*! + \brief Insert an application (instruction) to the given extension, before any of the low priority applications + \param session session associated with the extension (bound by scope) + \param caller_extension extension to add the application to + \param application_name the name of the application + \param extra_data optional argument to the application + \param low_priority_applications array of application names to insert before + \param low_priority_count number of applications in the array +*/ +SWITCH_DECLARE(void) switch_caller_extension_insert_application(_In_ switch_core_session_t *session, + _In_ switch_caller_extension_t *caller_extension, + _In_z_ const char *application_name, _In_z_ const char *extra_data, + _In_opt_ char **low_priority_applications, _In_z_ size_t low_priority_count); + /*! \brief Add an application (instruction) to the given extension \param session session associated with the extension (bound by scope) diff --git a/src/switch_caller.c b/src/switch_caller.c index 4485920c01c..3fc1a5ffd43 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -570,8 +570,6 @@ SWITCH_DECLARE(void) switch_caller_extension_add_application(switch_core_session caller_application->application_name = switch_core_session_strdup(session, application_name); caller_application->application_data = switch_core_session_strdup(session, application_data); - - if (caller_application->application_data && strstr(caller_application->application_data, "\\'")) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "App not added, Invalid character sequence in data string [%s]\n", caller_application->application_data); @@ -587,7 +585,66 @@ SWITCH_DECLARE(void) switch_caller_extension_add_application(switch_core_session caller_extension->last_application = caller_application; caller_extension->current_application = caller_extension->applications; } +} +SWITCH_DECLARE(void) switch_caller_extension_insert_application(switch_core_session_t *session, + switch_caller_extension_t *caller_extension, + const char *application_name, + const char *application_data, + char **low_priority_applications, + size_t low_priority_count) +{ + switch_caller_application_t *caller_application = NULL; + switch_caller_application_t *prev = NULL, *current = NULL; + + switch_assert(session != NULL); + + if ((caller_application = switch_core_session_alloc(session, sizeof(switch_caller_application_t))) != 0) { + caller_application->application_name = switch_core_session_strdup(session, application_name); + caller_application->application_data = switch_core_session_strdup(session, application_data); + + if (caller_application->application_data && strstr(caller_application->application_data, "\\'")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "App not added, Invalid character sequence in data string [%s]\n", + caller_application->application_data); + return; + } + + // Traverse the list of existing applications + current = caller_extension->applications; + while (current) { + // Check if the current application's name matches any in the priority list + for (size_t i = 0; i < low_priority_count; ++i) { + if (low_priority_applications[i] && strcmp(current->application_name, low_priority_applications[i]) == 0) { + // Insert caller_application before current + if (prev) { + prev->next = caller_application; + } else { + caller_extension->applications = caller_application; + } + caller_application->next = current; + + // Update last_application if added at the end + if (current == caller_extension->last_application) { + caller_extension->last_application = caller_application; + } + return; + } + } + prev = current; + current = current->next; + } + + // If no priority match found, append to the end + if (!caller_extension->applications) { + caller_extension->applications = caller_application; + } else if (caller_extension->last_application) { + caller_extension->last_application->next = caller_application; + } + + caller_extension->last_application = caller_application; + caller_extension->current_application = caller_extension->applications; + } } /* For Emacs: diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index e2cec690893..17257a4b6c8 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -4,7 +4,7 @@ noinst_PROGRAMS = switch_event switch_hash switch_ivr_originate switch_utils swi switch_ivr_play_say switch_core_codec switch_rtp switch_xml noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_packetizer switch_core_session test_sofia switch_ivr_async switch_core_asr switch_log -noinst_PROGRAMS+= switch_hold switch_sip +noinst_PROGRAMS+= switch_hold switch_sip switch_mod_telnyx if HAVE_PCAP noinst_PROGRAMS += switch_rtp_pcap diff --git a/tests/unit/conf_telnyx/freeswitch.xml b/tests/unit/conf_telnyx/freeswitch.xml new file mode 100644 index 00000000000..ebc25718b59 --- /dev/null +++ b/tests/unit/conf_telnyx/freeswitch.xml @@ -0,0 +1,211 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + +
+
diff --git a/tests/unit/switch_mod_telnyx.c b/tests/unit/switch_mod_telnyx.c new file mode 100644 index 00000000000..48b81a66e06 --- /dev/null +++ b/tests/unit/switch_mod_telnyx.c @@ -0,0 +1,46 @@ +#include +#include + +#include + +int timeout_sec = 10; + +FST_CORE_BEGIN("./conf_telnyx") +{ + FST_SUITE_BEGIN(switch_mod_telnyx) + { + FST_SETUP_BEGIN() + { + fst_requires_module("mod_telnyx"); + } + FST_SETUP_END() + + FST_TEARDOWN_BEGIN() + { + } + FST_TEARDOWN_END() + + FST_TEST_BEGIN(post_dialplan) + { + switch_core_session_t *session = NULL; + switch_call_cause_t cause; + char *originate_str = switch_mprintf("sofia/gateway/test_gateway/+15553332901"); + + switch_ivr_originate(NULL, &session, &cause, originate_str, timeout_sec, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); + switch_safe_free(originate_str); + fst_requires(session); + + if (session) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + fst_requires(channel); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + switch_core_session_rwunlock(session); + } + } + FST_TEST_END() + } + FST_SUITE_END() +} +FST_CORE_END() From 91d18aeaaf0c76c93d0f6991dfc6c791672179c9 Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Tue, 10 Dec 2024 13:17:36 +0100 Subject: [PATCH 7/9] TEL-6201: Optimize adding applications. New test. --- src/include/switch_caller.h | 12 ++-- src/switch_caller.c | 108 ++++++++++++++++++++------------- tests/unit/switch_mod_telnyx.c | 50 +++++++++++++++ 3 files changed, 124 insertions(+), 46 deletions(-) diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index 72e602cc2b0..506c01207bd 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -189,15 +189,17 @@ SWITCH_DECLARE(void) switch_caller_extension_add_application(_In_ switch_core_se \brief Insert an application (instruction) to the given extension, before any of the low priority applications \param session session associated with the extension (bound by scope) \param caller_extension extension to add the application to - \param application_name the name of the application - \param extra_data optional argument to the application + \param application_names the name of the applications + \param application_data optional argument to the applications + \param app_count number of applications in the array \param low_priority_applications array of application names to insert before \param low_priority_count number of applications in the array */ -SWITCH_DECLARE(void) switch_caller_extension_insert_application(_In_ switch_core_session_t *session, +SWITCH_DECLARE(void) switch_caller_extension_insert_applications(_In_ switch_core_session_t *session, _In_ switch_caller_extension_t *caller_extension, - _In_z_ const char *application_name, _In_z_ const char *extra_data, - _In_opt_ char **low_priority_applications, _In_z_ size_t low_priority_count); + _In_z_ const char **application_names, _In_z_ const char **application_data, + _In_z_ size_t app_count, _In_opt_ char **low_priority_applications, + _In_z_ size_t low_priority_count); /*! \brief Add an application (instruction) to the given extension diff --git a/src/switch_caller.c b/src/switch_caller.c index 3fc1a5ffd43..f91b4bc84c7 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -587,64 +587,90 @@ SWITCH_DECLARE(void) switch_caller_extension_add_application(switch_core_session } } -SWITCH_DECLARE(void) switch_caller_extension_insert_application(switch_core_session_t *session, +SWITCH_DECLARE(void) switch_caller_extension_insert_applications(switch_core_session_t *session, switch_caller_extension_t *caller_extension, - const char *application_name, - const char *application_data, + const char **application_names, + const char **application_data, + size_t app_count, char **low_priority_applications, size_t low_priority_count) { - switch_caller_application_t *caller_application = NULL; - switch_caller_application_t *prev = NULL, *current = NULL; + switch_caller_application_t *new_applications = NULL, *last_new_application = NULL; + switch_caller_application_t *prev = NULL, *current; - switch_assert(session != NULL); + switch_assert(session != NULL); + switch_assert(application_names != NULL); + switch_assert(application_data != NULL); + + // Allocate memory for all applications upfront + for (size_t i = 0; i < app_count; ++i) { + switch_caller_application_t *caller_application; + + if (!application_names[i] || !application_data[i]) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "Skipping null application name or data at index [%zu]\n", i); + continue; + } - if ((caller_application = switch_core_session_alloc(session, sizeof(switch_caller_application_t))) != 0) { - caller_application->application_name = switch_core_session_strdup(session, application_name); - caller_application->application_data = switch_core_session_strdup(session, application_data); + // Allocate and populate new application + caller_application = switch_core_session_alloc(session, sizeof(switch_caller_application_t)); + caller_application->application_name = switch_core_session_strdup(session, application_names[i]); + caller_application->application_data = switch_core_session_strdup(session, application_data[i]); if (caller_application->application_data && strstr(caller_application->application_data, "\\'")) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "App not added, Invalid character sequence in data string [%s]\n", + "Skipping invalid character sequence in application data [%s]\n", caller_application->application_data); - return; + continue; } - // Traverse the list of existing applications - current = caller_extension->applications; - while (current) { - // Check if the current application's name matches any in the priority list - for (size_t i = 0; i < low_priority_count; ++i) { - if (low_priority_applications[i] && strcmp(current->application_name, low_priority_applications[i]) == 0) { - // Insert caller_application before current - if (prev) { - prev->next = caller_application; - } else { - caller_extension->applications = caller_application; - } - caller_application->next = current; - - // Update last_application if added at the end - if (current == caller_extension->last_application) { - caller_extension->last_application = caller_application; - } - return; - } - } - prev = current; - current = current->next; + // Append to the local new applications list + if (!new_applications) { + new_applications = caller_application; + } else { + last_new_application->next = caller_application; } + last_new_application = caller_application; + } - // If no priority match found, append to the end - if (!caller_extension->applications) { - caller_extension->applications = caller_application; - } else if (caller_extension->last_application) { - caller_extension->last_application->next = caller_application; + if (!new_applications) { + // No valid applications to insert + return; + } + + // Traverse the existing applications list to find the insertion point + current = caller_extension->applications; + while (current) { + for (size_t i = 0; i < low_priority_count; ++i) { + if (low_priority_applications[i] && strcmp(current->application_name, low_priority_applications[i]) == 0) { + // Insert the new applications before the current application + if (prev) { + prev->next = new_applications; + } else { + caller_extension->applications = new_applications; + } + last_new_application->next = current; + + // Update the last_application if needed + if (current == caller_extension->last_application) { + caller_extension->last_application = last_new_application; + } + return; + } } + prev = current; + current = current->next; + } - caller_extension->last_application = caller_application; - caller_extension->current_application = caller_extension->applications; + // Append to the end if no priority match was found + if (!caller_extension->applications) { + caller_extension->applications = new_applications; + } else if (caller_extension->last_application) { + caller_extension->last_application->next = new_applications; } + + caller_extension->last_application = last_new_application; + caller_extension->current_application = caller_extension->applications; } /* For Emacs: diff --git a/tests/unit/switch_mod_telnyx.c b/tests/unit/switch_mod_telnyx.c index 48b81a66e06..ca28443dcc1 100644 --- a/tests/unit/switch_mod_telnyx.c +++ b/tests/unit/switch_mod_telnyx.c @@ -20,6 +20,56 @@ FST_CORE_BEGIN("./conf_telnyx") } FST_TEARDOWN_END() + FST_SESSION_BEGIN(test_switch_caller_extension_insert_applications) + { + switch_caller_extension_t *caller_extension = NULL; + + // Prepare test data + const char *application_names[] = { "app1", "app2", "app3" }; + const char *application_data[] = { "data1", "data2", "data3" }; + const size_t app_count = sizeof(application_names) / sizeof(application_names[0]); + + // Low priority applications (ensure they remain at the end) + char *low_priority[] = { "low_priority_app" }; + const size_t low_priority_count = sizeof(low_priority) / sizeof(low_priority[0]); + switch_caller_application_t *current; + switch_caller_application_t *low_prio; + + // Initialize a caller extension + caller_extension = switch_core_session_alloc(fst_session, sizeof(switch_caller_extension_t)); + fst_check(caller_extension != NULL); + + switch_caller_extension_add_application(fst_session, caller_extension, "low_priority_app", "data"); + low_prio = caller_extension->applications; + + // Insert applications into the caller extension + switch_caller_extension_insert_applications( + fst_session, + caller_extension, + application_names, + application_data, + app_count, + low_priority, + low_priority_count + ); + + // Verify the applications are inserted correctly + current = caller_extension->applications; + + // Check the order of applications + for (size_t i = 0; i < app_count; ++i) { + fst_check(current != NULL); + fst_check(strcmp(current->application_name, application_names[i]) == 0); + fst_check(strcmp(current->application_data, application_data[i]) == 0); + current = current->next; + } + + // Verify the last_application pointer + fst_check(caller_extension->last_application != NULL); + fst_check(current == low_prio); + } + FST_SESSION_END() + FST_TEST_BEGIN(post_dialplan) { switch_core_session_t *session = NULL; From 50b12b8be295eba69c5ef77312232e84f47d4a3d Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Tue, 10 Dec 2024 14:41:13 +0100 Subject: [PATCH 8/9] TEL-6201: Fix indent. Allow NULL or empty app data. Do not allow empty app names. --- src/switch_caller.c | 146 ++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/switch_caller.c b/src/switch_caller.c index f91b4bc84c7..36b3f783140 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -595,82 +595,82 @@ SWITCH_DECLARE(void) switch_caller_extension_insert_applications(switch_core_ses char **low_priority_applications, size_t low_priority_count) { - switch_caller_application_t *new_applications = NULL, *last_new_application = NULL; + switch_caller_application_t *new_applications = NULL, *last_new_application = NULL; switch_caller_application_t *prev = NULL, *current; switch_assert(session != NULL); - switch_assert(application_names != NULL); - switch_assert(application_data != NULL); - - // Allocate memory for all applications upfront - for (size_t i = 0; i < app_count; ++i) { - switch_caller_application_t *caller_application; - - if (!application_names[i] || !application_data[i]) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "Skipping null application name or data at index [%zu]\n", i); - continue; - } - - // Allocate and populate new application - caller_application = switch_core_session_alloc(session, sizeof(switch_caller_application_t)); - caller_application->application_name = switch_core_session_strdup(session, application_names[i]); - caller_application->application_data = switch_core_session_strdup(session, application_data[i]); - - if (caller_application->application_data && strstr(caller_application->application_data, "\\'")) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "Skipping invalid character sequence in application data [%s]\n", - caller_application->application_data); - continue; - } - - // Append to the local new applications list - if (!new_applications) { - new_applications = caller_application; - } else { - last_new_application->next = caller_application; - } - last_new_application = caller_application; - } - - if (!new_applications) { - // No valid applications to insert - return; - } - - // Traverse the existing applications list to find the insertion point - current = caller_extension->applications; - while (current) { - for (size_t i = 0; i < low_priority_count; ++i) { - if (low_priority_applications[i] && strcmp(current->application_name, low_priority_applications[i]) == 0) { - // Insert the new applications before the current application - if (prev) { - prev->next = new_applications; - } else { - caller_extension->applications = new_applications; - } - last_new_application->next = current; - - // Update the last_application if needed - if (current == caller_extension->last_application) { - caller_extension->last_application = last_new_application; - } - return; - } - } - prev = current; - current = current->next; - } - - // Append to the end if no priority match was found - if (!caller_extension->applications) { - caller_extension->applications = new_applications; - } else if (caller_extension->last_application) { - caller_extension->last_application->next = new_applications; - } - - caller_extension->last_application = last_new_application; - caller_extension->current_application = caller_extension->applications; + switch_assert(application_names != NULL); + switch_assert(application_data != NULL); + + // Allocate memory for all applications upfront + for (size_t i = 0; i < app_count; ++i) { + switch_caller_application_t *caller_application; + + if (zstr(application_names[i])) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "Skipping null application name or data at index [%zu]\n", i); + continue; + } + + // Allocate and populate new application + caller_application = switch_core_session_alloc(session, sizeof(switch_caller_application_t)); + caller_application->application_name = switch_core_session_strdup(session, application_names[i]); + caller_application->application_data = switch_core_session_strdup(session, application_data[i]); + + if (caller_application->application_data && strstr(caller_application->application_data, "\\'")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "Skipping invalid character sequence in application data [%s]\n", + caller_application->application_data); + continue; + } + + // Append to the local new applications list + if (!new_applications) { + new_applications = caller_application; + } else { + last_new_application->next = caller_application; + } + last_new_application = caller_application; + } + + if (!new_applications) { + // No valid applications to insert + return; + } + + // Traverse the existing applications list to find the insertion point + current = caller_extension->applications; + while (current) { + for (size_t i = 0; i < low_priority_count; ++i) { + if (low_priority_applications[i] && strcmp(current->application_name, low_priority_applications[i]) == 0) { + // Insert the new applications before the current application + if (prev) { + prev->next = new_applications; + } else { + caller_extension->applications = new_applications; + } + last_new_application->next = current; + + // Update the last_application if needed + if (current == caller_extension->last_application) { + caller_extension->last_application = last_new_application; + } + return; + } + } + prev = current; + current = current->next; + } + + // Append to the end if no priority match was found + if (!caller_extension->applications) { + caller_extension->applications = new_applications; + } else if (caller_extension->last_application) { + caller_extension->last_application->next = new_applications; + } + + caller_extension->last_application = last_new_application; + caller_extension->current_application = caller_extension->applications; } /* For Emacs: From 79d46555520c8b1d4416fe6642d0d76584763235 Mon Sep 17 00:00:00 2001 From: Damir Nedzibovic Date: Tue, 10 Dec 2024 14:41:43 +0100 Subject: [PATCH 9/9] TEL-6201: Fix warning msg. --- src/switch_caller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_caller.c b/src/switch_caller.c index 36b3f783140..3250cdf0d76 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -608,7 +608,7 @@ SWITCH_DECLARE(void) switch_caller_extension_insert_applications(switch_core_ses if (zstr(application_names[i])) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "Skipping null application name or data at index [%zu]\n", i); + "Skipping null or empty application name at index [%zu]\n", i); continue; }