#include "asterisk/format_cache.h"
#include "asterisk/translate.h"
#include "asterisk/taskprocessor.h"
+#include "asterisk/message.h"
/*** DOCUMENTATION
<manager name="Ping" language="en_US">
</manager>
<manager name="SendText" language="en_US">
<synopsis>
- Send text message to channel.
+ Sends a text message to channel. A content type can be optionally specified. If not set
+ it is set to an empty string allowing a custom handler to default it as it sees fit.
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Message" required="true">
<para>Message to send.</para>
</parameter>
+ <parameter name="Content-Type" required="false" default="">
+ <para>The type of content in the message</para>
+ </parameter>
</syntax>
<description>
<para>Sends A Text Message to a channel while in a call.</para>
</description>
+ <see-also>
+ <ref type="application">SendText</ref>
+ </see-also>
</manager>
<manager name="UserEvent" language="en_US">
<synopsis>
return 0;
}
+/*!
+ * \brief Queue a given read action containing a payload onto a channel
+ *
+ * This queues a READ_ACTION control frame that contains a given "payload", or
+ * data to be triggered and handled on the channel's read side. This ensures
+ * the "action" is handled by the channel's media reading thread.
+ *
+ * \param chan The channel to queue the action on
+ * \param payload The read action's payload
+ * \param payload_size The size of the given payload
+ * \param action The type of read action to queue
+ *
+ * \return -1 on error, 0 on success
+ */
+static int queue_read_action_payload(struct ast_channel *chan, const unsigned char *payload,
+ size_t payload_size, enum ast_frame_read_action action)
+{
+ struct ast_control_read_action_payload *obj;
+ size_t obj_size;
+ int res;
+
+ obj_size = payload_size + sizeof(*obj);
+
+ obj = ast_malloc(obj_size);
+ if (!obj) {
+ return -1;
+ }
+
+ obj->action = action;
+ obj->payload_size = payload_size;
+ memcpy(obj->payload, payload, payload_size);
+
+ res = ast_queue_control_data(chan, AST_CONTROL_READ_ACTION, obj, obj_size);
+
+ ast_free(obj);
+ return res;
+}
+
+/*!
+ * \brief Queue a read action to send a text message
+ *
+ * \param chan The channel to queue the action on
+ * \param body The body of the message
+ *
+ * \return -1 on error, 0 on success
+ */
+static int queue_sendtext(struct ast_channel *chan, const char *body)
+{
+ return queue_read_action_payload(chan, (const unsigned char *)body,
+ strlen(body) + 1, AST_FRAME_READ_ACTION_SEND_TEXT);
+}
+
+/*!
+ * \brief Queue a read action to send a text data message
+ *
+ * \param chan The channel to queue the action on
+ * \param body The body of the message
+ * \param content_type The message's content type
+ *
+ * \return -1 on error, 0 on success
+ */
+static int queue_sendtext_data(struct ast_channel *chan, const char *body,
+ const char *content_type)
+{
+ int res;
+ struct ast_msg_data *obj;
+
+ obj = ast_msg_data_alloc2(AST_MSG_DATA_SOURCE_TYPE_UNKNOWN,
+ NULL, NULL, content_type, body);
+ if (!obj) {
+ return -1;
+ }
+
+ res = queue_read_action_payload(chan, (const unsigned char *)obj,
+ ast_msg_data_get_length(obj), AST_FRAME_READ_ACTION_SEND_TEXT_DATA);
+
+ ast_free(obj);
+ return res;
+}
+
static int action_sendtext(struct mansession *s, const struct message *m)
{
struct ast_channel *c;
const char *name = astman_get_header(m, "Channel");
const char *textmsg = astman_get_header(m, "Message");
- struct ast_control_read_action_payload *frame_payload;
- int payload_size;
- int frame_size;
+ const char *content_type = astman_get_header(m, "Content-Type");
int res;
if (ast_strlen_zero(name)) {
return 0;
}
- payload_size = strlen(textmsg) + 1;
- frame_size = payload_size + sizeof(*frame_payload);
-
- frame_payload = ast_malloc(frame_size);
- if (!frame_payload) {
- ast_channel_unref(c);
- astman_send_error(s, m, "Failure");
- return 0;
- }
-
- frame_payload->action = AST_FRAME_READ_ACTION_SEND_TEXT;
- frame_payload->payload_size = payload_size;
- memcpy(frame_payload->payload, textmsg, payload_size);
- res = ast_queue_control_data(c, AST_CONTROL_READ_ACTION, frame_payload, frame_size);
+ /*
+ * If the "extra" data is not available, then send using "string" only.
+ * Doing such maintains backward compatibilities.
+ */
+ res = ast_strlen_zero(content_type) ? queue_sendtext(c, textmsg) :
+ queue_sendtext_data(c, textmsg, content_type);
- ast_free(frame_payload);
ast_channel_unref(c);
if (res >= 0) {
return msg;
}
+struct ast_msg_data *ast_msg_data_alloc2(enum ast_msg_data_source_type source_type,
+ const char *to, const char *from, const char *content_type, const char *body)
+{
+ struct ast_msg_data_attribute attrs[] =
+ {
+ {
+ .type = AST_MSG_DATA_ATTR_TO,
+ .value = (char *)S_OR(to, ""),
+ },
+ {
+ .type = AST_MSG_DATA_ATTR_FROM,
+ .value = (char *)S_OR(from, ""),
+ },
+ {
+ .type = AST_MSG_DATA_ATTR_CONTENT_TYPE,
+ .value = (char *)S_OR(content_type, ""),
+ },
+ {
+ .type = AST_MSG_DATA_ATTR_BODY,
+ .value = (char *)S_OR(body, ""),
+ },
+ };
+
+ return ast_msg_data_alloc(source_type, attrs, ARRAY_LEN(attrs));
+}
+
struct ast_msg_data *ast_msg_data_dup(struct ast_msg_data *msg)
{
struct ast_msg_data *dest;