diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 217 | ||||
-rw-r--r-- | main/dial.c | 4 | ||||
-rw-r--r-- | main/features.c | 13 | ||||
-rw-r--r-- | main/rtp_engine.c | 20 |
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, ¯o_chan->connected); } else { - pointer.connected = connected_info; + const struct ast_party_connected_line *connected = connected_info; + ast_party_connected_line_copy(¯o_chan->connected, connected); } + if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) { + ast_channel_update_connected_line(macro_chan, ¯o_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, ¯o_chan->connected); + if (is_frame) { + const struct ast_frame *frame = redirecting_info; + + ast_redirecting_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->redirecting); } else { - ast_party_connected_line_copy(¯o_chan->connected, pointer.connected); + const struct ast_party_redirecting *redirecting = redirecting_info; + + ast_party_redirecting_copy(¯o_chan->redirecting, redirecting); } - if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) { - ast_channel_update_connected_line(macro_chan, ¯o_chan->connected); + retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); + if (!retval) { + ast_channel_update_redirecting(macro_chan, ¯o_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; |