diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 2d7ac406ee..d0e28cacec 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -134,6 +134,7 @@ struct switch_core_session { switch_queue_t *event_queue; switch_queue_t *message_queue; switch_queue_t *private_event_queue; + switch_queue_t *private_event_queue_pri; switch_thread_rwlock_t *bug_rwlock; switch_media_bug_t *bugs; switch_app_log_t *app_log; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3f9eddb584..d96a9dbabb 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -986,9 +986,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(_In_ switch_co \brief Queue a private event on a given session \param session the session to queue the message on \param event the event to queue + \param priority event has high priority \return the status returned by the message handler */ -SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event); +SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event, switch_bool_t priority); /*! diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 4a59925ec4..c94b1eddb7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -326,7 +326,8 @@ typedef enum { SMF_LOOP = (1 << 4), SMF_HOLD_BLEG = (1 << 5), SMF_IMMEDIATE = (1 << 6), - SMF_EXEC_INLINE = (1 << 7) + SMF_EXEC_INLINE = (1 << 7), + SMF_PRIORITY = (1 << 8) } switch_media_flag_enum_t; typedef uint32_t switch_media_flag_t; @@ -919,6 +920,7 @@ typedef enum { CF_UNICAST, CF_VIDEO, CF_EVENT_LOCK, + CF_EVENT_LOCK_PRI, CF_RESET, CF_ORIGINATING, CF_STOP_BROADCAST, diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index ab9e244501..db07c3f8e9 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2938,7 +2938,8 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) switch_channel_set_flag(tech_pvt->channel, CF_HOLD); switch_ivr_hold_uuid(switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE), NULL, 0); } else { - switch_ivr_broadcast(switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE), stream, SMF_ECHO_ALEG | SMF_LOOP); + switch_ivr_broadcast(switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE), stream, + SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY); switch_yield(250000); } } diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index d818d1b6ca..7f24d2b9e5 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -1655,7 +1655,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even if (zstr(uuid) && listener->session) { if (async) { - if ((status = switch_core_session_queue_private_event(listener->session, event)) == SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_private_event(listener->session, event, SWITCH_FALSE)) == SWITCH_STATUS_SUCCESS) { switch_snprintf(reply, reply_len, "+OK"); } else { switch_snprintf(reply, reply_len, "-ERR memory error"); @@ -1666,7 +1666,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even } } else { if (!zstr(uuid) && (session = switch_core_session_locate(uuid))) { - if ((status = switch_core_session_queue_private_event(session, event)) == SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_private_event(session, event, SWITCH_FALSE)) == SWITCH_STATUS_SUCCESS) { switch_snprintf(reply, reply_len, "+OK"); } else { switch_snprintf(reply, reply_len, "-ERR memory error"); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index cfdb420adb..2e900c8e9f 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -847,15 +847,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(switch_core_se return status; } -SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(switch_core_session_t *session, switch_event_t **event) +SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(switch_core_session_t *session, switch_event_t **event, switch_bool_t priority) { switch_status_t status = SWITCH_STATUS_FALSE; + switch_queue_t *queue; switch_assert(session != NULL); if (session->private_event_queue) { + queue = priority ? session->private_event_queue_pri : session->private_event_queue; + (*event)->event_id = SWITCH_EVENT_PRIVATE_COMMAND; - if (switch_queue_trypush(session->private_event_queue, *event) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_trypush(queue, *event) == SWITCH_STATUS_SUCCESS) { *event = NULL; switch_core_session_kill_channel(session, SWITCH_SIG_BREAK); status = SWITCH_STATUS_SUCCESS; @@ -878,8 +881,16 @@ SWITCH_DECLARE(uint32_t) switch_core_session_private_event_count(switch_core_ses switch_channel_t *channel = switch_core_session_get_channel(session); uint32_t count = 0; - if (!switch_channel_test_flag(channel, CF_EVENT_LOCK) && session->private_event_queue) { - count = switch_queue_size(session->private_event_queue); + if (session->private_event_queue) { + + if (!switch_channel_test_flag(channel, CF_EVENT_LOCK)) { + count = switch_queue_size(session->private_event_queue); + } + + if (!switch_channel_test_flag(channel, CF_EVENT_LOCK_PRI)) { + count += switch_queue_size(session->private_event_queue_pri); + } + if (count == 0) { check_media(session); } @@ -893,13 +904,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch switch_status_t status = SWITCH_STATUS_FALSE; void *pop; switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_channel_test_flag(channel, CF_EVENT_LOCK)) { - return status; - } - + switch_queue_t *queue; + if (session->private_event_queue) { - if ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_size(session->private_event_queue_pri)) { + queue = session->private_event_queue_pri; + + if (switch_channel_test_flag(channel, CF_EVENT_LOCK_PRI)) { + return SWITCH_STATUS_FALSE; + } + } else { + queue = session->private_event_queue; + + if (switch_channel_test_flag(channel, CF_EVENT_LOCK)) { + return SWITCH_STATUS_FALSE; + } + } + + if ((status = (switch_status_t) switch_queue_trypop(queue, &pop)) == SWITCH_STATUS_SUCCESS) { *event = (switch_event_t *) pop; } else { check_media(session); @@ -916,6 +938,9 @@ SWITCH_DECLARE(uint32_t) switch_core_session_flush_private_events(switch_core_se void *pop; if (session->private_event_queue) { + while ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue_pri, &pop)) == SWITCH_STATUS_SUCCESS) { + x++; + } while ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) { x++; } @@ -1327,6 +1352,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool); switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool); + switch_queue_create(&session->private_event_queue_pri, SWITCH_EVENT_QUEUE_LEN, session->pool); switch_mutex_lock(runtime.session_hash_mutex); switch_core_hash_insert(session_manager.session_table, session->uuid_str, session); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 6236ee12cf..a6d54a4dfb 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -461,6 +461,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); char *lead_frames = switch_event_get_header(event, "lead-frames"); char *event_lock = switch_event_get_header(event, "event-lock"); + char *event_lock_pri = switch_event_get_header(event, "event-lock-pri"); switch_status_t status = SWITCH_STATUS_FALSE; if (zstr(cmd)) { @@ -476,6 +477,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se switch_channel_set_flag_recursive(channel, CF_EVENT_LOCK); } + if (switch_true(event_lock_pri)) { + switch_channel_set_flag_recursive(channel, CF_EVENT_LOCK_PRI); + } + if (lead_frames) { switch_frame_t *read_frame; int frame_count = atoi(lead_frames); @@ -606,6 +611,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se done: switch_channel_clear_flag_recursive(channel, CF_EVENT_PARSE); switch_channel_clear_flag_recursive(channel, CF_EVENT_LOCK); + switch_channel_clear_flag_recursive(channel, CF_EVENT_LOCK_PRI); return status; } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index b9d953c5fc..73a02768b9 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1740,7 +1740,7 @@ static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_da switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", cont->list[i].app); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cont->list[i].data); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_core_session_queue_private_event(cont->session, &event); + switch_core_session_queue_private_event(cont->session, &event, SWITCH_FALSE); } } @@ -2713,8 +2713,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + if ((flags & SMF_LOOP)) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1); } @@ -2723,7 +2725,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true"); } - switch_core_session_queue_private_event(other_session, &event); + switch_core_session_queue_private_event(other_session, &event, (flags & SMF_PRIORITY)); } } @@ -2745,15 +2747,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", app); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", path); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-lock", "true"); + if ((flags & SMF_LOOP)) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "loops", "%d", -1); } if ((flags & SMF_HOLD_BLEG)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hold-bleg", "true"); } - switch_core_session_queue_private_event(session, &event); + + switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY)); + if (nomedia) switch_channel_set_flag(channel, CF_BROADCAST_DROP_MEDIA); } } @@ -2765,8 +2770,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", cause); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session, &event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, (flags & SMF_PRIORITY) ? "event-lock-pri" : "event-lock", "true"); + switch_core_session_queue_private_event(session, &event, (flags & SMF_PRIORITY)); } } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 437c6340e2..c5ba9278ea 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1059,7 +1059,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(session, &execute_event); + switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE); a_leg->skip_frames = DEFAULT_LEAD_FRAMES; } @@ -1074,7 +1074,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", data); switch_event_add_header(execute_event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true"); - switch_core_session_queue_private_event(peer_session, &execute_event); + switch_core_session_queue_private_event(peer_session, &execute_event, SWITCH_FALSE); b_leg->skip_frames = DEFAULT_LEAD_FRAMES; } }