diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 833aa853fe..f3c5a9bdd4 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -153,6 +153,7 @@ struct switch_core_session { switch_codec_t bug_codec; uint32_t read_frame_count; uint32_t track_duration; + uint32_t track_id; }; struct switch_media_bug { diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ffe46a6914..5820a05ce5 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -119,6 +119,9 @@ struct switch_core_port_allocator; ///\{ +SWITCH_DECLARE(void) switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds); +SWITCH_DECLARE(void) switch_core_session_unsched_heartbeat(switch_core_session_t *session); + SWITCH_DECLARE(void) switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds); SWITCH_DECLARE(void) switch_core_session_disable_heartbeat(switch_core_session_t *session); diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 0e49e644f2..46070d45f7 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2352,13 +2352,14 @@ SWITCH_STANDARD_API(help_function) return SWITCH_STATUS_SUCCESS; } -#define HEARTBEAT_SYNTAX " >" +#define HEARTBEAT_SYNTAX " [sched] >" SWITCH_STANDARD_API(uuid_session_heartbeat_function) { - char *mycmd = NULL, *argv[2] = { 0 }; + char *mycmd = NULL, *argv[3] = { 0 }; uint32_t seconds = 60; int argc, tmp; switch_core_session_t *l_session = NULL; + int x = 0, sched = 0; if (switch_strlen_zero(cmd) || !(mycmd = strdup(cmd))) { goto error; @@ -2366,26 +2367,38 @@ SWITCH_STANDARD_API(uuid_session_heartbeat_function) argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - if (argc != 2 || !argv[0]) { + if (argc < 2 || !argv[0]) { goto error; } - + if (!(l_session = switch_core_session_locate(argv[0]))) { stream->write_function(stream, "-ERR Usage: cannot locate session.\n"); return SWITCH_STATUS_SUCCESS; } + + if (!strcasecmp(argv[1], "sched")) { + x = 2; + sched++; + } else { + x = 1; + } - if (switch_is_number(argv[1])) { - tmp = atoi(argv[1]); + if (switch_is_number(argv[x])) { + tmp = atoi(argv[x]); if (tmp > 0) { seconds = tmp; } - } else if (!switch_true(argv[1])) { + } else if (!switch_true(argv[x])) { seconds = 0; } if (seconds) { - switch_core_session_enable_heartbeat(l_session, seconds); + if (sched) { + switch_core_session_sched_heartbeat(l_session, seconds); + } else { + switch_core_session_enable_heartbeat(l_session, seconds); + } + } else { switch_core_session_disable_heartbeat(l_session); } diff --git a/src/switch_core_io.c b/src/switch_core_io.c index b3b99ba6f4..4fcdd26902 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -122,7 +122,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi *frame = NULL; - if (session->read_codec && session->track_duration) { + if (session->read_codec && !session->track_id && session->track_duration) { if (session->read_frame_count == 0) { switch_event_t *event; session->read_frame_count = (session->read_codec->implementation->actual_samples_per_second / diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 4605713eab..954a225df6 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -780,6 +780,39 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * } +SWITCH_STANDARD_SCHED_FUNC(sch_heartbeat_callback) +{ + switch_event_t *event; + switch_core_session_t *session; + char *uuid = task->cmd_arg; + + if ((session = switch_core_session_locate(uuid))) { + switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT); + switch_channel_event_set_data(session->channel, event); + switch_event_fire(&event); + switch_core_session_rwunlock(session); + } + + /* reschedule this task */ + task->runtime = switch_timestamp(NULL) + session->track_duration; +} + +SWITCH_DECLARE(void) switch_core_session_unsched_heartbeat(switch_core_session_t *session) +{ + if (session->track_id) { + switch_scheduler_del_task_id(session->track_id); + session->track_id = 0; + } +} + +SWITCH_DECLARE(void) switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds) +{ + + switch_core_session_unsched_heartbeat(session); + session->track_id = switch_scheduler_add_task(switch_timestamp(NULL), sch_heartbeat_callback, (char *) __SWITCH_FUNC__, + switch_core_session_get_uuid(session), 0, strdup(switch_core_session_get_uuid(session)), SSHF_FREE_ARG); +} + SWITCH_DECLARE(void) switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds) { switch_assert(session != NULL); @@ -788,17 +821,28 @@ SWITCH_DECLARE(void) switch_core_session_enable_heartbeat(switch_core_session_t seconds = 60; } + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s using scheduler due to bypass_media mode\n", switch_channel_get_name(session->channel)); + switch_core_session_sched_heartbeat(session, seconds); + return; + } + + switch_core_session_unsched_heartbeat(session); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s setting session heartbeat to %u second(s).\n", switch_channel_get_name(session->channel), seconds); session->track_duration = seconds; session->read_frame_count = 0; + } SWITCH_DECLARE(void) switch_core_session_disable_heartbeat(switch_core_session_t *session) { + switch_core_session_unsched_heartbeat(session); switch_assert(session != NULL); session->read_frame_count = 0; session->track_duration = 0; + } static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)