]> 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 22:05:57 +0000 (17:05 -0500)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Tue, 25 Aug 2020 18:47:12 +0000 (13:47 -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 dd59c6b0f7d487c03f614d4988f6dbf9a7a556b1..116ff993c18fd08bf4194329e52d05264f3887c6 100644 (file)
@@ -335,9 +335,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 72a667d1f7ebde9b852c8916e8113992b76f2ef3..910eb5df70e57f74e97d2e42630780d498931ac0 100644 (file)
@@ -54,7 +54,7 @@
 - \ref manager.c Main manager code file
  */
 
-#define AMI_VERSION                     "5.0.1"
+#define AMI_VERSION                     "5.0.2"
 #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 826fa0ac3aeffc6bd32cca44ef0c91020be94ff7..72ccd9620a281a7f611f0836d158d27de38e70fa 100644 (file)
@@ -466,6 +466,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 33909170fae281d21745d1f8cb39261300827b92..92b6b06f1be0f6948f1634f4e159fae8fe7da7d7 100644 (file)
@@ -3847,7 +3847,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
                                        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 1963151c1e9de9d879d839bca82b9c05f24ea0d7..7f8dc0fd81449d8682a4a9dac6c9a354deaf98a7 100644 (file)
 #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>
@@ -4836,14 +4844,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)) {
@@ -4862,22 +4948,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 26b356d1431b96139219f323abd3a31341b1df70..d4cbd484bb062e4993fe0ad9c95dde9b16366f89 100644 (file)
@@ -1416,6 +1416,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;