From 14a985560ed5830aa3e1b5880890a59a5d0f0c2f Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Mon, 4 Jun 2012 20:26:12 +0000 Subject: Merge changes dealing with support for Digium phones. Presence support has been added. This is accomplished by allowing for presence hints in addition to device state hints. A dialplan function called PRESENCE_STATE has been added to allow for setting and reading presence. Presence can be transmitted to Digium phones using custom XML elements in a PIDF presence document. Voicemail has new APIs that allow for moving, removing, forwarding, and playing messages. Messages have had a new unique message ID added to them so that the APIs will work reliably. The state of a voicemail mailbox can be obtained using an API that allows one to get a snapshot of the mailbox. A voicemail Dialplan App called VoiceMailPlayMsg has been added to be able to play back a specific message. Configuration hooks have been added. Configuration hooks allow for a piece of code to be executed when a specific configuration file is loaded by a specific module. This is useful for modules that are dependent on the configuration of other modules. chan_sip now has a public method that allows for a custom SIP INFO request to be sent mid-dialog. Digium phones use this in order to display progress bars when files are played. Messaging support has been expanded a bit. The main visible difference is the addition of an AMI action MessageSend. Finally, a ParkingLots manager action has been added in order to get a list of parking lots. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@368435 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/message.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 2 deletions(-) (limited to 'main/message.c') diff --git a/main/message.c b/main/message.c index 5722969d0..e26b8c375 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" @@ -56,6 +57,18 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Read-only. The source of the message. When processing an incoming message, this will be set to the source of the message. + + Write-only. Mark or unmark all message headers for an outgoing + message. The following values can be set: + + + Mark all headers for an outgoing message. + + + Unmark all headers for an outgoing message. + + + Read/Write. The message body. When processing an incoming message, this includes the body of the message that Asterisk @@ -139,6 +152,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + + + Send an out of call message to an endpoint. + + + + + The URI the message is to be sent to. + + + A From URI for the message if needed for the + message technology being used to send this message. + + For SIP the from parameter can be a configured peer name + or in the form of "display-name" <URI>. + + + + 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. Base64Body will be decoded before being sent out. + Base64Body takes precedence over Body. + + + Message variable to set, multiple Variable: headers are + allowed. The header value is a comma separated list of + name=value pairs. + + + ***/ struct msg_data { @@ -393,6 +439,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); @@ -519,7 +571,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); } @@ -850,6 +902,26 @@ static int msg_func_write(struct ast_channel *chan, const char *function, ast_msg_set_from(msg, "%s", value); } else if (!strcasecmp(data, "body")) { ast_msg_set_body(msg, "%s", value); + } 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 *hdr_data; + struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0); + + while ((hdr_data = ao2_iterator_next(&iter))) { + hdr_data->send = outbound; + ao2_ref(hdr_data, -1); + } + ao2_iterator_destroy(&iter); + } } else { ast_log(LOG_WARNING, "'%s' is not a valid write argument.\n", data); } @@ -910,7 +982,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); @@ -1041,6 +1113,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 = { @@ -1125,6 +1311,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_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend); return res; } -- cgit v1.2.3