From c2e240d6dca09e2ccfcd626ef0fd456d4095649b Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 23 Jun 2020 17:50:18 -0400 Subject: [PATCH] [core] Add switch_core_session_set_external_id() which lets you define an additional identifier that you can use in switch_core_session_locate(). --- src/include/private/switch_core_pvt.h | 1 + src/include/switch_core.h | 11 +++- src/switch_channel.c | 3 +- src/switch_core_session.c | 48 +++++++++++++++++ tests/unit/Makefile.am | 2 +- tests/unit/switch_core_session.c | 75 +++++++++++++++++++++++++++ tests/unit/switch_ivr_originate.c | 47 +++++++++++++++++ 7 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 tests/unit/switch_core_session.c diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index a69c3173cc..aece2e7e17 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -189,6 +189,7 @@ struct switch_core_session { switch_buffer_t *text_buffer; switch_buffer_t *text_line_buffer; switch_mutex_t *text_mutex; + const char *external_id; }; struct switch_media_bug { diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 263c1f7ff7..e4c615941d 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2014, Anthony Minessale II + * Copyright (C) 2005-2020, Anthony Minessale II * * Version: MPL 1.1 * @@ -804,6 +804,8 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(_In_ sw SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(_In_ switch_core_session_t *session, _In_z_ const char *use_uuid); +SWITCH_DECLARE(switch_status_t) switch_core_session_set_external_id(_In_ switch_core_session_t *session, _In_z_ const char *use_external_id); + SWITCH_DECLARE(void) switch_core_session_perform_destroy(_Inout_ switch_core_session_t **session, _In_z_ const char *file, _In_z_ const char *func, _In_ int line); @@ -875,6 +877,13 @@ SWITCH_DECLARE(void) switch_core_session_signal_state_change(_In_ switch_core_se */ SWITCH_DECLARE(char *) switch_core_session_get_uuid(_In_ switch_core_session_t *session); +/*! + \brief Retrieve the unique external identifier from a session + \param session the session to retrieve the uuid from + \return a string representing the uuid +*/ +SWITCH_DECLARE(const char *) switch_core_session_get_external_id(_In_ switch_core_session_t *session); + /*! \brief Sets the log level for a session diff --git a/src/switch_channel.c b/src/switch_channel.c index d2b10ed15d..d6c0e64883 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2014, Anthony Minessale II + * Copyright (C) 2005-2020, Anthony Minessale II * * Version: MPL 1.1 * @@ -2655,6 +2655,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", state_num); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Name", switch_channel_get_name(channel)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Session-External-ID", switch_core_session_get_external_id(channel->session)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Direction", channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 4440da639d..23c787fb23 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -625,6 +625,7 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_ switch_event_t *event; switch_channel_t *peer_channel = switch_core_session_get_channel(*new_session); const char *use_uuid; + const char *use_external_id; switch_core_session_t *other_session = NULL; switch_assert(peer_channel); @@ -646,6 +647,17 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_ } } + if ((use_external_id = switch_event_get_header(var_event, "origination_external_id"))) { + if (switch_core_session_set_external_id(*new_session, use_external_id) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, "%s set external_id=%s\n", switch_channel_get_name(peer_channel), + use_external_id); + switch_event_del_header(var_event, "origination_external_id"); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "%s set external_id=%s FAILED\n", + switch_channel_get_name(peer_channel), use_external_id); + } + } + if (!channel && var_event) { const char *other_uuid; @@ -1558,6 +1570,9 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * switch_mutex_lock(runtime.session_hash_mutex); switch_core_hash_delete(session_manager.session_table, (*session)->uuid_str); + if ((*session)->external_id) { + switch_core_hash_delete(session_manager.session_table, (*session)->external_id); + } if (session_manager.session_count) { session_manager.session_count--; if (session_manager.session_count == 0) { @@ -2055,6 +2070,34 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(switch_core_session return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_core_session_set_external_id(switch_core_session_t *session, const char *use_external_id) +{ + switch_assert(use_external_id); + + if (session->external_id && !strcmp(use_external_id, session->external_id)) { + return SWITCH_STATUS_SUCCESS; + } + + + switch_mutex_lock(runtime.session_hash_mutex); + if (switch_core_hash_find(session_manager.session_table, use_external_id)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Duplicate External ID!\n"); + switch_mutex_unlock(runtime.session_hash_mutex); + return SWITCH_STATUS_FALSE; + } + + switch_channel_set_variable(session->channel, "session_external_id", use_external_id); + + if (session->external_id) { + switch_core_hash_delete(session_manager.session_table, session->external_id); + } + session->external_id = switch_core_session_strdup(session, use_external_id); + switch_core_hash_insert(session_manager.session_table, session->external_id, session); + switch_mutex_unlock(runtime.session_hash_mutex); + + return SWITCH_STATUS_SUCCESS; +} + static char *xml_find_var(switch_xml_t vars, const char *name) { switch_xml_t var; @@ -2540,6 +2583,11 @@ SWITCH_DECLARE(char *) switch_core_session_get_uuid(switch_core_session_t *sessi return session->uuid_str; } +SWITCH_DECLARE(const char *) switch_core_session_get_external_id(switch_core_session_t *session) +{ + if (!session) return NULL; + return session->external_id; +} SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit) { diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 212c54b2bf..10660c7dbd 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/build/modmake.rulesam noinst_PROGRAMS = switch_event switch_hash switch_ivr_originate switch_utils switch_core switch_console switch_vpx switch_core_file \ switch_ivr_play_say switch_core_codec switch_rtp switch_xml -noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_packetizer test_sofia switch_core_asr +noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_packetizer test_sofia switch_core_asr switch_core_session AM_LDFLAGS += -avoid-version -no-undefined $(SWITCH_AM_LDFLAGS) $(openssl_LIBS) AM_LDFLAGS += $(FREESWITCH_LIBS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS) diff --git a/tests/unit/switch_core_session.c b/tests/unit/switch_core_session.c new file mode 100644 index 0000000000..0319683000 --- /dev/null +++ b/tests/unit/switch_core_session.c @@ -0,0 +1,75 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2020, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Rienzo + * + * + * switch_core_session.c -- tests sessions + * + */ +#include +#include + + +FST_CORE_BEGIN("./conf") +{ + FST_SUITE_BEGIN(switch_core_session) + { + FST_SETUP_BEGIN() + { + } + FST_SETUP_END() + + FST_TEARDOWN_BEGIN() + { + } + FST_TEARDOWN_END() + + FST_SESSION_BEGIN(session_external_id) + { + fst_check(switch_core_session_set_external_id(fst_session, switch_core_session_get_uuid(fst_session)) != SWITCH_STATUS_SUCCESS); + fst_check(switch_core_session_set_external_id(fst_session, "foo") == SWITCH_STATUS_SUCCESS); + switch_core_session_t *session = switch_core_session_locate("foo"); + fst_requires(session); + fst_check_string_equals(switch_core_session_get_uuid(session), switch_core_session_get_uuid(fst_session)); + fst_check_string_equals(switch_core_session_get_external_id(session), "foo"); + fst_check(switch_core_session_set_external_id(fst_session, "bar") == SWITCH_STATUS_SUCCESS); + fst_check_string_equals(switch_core_session_get_external_id(session), "bar"); + fst_requires(switch_core_session_locate("foo") == NULL); + switch_core_session_rwunlock(session); + session = switch_core_session_locate("bar"); + fst_requires(session); + switch_core_session_rwunlock(session); + session = switch_core_session_locate(switch_core_session_get_uuid(fst_session)); + fst_requires(session); + switch_core_session_rwunlock(session); + switch_channel_hangup(fst_channel, SWITCH_CAUSE_NORMAL_CLEARING); + session = switch_core_session_locate("bar"); + fst_check(session == NULL); + } + FST_SESSION_END() + } + FST_SUITE_END() +} +FST_CORE_END() diff --git a/tests/unit/switch_ivr_originate.c b/tests/unit/switch_ivr_originate.c index 6c34fcc1e8..b6ffe7cf51 100644 --- a/tests/unit/switch_ivr_originate.c +++ b/tests/unit/switch_ivr_originate.c @@ -55,6 +55,20 @@ static switch_status_t my_on_destroy(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } + +const char *external_id_to_match = NULL; +static int got_external_id_in_event = 0; + +static void on_hangup_event(switch_event_t *event) +{ + if (external_id_to_match) { + const char *external_id = switch_event_get_header(event, "Session-External-ID"); + if (external_id && !strcmp(external_id_to_match, external_id)) { + got_external_id_in_event = 1; + } + } +} + static switch_state_handler_table_t state_handlers = { /*.on_init */ NULL, /*.on_routing */ NULL, @@ -89,6 +103,8 @@ FST_CORE_BEGIN("./conf") { fst_requires_module("mod_loopback"); application_hit = 0; + external_id_to_match = NULL; + got_external_id_in_event = 0; } FST_SETUP_END() @@ -97,6 +113,37 @@ FST_CORE_BEGIN("./conf") } FST_TEARDOWN_END() + FST_TEST_BEGIN(originate_test_external_id) + { + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + switch_status_t status; + switch_call_cause_t cause; + switch_event_t *ovars = NULL; + switch_event_create(&ovars, SWITCH_EVENT_CLONE); + switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "origination_external_id", "zzzz"); + status = switch_ivr_originate(NULL, &session, &cause, "null/+15553334444", 2, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL, NULL); + fst_requires(session); + fst_check(status == SWITCH_STATUS_SUCCESS); + switch_event_destroy(&ovars); + switch_core_session_rwunlock(session); + + session = switch_core_session_locate("zzzz"); + fst_requires(session); + + channel = switch_core_session_get_channel(session); + fst_requires(channel); + + external_id_to_match = "zzzz"; + switch_event_bind("originate_test_external_id", SWITCH_EVENT_CHANNEL_HANGUP, SWITCH_EVENT_SUBCLASS_ANY, on_hangup_event, NULL); + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + switch_core_session_rwunlock(session); + switch_yield(1000 * 1000); + fst_check(got_external_id_in_event == 1); + switch_event_unbind_callback(on_hangup_event); + } + FST_TEST_END() + FST_TEST_BEGIN(originate_test_early_state_handler) { switch_core_session_t *session = NULL;