/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005/2006, Anthony Minessale II * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * * The Initial Developer of the Original Code is * Anthony Minessale II * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Anthony Minessale II * Michael Jerris * Johny Kadarisman * Paul Tinsley * Marcel Barbulescu * Bret McDanel * * * mod_commands.c -- Misc. Command Module * */ #include #include SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load); SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, NULL, NULL); SWITCH_STANDARD_API(user_data_function) { switch_xml_t x_domain, xml = NULL, x_user = NULL, x_param, x_params; int argc; char *mydata = NULL, *argv[3], *key = NULL, *type = NULL, *user, *domain; char delim = ' '; const char *container = "params", *elem = "param"; switch_event_t *params = NULL; if (switch_strlen_zero(cmd) || !(mydata = strdup(cmd))) { goto end; } if ((argc = switch_separate_string(mydata, delim, argv, (sizeof(argv) / sizeof(argv[0])))) < 3) { goto end; } user = argv[0]; type = argv[1]; key = argv[2]; if ((domain = strchr(user, '@'))) { *domain++ = '\0'; } else { domain = "cluecon.com"; } switch_event_create(¶ms, SWITCH_EVENT_MESSAGE); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "user", user); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "type", type); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "key", key); if (key && type && switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, params) == SWITCH_STATUS_SUCCESS) { if (!strcmp(type, "var")) { container = "variables"; elem = "variable"; } if ((x_params = switch_xml_child(x_user, container))) { for (x_param = switch_xml_child(x_params, elem); x_param; x_param = x_param->next) { const char *var = switch_xml_attr(x_param, "name"); const char *val = switch_xml_attr(x_param, "value"); if (var && val && !strcasecmp(var, key)) { stream->write_function(stream, "%s", val); break; } } } } end: switch_xml_free(xml); free(mydata); switch_event_destroy(¶ms); return SWITCH_STATUS_SUCCESS; } static switch_status_t _find_user(const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream, switch_bool_t tf) { switch_xml_t x_domain = NULL, x_user = NULL, xml = NULL; int argc; char *mydata = NULL, *argv[3]; char *key, *user, *domain; char *xmlstr; char *path_info = NULL; char delim = ' '; char *host = NULL; const char *err = NULL; if (stream->param_event && (host = switch_event_get_header(stream->param_event, "http-host"))) { stream->write_function(stream, "Content-Type: text/xml\r\n\r\n"); if ((path_info = switch_event_get_header(stream->param_event, "http-path-info"))) { cmd = path_info; delim = '/'; } } if (!cmd) { err = "bad args"; goto end; } mydata = strdup(cmd); switch_assert(mydata); argc = switch_separate_string(mydata, delim, argv, (sizeof(argv) / sizeof(argv[0]))); if (argc < 3) { err = "bad args"; goto end; } key = argv[0]; user = argv[1]; domain = argv[2]; if (!(key && user && domain)) { err = "bad args"; goto end; } if (switch_xml_locate_user(key, user, domain, NULL, &xml, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) { err = "can't find user"; goto end; } end: if (session || tf) { stream->write_function(stream, err ? "false" : "true"); switch_xml_free(xml); } else { if (err) { if (host) { stream->write_function(stream, "%s\n", err); } else { stream->write_function(stream, "-Error %s\n", err); } } if (xml && x_user) { xmlstr = switch_xml_toxml(x_user, SWITCH_FALSE); switch_assert(xmlstr); stream->write_function(stream, "%s", xmlstr); free(xmlstr); switch_xml_free(xml); } } free(mydata); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(user_exists_function) { return _find_user(cmd, session, stream, SWITCH_TRUE); } SWITCH_STANDARD_API(find_user_function) { return _find_user(cmd, session, stream, SWITCH_FALSE); } SWITCH_STANDARD_API(xml_locate_function) { switch_xml_t xml = NULL, obj = NULL; int argc; char *mydata = NULL, *argv[4]; char *section, *tag, *tag_attr_name, *tag_attr_val; switch_event_t *params = NULL; char *xmlstr; char *path_info, delim = ' '; char *host = NULL; const char *err = NULL; if (stream->param_event && (host = switch_event_get_header(stream->param_event, "http-host"))) { stream->write_function(stream, "Content-Type: text/xml\r\n\r\n"); if ((path_info = switch_event_get_header(stream->param_event, "http-path-info"))) { cmd = path_info; delim = '/'; } } if (!cmd) { err = "bad args"; goto end; } mydata = strdup(cmd); switch_assert(mydata); argc = switch_separate_string(mydata, delim, argv, (sizeof(argv) / sizeof(argv[0]))); if (argc == 1 && !strcasecmp(argv[0], "root")) { const char *error; xml = switch_xml_open_root(0, &error); obj = xml; goto end; } if (argc < 4) { err = "bad args"; goto end; } section = argv[0]; tag = argv[1]; tag_attr_name = argv[2]; tag_attr_val = argv[3]; switch_event_create(¶ms, SWITCH_EVENT_MESSAGE); switch_assert(params); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "section", section); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "tag", tag); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "tag_attr_name", tag_attr_name); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "tag_attr_val", tag_attr_val); if (switch_xml_locate(section, tag, tag_attr_name, tag_attr_val, &xml, &obj, params) != SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "can't find anything\n"); goto end; } end: if (err) { if (host) { stream->write_function(stream, "%s\n", err); } else { stream->write_function(stream, "-Error %s\n", err); } } if (xml && obj) { xmlstr = switch_xml_toxml(obj, SWITCH_FALSE); switch_assert(xmlstr); stream->write_function(stream, "%s", xmlstr); free(xmlstr); switch_xml_free(xml); } switch_event_destroy(¶ms); free(mydata); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(reload_acl_function) { const char *err; switch_xml_t xml_root; if (session) { return SWITCH_STATUS_FALSE; } if (cmd && !strcmp(cmd, "reloadxml")) { if ((xml_root = switch_xml_open_root(1, &err))) { switch_xml_free(xml_root); } } switch_load_network_lists(SWITCH_TRUE); stream->write_function(stream, "+OK acl reloaded\n"); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(acl_function) { int argc; char *mydata = NULL, *argv[3]; if (!cmd) { goto error; } mydata = strdup(cmd); switch_assert(mydata); argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc < 2) { goto error; } if (switch_check_network_list_ip(argv[0], argv[1])) { stream->write_function(stream, "true"); goto ok; } error: stream->write_function(stream, "false"); ok: switch_safe_free(mydata); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(regex_function) { switch_regex_t *re = NULL; int ovector[30]; int argc; char *mydata = NULL, *argv[3]; size_t len = 0; char *substituted = NULL; int proceed = 0; if (!cmd) { goto error; } mydata = strdup(cmd); switch_assert(mydata); argc = switch_separate_string(mydata, '|', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc < 2) { goto error; } if ((proceed = switch_regex_perform(argv[0], argv[1], &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { if (argc > 2) { len = strlen(argv[0]) * 3; substituted = malloc(len); switch_assert(substituted); memset(substituted, 0, len); switch_replace_char(argv[2], '%', '$', SWITCH_FALSE); switch_perform_substitution(re, proceed, argv[2], argv[0], substituted, len, ovector); stream->write_function(stream, "%s", substituted); free(substituted); } else { stream->write_function(stream, "true"); } } else { stream->write_function(stream, "false"); } goto ok; error: stream->write_function(stream, "-ERR"); ok: switch_regex_safe_free(re); switch_safe_free(mydata); return SWITCH_STATUS_SUCCESS; } typedef enum { O_NONE, O_EQ, O_NE, O_GT, O_GE, O_LT, O_LE } o_t; SWITCH_STANDARD_API(cond_function) { int argc; char *mydata = NULL, *argv[3]; char *expr; char *a, *b; double a_f = 0.0, b_f = 0.0; o_t o = O_NONE; int is_true = 0; char *p; if (!cmd) { goto error; } mydata = strdup(cmd); switch_assert(mydata); if ((p = strchr(mydata, '?'))) { *p = ':'; } else { goto error; } argc = switch_separate_string(mydata, ':', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc != 3) { goto error; } a = argv[0]; if ((expr = strchr(a, '!'))) { *expr++ = '\0'; if (*expr == '=') { o = O_NE; } } else if ((expr = strchr(a, '>'))) { if (*(expr + 1) == '=') { *expr++ = '\0'; o = O_GE; } else { o = O_GT; } } else if ((expr = strchr(a, '<'))) { if (*(expr + 1) == '=') { *expr++ = '\0'; o = O_LE; } else { o = O_LT; } } else if ((expr = strchr(a, '='))) { *expr++ = '\0'; if (*expr == '=') { o = O_EQ; } } if (o) { char *s_a = NULL, *s_b = NULL; int a_is_num, b_is_num; *expr++ = '\0'; b = expr; s_a = switch_strip_spaces(a); s_b = switch_strip_spaces(b); a_is_num = switch_is_number(s_a); b_is_num = switch_is_number(s_b); a_f = a_is_num ? atof(s_a) : (float) strlen(s_a); b_f = b_is_num ? atof(s_b) : (float) strlen(s_b); switch (o) { case O_EQ: if (!a_is_num && !b_is_num) { is_true = !strcmp(s_a, s_b); } else { is_true = a_f == b_f; } break; case O_NE: if (!a_is_num && !b_is_num) { is_true = strcmp(s_a, s_b); } else { is_true = a_f != b_f; } break; case O_GT: is_true = a_f > b_f; break; case O_GE: is_true = a_f >= b_f; break; case O_LT: is_true = a_f < b_f; break; case O_LE: is_true = a_f <= b_f; break; default: break; } switch_safe_free(s_a); switch_safe_free(s_b); stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]); goto ok; } error: stream->write_function(stream, "-ERR"); ok: switch_safe_free(mydata); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(lan_addr_function) { stream->write_function(stream, "%s", switch_is_lan_addr(cmd) ? "true" : "false"); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(status_function) { uint8_t html = 0; switch_core_time_duration_t duration = { 0 }; char *http = NULL; int sps = 0, last_sps = 0; if (session) { return SWITCH_STATUS_FALSE; } switch_core_measure_time(switch_core_uptime(), &duration); if (stream->param_event) { http = switch_event_get_header(stream->param_event, "http-host"); } if (http || (cmd && strstr(cmd, "html"))) { html = 1; stream->write_function(stream, "

