mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-31 15:44:21 +00:00
Addition of scheduler engine and a few applications to use it.
This patch adds a scheduler thread to the core and moves the heartbeat event to use the new scheduler as an example. Also The following features are implemented that use this scheduler: sched_hangup dialplan application: <action application="sched_hangup" data="+10 normal_clearing bleg"/> ** The cause code is optional and the optional bleg keyword will only hangup the channel the current channel is bridged to if the call is in a bridge. sched_transfer dialplan application: <action application="sched_transfer" data="+10 1000 XML default"/> ** The last 2 args (dialplan and context) are optional sched_broadcast dialplan application: <action application="sched_broadcast" data="+10 playback:/tmp/foo.wav"/> <action application="sched_broadcast" data="+10 playback!normal_clearing:/tmp/foo.wav"/> ** The optional !<cause_code> can be added to make the channel hangup after broadcasting the file. sched_hangup api function: sched_hangup +10 <uuid_string> normal_clearing ** The cause code is optional sched_transfer api function: sched_transfer +10 <uuid_string> 1000 XML default ** The last 2 args (dialplan and context) are optional sched_broadcast api function: sched_broadcast +10 <uuid_str> playback:/tmp/foo.wav sched_broadcast +10 <uuid_str> playback!normal_clearing:/tmp/foo.wav ** The optional !<cause_code> can be added to make the channel hangup after broadcasting the file. The new C functions in the core are documented in the doxeygen. *NOTE* This commit should satisfy at least 2 bounties on the wiki git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4785 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
24b1a46ceb
commit
8a4406ece2
9 files changed
+855
-51
No files matched your search
+190
-9
@@ -130,7 +130,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se
|
||||
if (cause_name) {
|
||||
cause = switch_channel_str2cause(cause_name);
|
||||
}
|
||||
|
||||
|
||||
switch_channel_hangup(channel, cause);
|
||||
} else if (cmd_hash == CMD_NOMEDIA) {
|
||||
char *uuid = switch_event_get_header(event, "nomedia-uuid");
|
||||
@@ -3240,6 +3240,157 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_unhold_uuid(char *uuid)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct hangup_helper {
|
||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
switch_bool_t bleg;
|
||||
switch_call_cause_t cause;
|
||||
};
|
||||
|
||||
static void sch_hangup_callback(switch_core_scheduler_task_t *task)
|
||||
{
|
||||
struct hangup_helper *helper;
|
||||
switch_core_session_t *session, *other_session;
|
||||
char *other_uuid;
|
||||
|
||||
assert(task);
|
||||
|
||||
helper = (struct hangup_helper *) task->cmd_arg;
|
||||
|
||||
if ((session = switch_core_session_locate(helper->uuid_str))) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
if (helper->bleg) {
|
||||
if ((other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
|
||||
(other_session = switch_core_session_locate(other_uuid))) {
|
||||
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
|
||||
switch_channel_hangup(other_channel, helper->cause);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No channel to hangup\n");
|
||||
}
|
||||
} else {
|
||||
switch_channel_hangup(channel, helper->cause);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(uint32_t) switch_ivr_schedule_hangup(time_t runtime, char *uuid, switch_call_cause_t cause, switch_bool_t bleg)
|
||||
{
|
||||
struct hangup_helper *helper;
|
||||
size_t len = sizeof(*helper);
|
||||
|
||||
assert((helper = malloc(len)));
|
||||
memset(helper, 0, len);
|
||||
|
||||
switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
|
||||
helper->cause = cause;
|
||||
helper->bleg = bleg;
|
||||
|
||||
return switch_core_scheduler_add_task(runtime, sch_hangup_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
|
||||
}
|
||||
|
||||
struct transfer_helper {
|
||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
char *extension;
|
||||
char *dialplan;
|
||||
char *context;
|
||||
};
|
||||
|
||||
static void sch_transfer_callback(switch_core_scheduler_task_t *task)
|
||||
{
|
||||
struct transfer_helper *helper;
|
||||
switch_core_session_t *session;
|
||||
|
||||
assert(task);
|
||||
|
||||
helper = (struct transfer_helper *) task->cmd_arg;
|
||||
|
||||
if ((session = switch_core_session_locate(helper->uuid_str))) {
|
||||
switch_ivr_session_transfer(session, helper->extension, helper->dialplan, helper->context);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(uint32_t) switch_ivr_schedule_transfer(time_t runtime, char *uuid, char *extension, char *dialplan, char *context)
|
||||
{
|
||||
struct transfer_helper *helper;
|
||||
size_t len = sizeof(*helper);
|
||||
char *cur = NULL;
|
||||
|
||||
if (extension) {
|
||||
len += strlen(extension) + 1;
|
||||
}
|
||||
|
||||
if (dialplan) {
|
||||
len += strlen(dialplan) + 1;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
len += strlen(context) + 1;
|
||||
}
|
||||
|
||||
assert((helper = malloc(len)));
|
||||
memset(helper, 0, len);
|
||||
|
||||
switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
|
||||
|
||||
cur = (char *) helper + sizeof(*helper);
|
||||
|
||||
if (extension) {
|
||||
helper->extension = cur;
|
||||
switch_copy_string(helper->extension, extension, strlen(extension) + 1);
|
||||
cur += strlen(helper->extension) + 1;
|
||||
}
|
||||
|
||||
if (dialplan) {
|
||||
helper->dialplan = cur;
|
||||
switch_copy_string(helper->dialplan, dialplan, strlen(dialplan) + 1);
|
||||
cur += strlen(helper->dialplan) + 1;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
helper->context = cur;
|
||||
switch_copy_string(helper->context, context, strlen(context)+1);
|
||||
}
|
||||
|
||||
return switch_core_scheduler_add_task(runtime, sch_transfer_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
|
||||
}
|
||||
|
||||
|
||||
struct broadcast_helper {
|
||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
char *path;
|
||||
switch_media_flag_t flags;
|
||||
};
|
||||
|
||||
static void sch_broadcast_callback(switch_core_scheduler_task_t *task)
|
||||
{
|
||||
struct broadcast_helper *helper;
|
||||
assert(task);
|
||||
|
||||
helper = (struct broadcast_helper *) task->cmd_arg;
|
||||
switch_ivr_broadcast(helper->uuid_str, helper->path, helper->flags);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, char *uuid, char *path, switch_media_flag_t flags)
|
||||
{
|
||||
struct broadcast_helper *helper;
|
||||
size_t len = sizeof(*helper) + strlen(path) + 1;
|
||||
|
||||
assert((helper = malloc(len)));
|
||||
memset(helper, 0, len);
|
||||
|
||||
switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
|
||||
helper->flags = flags;
|
||||
helper->path = (char *) helper + sizeof(*helper);
|
||||
switch_copy_string(helper->path, path, len - sizeof(helper));
|
||||
|
||||
|
||||
return switch_core_scheduler_add_task(runtime, sch_broadcast_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, switch_media_flag_t flags)
|
||||
{
|
||||
@@ -3249,9 +3400,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi
|
||||
switch_event_t *event;
|
||||
switch_core_session_t *other_session = NULL;
|
||||
char *other_uuid = NULL;
|
||||
char *app = "playback";
|
||||
|
||||
assert(path);
|
||||
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
char *app;
|
||||
char *cause = NULL;
|
||||
char *mypath = strdup(path);
|
||||
char *p;
|
||||
|
||||
master = session;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
@@ -3261,11 +3418,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi
|
||||
switch_ivr_media(uuid, SMF_REBRIDGE);
|
||||
}
|
||||
|
||||
if (!strncasecmp(path, "speak:", 6)) {
|
||||
path += 6;
|
||||
app = "speak";
|
||||
} else {
|
||||
app = "playback";
|
||||
if ((p = strchr(mypath, ':'))) {
|
||||
app = mypath;
|
||||
*p++ = '\0';
|
||||
path = p;
|
||||
}
|
||||
|
||||
if ((cause = strchr(app, '!'))) {
|
||||
*cause++ = '\0';
|
||||
if (!cause) {
|
||||
cause = "normal_clearing";
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))
|
||||
@@ -3299,8 +3462,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, swi
|
||||
}
|
||||
}
|
||||
|
||||
if (cause) {
|
||||
if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", cause);
|
||||
|
||||
switch_core_session_queue_private_event(session, &event);
|
||||
}
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
switch_safe_free(mypath);
|
||||
}
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
@@ -3449,11 +3625,16 @@ static switch_status_t signal_bridge_on_hangup(switch_core_session_t *session)
|
||||
switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, NULL);
|
||||
switch_channel_set_variable(other_channel, SWITCH_BRIDGE_VARIABLE, NULL);
|
||||
|
||||
switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
|
||||
if (switch_channel_get_state(other_channel) < CS_HANGUP &&
|
||||
switch_true(switch_channel_get_variable(other_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE))) {
|
||||
switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
|
||||
} else {
|
||||
switch_channel_set_state(other_channel, CS_EXECUTE);
|
||||
}
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user