Modify XML Dialplan

BTW, forget what I said yesterday RE: the strftime app I was at McDonalds, how can I concentrate there eh? 
see below....


The Definitive Guide To XML Dialplan:

The "dialplan" section of the freeswitch.xml meta document may contain several contexts

<?xml version="1.0"?>
<document type="freeswitch/xml">
  <section name="dialplan" description="Regex/XML Dialplan">
    <!-- the default context is a safe start -->
    <context name="default">

    <!-- one or more extension tags -->

    </context>
    
    <!-- more optional contexts -->
  </section>
</document>

The important thing to remember is that the dialplan is parsed once when the call
hits the dialplan parser in the RING state.  With one pass across the XML the result
will be a complete list of instructions installed into the channel based on
 parsed <action> or <anti-action> tags.

Those accustomed to Asterisk may expect the call to follow the dialplan by executing the 
applications as it parses them allowing data obtained from one action to influence the next action.
This not the case with the exception being the %{api func} {api arg} field type where an pluggable api call from
a module may be executed as the parsing occurs but this is meant to be used to draw realtime info such as
date and time or other quickly accessible information and shold *not* be abused.


The anatomy of an <extension> tag.

Legend: 
Text wrapped in [] indicates optional and is not part of the actual code.
a '|' inside [] indicates mutiple possible values and also is not part of the code.
Text wrapped in {} indicates it's a description of the parameter in place of the param itself.

<extension name="{exten_name}" [continue="[true|false]"]> 

continue=true means even if an extension executes to continue
parsing the next extension too

The {exten_name} above may anything but if it's 
an exact match with the destination number the parser will leap to this extension
to begin the searching that does not mean it will execute the extension.

Searching will either begin at the first extension in the context or at the point
the the parser has jumped to in the case described above.

Each condition is parsed in turn first taking the 'field' param.
The parser will apply the perl regular expression to each 'field' param encountered.

If the expression matches, it will parse each existing <action> tag in turn and add 
the data from the <application> tags to the channels todo list.	

If a matched expression contains any data wrapped in () the variables
$1,$2..$N will be valid and expanded in any of 'data' params from the subsequent action tags.

If the expression does NOT match, it will parse each <anti-action> tag in turn and add 
the data from the <application> tags to the channels todo list.
*NOTE* since there was no match the () feature is not availabe in anti-actions

The 'break' param indicates how to behave in relation to matching:
*) 'on-true'  - stop searching conditions after the first successful match.
*) 'on-false' - stop searching after the first unsuccessful match.
*) 'always'   - stop at this conditon regardless of a match or non-match.
*) 'never'    - continue searching regardless of a match or non-match.

<condition field="[{field name}|${variable name}|%{api func} {api arg}]" expression="{expression}" break="[on-true|on-false|always|never]">
  <action application="{app name}" data="{app arg}"/>
  <anti-action application="{app name}" data="{app arg}"/>
</condition>

  <!-- any number of condition tags may follow where the same rules apply -->
</extension>




git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2167 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-07-26 20:12:49 +00:00
parent 41c091e7bd
commit c4d890e0a4
13 changed files with 200 additions and 40 deletions

View File

@ -191,10 +191,11 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
\brief Execute a registered API command \brief Execute a registered API command
\param cmd the name of the API command to execute \param cmd the name of the API command to execute
\param arg the optional arguement to the command \param arg the optional arguement to the command
\param session an optional session
\param stream stream for output \param stream stream for output
\return the status returned by the API call \return the status returned by the API call
*/ */
SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_stream_handle_t *stream); SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);

View File