FreeSWITCH Status

\n"); } stream->write_function(stream, "UP %u year%s, %u day%s, %u hour%s, %u minute%s, %u second%s, %u millisecond%s, %u microsecond%s\n", duration.yr, duration.yr == 1 ? "" : "s", duration.day, duration.day == 1 ? "" : "s", duration.hr, duration.hr == 1 ? "" : "s", duration.min, duration.min == 1 ? "" : "s", duration.sec, duration.sec == 1 ? "" : "s", duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s"); stream->write_function(stream, "%" SWITCH_SIZE_T_FMT " session(s) since startup\n", switch_core_session_id() - 1); switch_core_session_ctl(SCSC_LAST_SPS, &last_sps); switch_core_session_ctl(SCSC_SPS, &sps); stream->write_function(stream, "%d session(s) %d/%d\n", switch_core_session_count(), last_sps, sps); if (html) { stream->write_function(stream, "\n"); } if (cmd && strstr(cmd, "refresh=")) { char *refresh = strchr(cmd, '='); if (refresh) { int r; refresh++; r = atoi(refresh); if (r > 0) { stream->write_function(stream, "\n", r, r, html ? "html=1" : ""); } } } return SWITCH_STATUS_SUCCESS; } #define CTL_SYNTAX "[hupall|pause|resume|shutdown|sync_clock|reclaim_mem|max_sessions|max_dtmf_duration [num]|loglevel [level]]" SWITCH_STANDARD_API(ctl_function) { int argc; char *mydata, *argv[5]; int32_t arg = 0; if (switch_strlen_zero(cmd)) { stream->write_function(stream, "-USAGE: %s\n", CTL_SYNTAX); return SWITCH_STATUS_SUCCESS; } if ((mydata = strdup(cmd))) { argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); if (!strcasecmp(argv[0], "hupall")) { arg = 1; switch_core_session_ctl(SCSC_HUPALL, &arg); } else if (!strcasecmp(argv[0], "pause")) { arg = 1; switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); } else if (!strcasecmp(argv[0], "resume")) { arg = 0; switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); } else if (!strcasecmp(argv[0], "shutdown")) { arg = 0; switch_core_session_ctl(SCSC_SHUTDOWN, &arg); } else if (!strcasecmp(argv[0], "reclaim_mem")) { switch_core_session_ctl(SCSC_RECLAIM, &arg); } else if (!strcasecmp(argv[0], "max_sessions")) { if (argc > 1) { arg = atoi(argv[1]); } switch_core_session_ctl(SCSC_MAX_SESSIONS, &arg); stream->write_function(stream, "+OK max sessions: %d\n", arg); } else if (!strcasecmp(argv[0], "max_dtmf_duration")) { if (argc > 1) { arg = atoi(argv[1]); } switch_core_session_ctl(SCSC_MAX_DTMF_DURATION, &arg); stream->write_function(stream, "+OK max dtmf duration: %d\n", arg); } else if (!strcasecmp(argv[0], "default_dtmf_duration")) { if (argc > 1) { arg = atoi(argv[1]); } switch_core_session_ctl(SCSC_DEFAULT_DTMF_DURATION, &arg); stream->write_function(stream, "+OK default dtmf duration: %d\n", arg); } else if (!strcasecmp(argv[0], "loglevel")) { if (argc > 1) { if (*argv[1] > 47 && *argv[1] < 58) { arg = atoi(argv[1]); } else { arg = switch_log_str2level(argv[1]); } } else { arg = -1; } if (arg == -1 || arg == SWITCH_LOG_INVALID) { stream->write_function(stream, "-ERR syntax error, log level not set!\n"); } else { switch_core_session_ctl(SCSC_LOGLEVEL, &arg); stream->write_function(stream, "+OK log level: %s [%d]\n", switch_log_level2str(arg), arg); } } else if (!strcasecmp(argv[0], "last_sps")) { switch_core_session_ctl(SCSC_LAST_SPS, &arg); stream->write_function(stream, "+OK last sessions per second: %d\n", arg); } else if (!strcasecmp(argv[0], "sps")) { if (argc > 1) { arg = atoi(argv[1]); } else { arg = 0; } switch_core_session_ctl(SCSC_SPS, &arg); stream->write_function(stream, "+OK sessions per second: %d\n", arg); } else if (!strcasecmp(argv[0], "sync_clock")) { arg = 0; switch_core_session_ctl(SCSC_SYNC_CLOCK, &arg); stream->write_function(stream, "+OK clock syncronized\n"); } else { stream->write_function(stream, "-ERR INVALID COMMAND\nUSAGE: fsctl %s", CTL_SYNTAX); goto end; } stream->write_function(stream, "+OK\n"); end: free(mydata); } else { stream->write_function(stream, "-ERR Memory error\n"); } return SWITCH_STATUS_SUCCESS; } #define LOAD_SYNTAX "" SWITCH_STANDARD_API(load_function) { const char *err; if (session) { return SWITCH_STATUS_FALSE; } if (switch_strlen_zero(cmd)) { stream->write_function(stream, "-USAGE: %s\n", LOAD_SYNTAX); return SWITCH_STATUS_SUCCESS; } if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, SWITCH_TRUE, &err) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR [%s]\n", err); } return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(unload_function) { const char *err; if (session) { return SWITCH_STATUS_FALSE; } if (switch_strlen_zero(cmd)) { stream->write_function(stream, "-USAGE: %s\n", LOAD_SYNTAX); return SWITCH_STATUS_SUCCESS; } if (switch_loadable_module_unload_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) cmd, &err) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR [%s]\n", err); } return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(reload_function) { const char *err; switch_xml_t xml_root; if (session) { return SWITCH_STATUS_FALSE; } if ((xml_root = switch_xml_open_root(1, &err))) { switch_xml_free(xml_root); } stream->write_function(stream, "+OK [%s]\n", err); return SWITCH_STATUS_SUCCESS; } #define KILL_SYNTAX "" SWITCH_STANDARD_API(kill_function) { switch_core_session_t *ksession = NULL; if (session) { return SWITCH_STATUS_FALSE; } if (!cmd) { stream->write_function(stream, "-USAGE: %s\n", KILL_SYNTAX); } else if ((ksession = switch_core_session_locate(cmd))) { switch_channel_t *channel = switch_core_session_get_channel(ksession); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); switch_core_session_rwunlock(ksession); stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR No Such Channel!\n"); } return SWITCH_STATUS_SUCCESS; } #define PARK_SYNTAX "" SWITCH_STANDARD_API(park_function) { switch_core_session_t *ksession = NULL; if (session) { return SWITCH_STATUS_FALSE; } if (!cmd) { stream->write_function(stream, "-USAGE: %s\n", PARK_SYNTAX); } else if ((ksession = switch_core_session_locate(cmd))) { switch_ivr_park_session(ksession); switch_core_session_rwunlock(ksession); stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR No Such Channel!\n"); } return SWITCH_STATUS_SUCCESS; } #define TRANSFER_SYNTAX " [-bleg|-both] [] []" SWITCH_STANDARD_API(transfer_function) { switch_core_session_t *tsession = NULL, *other_session = NULL; char *mycmd = NULL, *argv[5] = { 0 }; int argc = 0; char *tuuid, *dest, *dp, *context, *arg = NULL; if (session) { return SWITCH_STATUS_FALSE; } if (switch_strlen_zero(cmd) || !(mycmd = strdup(cmd))) { stream->write_function(stream, "-USAGE: %s\n", TRANSFER_SYNTAX); return SWITCH_STATUS_SUCCESS; } argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc < 2 || argc > 5) { stream->write_function(stream, "-USAGE: %s\n", TRANSFER_SYNTAX); goto done; } tuuid = argv[0]; dest = argv[1]; dp = argv[2]; context = argv[3]; if (switch_strlen_zero(tuuid) || !(tsession = switch_core_session_locate(tuuid))) { stream->write_function(stream, "-ERR No Such Channel!\n"); goto done; } if (*dest == '-') { arg = dest; dest = argv[2]; dp = argv[3]; context = argv[4]; } if (arg) { switch_channel_t *channel = switch_core_session_get_channel(tsession); const char *uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE); arg++; if (!strcasecmp(arg, "bleg")) { if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_core_session_t *tmp = tsession; tsession = other_session; other_session = NULL; switch_core_session_rwunlock(tmp); } } else if (!strcasecmp(arg, "both")) { if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_ivr_session_transfer(other_session, dest, dp, context); switch_core_session_rwunlock(other_session); } } } if (switch_ivr_session_transfer(tsession, dest, dp, context) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "-ERR\n"); } switch_core_session_rwunlock(tsession); done: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } #define TONE_DETECT_SYNTAX " [ ]" SWITCH_STANDARD_API(tone_detect_session_function) { char *argv[7] = { 0 }; int argc; char *mydata = NULL; time_t to = 0; switch_core_session_t *rsession; if (!cmd) { stream->write_function(stream, "-USAGE: %s\n", TONE_DETECT_SYNTAX); return SWITCH_STATUS_SUCCESS; } mydata = strdup(cmd); switch_assert(mydata != NULL); if ((argc = switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0]))) < 3 || !argv[0]) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "-ERR INVALID ARGS!\n"); return SWITCH_STATUS_SUCCESS; } if (!(rsession = switch_core_session_locate(argv[0]))) { stream->write_function(stream, "-ERR Error Cannot locate session!\n"); return SWITCH_STATUS_SUCCESS; } if (argv[4]) { uint32_t mto; if (*argv[4] == '+') { if ((mto = atoi(argv[4] + 1)) > 0) { to = switch_timestamp(NULL) + mto; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n"); goto done; } } else { if ((to = atoi(argv[4])) < switch_timestamp(NULL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n"); to = 0; goto done; } } } switch_ivr_tone_detect_session(rsession, argv[1], argv[2], argv[3], to, argv[5], argv[6]); stream->write_function(stream, "+OK Enabling tone detection '%s' '%s' '%s'\n", argv[1], argv[2], argv[3]); done: free(mydata); switch_core_session_rwunlock(rsession); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(uuid_function) { switch_uuid_t uuid; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; switch_uuid_get(&uuid); switch_uuid_format(uuid_str, &uuid); stream->write_function(stream, "%s", uuid_str); return SWITCH_STATUS_SUCCESS; } #define UUID_CHAT_SYNTAX " " SWITCH_STANDARD_API(uuid_chat) { switch_core_session_t *tsession = NULL; char *uuid = NULL, *text = NULL; if (!switch_strlen_zero(cmd) && (uuid = strdup(cmd))) { if ((text = strchr(uuid, ' '))) { *text++ = '\0'; } } if (switch_strlen_zero(uuid) || switch_strlen_zero(text)) { stream->write_function(stream, "-USAGE: %s\n", UUID_CHAT_SYNTAX); } else { if ((tsession = switch_core_session_locate(uuid))) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_body(event, "%s", text); if (switch_core_session_receive_event(tsession, &event) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); stream->write_function(stream, "-ERR Send Failed\n"); } else { stream->write_function(stream, "+OK\n"); } } switch_core_session_rwunlock(tsession); } else { stream->write_function(stream, "-ERR No Such Channel %s!\n", uuid); } } switch_safe_free(uuid); return SWITCH_STATUS_SUCCESS; } #define SCHED_TRANSFER_SYNTAX "[+]