From: Mark Michelson Date: Wed, 4 Apr 2012 19:11:47 +0000 (+0000) Subject: Add phone changes for message.c X-Git-Tag: 10.4.0-digiumphones-rc1~3^2~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87ea1deb44600766ec9bbd5d6a1ad9fd70c069b6;p=thirdparty%2Fasterisk.git Add phone changes for message.c git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@361200 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/main/message.c b/main/message.c index c4d2c43724..30a75f1d05 100644 --- a/main/message.c +++ b/main/message.c @@ -32,6 +32,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/module.h" #include "asterisk/datastore.h" #include "asterisk/pbx.h" +#include "asterisk/manager.h" #include "asterisk/strings.h" #include "asterisk/astobj2.h" #include "asterisk/app.h" @@ -139,6 +140,31 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + + + Send an out of call message to an endpoint. + + + + + The URI the message is to be sent to. + + + The URI the message is from. Not required. + + + The message body text. This must not contain any newlines as that + conflicts with the AMI protocol. + + + Text bodies requiring the use of newlines have to be base64 encoded + in this field. The Base64Body will be decoded before being sent out. + + + Message variable to set, multiple Variable: headers are allowed. + + + ***/ struct msg_data { @@ -393,6 +419,12 @@ struct ast_msg *ast_msg_alloc(void) return msg; } +struct ast_msg *ast_msg_ref(struct ast_msg *msg) +{ + ao2_ref(msg, 1); + return msg; +} + struct ast_msg *ast_msg_destroy(struct ast_msg *msg) { ao2_ref(msg, -1); @@ -516,7 +548,7 @@ static int msg_set_var_full(struct ast_msg *msg, const char *name, const char *v return 0; } -static int msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value) +int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value) { return msg_set_var_full(msg, name, value, 1); } @@ -812,6 +844,27 @@ static int msg_func_read(struct ast_channel *chan, const char *function, ast_copy_string(buf, ast_str_buffer(msg->from), len); } else if (!strcasecmp(data, "body")) { ast_copy_string(buf, ast_msg_get_body(msg), len); + } else if (!strcasecmp(data, "custom_data")) { + int outbound = -1; + if (!strcasecmp(value, "mark_all_outbound")) { + outbound = 1; + } else if (!strcasecmp(value, "clear_all_outbound")) { + outbound = 0; + } else { + ast_log(LOG_WARNING, "'%s' is not a valid value for custom_data\n", value); + } + + if (outbound != -1) { + struct msg_data *data; + struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0); + + while ((data= ao2_iterator_next(&iter))) { + data->send = outbound; + ao2_ref(data, -1); + } + ao2_iterator_destroy(&iter); + } + } else { ast_log(LOG_WARNING, "Invalid argument to MESSAGE(): '%s'\n", data); } @@ -907,7 +960,7 @@ static int msg_data_func_write(struct ast_channel *chan, const char *function, ao2_lock(msg); - msg_set_var_outbound(msg, data, value); + ast_msg_set_var_outbound(msg, data, value); ao2_unlock(msg); ao2_ref(msg, -1); @@ -1038,6 +1091,120 @@ exit_cleanup: return 0; } +static int action_messagesend(struct mansession *s, const struct message *m) +{ + const char *to = ast_strdupa(astman_get_header(m, "To")); + const char *from = astman_get_header(m, "From"); + const char *body = astman_get_header(m, "Body"); + const char *base64body = astman_get_header(m, "Base64Body"); + char base64decoded[1301] = { 0, }; + char *tech_name = NULL; + struct ast_variable *vars = NULL; + struct ast_variable *data = NULL; + struct ast_msg_tech_holder *tech_holder = NULL; + struct ast_msg *msg; + int res = -1; + + if (ast_strlen_zero(to)) { + astman_send_error(s, m, "No 'To' address specified."); + return -1; + } + + if (!ast_strlen_zero(base64body)) { + ast_base64decode((unsigned char *) base64decoded, base64body, sizeof(base64decoded) - 1); + body = base64decoded; + } + + tech_name = ast_strdupa(to); + tech_name = strsep(&tech_name, ":"); + { + struct ast_msg_tech tmp_msg_tech = { + .name = tech_name, + }; + struct ast_msg_tech_holder tmp_tech_holder = { + .tech = &tmp_msg_tech, + }; + + tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER); + } + + if (!tech_holder) { + astman_send_error(s, m, "Message technology not found."); + return -1; + } + + if (!(msg = ast_msg_alloc())) { + ao2_ref(tech_holder, -1); + astman_send_error(s, m, "Internal failure\n"); + return -1; + } + + data = astman_get_variables(m); + for (vars = data; vars; vars = vars->next) { + ast_msg_set_var_outbound(msg, vars->name, vars->value); + } + + ast_msg_set_body(msg, "%s", body); + + ast_rwlock_rdlock(&tech_holder->tech_lock); + if (tech_holder->tech) { + res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, "")); + } + ast_rwlock_unlock(&tech_holder->tech_lock); + + ast_variables_destroy(vars); + ao2_ref(tech_holder, -1); + ao2_ref(msg, -1); + + if (res) { + astman_send_error(s, m, "Message failed to send."); + } else { + astman_send_ack(s, m, "Message successfully sent"); + } + return res; +} + +int ast_msg_send(struct ast_msg *msg, const char *to, const char *from) +{ + char *tech_name = NULL; + struct ast_msg_tech_holder *tech_holder = NULL; + int res = -1; + + if (ast_strlen_zero(to)) { + ao2_ref(msg, -1); + return -1; + } + + tech_name = ast_strdupa(to); + tech_name = strsep(&tech_name, ":"); + { + struct ast_msg_tech tmp_msg_tech = { + .name = tech_name, + }; + struct ast_msg_tech_holder tmp_tech_holder = { + .tech = &tmp_msg_tech, + }; + + tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER); + } + + if (!tech_holder) { + ao2_ref(msg, -1); + return -1; + } + + ast_rwlock_rdlock(&tech_holder->tech_lock); + if (tech_holder->tech) { + res = tech_holder->tech->msg_send(msg, S_OR(to, ""), S_OR(from, "")); + } + ast_rwlock_unlock(&tech_holder->tech_lock); + + ao2_ref(tech_holder, -1); + ao2_ref(msg, -1); + + return res; +} + int ast_msg_tech_register(const struct ast_msg_tech *tech) { struct ast_msg_tech_holder tmp_tech_holder = { @@ -1122,6 +1289,7 @@ int ast_msg_init(void) res = __ast_custom_function_register(&msg_function, NULL); res |= __ast_custom_function_register(&msg_data_function, NULL); res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL); + res |= ast_manager_register_xml("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend); return res; }