@ -707,7 +707,7 @@ typedef switch_status_t (*switch_waitfor_write_hook_t)(switch_core_session_t *,
typedef switch_status_t (*switch_send_dtmf_hook_t)(switch_core_session_t *, char *); typedef switch_status_t (*switch_send_dtmf_hook_t)(switch_core_session_t *, char *);
typedef struct switch_stream_handle switch_stream_handle_t; typedef struct switch_stream_handle switch_stream_handle_t;
typedef switch_status_t (*switch_stream_handle_write_function_t)(switch_stream_handle_t *handle, char *fmt, ...); typedef switch_status_t (*switch_stream_handle_write_function_t)(switch_stream_handle_t *handle, char *fmt, ...);
typedef switch_status_t (*switch_api_function_t)(char *in, switch_stream_handle_t *stream); typedef switch_status_t (*switch_api_function_t)(char *in, switch_core_session_t *session, switch_stream_handle_t *stream);
typedef switch_status_t (*switch_input_callback_function_t)(switch_core_session_t *session, typedef switch_status_t (*switch_input_callback_function_t)(switch_core_session_t *session,
void *input, void *input,
switch_input_type_t input_type, switch_input_type_t input_type,

View File

@ -35,10 +35,15 @@
static const char modname[] = "mod_commands"; static const char modname[] = "mod_commands";
static switch_status_t status_function(char *cmd, switch_stream_handle_t *stream) static switch_status_t status_function(char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
uint8_t html = 0; uint8_t html = 0;
switch_core_time_duration_t duration; switch_core_time_duration_t duration;
if (session) {
return SWITCH_STATUS_FALSE;
}
switch_core_measure_time(switch_core_uptime(), &duration); switch_core_measure_time(switch_core_uptime(), &duration);
if (cmd && strstr(cmd, "html")) { if (cmd && strstr(cmd, "html")) {
@ -75,19 +80,27 @@ static switch_status_t status_function(char *cmd, switch_stream_handle_t *stream
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t load_function(char *mod, switch_stream_handle_t *stream) static switch_status_t load_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
if (session) {
return SWITCH_STATUS_FALSE;
}
switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod); switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) mod);
stream->write_function(stream, "OK\n"); stream->write_function(stream, "OK\n");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t reload_function(char *mod, switch_stream_handle_t *stream) static switch_status_t reload_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
const char *err; const char *err;
switch_xml_t xml_root; switch_xml_t xml_root;
if (session) {
return SWITCH_STATUS_FALSE;
}
if ((xml_root = switch_xml_open_root(1, &err))) { if ((xml_root = switch_xml_open_root(1, &err))) {
switch_xml_free(xml_root); switch_xml_free(xml_root);
} }
@ -96,10 +109,14 @@ static switch_status_t reload_function(char *mod, switch_stream_handle_t *stream
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t kill_function(char *dest, switch_stream_handle_t *stream) static switch_status_t kill_function(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream)
{ {
switch_core_session_t *session = NULL; switch_core_session_t *session = NULL;
if (isession) {
return SWITCH_STATUS_FALSE;
}
if ((session = switch_core_session_locate(dest))) { if ((session = switch_core_session_locate(dest))) {
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
switch_core_session_kill_channel(session, SWITCH_SIG_KILL); switch_core_session_kill_channel(session, SWITCH_SIG_KILL);
@ -114,12 +131,16 @@ static switch_status_t kill_function(char *dest, switch_stream_handle_t *stream)
} }
static switch_status_t transfer_function(char *cmd, switch_stream_handle_t *stream) static switch_status_t transfer_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
{ {
switch_core_session_t *session = NULL; switch_core_session_t *session = NULL;
char *argv[4] = {0}; char *argv[4] = {0};
int argc = 0; int argc = 0;
if (isession) {
return SWITCH_STATUS_FALSE;
}
argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 2 || argc > 4) { if (argc < 2 || argc > 4) {
@ -151,12 +172,16 @@ static switch_status_t transfer_function(char *cmd, switch_stream_handle_t *stre
static switch_status_t pause_function(char *cmd, switch_stream_handle_t *stream) static switch_status_t pause_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
{ {
switch_core_session_t *session = NULL; switch_core_session_t *session = NULL;
char *argv[4] = {0}; char *argv[4] = {0};
int argc = 0; int argc = 0;
if (isession) {
return SWITCH_STATUS_FALSE;
}
argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 2) { if (argc < 2) {
@ -230,13 +255,17 @@ static int show_callback(void *pArg, int argc, char **argv, char **columnNames){
return 0; return 0;
} }
static switch_status_t show_function(char *cmd, switch_stream_handle_t *stream) static switch_status_t show_function(char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
char sql[1024]; char sql[1024];
char *errmsg; char *errmsg;
switch_core_db_t *db = switch_core_db_handle(); switch_core_db_t *db = switch_core_db_handle();
struct holder holder = {0}; struct holder holder = {0};
if (session) {
return SWITCH_STATUS_FALSE;
}
if (stream->event) { if (stream->event) {
holder.http = switch_event_get_header(stream->event, "http-host"); holder.http = switch_event_get_header(stream->event, "http-host");
} }

View File

@ -188,7 +188,7 @@ static uint32_t conference_stop_file(conference_obj_t *conference, file_stop_t s
static switch_status_t conference_play_file(conference_obj_t *conference, char *file, uint32_t leadin); static switch_status_t conference_play_file(conference_obj_t *conference, char *file, uint32_t leadin);
static switch_status_t conference_say(conference_obj_t *conference, char *text, uint32_t leadin); static switch_status_t conference_say(conference_obj_t *conference, char *text, uint32_t leadin);
static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim); static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim);
static switch_status_t conf_function(char *buf, switch_stream_handle_t *stream); static switch_status_t conf_function(char *buf, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t audio_bridge_on_ring(switch_core_session_t *session); static switch_status_t audio_bridge_on_ring(switch_core_session_t *session);
static switch_status_t conference_outcall(conference_obj_t *conference, switch_core_session_t *session, char *bridgeto, char *cid_name, char *cid_num); static switch_status_t conference_outcall(conference_obj_t *conference, switch_core_session_t *session, char *bridgeto, char *cid_name, char *cid_num);
static void conference_function(switch_core_session_t *session, char *data); static void conference_function(switch_core_session_t *session, char *data);
@ -1232,6 +1232,7 @@ static switch_status_t conference_say(conference_obj_t *conference, char *text,
static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim) static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim)
{ {
conference_member_t *member = NULL; conference_member_t *member = NULL;
switch_mutex_lock(conference->member_mutex); switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) { for (member = conference->members; member; member = member->next) {
@ -1264,7 +1265,7 @@ static void conference_list(conference_obj_t *conference, switch_stream_handle_t
} }
/* API Interface Function */ /* API Interface Function */
static switch_status_t conf_function(char *buf, switch_stream_handle_t *stream) static switch_status_t conf_function(char *buf, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
char *lbuf = NULL; char *lbuf = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
@ -1293,6 +1294,10 @@ static switch_status_t conf_function(char *buf, switch_stream_handle_t *stream)
"conference <confname> transfer <member_id> <conference_name>\n" "conference <confname> transfer <member_id> <conference_name>\n"
; ;
if (session) {
return SWITCH_STATUS_FALSE;
}
if (stream->event) { if (stream->event) {
http = switch_event_get_header(stream->event, "http-host"); http = switch_event_get_header(stream->event, "http-host");
} }

View File

@ -91,9 +91,28 @@ static void strftime_function(switch_core_session_t *session, char *data)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SET [%s]=[%s]\n", argv[0], date); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SET [%s]=[%s]\n", argv[0], date);
switch_channel_set_variable(channel, argv[0], date); switch_channel_set_variable(channel, argv[0], date);
} }
} }
static switch_status_t strftime_api_function(char *fmt, switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_size_t retsize;
switch_time_exp_t tm;
char date[80] = "";
switch_time_exp_lt(&tm, switch_time_now());
switch_strftime(date, &retsize, sizeof(date), fmt, &tm);
stream->write_function(stream, date);
return SWITCH_STATUS_SUCCESS;
}
static switch_api_interface_t dptools_api_interface = {
/*.interface_name */ "strftime",
/*.desc */ "strftime",
/*.function */ strftime_api_function,
/*.next */ NULL
};
static const switch_application_interface_t set_application_interface = { static const switch_application_interface_t set_application_interface = {
/*.interface_name */ "set", /*.interface_name */ "set",
/*.application_function */ set_function /*.application_function */ set_function
@ -120,7 +139,8 @@ static const switch_loadable_module_interface_t mod_dptools_module_interface = {
/*.timer_interface = */ NULL, /*.timer_interface = */ NULL,
/*.dialplan_interface = */ NULL, /*.dialplan_interface = */ NULL,
/*.codec_interface = */ NULL, /*.codec_interface = */ NULL,
/*.application_interface */ &sleep_application_interface /*.application_interface */ &sleep_application_interface,
/*.api_interface */ &dptools_api_interface
}; };
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename) SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)

View File

@ -122,6 +122,13 @@ static void perform_substitution(pcre *re, int match_count, char *data, char *fi
substituted[y++] = '\0'; substituted[y++] = '\0';
} }
typedef enum {
BREAK_ON_TRUE,
BREAK_ON_FALSE,
BREAK_ALWAYS,
BREAK_NEVER
} break_t;
static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, switch_caller_extension_t **extension) static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, switch_caller_extension_t **extension)
{ {
switch_xml_t xcond, xaction; switch_xml_t xcond, xaction;
@ -135,17 +142,50 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
char *field = NULL; char *field = NULL;
char *do_break_a = NULL;
char *expression = NULL; char *expression = NULL;
char *field_data = NULL; char *field_data = NULL;
char retbuf[1024] = "";
pcre *re = NULL; pcre *re = NULL;
int ovector[30]; int ovector[30];
break_t do_break_i = BREAK_ON_FALSE;
field = (char *) switch_xml_attr(xcond, "field"); field = (char *) switch_xml_attr(xcond, "field");
expression = (char *) switch_xml_attr_soft(xcond, "expression"); expression = (char *) switch_xml_attr_soft(xcond, "expression");
if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
if (!strcasecmp(do_break_a, "on-true")) {
do_break_i = BREAK_ON_TRUE;
} else if (!strcasecmp(do_break_a, "on-false")) {
do_break_i = BREAK_ON_FALSE;
} else if (!strcasecmp(do_break_a, "always")) {
do_break_i = BREAK_ALWAYS;
} else if (!strcasecmp(do_break_a, "never")) {
do_break_i = BREAK_NEVER;
}
}
if (field) { if (field) {
if (*field == '$') { if (*field == '$') {
field_data = switch_channel_get_variable(channel, field + 1); field_data = switch_channel_get_variable(channel, field + 1);
} else if (*field == '%') {
switch_stream_handle_t stream = {0};
char *cmd = switch_core_session_strdup(session, field + 1);
char *arg;
if (cmd) {
if ((arg = strchr(cmd, ' '))) {
*arg++ = '\0';
}
stream.data = retbuf;
stream.end = stream.data;
stream.data_size = sizeof(retbuf);
stream.write_function = switch_console_stream_write;
if (switch_api_execute(cmd, arg, session, &stream) == SWITCH_STATUS_SUCCESS) {
field_data = retbuf;
}
}
} else { } else {
field_data = switch_caller_get_field_by_name(caller_profile, field); field_data = switch_caller_get_field_by_name(caller_profile, field);
} }
@ -155,7 +195,27 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test conditions %s(%s) =~ /%s/\n", field, field_data, expression); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test conditions %s(%s) =~ /%s/\n", field, field_data, expression);
if (!(proceed = perform_regex(channel, field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { if (!(proceed = perform_regex(channel, field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Regex mismatch\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Regex mismatch\n");
break;
for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
char *application = (char*) switch_xml_attr_soft(xaction, "application");
char *data = (char *) switch_xml_attr_soft(xaction, "data");
if (!*extension) {
if ((*extension =
switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "memory error!\n");
return 0;
}
}
switch_caller_extension_add_application(session, *extension, application, data);
}
if (do_break_i == BREAK_ON_FALSE || do_break_i == BREAK_ALWAYS) {
break;
} else {
continue;
}
} }
assert(re != NULL); assert(re != NULL);
} }
@ -186,6 +246,10 @@ static int parse_exten(switch_core_session_t *session, switch_xml_t xexten, swit
} }
cleanre(re); cleanre(re);
if (do_break_i == BREAK_ON_TRUE || do_break_i == BREAK_ALWAYS) {
break;
}
} }
return proceed; return proceed;
} }

View File

@ -151,8 +151,8 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
static switch_status_t dl_login(char *arg, switch_stream_handle_t *stream); static switch_status_t dl_login(char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t dl_logout(char *profile_name, switch_stream_handle_t *stream); static switch_status_t dl_logout(char *profile_name, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t channel_on_init(switch_core_session_t *session); static switch_status_t channel_on_init(switch_core_session_t *session);
static switch_status_t channel_on_hangup(switch_core_session_t *session); static switch_status_t channel_on_hangup(switch_core_session_t *session);
static switch_status_t channel_on_ring(switch_core_session_t *session); static switch_status_t channel_on_ring(switch_core_session_t *session);
@ -1248,10 +1248,14 @@ static void set_profile_val(struct mdl_profile *profile, char *var, char *val)
} }
} }
static switch_status_t dl_logout(char *profile_name, switch_stream_handle_t *stream) static switch_status_t dl_logout(char *profile_name, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
struct mdl_profile *profile; struct mdl_profile *profile;
if (session) {
return SWITCH_STATUS_FALSE;
}
if (!profile_name) { if (!profile_name) {
stream->write_function(stream, "NO PROFILE NAME SPECIFIED\n"); stream->write_function(stream, "NO PROFILE NAME SPECIFIED\n");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -1267,7 +1271,7 @@ static switch_status_t dl_logout(char *profile_name, switch_stream_handle_t *str
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t dl_login(char *arg, switch_stream_handle_t *stream) static switch_status_t dl_login(char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
char *argv[10] = {0}; char *argv[10] = {0};
int argc = 0; int argc = 0;
@ -1275,6 +1279,10 @@ static switch_status_t dl_login(char *arg, switch_stream_handle_t *stream)
struct mdl_profile *profile = NULL; struct mdl_profile *profile = NULL;
int x; int x;
if (session) {
return SWITCH_STATUS_FALSE;
}
if (switch_strlen_zero(arg)) { if (switch_strlen_zero(arg)) {
stream->write_function(stream, "FAIL\n"); stream->write_function(stream, "FAIL\n");
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;

View File

@ -116,11 +116,11 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
static int dump_info(void); static int dump_info(void);
static switch_status_t load_config(void); static switch_status_t load_config(void);
static int get_dev_by_name(char *name, int in); static int get_dev_by_name(char *name, int in);
static switch_status_t place_call(char *dest, switch_stream_handle_t *stream); static switch_status_t place_call(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t hup_call(char *callid, switch_stream_handle_t *stream); static switch_status_t hup_call(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t call_info(char *callid, switch_stream_handle_t *stream); static switch_status_t call_info(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t send_dtmf(char *callid, switch_stream_handle_t *stream); static switch_status_t send_dtmf(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream);
static switch_status_t answer_call(char *callid, switch_stream_handle_t *stream); static switch_status_t answer_call(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream);
/* /*
State methods they get called when the state changes to the specific state State methods they get called when the state changes to the specific state
@ -822,11 +822,15 @@ static switch_status_t engage_device(struct private_object *tech_pvt)
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
static switch_status_t place_call(char *dest, switch_stream_handle_t *stream) static switch_status_t place_call(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream)
{ {
switch_core_session_t *session; switch_core_session_t *session;
switch_status_t status = SWITCH_STATUS_FALSE; switch_status_t status = SWITCH_STATUS_FALSE;
if (isession) {
return SWITCH_STATUS_FALSE;
}
if (!dest) { if (!dest) {
stream->write_function(stream, "Usage: pacall <exten>"); stream->write_function(stream, "Usage: pacall <exten>");
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
@ -875,12 +879,16 @@ static switch_status_t place_call(char *dest, switch_stream_handle_t *stream)
} }
static switch_status_t hup_call(char *callid, switch_stream_handle_t *stream) static switch_status_t hup_call(char *callid, switch_core_session_t *isession, switch_stream_handle_t *stream)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
char tmp[50]; char tmp[50];
if (isession) {
return SWITCH_STATUS_FALSE;
}
if (callid && !strcasecmp(callid, "last")) { if (callid && !strcasecmp(callid, "last")) {
snprintf(tmp, sizeof(tmp), "%d", globals.call_id - 1); snprintf(tmp, sizeof(tmp), "%d", globals.call_id - 1);
callid = tmp; callid = tmp;
@ -919,12 +927,16 @@ static switch_status_t hup_call(char *callid, switch_stream_handle_t *stream)
} }
static switch_status_t send_dtmf(char *callid, switch_stream_handle_t *stream) static switch_status_t send_dtmf(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
char *dtmf; char *dtmf;
if (session) {
return SWITCH_STATUS_FALSE;
}
if ((dtmf = strchr(callid, ' ')) != 0) { if ((dtmf = strchr(callid, ' ')) != 0) {
*dtmf++ = '\0'; *dtmf++ = '\0';
} else { } else {
@ -943,11 +955,15 @@ static switch_status_t send_dtmf(char *callid, switch_stream_handle_t *stream)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
static switch_status_t answer_call(char *callid, switch_stream_handle_t *stream) static switch_status_t answer_call(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
switch_channel_t *channel = NULL; switch_channel_t *channel = NULL;
if (session) {
return SWITCH_STATUS_FALSE;
}
if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid)) != 0) { if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid)) != 0) {
channel = switch_core_session_get_channel(tech_pvt->session); channel = switch_core_session_get_channel(tech_pvt->session);
assert(channel != NULL); assert(channel != NULL);
@ -975,11 +991,16 @@ static void print_info(struct private_object *tech_pvt, switch_stream_handle_t *
} }
static switch_status_t call_info(char *callid, switch_stream_handle_t *stream) static switch_status_t call_info(char *callid, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
struct private_object *tech_pvt; struct private_object *tech_pvt;
switch_hash_index_t *hi; switch_hash_index_t *hi;
void *val; void *val;
if (session) {
return SWITCH_STATUS_FALSE;
}
if (!callid || !strcasecmp(callid, "all")) { if (!callid || !strcasecmp(callid, "all")) {
for (hi = switch_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) { for (hi = switch_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val); switch_hash_this(hi, NULL, NULL, &val);

View File

@ -429,7 +429,7 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t *event
*arg++ = '\0'; *arg++ = '\0';
} }
if (switch_api_execute(api_cmd, arg, &stream) == SWITCH_STATUS_SUCCESS) { if (switch_api_execute(api_cmd, arg, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
switch_size_t len; switch_size_t len;
char buf[1024]; char buf[1024];

View File

@ -1838,13 +1838,25 @@ static JSBool js_api_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *ar
if (argc > 1) { if (argc > 1) {
char *cmd = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); char *cmd = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
char *arg = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); char *arg = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
switch_core_session_t *session = NULL;
if (argc > 2) {
JSObject *session_obj;
struct js_session *jss;
if (JS_ValueToObject(cx, argv[2], &session_obj)) {
if ((jss = JS_GetPrivate(cx, session_obj))) {
session = jss->session;
}
}
}
switch_stream_handle_t stream = {0}; switch_stream_handle_t stream = {0};
char retbuf[2048] = ""; char retbuf[2048] = "";
stream.data = retbuf; stream.data = retbuf;
stream.end = stream.data; stream.end = stream.data;
stream.data_size = sizeof(retbuf); stream.data_size = sizeof(retbuf);
switch_api_execute(cmd, arg, &stream); switch_api_execute(cmd, arg, session, &stream);
stream.write_function = switch_console_stream_write; stream.write_function = switch_console_stream_write;
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, retbuf)); *rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, retbuf));
@ -2203,7 +2215,7 @@ static void js_thread_launch(char *text)
} }
static switch_status_t launch_async(char *text, switch_stream_handle_t *stream) static switch_status_t launch_async(char *text, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
if (switch_strlen_zero(text)) { if (switch_strlen_zero(text)) {

View File

@ -272,7 +272,7 @@ abyss_bool HandleHook(TSession *r)
ResponseStatus(r,200); ResponseStatus(r,200);
ResponseContentType(r, m); ResponseContentType(r, m);
ResponseWrite(r); ResponseWrite(r);
switch_api_execute(command, r->query, &stream); switch_api_execute(command, r->query, NULL, &stream);
HTTPWriteEnd(r); HTTPWriteEnd(r);
return TRUE; return TRUE;
} }
@ -296,7 +296,7 @@ static xmlrpc_value *freeswitch_api(xmlrpc_env *const envP, xmlrpc_value *const
stream.end = stream.data; stream.end = stream.data;
stream.data_size = CMDLEN; stream.data_size = CMDLEN;
stream.write_function = switch_console_stream_write; stream.write_function = switch_console_stream_write;
switch_api_execute(command, arg, &stream); switch_api_execute(command, arg, NULL, &stream);
/* Return our result. */ /* Return our result. */
val = xmlrpc_build_value(envP, "s", retbuf); val = xmlrpc_build_value(envP, "s", retbuf);

View File

@ -108,7 +108,7 @@ static int switch_console_process(char *cmd, char *retbuf, int retlen)
stream.end = stream.data; stream.end = stream.data;
stream.data_size = retlen; stream.data_size = retlen;
stream.write_function = switch_console_stream_write; stream.write_function = switch_console_stream_write;
if (switch_api_execute(cmd, arg, &stream) == SWITCH_STATUS_SUCCESS) { if (switch_api_execute(cmd, arg, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "API CALL [%s(%s)] output:\n%s\n", cmd, arg ? arg : "", retbuf); switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "API CALL [%s(%s)] output:\n%s\n", cmd, arg ? arg : "", retbuf);
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Unknown Command: %s\n", cmd); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Unknown Command: %s\n", cmd);

View File

@ -711,7 +711,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
return i; return i;
} }
SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_stream_handle_t *stream) SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
{ {
switch_api_interface_t *api; switch_api_interface_t *api;
switch_status_t status; switch_status_t status;
@ -734,7 +734,7 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(char *cmd, char *arg, switch_
} }
if ((api = switch_loadable_module_get_api_interface(cmd)) != 0) { if ((api = switch_loadable_module_get_api_interface(cmd)) != 0) {
status = api->function(arg, stream); status = api->function(arg, session, stream);
} else { } else {
status = SWITCH_STATUS_FALSE; status = SWITCH_STATUS_FALSE;
stream->write_function(stream, "INVALID COMMAND [%s]", cmd); stream->write_function(stream, "INVALID COMMAND [%s]", cmd);