diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 6057734123..0f46b8471d 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -313,6 +313,7 @@ struct switch_runtime { char *core_db_inner_post_trans_execute; int events_use_dispatch; uint32_t port_alloc_flags; + char *event_channel_key_separator; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index fa101a0ffa..8dcea8acf3 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2817,6 +2817,7 @@ SWITCH_DECLARE(void) switch_core_autobind_cpu(void); SWITCH_DECLARE(switch_status_t) switch_core_session_start_text_thread(switch_core_session_t *session); +SWITCH_DECLARE(const char *) switch_core_get_event_channel_key_separator(void); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index e0cc9f3698..ff69cbd9e5 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -386,7 +386,8 @@ typedef enum { SCF_SESSION_THREAD_POOL = (1 << 23), SCF_DIALPLAN_TIMESTAMPS = (1 << 24), SCF_CPF_SOFT_PREFIX = (1 << 25), - SCF_CPF_SOFT_LOOKUP = (1 << 26) + SCF_CPF_SOFT_LOOKUP = (1 << 26), + SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY = (1 << 27) } switch_core_flag_enum_t; typedef uint32_t switch_core_flag_t; diff --git a/src/switch_core.c b/src/switch_core.c index 56ca7e81c7..359265c02f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2360,10 +2360,23 @@ static void switch_load_core_config(const char *file) } else { switch_clear_flag((&runtime), SCF_CPF_SOFT_LOOKUP); } + } else if (!strcasecmp(var, "event-channel-key-separator") && !zstr(val)) { + runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "event-channel-enable-hierarchy-deliver") && !zstr(val)) { + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY); + } else { + switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY); + } } } } + if (runtime.event_channel_key_separator == NULL) { + runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, "."); + } + if ((settings = switch_xml_child(cfg, "variables"))) { for (param = switch_xml_child(settings, "variable"); param; param = param->next) { const char *var = switch_xml_attr_soft(param, "name"); @@ -3375,6 +3388,11 @@ SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_end_port() return end_port; } +SWITCH_DECLARE(const char *) switch_core_get_event_channel_key_separator(void) +{ + return runtime.event_channel_key_separator; +} + /* For Emacs: * Local Variables: * mode:c diff --git a/src/switch_event.c b/src/switch_event.c index 172e64b6cb..7392e41618 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -2915,24 +2915,53 @@ static void destroy_ecd(event_channel_data_t **ecdP) free(ecd); } +#ifndef SWITCH_CHANNEL_DISPATCH_MAX_KEY_PARTS +#define SWITCH_CHANNEL_DISPATCH_MAX_KEY_PARTS 10 +#endif + static void ecd_deliver(event_channel_data_t **ecdP) { event_channel_data_t *ecd = *ecdP; - char *p; + char *key; + uint32_t t = 0; *ecdP = NULL; - _switch_event_channel_broadcast(ecd->event_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id); + t = _switch_event_channel_broadcast(ecd->event_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id); - if ((p = strchr(ecd->event_channel, '.'))) { - char *main_channel = strdup(ecd->event_channel); - switch_assert(main_channel); - p = strchr(main_channel, '.'); - *p = '\0'; - _switch_event_channel_broadcast(main_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id); - free(main_channel); + key = strdup(ecd->event_channel); + if (switch_core_test_flag(SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY)) { + const char *sep = switch_core_get_event_channel_key_separator(); + char *x_argv[SWITCH_CHANNEL_DISPATCH_MAX_KEY_PARTS] = { 0 }; + int x_argc = switch_separate_string_string(key, (char*) sep, x_argv, SWITCH_CHANNEL_DISPATCH_MAX_KEY_PARTS); + char buf[512]; + int i; + for(i=x_argc - 1; i > 0; i--) { + int z; + memset(buf, 0, 512); + sprintf(buf, "%s", x_argv[0]); + for(z=1; z < i; z++) { + strcat(buf, sep); + strcat(buf, x_argv[z]); + } + t += _switch_event_channel_broadcast(buf, ecd->event_channel, ecd->json, ecd->key, ecd->id); + } + } else { + char *p = NULL; + if ((p = strchr(key, '.'))) { + *p = '\0'; + t += _switch_event_channel_broadcast(key, ecd->event_channel, ecd->json, ecd->key, ecd->id); + } + } + switch_safe_free(key); + + t += _switch_event_channel_broadcast(SWITCH_EVENT_CHANNEL_GLOBAL, ecd->event_channel, ecd->json, ecd->key, ecd->id); + + if(t == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "no subscribers for %s , %s\n", ecd->event_channel, ecd->key); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "delivered to %u subscribers for %s\n", t, ecd->event_channel); } - _switch_event_channel_broadcast(SWITCH_EVENT_CHANNEL_GLOBAL, ecd->event_channel, ecd->json, ecd->key, ecd->id); destroy_ecd(&ecd); }