]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
manager - Add Content-Type parameter to the SendText action
authorKevin Harwell <kharwell@digium.com>
Wed, 10 Jun 2020 21:58:24 +0000 (16:58 -0500)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Mon, 6 Jul 2020 10:23:11 +0000 (05:23 -0500)
This patch allows a user of AMI to now specify the type of message
content contained within by setting the 'Content-Type' parameter.

Note, the AMI version has been bumped for this change.

ASTERISK-28945 #close

Change-Id: Ibb5315702532c6b954e1498beddc8855fabdf4bb

doc/CHANGES-staging/ami_sendtext_content_type.txt [new file with mode: 0644]
include/asterisk/frame.h
include/asterisk/manager.h
include/asterisk/message.h
main/channel.c
main/manager.c
main/message.c

diff --git a/doc/CHANGES-staging/ami_sendtext_content_type.txt b/doc/CHANGES-staging/ami_sendtext_content_type.txt
new file mode 100644 (file)
index 0000000..45037ff
--- /dev/null
@@ -0,0 +1,4 @@
+Subject: AMI
+
+You can now specify an optional 'Content-Type' as an argument for the Asterisk
+SendText manager action.
index 4572b6e122113623a7afa806e58204d31b4774be..776040f975952c7615f95f3b2a42639dfb8a7e62 100644 (file)
@@ -328,9 +328,16 @@ enum ast_control_frame_type {
        AST_CONTROL_RECORD_MUTE = 1103, /*!< Indicated to a channel in record to mute/unmute (i.e. write silence) recording */
 };
 
+/*!
+ * \brief Actions to indicate to, and be handled on channel read
+ *
+ * The subtype to specify for an AST_CONTROL_READ_ACTION frame. These
+ * frames are then to be enacted on within a channel's read thread.
+ */
 enum ast_frame_read_action {
        AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO,
        AST_FRAME_READ_ACTION_SEND_TEXT,
+       AST_FRAME_READ_ACTION_SEND_TEXT_DATA,
 };
 
 struct ast_control_read_action_payload {
index 9968ec8cc174da7c98362b9c95237e63aa46af5a..85c26c1ea12e0dcc5a53e97209dc41eeb13e6cbf 100644 (file)
@@ -54,7 +54,7 @@
 - \ref manager.c Main manager code file
  */
 
-#define AMI_VERSION                     "2.10.5"
+#define AMI_VERSION                     "2.10.6"
 #define DEFAULT_MANAGER_PORT 5038      /* Default port for Asterisk management via TCP */
 #define DEFAULT_MANAGER_TLS_PORT 5039  /* Default port for Asterisk management via TCP */
 
index f5b7a7528da6d014e85ae39cdda6d274c34ab2fa..94b5e916f0b04b7f77f0ad10a54874154e3c2c6e 100644 (file)
@@ -479,6 +479,24 @@ struct ast_msg_data_attribute {
 struct ast_msg_data *ast_msg_data_alloc(enum ast_msg_data_source_type source,
        struct ast_msg_data_attribute attributes[], size_t count);
 
+/*!
+ * \brief Allocates an ast_msg_data structure.
+ * \since 13.35.0
+ * \since 16.12.0
+ * \since 17.6.0
+ *
+ * \param source The source type of the message
+ * \param to Where the message is sent to
+ * \param from Where the message is sent from
+ * \param content_type Content type of the body
+ * \param body The message body
+ *
+ * \return Pointer to msg structure or NULL on allocation failure.
+ *         Caller must call ast_free when done.
+ */
+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);
+
 /*!
  * \brief Clone an ast_msg_data structure
  * \since 13.22.0
index 9f68a9aafd9efb60077f0cc5c3346e3368e1e5fb..508205f9f3d90b91f5dba945fe10ba52db61b21d 100644 (file)
@@ -4115,7 +4115,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
                                        break;
                                case AST_FRAME_READ_ACTION_SEND_TEXT:
                                        ast_channel_unlock(chan);
-                                       ast_sendtext(chan, (const char *) read_action_payload->payload);
+                                       ast_sendtext(chan, (const char *)read_action_payload->payload);
+                                       ast_channel_lock(chan);
+                                       break;
+                               case AST_FRAME_READ_ACTION_SEND_TEXT_DATA:
+                                       ast_channel_unlock(chan);
+                                       ast_sendtext_data(chan, (struct ast_msg_data *)read_action_payload->payload);
                                        ast_channel_lock(chan);
                                        break;
                                }
index c79d4f1eedbc8392ffdb978bce2b9f9a040d5f3a..54315f328a25a33fbcbca158fb94beb6fe8dffbd 100644 (file)
@@ -102,6 +102,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/format_cache.h"
 #include "asterisk/translate.h"
 #include "asterisk/taskprocessor.h"
+#include "asterisk/message.h"
 
 /*** DOCUMENTATION
        <manager name="Ping" language="en_US">
@@ -867,7 +868,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
        </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'])" />
@@ -877,10 +879,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        <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>
@@ -4809,14 +4817,92 @@ static int action_status(struct mansession *s, const struct message *m)
        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)) {
@@ -4835,22 +4921,13 @@ static int action_sendtext(struct mansession *s, const struct message *m)
                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) {
index b3d739e3d1db4ad989adb8981ac0e3d43c52a6fb..1eea006945a113872e3ca70b95dc19fe9508d653 100644 (file)
@@ -1427,6 +1427,32 @@ struct ast_msg_data *ast_msg_data_alloc(enum ast_msg_data_source_type source,
        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;