summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJenkins2 <jenkins2@gerrit.asterisk.org>2018-04-27 10:06:30 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2018-04-27 10:06:30 -0500
commit9c430569d4ccfb035970554641eacde88fc0c295 (patch)
tree00204a3a02b9917963e1eb3ff13c67582e9bd776 /main
parent2cef65dc777a24da6999c6bed21f896e8ab79507 (diff)
parent4fb7967c7327fd73a93c587f3eca0564201be049 (diff)
Merge "bridge_softmix: Forward TEXT frames"
Diffstat (limited to 'main')
-rw-r--r--main/bridge_channel.c31
-rw-r--r--main/channel.c76
-rw-r--r--main/frame.c3
-rw-r--r--main/message.c142
4 files changed, 237 insertions, 15 deletions
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 3aac5eb25..eb4b9ad0e 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -56,6 +56,7 @@
#include "asterisk/test.h"
#include "asterisk/sem.h"
#include "asterisk/stream.h"
+#include "asterisk/message.h"
/*!
* \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
@@ -1055,6 +1056,20 @@ int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, st
return 0;
}
+ if (DEBUG_ATLEAST(1)) {
+ if (fr->frametype == AST_FRAME_TEXT) {
+ ast_log(LOG_DEBUG, "Queuing TEXT frame to '%s': %*.s\n", ast_channel_name(bridge_channel->chan),
+ fr->datalen, (char *)fr->data.ptr);
+ } else if (fr->frametype == AST_FRAME_TEXT_DATA) {
+ struct ast_msg_data *msg = fr->data.ptr;
+ ast_log(LOG_DEBUG, "Queueing TEXT_DATA frame from '%s' to '%s:%s': %s\n",
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_FROM),
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_TO),
+ ast_channel_name(bridge_channel->chan),
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_BODY));
+ }
+ }
+
AST_LIST_INSERT_TAIL(&bridge_channel->wr_queue, dup, frame_list);
if (ast_alertpipe_write(bridge_channel->alert_pipe)) {
ast_log(LOG_ERROR, "We couldn't write alert pipe for %p(%s)... something is VERY wrong\n",
@@ -2349,6 +2364,7 @@ static void bridge_channel_handle_write(struct ast_bridge_channel *bridge_channe
struct ast_frame *fr;
struct sync_payload *sync_payload;
int num;
+ struct ast_msg_data *msg;
ast_bridge_channel_lock(bridge_channel);
@@ -2381,6 +2397,7 @@ static void bridge_channel_handle_write(struct ast_bridge_channel *bridge_channe
AST_LIST_TRAVERSE_SAFE_END;
ast_bridge_channel_unlock(bridge_channel);
+
if (!fr) {
/*
* Wait some to reduce CPU usage from a tight loop
@@ -2404,6 +2421,20 @@ static void bridge_channel_handle_write(struct ast_bridge_channel *bridge_channe
break;
case AST_FRAME_NULL:
break;
+ case AST_FRAME_TEXT:
+ ast_debug(1, "Sending TEXT frame to '%s': %*.s\n",
+ ast_channel_name(bridge_channel->chan), fr->datalen, (char *)fr->data.ptr);
+ ast_sendtext(bridge_channel->chan, fr->data.ptr);
+ break;
+ case AST_FRAME_TEXT_DATA:
+ msg = (struct ast_msg_data *)fr->data.ptr;
+ ast_debug(1, "Sending TEXT_DATA frame from '%s' to '%s:%s': %s\n",
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_FROM),
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_TO),
+ ast_channel_name(bridge_channel->chan),
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_BODY));
+ ast_sendtext_data(bridge_channel->chan, msg);
+ break;
default:
/* Assume that there is no mapped stream for this */
num = -1;
diff --git a/main/channel.c b/main/channel.c
index 815d5dbfe..a23dfa10c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -73,6 +73,7 @@
#include "asterisk/stasis_channels.h"
#include "asterisk/max_forwards.h"
#include "asterisk/stream.h"
+#include "asterisk/message.h"
/*** DOCUMENTATION
***/
@@ -1492,6 +1493,7 @@ int ast_is_deferrable_frame(const struct ast_frame *frame)
case AST_FRAME_BRIDGE_ACTION_SYNC:
case AST_FRAME_CONTROL:
case AST_FRAME_TEXT:
+ case AST_FRAME_TEXT_DATA:
case AST_FRAME_IMAGE:
case AST_FRAME_HTML:
return 1;
@@ -2767,6 +2769,7 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
case AST_FRAME_VOICE:
case AST_FRAME_VIDEO:
case AST_FRAME_TEXT:
+ case AST_FRAME_TEXT_DATA:
case AST_FRAME_DTMF_BEGIN:
case AST_FRAME_DTMF_END:
case AST_FRAME_IMAGE:
@@ -4652,9 +4655,11 @@ char *ast_recvtext(struct ast_channel *chan, int timeout)
return buf;
}
-int ast_sendtext(struct ast_channel *chan, const char *text)
+int ast_sendtext_data(struct ast_channel *chan, struct ast_msg_data *msg)
{
int res = 0;
+ const char *body = ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_BODY);
+ const char *content_type = ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_CONTENT_TYPE);
ast_channel_lock(chan);
/* Stop if we're a zombie or need a soft hangup */
@@ -4663,35 +4668,76 @@ int ast_sendtext(struct ast_channel *chan, const char *text)
return -1;
}
- if (ast_strlen_zero(text)) {
- ast_channel_unlock(chan);
- return 0;
- }
-
CHECK_BLOCKING(chan);
- if (ast_channel_tech(chan)->write_text && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_TEXT))) {
+ if (ast_channel_tech(chan)->write_text
+ && (ast_strlen_zero(content_type) || strcasecmp(content_type, "text/plain") == 0)
+ && (ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_TEXT))) {
struct ast_frame f;
+ size_t body_len = strlen(body) + 1;
+ /* Process as T.140 text (moved here from ast_sendtext() */
memset(&f, 0, sizeof(f));
- f.frametype = AST_FRAME_TEXT;
f.src = "DIALPLAN";
- f.mallocd = AST_MALLOCD_DATA;
- f.datalen = strlen(text);
- f.data.ptr = ast_strdup(text);
f.subclass.format = ast_format_t140;
-
+ f.frametype = AST_FRAME_TEXT;
+ f.datalen = body_len;
+ f.mallocd = AST_MALLOCD_DATA;
+ f.data.ptr = ast_strdup(body);
if (f.data.ptr) {
res = ast_channel_tech(chan)->write_text(chan, &f);
- ast_frfree(&f);
+ } else {
+ res = -1;
}
- } else if (ast_channel_tech(chan)->send_text) {
- res = ast_channel_tech(chan)->send_text(chan, text);
+ ast_frfree(&f);
+ } else if ((ast_channel_tech(chan)->properties & AST_CHAN_TP_SEND_TEXT_DATA)
+ && ast_channel_tech(chan)->send_text_data) {
+ /* Send enhanced message to a channel driver that supports it */
+ ast_debug(1, "Sending TEXT_DATA from '%s' to %s:%s %s\n",
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_FROM),
+ ast_msg_data_get_attribute(msg, AST_MSG_DATA_ATTR_TO),
+ ast_channel_name(chan), body);
+ res = ast_channel_tech(chan)->send_text_data(chan, msg);
+ } else if (ast_channel_tech(chan)->send_text
+ && (ast_strlen_zero(content_type) || strcasecmp(content_type, "text/plain") == 0)) {
+ /* Send the body of an enhanced message to a channel driver that supports only a char str */
+ ast_debug(1, "Sending TEXT to %s: %s\n", ast_channel_name(chan), body);
+ res = ast_channel_tech(chan)->send_text(chan, body);
+ } else {
+ ast_debug(1, "Channel technology does not support sending text on channel '%s'\n",
+ ast_channel_name(chan));
+ res = -1;
}
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);
ast_channel_unlock(chan);
return res;
}
+int ast_sendtext(struct ast_channel *chan, const char *text)
+{
+ struct ast_msg_data *msg;
+ int rc;
+ struct ast_msg_data_attribute attrs[] =
+ {
+ {
+ .type = AST_MSG_DATA_ATTR_BODY,
+ .value = (char *)text,
+ }
+ };
+
+ if (ast_strlen_zero(text)) {
+ return 0;
+ }
+
+ msg = ast_msg_data_alloc(AST_MSG_DATA_SOURCE_TYPE_UNKNOWN, attrs, ARRAY_LEN(attrs));
+ if (!msg) {
+ return -1;
+ }
+ rc = ast_sendtext_data(chan, msg);
+ ast_free(msg);
+
+ return rc;
+}
+
int ast_senddigit_begin(struct ast_channel *chan, char digit)
{
/* Device does not support DTMF tones, lets fake
diff --git a/main/frame.c b/main/frame.c
index dd47f42d0..383571f65 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -593,6 +593,9 @@ void ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
case AST_FRAME_TEXT:
ast_copy_string(ftype, "Text", len);
break;
+ case AST_FRAME_TEXT_DATA:
+ ast_copy_string(ftype, "Text Data", len);
+ break;
case AST_FRAME_IMAGE:
ast_copy_string(ftype, "Image", len);
break;
diff --git a/main/message.c b/main/message.c
index ac7965ea7..b7d14f1e8 100644
--- a/main/message.c
+++ b/main/message.c
@@ -1348,6 +1348,148 @@ int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
return res;
}
+/*!
+ * \brief Structure used to transport a message through the frame core
+ * \since 13.22.0
+ * \since 15.5.0
+ */
+struct ast_msg_data {
+ /*! The length of this structure plus the actual length of the allocated buffer */
+ size_t length;
+ enum ast_msg_data_source_type source;
+ /*! These are indices into the buffer where teh attribute starts */
+ int attribute_value_offsets[__AST_MSG_DATA_ATTR_LAST];
+ /*! The buffer containing the NULL separated attributes */
+ char buf[0];
+};
+
+#define ATTRIBUTE_UNSET -1
+
+struct ast_msg_data *ast_msg_data_alloc(enum ast_msg_data_source_type source,
+ struct ast_msg_data_attribute attributes[], size_t count)
+{
+ struct ast_msg_data *msg;
+ size_t len = sizeof(*msg);
+ size_t i;
+ size_t current_offset = 0;
+ enum ast_msg_data_attribute_type attr_type;
+
+ if (!attributes) {
+ ast_assert(attributes != NULL);
+ return NULL;
+ }
+
+ if (!count) {
+ ast_assert(count > 0);
+ return NULL;
+ }
+
+ /* Calculate the length required for the buffer */
+ for (i=0; i < count; i++) {
+ if (!attributes[i].value) {
+ ast_assert(attributes[i].value != NULL);
+ return NULL;
+ }
+ len += (strlen(attributes[i].value) + 1);
+ }
+
+ msg = ast_calloc(1, len);
+ if (!msg) {
+ return NULL;
+ }
+ msg->source = source;
+ msg->length = len;
+
+ /* Mark all of the attributes as unset */
+ for (attr_type = 0; attr_type < __AST_MSG_DATA_ATTR_LAST; attr_type++) {
+ msg->attribute_value_offsets[attr_type] = ATTRIBUTE_UNSET;
+ }
+
+ /* Set the ones we have and increment the offset */
+ for (i=0; i < count; i++) {
+ len = (strlen(attributes[i].value) + 1);
+ strcpy(msg->buf + current_offset, attributes[i].value); /* Safe */
+ msg->attribute_value_offsets[attributes[i].type] = current_offset;
+ current_offset += len;
+ }
+
+ return msg;
+}
+
+struct ast_msg_data *ast_msg_data_dup(struct ast_msg_data *msg)
+{
+ struct ast_msg_data *dest;
+
+ if (!msg) {
+ ast_assert(msg != NULL);
+ return NULL;
+ }
+
+ dest = ast_malloc(msg->length);
+ if (!dest) {
+ return NULL;
+ }
+ memcpy(dest, msg, msg->length);
+
+ return dest;
+}
+
+size_t ast_msg_data_get_length(struct ast_msg_data *msg)
+{
+ if (!msg) {
+ ast_assert(msg != NULL);
+ return 0;
+ }
+
+ return msg->length;
+}
+
+enum ast_msg_data_source_type ast_msg_data_get_source_type(struct ast_msg_data *msg)
+{
+ if (!msg) {
+ ast_assert(msg != NULL);
+ return AST_MSG_DATA_SOURCE_TYPE_UNKNOWN;
+ }
+
+ return msg->source;
+}
+
+const char *ast_msg_data_get_attribute(struct ast_msg_data *msg,
+ enum ast_msg_data_attribute_type attribute_type)
+{
+ if (!msg) {
+ ast_assert(msg != NULL);
+ return "";
+ }
+
+ if (msg->attribute_value_offsets[attribute_type] > ATTRIBUTE_UNSET) {
+ return msg->buf + msg->attribute_value_offsets[attribute_type];
+ }
+
+ return "";
+}
+
+int ast_msg_data_queue_frame(struct ast_channel *channel, struct ast_msg_data *msg)
+{
+ struct ast_frame f;
+
+ if (!channel) {
+ ast_assert(channel != NULL);
+ return -1;
+ }
+
+ if (!msg) {
+ ast_assert(msg != NULL);
+ return -1;
+ }
+
+ memset(&f, 0, sizeof(f));
+ f.frametype = AST_FRAME_TEXT_DATA;
+ f.data.ptr = msg;
+ f.datalen = msg->length;
+ return ast_queue_frame(channel, &f);
+}
+
int ast_msg_tech_register(const struct ast_msg_tech *tech)
{
const struct ast_msg_tech *match;