diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 2260ca3174..36f1c02e86 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -797,6 +797,10 @@ typedef enum { SWITCH_EVENT_PRIVATE_COMMAND - A private command event SWITCH_EVENT_HEARTBEAT - Machine is alive SWITCH_EVENT_TRAP - Error Trap + SWITCH_EVENT_ADD_SCHEDULE - Something has been scheduled + SWITCH_EVENT_DEL_SCHEDULE - Something has been unscheduled + SWITCH_EVENT_EXE_SCHEDULE - Something scheduled has been executed + SWITCH_EVENT_RE_SCHEDULE - Something scheduled has been rescheduled SWITCH_EVENT_ALL - All events at once </pre> @@ -839,6 +843,10 @@ typedef enum { SWITCH_EVENT_PRIVATE_COMMAND, SWITCH_EVENT_HEARTBEAT, SWITCH_EVENT_TRAP, + SWITCH_EVENT_ADD_SCHEDULE, + SWITCH_EVENT_DEL_SCHEDULE, + SWITCH_EVENT_EXE_SCHEDULE, + SWITCH_EVENT_RE_SCHEDULE, SWITCH_EVENT_ALL } switch_event_types_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 856d2fa97d..b4049d26c8 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -696,6 +696,56 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises return SWITCH_STATUS_SUCCESS;; } +static void sch_api_callback(switch_scheduler_task_t *task) +{ + char *cmd, *arg = NULL; + switch_stream_handle_t stream = { 0 }; + + assert(task); + + cmd = (char *) task->cmd_arg; + + if ((arg = strchr(cmd, ' '))) { + *arg++ = '\0'; + } + + SWITCH_STANDARD_STREAM(stream); + switch_api_execute(cmd, arg, NULL, &stream); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Command %s(%s):\n%s\n", cmd, arg, switch_str_nil((char *)stream.data)); + switch_safe_free(stream.data); +} + +static switch_status_t sched_api_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) +{ + char *tm = NULL, *dcmd; + time_t when; + + assert(cmd != NULL); + tm = strdup(cmd); + assert(tm != NULL); + + if ((dcmd = strchr(tm, ' '))) { + uint32_t id; + + *dcmd++ = '\0'; + + if (*tm == '+') { + when = time(NULL) + atol(tm + 1); + } else { + when = atol(tm); + } + id = switch_scheduler_add_task(when, sch_api_callback, (char *) __SWITCH_FUNC__, dcmd, 0, strdup(dcmd), SSHF_FREE_ARG); + stream->write_function(stream, "Added task %u\n", id); + } else { + stream->write_function(stream, "Invalid syntax\n"); + } + + switch_safe_free(tm); + + return SWITCH_STATUS_SUCCESS; +} + + struct holder { switch_stream_handle_t *stream; char *http; @@ -769,6 +819,8 @@ static switch_status_t show_function(char *cmd, switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } else if (!strcmp(cmd, "codec") || !strcmp(cmd, "dialplan") || !strcmp(cmd, "file") || !strcmp(cmd, "timer")) { sprintf(sql, "select type, name from interfaces where type = '%s'", cmd); + } else if (!strcmp(cmd, "tasks")) { + sprintf(sql, "select * from %s", cmd); } else if (!strcmp(cmd, "application") || !strcmp(cmd, "api")) { sprintf(sql, "select name, description, syntax from interfaces where type = '%s' and description != ''", cmd); } else if (!strcmp(cmd, "calls")) { @@ -849,12 +901,20 @@ static switch_status_t help_function(char *cmd, switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } +static switch_api_interface_t sched_api_api_interface = { + /*.interface_name */ "sched_api", + /*.desc */ "Schedule an api command", + /*.function */ sched_api_function, + /*.syntax */ "[+]<time> <command string>", + /*.next */ NULL +}; + static switch_api_interface_t sched_transfer_api_interface = { /*.interface_name */ "sched_transfer", /*.desc */ "Schedule a broadcast event to a running call", /*.function */ sched_transfer_function, /*.syntax */ "[+]<time> <uuid> <extension> [<dialplan>] [<context>]", - /*.next */ NULL + /*.next */ &sched_api_api_interface }; static switch_api_interface_t sched_broadcast_api_interface = { diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 2406c7cfd1..d2601215c6 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -225,8 +225,25 @@ static void core_event_handler(switch_event_t *event) char *sql = NULL; switch (event->event_id) { + case SWITCH_EVENT_ADD_SCHEDULE: + sql = switch_mprintf("insert into tasks values('%q','%q','%q','%q')", + switch_event_get_header(event, "task-id"), + switch_event_get_header(event, "task-desc"), + switch_event_get_header(event, "task-group"), + switch_event_get_header(event, "task-runtime") + ); + break; + case SWITCH_EVENT_DEL_SCHEDULE: + case SWITCH_EVENT_EXE_SCHEDULE: + sql = switch_mprintf("delete from tasks where task_id=%q", switch_event_get_header(event, "task-id")); + break; + case SWITCH_EVENT_RE_SCHEDULE: + sql = switch_mprintf("update tasks set task_runtime='%q' where task_id=%q", + switch_event_get_header(event, "task-runtime"), + switch_event_get_header(event, "task-id")); + break; case SWITCH_EVENT_CHANNEL_DESTROY: - sql = switch_mprintf("delete from channels where uuid='%s'", switch_event_get_header(event, "unique-id")); + sql = switch_mprintf("delete from channels where uuid='%q'", switch_event_get_header(event, "unique-id")); break; case SWITCH_EVENT_CHANNEL_CREATE: sql = switch_mprintf("insert into channels (uuid,created,name,state) values('%q','%q','%q','%q')", @@ -375,14 +392,23 @@ SWITCH_DECLARE(void) switch_core_sqldb_start(switch_memory_pool_t *pool) " type VARCHAR(255),\n" " name VARCHAR(255),\n" " description VARCHAR(255),\n" " syntax VARCHAR(255)\n" ");\n"; + char create_tasks_sql[] = + "CREATE TABLE tasks (\n" + " task_id INTEGER(4),\n" + " task_desc VARCHAR(255),\n" + " task_group VARCHAR(255),\n" + " task_runtime INTEGER(8)\n" + ");\n"; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n"); switch_core_db_exec(runtime.db, "drop table channels", NULL, NULL, NULL); switch_core_db_exec(runtime.db, "drop table calls", NULL, NULL, NULL); switch_core_db_exec(runtime.db, "drop table interfaces", NULL, NULL, NULL); + switch_core_db_exec(runtime.db, "drop table tasks", NULL, NULL, NULL); switch_core_db_exec(runtime.db, create_channels_sql, NULL, NULL, NULL); switch_core_db_exec(runtime.db, create_calls_sql, NULL, NULL, NULL); switch_core_db_exec(runtime.db, create_interfaces_sql, NULL, NULL, NULL); + switch_core_db_exec(runtime.db, create_tasks_sql, NULL, NULL, NULL); if (switch_event_bind("core_db", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event handler!\n"); diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index b444221d53..d73974cad8 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -134,6 +134,13 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return; } + + if (switch_channel_test_flag(session->channel, CF_NOMEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Cannot be used with NO_MEDIA mode!\n", + extension->current_application->application_name); + switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return; + } if (!application_interface->application_function) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", diff --git a/src/switch_event.c b/src/switch_event.c index 2c7fb82d7e..bb9ec11daa 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -133,6 +133,10 @@ static char *EVENT_NAMES[] = { "PRIVATE_COMMAND", "HEARTBEAT", "TRAP", + "ADD_SCHEDULE", + "DEL_SCHEDULE", + "EXE_SCHEDULE", + "RE_SCHEDULE", "ALL" }; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 853a28aa2f..2502e4046e 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -795,3 +795,5 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi return SWITCH_STATUS_SUCCESS; } + + diff --git a/src/switch_scheduler.c b/src/switch_scheduler.c index 3b6fbb5e26..9b6a3ca445 100644 --- a/src/switch_scheduler.c +++ b/src/switch_scheduler.c @@ -22,15 +22,30 @@ static struct { switch_memory_pool_t *memory_pool; } globals; -static void switch_scheduler_execute(switch_scheduler_task_container_t * tp) +static void switch_scheduler_execute(switch_scheduler_task_container_t *tp) { + switch_event_t *event; //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing task %u %s (%s)\n", tp->task.task_id, tp->desc, switch_str_nil(tp->task.group)); tp->func(&tp->task); if (tp->task.runtime > tp->executed) { tp->executed = 0; + if (switch_event_create(&event, SWITCH_EVENT_RE_SCHEDULE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Desc", "%s", tp->desc); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Group", "%s", switch_str_nil(tp->task.group)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" TIME_T_FMT, tp->task.runtime); + switch_event_fire(&event); + } } else { + if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Desc", "%s", tp->desc); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Group", "%s", switch_str_nil(tp->task.group)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" TIME_T_FMT, tp->task.runtime); + switch_event_fire(&event); + } tp->destroyed = 1; } } @@ -134,6 +149,7 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags) { switch_scheduler_task_container_t *container, *tp; + switch_event_t *event; switch_mutex_lock(globals.task_mutex); switch_zmalloc(container, sizeof(*container)); @@ -163,7 +179,13 @@ SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added task %u %s (%s) to run at %" TIME_T_FMT "\n", tp->task.task_id, tp->desc, switch_str_nil(tp->task.group), task_runtime); - + if (switch_event_create(&event, SWITCH_EVENT_ADD_SCHEDULE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Desc", "%s", tp->desc); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Group", "%s", switch_str_nil(tp->task.group)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" TIME_T_FMT, tp->task.runtime); + switch_event_fire(&event); + } return container->task.task_id; } @@ -171,11 +193,19 @@ SWITCH_DECLARE(switch_status_t) switch_scheduler_del_task_id(uint32_t task_id) { switch_scheduler_task_container_t *tp; switch_status_t status = SWITCH_STATUS_FALSE; + switch_event_t *event; switch_mutex_lock(globals.task_mutex); for (tp = globals.task_list; tp; tp = tp->next) { if (tp->task.task_id == task_id) { tp->destroyed++; + if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Desc", "%s", tp->desc); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Group", "%s", switch_str_nil(tp->task.group)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" TIME_T_FMT, tp->task.runtime); + switch_event_fire(&event); + } status = SWITCH_STATUS_SUCCESS; break; } @@ -189,10 +219,18 @@ SWITCH_DECLARE(switch_status_t) switch_scheduler_del_task_group(char *group) { switch_scheduler_task_container_t *tp; switch_status_t status = SWITCH_STATUS_FALSE; + switch_event_t *event; switch_mutex_lock(globals.task_mutex); for (tp = globals.task_list; tp; tp = tp->next) { if (!strcmp(tp->task.group, group)) { + if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Desc", "%s", tp->desc); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Group", "%s", switch_str_nil(tp->task.group)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" TIME_T_FMT, tp->task.runtime); + switch_event_fire(&event); + } tp->destroyed++; status = SWITCH_STATUS_SUCCESS; }