aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/channel.c217
-rw-r--r--main/dial.c4
-rw-r--r--main/features.c13
-rw-r--r--main/rtp_engine.c20
4 files changed, 234 insertions, 20 deletions
diff --git a/main/channel.c b/main/channel.c
index c91d60219..5850c89de 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1528,6 +1528,8 @@ static void free_cid(struct ast_callerid *cid)
ast_free(cid->cid_name);
if (cid->cid_ani)
ast_free(cid->cid_ani);
+ if (cid->cid_tag)
+ ast_free(cid->cid_tag);
cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = NULL;
ast_party_subaddress_free(&cid->subaddress);
ast_party_subaddress_free(&cid->dialed_subaddress);
@@ -1611,6 +1613,7 @@ static void ast_party_id_init(struct ast_party_id *init)
{
init->number = NULL;
init->name = NULL;
+ init->tag = NULL;
init->number_type = 0; /* Unknown */
init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
ast_party_subaddress_init(&init->subaddress);
@@ -1642,6 +1645,11 @@ static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_
}
dest->name = ast_strdup(src->name);
+ if (dest->tag) {
+ ast_free(dest->tag);
+ }
+ dest->tag = ast_strdup(src->tag);
+
dest->number_type = src->number_type;
dest->number_presentation = src->number_presentation;
ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
@@ -1668,6 +1676,7 @@ static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_pa
{
init->number = NULL;
init->name = NULL;
+ init->tag = NULL;
init->number_type = guide->number_type;
init->number_presentation = guide->number_presentation;
ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
@@ -1703,6 +1712,13 @@ static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_i
dest->number = ast_strdup(src->number);
}
+ if (src->tag && src->tag != dest->tag) {
+ if (dest->tag) {
+ ast_free(dest->tag);
+ }
+ dest->tag = ast_strdup(src->tag);
+ }
+
dest->number_type = src->number_type;
dest->number_presentation = src->number_presentation;
ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
@@ -1727,6 +1743,11 @@ static void ast_party_id_free(struct ast_party_id *doomed)
ast_free(doomed->name);
doomed->name = NULL;
}
+
+ if (doomed->tag) {
+ ast_free(doomed->tag);
+ doomed->tag = NULL;
+ }
ast_party_subaddress_free(&doomed->subaddress);
}
@@ -1758,6 +1779,11 @@ void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid
}
dest->cid_name = ast_strdup(src->cid_name);
+ if (dest->cid_tag) {
+ ast_free(dest->cid_tag);
+ }
+ dest->cid_tag = ast_strdup(src->cid_tag);
+
dest->cid_ton = src->cid_ton;
dest->cid_pres = src->cid_pres;
@@ -1843,6 +1869,7 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co
connected->id.name = cid->cid_name;
connected->id.number_type = cid->cid_ton;
connected->id.number_presentation = cid->cid_pres;
+ connected->id.tag = cid->cid_tag;
connected->id.subaddress = cid->subaddress;
connected->ani = cid->cid_ani;
@@ -3354,6 +3381,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
if (f) {
struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq);
+ struct ast_control_read_action_payload *read_action_payload;
+ struct ast_party_connected_line connected;
/* if the channel driver returned more than one frame, stuff the excess
into the readq for the next ast_read call
@@ -3381,6 +3410,23 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
/* removed a call to ast_cdr_answer(chan->cdr) from here. */
ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL);
}
+ } else if (f->subclass.integer == AST_CONTROL_READ_ACTION) {
+ ast_party_connected_line_init(&connected);
+ read_action_payload = f->data.ptr;
+ switch (read_action_payload->action) {
+ case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO:
+ if (ast_connected_line_parse_data(read_action_payload->payload,
+ read_action_payload->payload_size, &connected)) {
+ break;
+ }
+ if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) {
+ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE,
+ read_action_payload->payload, read_action_payload->payload_size);
+ }
+ break;
+ }
+ ast_frfree(f);
+ f = &ast_null_frame;
}
break;
case AST_FRAME_DTMF_END:
@@ -3606,6 +3652,25 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
* and synchronous generation of outgoing frames is necessary */
ast_read_generator_actions(chan, f);
}
+ break;
+ case AST_CONTROL_READ_ACTION:
+ ast_log(LOG_NOTICE, "Read a read action frame\n");
+ read_action_payload = f->data.ptr;
+ switch (read_action_payload->action) {
+ case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO:
+ if (ast_connected_line_parse_data(read_action_payload->payload,
+ read_action_payload->payload_size, &connected)) {
+ break;
+ }
+ if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) {
+ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE,
+ read_action_payload->payload, read_action_payload->payload_size);
+ }
+ break;
+ }
+ ast_frfree(f);
+ f = &ast_null_frame;
+ break;
default:
/* Just pass it on! */
break;
@@ -3679,6 +3744,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
case AST_CONTROL_T38_PARAMETERS:
case _XXX_AST_CONTROL_T38:
case AST_CONTROL_CC:
+ case AST_CONTROL_READ_ACTION:
break;
case AST_CONTROL_CONGESTION:
@@ -3823,6 +3889,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
case AST_CONTROL_CONNECTED_LINE:
case AST_CONTROL_REDIRECTING:
case AST_CONTROL_CC:
+ case AST_CONTROL_READ_ACTION:
/* Nothing left to do for these. */
res = 0;
break;
@@ -5794,7 +5861,9 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
switch (f->subclass.integer) {
case AST_CONTROL_REDIRECTING:
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
+ if (ast_channel_redirecting_macro(who, other, f, other == c0, 1)) {
+ ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
+ }
break;
case AST_CONTROL_CONNECTED_LINE:
if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
@@ -6781,6 +6850,11 @@ void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest,
}
dest->id.name = ast_strdup(src->cid_name);
+ if (dest->id.tag) {
+ ast_free(dest->id.tag);
+ }
+ dest->id.tag = ast_strdup(src->cid_tag);
+
dest->id.number_type = src->cid_ton;
dest->id.number_presentation = src->cid_pres;
@@ -6823,6 +6897,11 @@ void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct a
}
dest->cid_name = ast_strdup(src->id.name);
+ if (dest->cid_tag) {
+ ast_free(dest->cid_tag);
+ }
+ dest->cid_tag = ast_strdup(src->id.tag);
+
dest->cid_ton = src->id.number_type;
dest->cid_pres = src->id.number_presentation;
@@ -6876,7 +6955,8 @@ enum {
AST_CONNECTED_LINE_SUBADDRESS,
AST_CONNECTED_LINE_SUBADDRESS_TYPE,
AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
- AST_CONNECTED_LINE_SUBADDRESS_VALID
+ AST_CONNECTED_LINE_SUBADDRESS_VALID,
+ AST_CONNECTED_LINE_TAG,
};
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
@@ -6915,6 +6995,18 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str
pos += length;
}
+ if (connected->id.tag) {
+ length = strlen(connected->id.tag);
+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+ ast_log(LOG_WARNING, "No space left for connected line tag\n");
+ return -1;
+ }
+ data[pos++] = AST_CONNECTED_LINE_TAG;
+ data[pos++] = length;
+ memcpy(data + pos, connected->id.tag, length);
+ pos += length;
+ }
+
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING, "No space left for connected line type of number\n");
return -1;
@@ -7025,6 +7117,16 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
connected->id.name[ie_len] = 0;
}
break;
+ case AST_CONNECTED_LINE_TAG:
+ if (connected->id.tag) {
+ ast_free(connected->id.tag);
+ }
+ connected->id.tag = ast_malloc(ie_len + 1);
+ if (connected->id.tag) {
+ memcpy(connected->id.tag, data + pos, ie_len);
+ connected->id.tag[ie_len] = 0;
+ }
+ break;
case AST_CONNECTED_LINE_NUMBER_TYPE:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid connected line type of number (%u)\n", (unsigned) ie_len);
@@ -7156,7 +7258,9 @@ enum {
AST_REDIRECTING_TO_SUBADDRESS,
AST_REDIRECTING_TO_SUBADDRESS_TYPE,
AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN,
- AST_REDIRECTING_TO_SUBADDRESS_VALID
+ AST_REDIRECTING_TO_SUBADDRESS_VALID,
+ AST_REDIRECTING_FROM_TAG,
+ AST_REDIRECTING_TO_TAG,
};
int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
@@ -7195,6 +7299,18 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
pos += length;
}
+ if (redirecting->from.tag) {
+ length = strlen(redirecting->from.tag);
+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+ ast_log(LOG_WARNING, "No space left for redirecting from name\n");
+ return -1;
+ }
+ data[pos++] = AST_REDIRECTING_FROM_TAG;
+ data[pos++] = length;
+ memcpy(data + pos, redirecting->from.tag, length);
+ pos += length;
+ }
+
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING, "No space left for redirecting from type of number\n");
return -1;
@@ -7274,6 +7390,18 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
pos += length;
}
+ if (redirecting->to.tag) {
+ length = strlen(redirecting->to.tag);
+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+ ast_log(LOG_WARNING, "No space left for redirecting to name\n");
+ return -1;
+ }
+ data[pos++] = AST_REDIRECTING_TO_TAG;
+ data[pos++] = length;
+ memcpy(data + pos, redirecting->to.tag, length);
+ pos += length;
+ }
+
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING, "No space left for redirecting to type of number\n");
return -1;
@@ -7393,6 +7521,16 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
redirecting->from.name[ie_len] = 0;
}
break;
+ case AST_REDIRECTING_FROM_TAG:
+ if (redirecting->from.tag) {
+ ast_free(redirecting->from.tag);
+ }
+ redirecting->from.tag = ast_malloc(ie_len + 1);
+ if (redirecting->from.tag) {
+ memcpy(redirecting->from.tag, data + pos, ie_len);
+ redirecting->from.tag[ie_len] = 0;
+ }
+ break;
case AST_REDIRECTING_FROM_NUMBER_TYPE:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid redirecting from type of number (%u)\n", (unsigned) ie_len);
@@ -7462,6 +7600,16 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
redirecting->to.name[ie_len] = 0;
}
break;
+ case AST_REDIRECTING_TO_TAG:
+ if (redirecting->to.tag) {
+ ast_free(redirecting->to.tag);
+ }
+ redirecting->to.tag = ast_malloc(ie_len + 1);
+ if (redirecting->to.tag) {
+ memcpy(redirecting->to.tag, data + pos, ie_len);
+ redirecting->to.tag[ie_len] = 0;
+ }
+ break;
case AST_REDIRECTING_TO_NUMBER_TYPE:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid redirecting to type of number (%u)\n", (unsigned) ie_len);
@@ -7562,39 +7710,72 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
}
-int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
+int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame)
{
const char *macro;
const char *macro_args;
- union {
- const struct ast_frame *frame;
- const struct ast_party_connected_line *connected;
- } pointer;
int retval;
- if (frame) {
- pointer.frame = connected_info;
+ ast_channel_lock(macro_chan);
+ macro = pbx_builtin_getvar_helper(macro_chan, is_caller
+ ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO");
+ macro = ast_strdupa(S_OR(macro, ""));
+ macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller
+ ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARSG" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS");
+ macro_args = ast_strdupa(S_OR(macro_args, ""));
+ ast_channel_unlock(macro_chan);
+
+ if (ast_strlen_zero(macro)) {
+ return -1;
+ }
+
+ if (is_frame) {
+ const struct ast_frame *frame = connected_info;
+ ast_connected_line_parse_data(frame->data.ptr, frame->datalen, &macro_chan->connected);
} else {
- pointer.connected = connected_info;
+ const struct ast_party_connected_line *connected = connected_info;
+ ast_party_connected_line_copy(&macro_chan->connected, connected);
}
+ if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
+ ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
+ }
+
+ return retval;
+}
+
+int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
+{
+ const char *macro;
+ const char *macro_args;
+ int retval;
+
ast_channel_lock(macro_chan);
- macro = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"), ""));
- macro_args = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"), ""));
+ macro = pbx_builtin_getvar_helper(macro_chan, is_caller
+ ? "REDIRECTING_CALLER_SEND_MACRO" : "REDIRECTING_CALLEE_SEND_MACRO");
+ macro = ast_strdupa(S_OR(macro, ""));
+ macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller
+ ? "REDIRECTING_CALLER_SEND_MACRO_ARGS" : "REDIRECTING_CALLEE_SEND_MACRO_ARGS");
+ macro_args = ast_strdupa(S_OR(macro_args, ""));
ast_channel_unlock(macro_chan);
if (ast_strlen_zero(macro)) {
return -1;
}
- if (frame) {
- ast_connected_line_parse_data(pointer.frame->data.ptr, pointer.frame->datalen, &macro_chan->connected);
+ if (is_frame) {
+ const struct ast_frame *frame = redirecting_info;
+
+ ast_redirecting_parse_data(frame->data.ptr, frame->datalen, &macro_chan->redirecting);
} else {
- ast_party_connected_line_copy(&macro_chan->connected, pointer.connected);
+ const struct ast_party_redirecting *redirecting = redirecting_info;
+
+ ast_party_redirecting_copy(&macro_chan->redirecting, redirecting);
}
- if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
- ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
+ retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
+ if (!retval) {
+ ast_channel_update_redirecting(macro_chan, &macro_chan->redirecting);
}
return retval;
diff --git a/main/dial.c b/main/dial.c
index 7435d926c..bfd0c44a4 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -426,7 +426,9 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
break;
case AST_CONTROL_REDIRECTING:
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
+ if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
+ ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
+ }
break;
case AST_CONTROL_PROCEEDING:
ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
diff --git a/main/features.c b/main/features.c
index 0a26ad1c0..72a626e45 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2728,6 +2728,10 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
}
+ } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
+ if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
+ ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ }
} else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) {
ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
}
@@ -3196,7 +3200,14 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
break;
}
- /* The implied "else" falls through purposely */
+ ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
+ break;
+ case AST_CONTROL_REDIRECTING:
+ if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
+ break;
+ }
+ ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
+ break;
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 88f534614..0027b04ee 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -887,6 +887,16 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
}
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
+ if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
+ if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ ast_frfree(fr);
} else {
*fo = fr;
*rc = who;
@@ -1113,6 +1123,16 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
}
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
+ if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
+ if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ }
+ ast_frfree(fr);
} else {
*fo = fr;
*rc = who;