manager - Add Content-Type parameter to the SendText action
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
This commit is contained in:
parent
43ba72dea0
commit
d9b8f04cd4
|
@ -0,0 +1,4 @@
|
|||
Subject: AMI
|
||||
|
||||
You can now specify an optional 'Content-Type' as an argument for the Asterisk
|
||||
SendText manager action.
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
115
main/manager.c
115
main/manager.c
|
@ -100,6 +100,7 @@
|
|||
#include "asterisk/format_cache.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/taskprocessor.h"
|
||||
#include "asterisk/message.h"
|
||||
|
||||
/*** DOCUMENTATION
|
||||
<manager name="Ping" language="en_US">
|
||||
|
@ -873,7 +874,8 @@
|
|||
</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'])" />
|
||||
|
@ -883,10 +885,16 @@
|
|||
<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>
|
||||
|
@ -4839,14 +4847,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)) {
|
||||
|
@ -4865,22 +4951,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);
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
ast_free(frame_payload);
|
||||
ast_channel_unref(c);
|
||||
|
||||
if (res >= 0) {
|
||||
|
|
|
@ -1429,6 +1429,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;
|
||||
|
|
Loading…
Reference in New Issue