diff options
Diffstat (limited to 'extra/asterisk/asterisk-07-issue14068.patch')
-rw-r--r-- | extra/asterisk/asterisk-07-issue14068.patch | 1423 |
1 files changed, 1423 insertions, 0 deletions
diff --git a/extra/asterisk/asterisk-07-issue14068.patch b/extra/asterisk/asterisk-07-issue14068.patch new file mode 100644 index 0000000000..49cad1681b --- /dev/null +++ b/extra/asterisk/asterisk-07-issue14068.patch @@ -0,0 +1,1423 @@ +Index: channels/chan_dahdi.c +=================================================================== +--- a/channels/chan_dahdi.c (.../trunk) (revision 186562) ++++ b/channels/chan_dahdi.c (.../team/group/issue14068) (revision 186562) +@@ -3096,6 +3096,196 @@ + } + #endif /* defined(HAVE_SS7) */ + ++#if defined(HAVE_PRI) ++static enum AST_REDIRECTING_REASON pri_to_ast_reason(int pri_reason) ++{ ++ enum AST_REDIRECTING_REASON ast_reason; ++ ++ switch (pri_reason) { ++ case PRI_REDIR_FORWARD_ON_BUSY: ++ ast_reason = AST_REDIRECTING_REASON_USER_BUSY; ++ break; ++ case PRI_REDIR_FORWARD_ON_NO_REPLY: ++ ast_reason = AST_REDIRECTING_REASON_NO_ANSWER; ++ break; ++ case PRI_REDIR_DEFLECTION: ++ ast_reason = AST_REDIRECTING_REASON_DEFLECTION; ++ break; ++ case PRI_REDIR_UNCONDITIONAL: ++ ast_reason = AST_REDIRECTING_REASON_UNCONDITIONAL; ++ break; ++ case PRI_REDIR_UNKNOWN: ++ default: ++ ast_reason = AST_REDIRECTING_REASON_UNKNOWN; ++ break; ++ } /* end switch */ ++ ++ return ast_reason; ++} ++#endif /* defined(HAVE_PRI) */ ++ ++#if defined(HAVE_PRI) ++static int ast_to_pri_reason(enum AST_REDIRECTING_REASON ast_reason) ++{ ++ int pri_reason; ++ ++ switch (ast_reason) { ++ case AST_REDIRECTING_REASON_USER_BUSY: ++ pri_reason = PRI_REDIR_FORWARD_ON_BUSY; ++ break; ++ case AST_REDIRECTING_REASON_NO_ANSWER: ++ pri_reason = PRI_REDIR_FORWARD_ON_NO_REPLY; ++ break; ++ case AST_REDIRECTING_REASON_UNCONDITIONAL: ++ pri_reason = PRI_REDIR_UNCONDITIONAL; ++ break; ++ case AST_REDIRECTING_REASON_DEFLECTION: ++ pri_reason = PRI_REDIR_DEFLECTION; ++ break; ++ case AST_REDIRECTING_REASON_UNKNOWN: ++ default: ++ pri_reason = PRI_REDIR_UNKNOWN; ++ break; ++ } /* end switch */ ++ ++ return pri_reason; ++} ++#endif /* defined(HAVE_PRI) */ ++ ++#if defined(HAVE_PRI) ++static int pri_to_ast_presentation(int pri_presentation) ++{ ++ int ast_presentation; ++ ++ switch (pri_presentation) { ++ case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: ++ ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; ++ break; ++ case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: ++ ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; ++ break; ++ case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: ++ ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN; ++ break; ++ case PRES_ALLOWED_NETWORK_NUMBER: ++ ast_presentation = AST_PRES_ALLOWED_NETWORK_NUMBER; ++ break; ++ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: ++ ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; ++ break; ++ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: ++ ast_presentation = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; ++ break; ++ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: ++ ast_presentation = AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN; ++ break; ++ case PRES_PROHIB_NETWORK_NUMBER: ++ ast_presentation = AST_PRES_PROHIB_NETWORK_NUMBER; ++ break; ++ case PRES_NUMBER_NOT_AVAILABLE: ++ ast_presentation = AST_PRES_NUMBER_NOT_AVAILABLE; ++ break; ++ default: ++ ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; /* ?? */ ++ break; ++ } /* end switch */ ++ ++ return ast_presentation; ++} ++#endif /* defined(HAVE_PRI) */ ++ ++#if defined(HAVE_PRI) ++static int ast_to_pri_presentation(int ast_presentation) ++{ ++ int pri_presentation; ++ ++ switch (ast_presentation) { ++ case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: ++ pri_presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; ++ break; ++ case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: ++ pri_presentation = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; ++ break; ++ case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: ++ pri_presentation = PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN; ++ break; ++ case AST_PRES_ALLOWED_NETWORK_NUMBER: ++ pri_presentation = PRES_ALLOWED_NETWORK_NUMBER; ++ break; ++ case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: ++ pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; ++ break; ++ case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: ++ pri_presentation = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; ++ break; ++ case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: ++ pri_presentation = PRES_PROHIB_USER_NUMBER_FAILED_SCREEN; ++ break; ++ case AST_PRES_PROHIB_NETWORK_NUMBER: ++ pri_presentation = PRES_PROHIB_NETWORK_NUMBER; ++ break; ++ case AST_PRES_NUMBER_NOT_AVAILABLE: ++ pri_presentation = PRES_NUMBER_NOT_AVAILABLE; ++ break; ++ default: ++ pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; /* ?? */ ++ break; ++ } /* end switch */ ++ ++ return pri_presentation; ++} ++#endif /* defined(HAVE_PRI) */ ++ ++#if defined(HAVE_PRI) ++static enum AST_CONNECTED_LINE_UPDATE_SOURCE pri_to_ast_connected_line_update_source(enum PRI_CONNECTED_LINE_UPDATE_SOURCE pri_source) ++{ ++ enum AST_CONNECTED_LINE_UPDATE_SOURCE ast_source; ++ ++ switch (pri_source) { ++ case PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER: ++ ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ++ break; ++ case PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER: ++ ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ++ break; ++ case PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING: ++ ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING; ++ break; ++ case PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN: ++ default: ++ ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; ++ break; ++ } /* end switch */ ++ ++ return ast_source; ++} ++#endif /* defined(HAVE_PRI) */ ++ ++#if defined(HAVE_PRI) ++static enum PRI_CONNECTED_LINE_UPDATE_SOURCE ast_to_pri_connected_line_update_source(enum AST_CONNECTED_LINE_UPDATE_SOURCE ast_source) ++{ ++ enum PRI_CONNECTED_LINE_UPDATE_SOURCE pri_source; ++ ++ switch (ast_source) { ++ case AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER: ++ pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ++ break; ++ case AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER: ++ pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ++ break; ++ case AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING: ++ pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING; ++ break; ++ case AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN: ++ default: ++ pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; ++ break; ++ } /* end switch */ ++ ++ return pri_source; ++} ++#endif /* defined(HAVE_PRI) */ ++ + static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) + { + struct dahdi_pvt *p = ast->tech_pvt; +@@ -3391,7 +3581,8 @@ + ast_mutex_unlock(&p->lock); + return -1; + } +-#ifdef HAVE_SS7 ++ ++#if defined(HAVE_SS7) + if (p->ss7) { + char ss7_called_nai; + int called_nai_strip; +@@ -3528,7 +3719,8 @@ + ast_setstate(ast, AST_STATE_DIALING); + ss7_rel(p->ss7); + } +-#endif /* HAVE_SS7 */ ++#endif /* defined(HAVE_SS7) */ ++ + #ifdef HAVE_OPENR2 + if (p->mfcr2) { + openr2_calling_party_category_t chancat; +@@ -3563,7 +3755,8 @@ + ast_setstate(ast, AST_STATE_DIALING); + } + #endif /* HAVE_OPENR2 */ +-#ifdef HAVE_PRI ++ ++#if defined(HAVE_PRI) + if (p->pri) { + struct pri_sr *sr; + #ifdef SUPPORT_USERUSER +@@ -3574,8 +3767,6 @@ + int prilocaldialplan; + int ldp_strip; + int exclusive; +- const char *rr_str; +- int redirect_reason; + + c = strchr(dest, '/'); + if (c) { +@@ -3804,20 +3995,10 @@ + } + pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, + p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); +- if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { +- if (!strcasecmp(rr_str, "UNKNOWN")) +- redirect_reason = 0; +- else if (!strcasecmp(rr_str, "BUSY")) +- redirect_reason = 1; +- else if (!strcasecmp(rr_str, "NO_REPLY")) +- redirect_reason = 2; +- else if (!strcasecmp(rr_str, "UNCONDITIONAL")) +- redirect_reason = 15; +- else +- redirect_reason = PRI_REDIR_UNCONDITIONAL; +- } else +- redirect_reason = PRI_REDIR_UNCONDITIONAL; +- pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); ++ pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, ast->redirecting.from.number_type, ++ ast->redirecting.from.number_presentation, ++ ast_to_pri_reason(ast->redirecting.reason)); ++ pri_sr_set_redirecting_name(sr, ast->redirecting.from.name); + + #ifdef SUPPORT_USERUSER + /* User-user info */ +@@ -3838,7 +4019,8 @@ + ast_setstate(ast, AST_STATE_DIALING); + pri_rel(p->pri); + } +-#endif ++#endif /* defined(HAVE_PRI) */ ++ + ast_mutex_unlock(&p->lock); + return 0; + } +@@ -7111,6 +7293,7 @@ + int res=-1; + int idx; + int func = DAHDI_FLASH; ++ + ast_mutex_lock(&p->lock); + idx = dahdi_get_index(chan, p, 0); + ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); +@@ -7345,6 +7528,65 @@ + case -1: + res = tone_zone_play_tone(p->subs[idx].dfd, -1); + break; ++ case AST_CONTROL_CONNECTED_LINE: ++ ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", chan->name); ++#if defined(HAVE_PRI) ++ if (p->pri) { ++ struct pri_party_connected_line connected; ++ ++ if (chan->connected.id.number) { ++ ast_copy_string(connected.id.number, chan->connected.id.number, sizeof(connected.id.number)); ++ } else { ++ connected.id.number[0] = '\0'; ++ } ++ if (chan->connected.id.name) { ++ ast_copy_string(connected.id.name, chan->connected.id.name, sizeof(connected.id.name)); ++ } else { ++ connected.id.name[0] = '\0'; ++ } ++ connected.id.number_type = chan->connected.id.number_type; ++ connected.id.number_presentation = ast_to_pri_presentation(chan->connected.id.number_presentation); ++ connected.source = ast_to_pri_connected_line_update_source(chan->connected.source); ++ pri_connected_line_update(p->pri->pri, p->call, &connected); ++ } ++#endif /* defined(HAVE_PRI) */ ++ break; ++ case AST_CONTROL_REDIRECTING: ++ ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", chan->name); ++#if defined(HAVE_PRI) ++ if (p->pri) { ++ struct pri_party_redirecting redirecting; ++ ++ if (chan->cid.cid_rdnis) { ++ ast_copy_string(redirecting.from.number, chan->cid.cid_rdnis, sizeof(redirecting.from.number)); ++ } else { ++ redirecting.from.number[0] = '\0'; ++ } ++ if (chan->redirecting.from.name) { ++ ast_copy_string(redirecting.from.name, chan->redirecting.from.name, sizeof(redirecting.from.name)); ++ } else { ++ redirecting.from.name[0] = '\0'; ++ } ++ redirecting.from.number_type = chan->redirecting.from.number_type; ++ redirecting.from.number_presentation = ast_to_pri_presentation(chan->redirecting.from.number_presentation); ++ if (chan->redirecting.to.number) { ++ ast_copy_string(redirecting.to.number, chan->redirecting.to.number, sizeof(redirecting.to.number)); ++ } else { ++ redirecting.to.number[0] = '\0'; ++ } ++ if (chan->redirecting.to.name) { ++ ast_copy_string(redirecting.to.name, chan->redirecting.to.name, sizeof(redirecting.to.name)); ++ } else { ++ redirecting.to.name[0] = '\0'; ++ } ++ redirecting.to.number_type = chan->redirecting.to.number_type; ++ redirecting.to.number_presentation = ast_to_pri_presentation(chan->redirecting.to.number_presentation); ++ redirecting.count = chan->redirecting.count; ++ redirecting.reason = ast_to_pri_reason(chan->redirecting.reason); ++ pri_redirecting_update(p->pri->pri, p->call, &redirecting); ++ } ++#endif /* defined(HAVE_PRI) */ ++ break; + } + } else + res = 0; +@@ -12607,17 +12849,17 @@ + if (chanpos > -1) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ +- if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { ++ if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) ++ && pri->pvts[chanpos]->call == e->digit.call ++ && pri->pvts[chanpos]->owner) { + /* how to do that */ + int digitlen = strlen(e->digit.digits); +- char digit; + int i; ++ + for (i = 0; i < digitlen; i++) { +- digit = e->digit.digits[i]; +- { +- struct ast_frame f = { AST_FRAME_DTMF, digit, }; +- dahdi_queue_frame(pri->pvts[chanpos], &f, pri); +- } ++ struct ast_frame f = { AST_FRAME_DTMF, e->digit.digits[i], }; ++ ++ dahdi_queue_frame(pri->pvts[chanpos], &f, pri); + } + } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); +@@ -12635,17 +12877,40 @@ + if (chanpos > -1) { + ast_mutex_lock(&pri->pvts[chanpos]->lock); + /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ +- if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { ++ if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) ++ && pri->pvts[chanpos]->call == e->ring.call ++ && pri->pvts[chanpos]->owner) { + /* how to do that */ + int digitlen = strlen(e->ring.callednum); +- char digit; + int i; ++ + for (i = 0; i < digitlen; i++) { +- digit = e->ring.callednum[i]; +- { +- struct ast_frame f = { AST_FRAME_DTMF, digit, }; +- dahdi_queue_frame(pri->pvts[chanpos], &f, pri); ++ struct ast_frame f = { AST_FRAME_DTMF, e->ring.callednum[i], }; ++ ++ dahdi_queue_frame(pri->pvts[chanpos], &f, pri); ++ } ++ if (pri->pvts[chanpos]->owner) { ++ char dnid[AST_MAX_EXTENSION]; ++ ++ /* ++ * Append the received info digits to the end of ++ * the exten and dnid strings ++ */ ++ strncat(pri->pvts[chanpos]->owner->exten, ++ e->ring.callednum, ++ sizeof(pri->pvts[chanpos]->owner->exten) - 1 ++ - strlen(pri->pvts[chanpos]->owner->exten)); ++ if (pri->pvts[chanpos]->owner->cid.cid_dnid) { ++ ast_copy_string(dnid, ++ pri->pvts[chanpos]->owner->cid.cid_dnid, ++ sizeof(dnid)); ++ ast_free(pri->pvts[chanpos]->owner->cid.cid_dnid); ++ } else { ++ dnid[0] = 0; + } ++ strncat(dnid, e->ring.callednum, ++ sizeof(dnid) - 1 - strlen(dnid)); ++ pri->pvts[chanpos]->owner->cid.cid_dnid = ast_strdup(dnid); + } + } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); +@@ -12683,6 +12948,7 @@ + if ((chanpos < 0) && (e->ring.flexible)) + chanpos = pri_find_empty_chan(pri, 1); + if (chanpos > -1) { ++ struct ast_party_redirecting redirecting = {{0,},}; + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->switchtype == PRI_SWITCH_GR303_TMC) { + /* Should be safe to lock CRV AFAIK while bearer is still locked */ +@@ -12704,6 +12970,17 @@ + break; + } + } ++ if (e->ring.redirectingnum[0] || e->ring.redirectingname[0]) { ++ redirecting.to.number = e->ring.callednum; ++ redirecting.to.number_type = e->ring.calledplan; ++ redirecting.to.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; ++ redirecting.from.name = e->ring.redirectingname; ++ redirecting.from.number = e->ring.redirectingnum; ++ redirecting.from.number_presentation = e->ring.redirectingpres; ++ redirecting.from.number_type = e->ring.callingplanrdnis; ++ redirecting.reason = pri_to_ast_reason(e->ring.redirectingreason); ++ redirecting.count = e->ring.redirectingcount; ++ } + pri->pvts[chanpos]->call = e->ring.call; + apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); + if (pri->pvts[chanpos]->use_callerid) { +@@ -12789,7 +13066,9 @@ + pri->pvts[chanpos]->callingpres = e->ring.callingpres; + + /* Start PBX */ +- if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { ++ if (!e->ring.complete ++ && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) ++ && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { + /* Release the PRI lock while we create the channel */ + ast_mutex_unlock(&pri->lock); + if (crv) { +@@ -12804,6 +13083,9 @@ + + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + ++ if (c && (redirecting.from.number || redirecting.from.name)) { ++ ast_channel_update_redirecting(c, &redirecting); ++ } + if (!ast_strlen_zero(e->ring.callingsubaddr)) { + pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); + } +@@ -12821,8 +13103,10 @@ + + snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); + pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); +- if (e->ring.redirectingreason >= 0) ++ if (e->ring.redirectingreason >= 0) { ++ /* This is now just a status variable. Use REDIRECTING() dialplan function. */ + pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); ++ } + + ast_mutex_lock(&pri->pvts[chanpos]->lock); + ast_mutex_lock(&pri->lock); +@@ -12849,6 +13133,9 @@ + + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + ++ if (redirecting.from.number || redirecting.from.name) { ++ ast_channel_update_redirecting(c, &redirecting); ++ } + if (e->ring.ani2 >= 0) { + snprintf(ani2str, 5, "%d", e->ring.ani2); + pbx_builtin_setvar_helper(c, "ANI2", ani2str); +@@ -12861,8 +13148,10 @@ + } + #endif + +- if (e->ring.redirectingreason >= 0) ++ if (e->ring.redirectingreason >= 0) { ++ /* This is now just a status variable. Use REDIRECTING() dialplan function. */ + pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); ++ } + + snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); + pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); +@@ -12946,6 +13235,19 @@ + } + #endif + ++ if ((e->ringing.calledname[0] || e->ringing.callednum[0]) && pri->pvts[chanpos]->owner) { ++ struct ast_party_connected_line connected; ++ ++ /* Update the connected line information on the other channel */ ++ ast_party_connected_line_init(&connected); ++ connected.id.name = e->ringing.calledname; ++ connected.id.number = e->ringing.callednum; ++ connected.id.number_type = e->ringing.calledplan; ++ connected.id.number_presentation = pri_to_ast_presentation(e->ringing.calledpres); ++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ++ ast_channel_queue_connected_line_update(pri->pvts[chanpos]->owner, &connected); ++ } ++ + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + } + } +@@ -13050,12 +13352,85 @@ + ast_mutex_lock(&pri->pvts[chanpos]->lock); + ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); + ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); +- pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; ++ pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1; + dahdi_enable_ec(pri->pvts[chanpos]); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + } + } + break; ++ case PRI_EVENT_FACILITY: ++ chanpos = pri_find_principle(pri, e->facility.channel); ++ if (chanpos < 0) { ++ ast_log(LOG_WARNING, "Facility requested on unconfigured channel %d/%d span %d\n", ++ PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span); ++ } else { ++ chanpos = pri_fixup_principle(pri, chanpos, e->facility.call); ++ if (chanpos < 0) { ++ ast_log(LOG_WARNING, "Facility requested on channel %d/%d not in use on span %d\n", ++ PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span); ++ } else { ++ int i; ++ ++ ast_mutex_lock(&pri->pvts[chanpos]->lock); ++ for (i = 0; i < e->facility.subcmds.counter_subcmd; i++) { ++ struct subcommand *subcmd = &e->facility.subcmds.subcmd[i]; ++ struct ast_channel *owner; ++ ++ switch (subcmd->cmd) { ++ case CMD_CONNECTEDLINE: ++ owner = pri->pvts[chanpos]->owner; ++ if (owner) { ++ struct ast_party_connected_line connected; ++ struct cmd_connectedline *cmdcl; ++ ++ /* Update the connected line information on the other channel */ ++ ast_party_connected_line_init(&connected); ++ cmdcl = &subcmd->connectedline; ++ connected.id.number = cmdcl->connected.id.number; ++ connected.id.name = cmdcl->connected.id.name; ++ connected.id.number_type = cmdcl->connected.id.number_type; ++ connected.id.number_presentation = pri_to_ast_presentation(cmdcl->connected.id.number_presentation); ++ connected.source = pri_to_ast_connected_line_update_source(cmdcl->connected.source); ++ ast_channel_queue_connected_line_update(owner, &connected); ++ ++ ast_copy_string(pri->pvts[chanpos]->lastcid_num, cmdcl->connected.id.number, sizeof(pri->pvts[chanpos]->lastcid_num)); ++ ast_copy_string(pri->pvts[chanpos]->lastcid_name, cmdcl->connected.id.name, sizeof(pri->pvts[chanpos]->lastcid_name)); ++ ++ pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1; ++ //dahdi_enable_ec(pri->pvts[chanpos]); ++ } ++ break; ++ case CMD_REDIRECTING: ++ owner = pri->pvts[chanpos]->owner; ++ if (owner) { ++ struct ast_party_redirecting redirecting = {{0,},}; ++ struct cmd_redirecting *cmdr; ++ ++ cmdr = &subcmd->redirecting; ++ redirecting.from.number = cmdr->redirecting.from.number; ++ redirecting.from.name = cmdr->redirecting.from.name; ++ redirecting.from.number_type = cmdr->redirecting.from.number_type; ++ redirecting.from.number_presentation = pri_to_ast_presentation(cmdr->redirecting.from.number_presentation); ++ redirecting.to.number = cmdr->redirecting.to.number; ++ redirecting.to.name = cmdr->redirecting.to.name; ++ redirecting.to.number_type = cmdr->redirecting.to.number_type; ++ redirecting.to.number_presentation = pri_to_ast_presentation(cmdr->redirecting.to.number_presentation); ++ redirecting.count = 0; ++ redirecting.reason = pri_to_ast_reason(cmdr->redirecting.reason); ++ ast_channel_queue_redirecting_update(owner, &redirecting); ++ } ++ break; ++ default: ++ ast_log(LOG_WARNING, ++ "Illegal subcommand %d in facility request on channel %d/%d not in use on span %d\n", ++ subcmd->cmd, PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span); ++ break; ++ } ++ } ++ ast_mutex_unlock(&pri->pvts[chanpos]->lock); ++ } ++ } ++ break; + case PRI_EVENT_ANSWER: + chanpos = pri_find_principle(pri, e->answer.channel); + if (chanpos < 0) { +@@ -13067,6 +13442,9 @@ + ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", + PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); + } else { ++ struct ast_party_connected_line connected; ++ struct ast_channel *owner; ++ + ast_mutex_lock(&pri->pvts[chanpos]->lock); + /* Now we can do call progress detection */ + +@@ -13105,15 +13483,26 @@ + dahdi_enable_ec(pri->pvts[chanpos]); + } + ++ owner = pri->pvts[chanpos]->owner; + #ifdef SUPPORT_USERUSER + if (!ast_strlen_zero(e->answer.useruserinfo)) { +- struct ast_channel *owner = pri->pvts[chanpos]->owner; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + } + #endif + ++ if (owner) { ++ /* Update the connected line information on the other channel */ ++ ast_party_connected_line_init(&connected); ++ connected.id.name = e->answer.connectedname; ++ connected.id.number = e->answer.connectednum; ++ connected.id.number_type = e->answer.connectedplan; ++ connected.id.number_presentation = pri_to_ast_presentation(e->answer.connectedpres); ++ connected.source = pri_to_ast_connected_line_update_source(e->answer.source); ++ ast_channel_queue_connected_line_update(owner, &connected); ++ } ++ + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + } + } +@@ -13152,6 +13541,7 @@ + break; + default: + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; ++ break; + } + } + } +Index: CHANGES +=================================================================== +--- a/CHANGES (.../trunk) (revision 186562) ++++ b/CHANGES (.../team/group/issue14068) (revision 186562) +@@ -55,6 +55,10 @@ + received number from the ISDN link if that number has the corresponding + Type-Of-Number. + ++libpri channel driver (chan_dahdi) changes ++------------------------------------------- ++ * The channel variable PRIREDIRECTREASON is now just a status variable. ++ Use the REDIRECTING(reason) dialplan function to alter the reason. + + SIP channel driver (chan_sip) changes + ------------------------------------------- +Index: funcs/func_redirecting.c +=================================================================== +--- a/funcs/func_redirecting.c (.../trunk) (revision 0) ++++ b/funcs/func_redirecting.c (.../team/group/issue14068) (revision 186562) +@@ -0,0 +1,474 @@ ++/* ++ * Asterisk -- An open source telephony toolkit. ++ * ++ * Copyright (C) 2008 Digium, Inc. ++ * ++ * Richard Mudgett <rmudgett@digium.com> ++ * ++ * See http://www.asterisk.org for more information about ++ * the Asterisk project. Please do not directly contact ++ * any of the maintainers of this project for assistance; ++ * the project provides a web site, mailing lists and IRC ++ * channels for your use. ++ * ++ * This program is free software, distributed under the terms of ++ * the GNU General Public License Version 2. See the LICENSE file ++ * at the top of the source tree. ++ */ ++ ++/*! ++ * \file ++ * \brief Redirecting data dialplan function ++ * \ingroup functions ++ * ++ * \author Richard Mudgett <rmudgett@digium.com> ++ * ++ * See Also: ++ * \arg \ref AstCREDITS ++ */ ++ ++ ++#include "asterisk.h" ++ ++ASTERISK_FILE_VERSION(__FILE__, "$Revision$") ++ ++/* ------------------------------------------------------------------- */ ++ ++ ++#include <stdlib.h> ++#include <stdio.h> ++#include <string.h> ++#include <sys/types.h> ++ ++#include "asterisk/module.h" ++#include "asterisk/channel.h" ++#include "asterisk/pbx.h" ++#include "asterisk/logger.h" ++#include "asterisk/utils.h" ++#include "asterisk/app.h" ++#include "asterisk/options.h" ++#include "asterisk/callerid.h" ++ ++/*** DOCUMENTATION ++ <function name="REDIRECTING" language="en_US"> ++ <synopsis> ++ Gets or sets Redirecting data on the channel. ++ </synopsis> ++ <syntax> ++ <parameter name="datatype" required="true"> ++ <para>The allowable datatypes are:</para> ++ <enumlist> ++ <enum name = "from-all" /> ++ <enum name = "from-num" /> ++ <enum name = "from-name" /> ++ <enum name = "from-ton" /> ++ <enum name = "to-all" /> ++ <enum name = "to-num" /> ++ <enum name = "to-name" /> ++ <enum name = "to-ton" /> ++ <enum name = "pres" /> ++ <enum name = "reason" /> ++ <enum name = "count" /> ++ </enumlist> ++ </parameter> ++ <parameter name="i"> ++ <para>If set, this will prevent the channel from sending out protocol ++ messages because of the value being set</para> ++ </parameter> ++ </syntax> ++ <description> ++ <para>Gets or sets Redirecting data on the channel. The allowable values ++ for the <replaceable>reason</replaceable> field are the following:</para> ++ <enumlist> ++ <enum name = "unknown"><para>Unknown</para></enum> ++ <enum name = "cfb"><para>Call Forwarding Busy</para></enum> ++ <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum> ++ <enum name = "unavailable"><para>Callee is Unavailable</para></enum> ++ <enum name = "time_of_day"><para>Time of Day</para></enum> ++ <enum name = "dnd"><para>Do Not Disturb</para></enum> ++ <enum name = "deflection"><para>Call Deflection</para></enum> ++ <enum name = "follow_me"><para>Follow Me</para></enum> ++ <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum> ++ <enum name = "away"><para>Callee is Away</para></enum> ++ <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum> ++ <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum> ++ </enumlist> ++ </description> ++ </function> ++ ***/ ++ ++enum ID_FIELD_STATUS { ++ ID_FIELD_VALID, ++ ID_FIELD_INVALID, ++ ID_FIELD_UNKNOWN ++}; ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Read values from the party id struct. ++ * ++ * \param buf Buffer to fill with read value. ++ * \param len Length of the buffer ++ * \param data Remaining function datatype string ++ * ++ * \retval ID_FIELD_VALID on success. ++ * \retval ID_FIELD_UNKNOWN on unknown field name. ++ */ ++static enum ID_FIELD_STATUS redirecting_id_read(char *buf, size_t len, char *data, const struct ast_party_id *id) ++{ ++ enum ID_FIELD_STATUS status; ++ ++ status = ID_FIELD_VALID; ++ ++ if (!strncasecmp("all", data, 3)) { ++ snprintf(buf, len, "\"%s\" <%s>", ++ S_OR(id->name, ""), ++ S_OR(id->number, "")); ++ } else if (!strncasecmp("name", data, 4)) { ++ if (id->name) { ++ ast_copy_string(buf, id->name, len); ++ } ++ } else if (!strncasecmp("num", data, 3)) { ++ if (id->number) { ++ ast_copy_string(buf, id->number, len); ++ } ++ } else if (!strncasecmp("ton", data, 3)) { ++ snprintf(buf, len, "%d", id->number_type); ++ } else if (!strncasecmp("pres", data, 4)) { ++ ast_copy_string(buf, ast_named_caller_presentation(id->number_presentation), len); ++ } else { ++ status = ID_FIELD_UNKNOWN; ++ } ++ ++ return status; ++} ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Read values from the redirecting information struct. ++ * ++ * \param chan Asterisk channel to read ++ * \param cmd Not used ++ * \param data Redirecting function datatype string ++ * \param buf Buffer to fill with read value. ++ * \param len Length of the buffer ++ * ++ * \retval 0 on success. ++ * \retval -1 on error. ++ */ ++static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) ++{ ++ /* Ensure that the buffer is empty */ ++ *buf = 0; ++ ++ if (!chan) ++ return -1; ++ ++ ast_channel_lock(chan); ++ ++ if (!strncasecmp("from-", data, 5)) { ++ struct ast_party_id from_id; ++ ++ from_id = chan->redirecting.from; ++ from_id.number = chan->cid.cid_rdnis; ++ switch (redirecting_id_read(buf, len, data + 5, &from_id)) { ++ case ID_FIELD_VALID: ++ case ID_FIELD_INVALID: ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ break; ++ } ++ } else if (!strncasecmp("to-", data, 3)) { ++ switch (redirecting_id_read(buf, len, data + 3, &chan->redirecting.to)) { ++ case ID_FIELD_VALID: ++ case ID_FIELD_INVALID: ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ break; ++ } ++ } else if (!strncasecmp("pres", data, 4)) { ++ ast_copy_string(buf, ast_named_caller_presentation(chan->redirecting.from.number_presentation), len); ++ } else if (!strncasecmp("reason", data, 6)) { ++ ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len); ++ } else if (!strncasecmp("count", data, 5)) { ++ snprintf(buf, len, "%d", chan->redirecting.count); ++ } else { ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ } ++ ++ ast_channel_unlock(chan); ++ ++ return 0; ++} ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Write new values to the party id struct ++ * ++ * \param id Party ID struct to write values ++ * \param data Remaining function datatype string ++ * \param value Value to assign to the party id. ++ * ++ * \retval ID_FIELD_VALID on success. ++ * \retval ID_FIELD_INVALID on error with field value. ++ * \retval ID_FIELD_UNKNOWN on unknown field name. ++ */ ++static enum ID_FIELD_STATUS redirecting_id_write(struct ast_party_id *id, char *data, const char *value) ++{ ++ char *val; ++ enum ID_FIELD_STATUS status; ++ ++ status = ID_FIELD_VALID; ++ ++ if (!strncasecmp("all", data, 3)) { ++ char name[256]; ++ char num[256]; ++ ++ ast_callerid_split(value, name, sizeof(name), num, sizeof(num)); ++ if (!(id->name = ast_strdup(name))) { ++ return ID_FIELD_INVALID; ++ } ++ if (!(id->number = ast_strdup(num))) { ++ return ID_FIELD_INVALID; ++ } ++ } else if (!strncasecmp("name", data, 4)) { ++ id->name = ast_strdup(value); ++ ast_trim_blanks(id->name); ++ } else if (!strncasecmp("num", data, 3)) { ++ id->number = ast_strdup(value); ++ ast_trim_blanks(id->number); ++ } else if (!strncasecmp("ton", data, 3)) { ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ id->number_type = atoi(val); ++ } else { ++ ast_log(LOG_ERROR, "Unknown redirecting type of number '%s', value unchanged\n", val); ++ status = ID_FIELD_INVALID; ++ } ++ } else if (!strncasecmp("pres", data, 4)) { ++ int pres; ++ ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ pres = atoi(val); ++ } else { ++ pres = ast_parse_caller_presentation(val); ++ } ++ ++ if (pres < 0) { ++ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val); ++ status = ID_FIELD_INVALID; ++ } else { ++ id->number_presentation = pres; ++ } ++ } else { ++ status = ID_FIELD_UNKNOWN; ++ } ++ ++ return status; ++} ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Write new values to the redirecting information struct. ++ * ++ * \param chan Asterisk channel to update ++ * \param cmd Not used ++ * \param data Redirecting function datatype string ++ * \param value Value to assign to the redirecting information struct. ++ * ++ * \retval 0 on success. ++ * \retval -1 on error. ++ */ ++static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) ++{ ++ struct ast_party_redirecting redirecting; ++ char *val; ++ char *option; ++ void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting); ++ ++ if (!value || !chan) { ++ return -1; ++ } ++ ++ /* Determine if the update indication inhibit option is present */ ++ option = strchr(data, ','); ++ if (option) { ++ option = ast_skip_blanks(option + 1); ++ switch (*option) { ++ case 'i': ++ set_it = ast_channel_set_redirecting; ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown redirecting option '%s'.\n", option); ++ return 0; ++ } ++ } ++ else { ++ set_it = ast_channel_update_redirecting; ++ } ++ ++ ast_channel_lock(chan); ++ ast_party_redirecting_set_init(&redirecting, &chan->redirecting); ++ ast_channel_unlock(chan); ++ ++ value = ast_skip_blanks(value); ++ ++ if (!strncasecmp("from-", data, 5)) { ++ switch (redirecting_id_write(&redirecting.from, data + 5, value)) { ++ case ID_FIELD_VALID: ++ set_it(chan, &redirecting); ++ ast_party_redirecting_free(&redirecting); ++ break; ++ ++ case ID_FIELD_INVALID: ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ break; ++ } ++ } else if (!strncasecmp("to-", data, 3)) { ++ switch (redirecting_id_write(&redirecting.to, data + 3, value)) { ++ case ID_FIELD_VALID: ++ set_it(chan, &redirecting); ++ ast_party_redirecting_free(&redirecting); ++ break; ++ ++ case ID_FIELD_INVALID: ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ break; ++ } ++ } else if (!strncasecmp("pres", data, 4)) { ++ int pres; ++ ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ pres = atoi(val); ++ } else { ++ pres = ast_parse_caller_presentation(val); ++ } ++ ++ if (pres < 0) { ++ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val); ++ } else { ++ redirecting.from.number_presentation = pres; ++ redirecting.to.number_presentation = pres; ++ set_it(chan, &redirecting); ++ } ++ } else if (!strncasecmp("reason", data, 6)) { ++ int reason; ++ ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ reason = atoi(val); ++ } else { ++ reason = ast_redirecting_reason_parse(val); ++ } ++ ++ if (reason < 0) { ++ ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val); ++ } else { ++ redirecting.reason = reason; ++ set_it(chan, &redirecting); ++ } ++ } else if (!strncasecmp("count", data, 5)) { ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ redirecting.count = atoi(val); ++ set_it(chan, &redirecting); ++ } else { ++ ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val); ++ } ++ } else { ++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); ++ } ++ ++ return 0; ++} ++ ++ ++ ++ ++static struct ast_custom_function redirecting_function = { ++ .name = "REDIRECTING", ++ .read = redirecting_read, ++ .write = redirecting_write, ++}; ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Unload the function module ++ * ++ * \retval 0 on success. ++ * \retval -1 on error. ++ */ ++static int unload_module(void) ++{ ++ return ast_custom_function_unregister(&redirecting_function); ++} ++ ++ ++ ++ ++/* ******************************************************************* */ ++/*! ++ * \internal ++ * \brief Load and initialize the function module. ++ * ++ * \retval 0 on success. ++ * \retval -1 on error. ++ */ ++static int load_module(void) ++{ ++ return ast_custom_function_register(&redirecting_function) ++ ? AST_MODULE_LOAD_DECLINE ++ : AST_MODULE_LOAD_SUCCESS; ++} ++ ++ ++ ++ ++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirecting data dialplan function"); ++ ++ ++/* ------------------------------------------------------------------- */ ++/* end func_redirecting.c */ + +Property changes on: funcs/func_redirecting.c +___________________________________________________________________ +Added: svn:eol-style + + native +Added: svn:mime-type + + text/plain +Added: svn:keywords + + Author Date Id Revision + +Index: funcs/func_connectedline.c +=================================================================== +--- a/funcs/func_connectedline.c (.../trunk) (revision 0) ++++ b/funcs/func_connectedline.c (.../team/group/issue14068) (revision 186562) +@@ -0,0 +1,239 @@ ++/* ++ * Asterisk -- An open source telephony toolkit. ++ * ++ * Copyright (C) 2007, Gareth Palmer ++ * ++ * Gareth Palmer <gareth@acsdata.co.nz> ++ * ++ * See http://www.asterisk.org for more information about ++ * the Asterisk project. Please do not directly contact ++ * any of the maintainers of this project for assistance; ++ * the project provides a web site, mailing lists and IRC ++ * channels for your use. ++ * ++ * This program is free software, distributed under the terms of ++ * the GNU General Public License Version 2. See the LICENSE file ++ * at the top of the source tree. ++ */ ++ ++/*! \file ++ * ++ * \brief Connected Line dialplan function ++ * ++ * \ingroup functions ++ */ ++ ++#include "asterisk.h" ++ ++ASTERISK_FILE_VERSION(__FILE__, "$Revision$") ++ ++#include <stdlib.h> ++#include <stdio.h> ++#include <string.h> ++#include <sys/types.h> ++ ++#include "asterisk/module.h" ++#include "asterisk/channel.h" ++#include "asterisk/pbx.h" ++#include "asterisk/logger.h" ++#include "asterisk/utils.h" ++#include "asterisk/app.h" ++#include "asterisk/options.h" ++#include "asterisk/callerid.h" ++ ++/*** DOCUMENTATION ++ <function name="CONNECTEDLINE" language="en_US"> ++ <synopsis> ++ Gets or sets Connected Line data on the channel. ++ </synopsis> ++ <syntax> ++ <parameter name="datatype" required="true"> ++ <para>The allowable datatypes are:</para> ++ <enumlist> ++ <enum name = "all" /> ++ <enum name = "num" /> ++ <enum name = "name" /> ++ <enum name = "ton" /> ++ <enum name = "pres" /> ++ <enum name = "source" /> ++ </enumlist> ++ </parameter> ++ <parameter name="i"> ++ <para>If set, this will prevent the channel from sending out protocol ++ messages because of the value being set</para> ++ </parameter> ++ </syntax> ++ <description> ++ <para>Gets or sets Connected Line data on the channel. Possible values ++ for the <replaceable>source</replaceable> datatype are:</para> ++ <enumlist> ++ <enum name="answer"><para>Normal Call Answering</para></enum> ++ <enum name="transfer_alerting"><para>Call Transfer(Alerting)</para></enum> ++ <enum name="transfer_active"><para>Call Transfer(Active)</para></enum> ++ </enumlist> ++ </description> ++ </function> ++ ***/ ++ ++static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, ++ char *buf, size_t len) ++{ ++ /* Ensure that the buffer is empty */ ++ *buf = 0; ++ ++ if (!chan) ++ return -1; ++ ++ ast_channel_lock(chan); ++ ++ if (!strncasecmp("all", data, 3)) { ++ snprintf(buf, len, "\"%s\" <%s>", ++ S_OR(chan->connected.id.name, ""), ++ S_OR(chan->connected.id.number, "")); ++ } else if (!strncasecmp("name", data, 4)) { ++ if (chan->connected.id.name) { ++ ast_copy_string(buf, chan->connected.id.name, len); ++ } ++ } else if (!strncasecmp("num", data, 3)) { ++ if (chan->connected.id.number) { ++ ast_copy_string(buf, chan->connected.id.number, len); ++ } ++ } else if (!strncasecmp("ton", data, 3)) { ++ snprintf(buf, len, "%d", chan->connected.id.number_type); ++ } else if (!strncasecmp("pres", data, 4)) { ++ ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len); ++ } else if (!strncasecmp("source", data, 6)) { ++ ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len); ++ } else { ++ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data); ++ } ++ ++ ast_channel_unlock(chan); ++ ++ return 0; ++} ++ ++static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, ++ const char *value) ++{ ++ struct ast_party_connected_line connected; ++ char *val; ++ char *option; ++ void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected); ++ ++ if (!value || !chan) { ++ return -1; ++ } ++ ++ /* Determine if the update indication inhibit option is present */ ++ option = strchr(data, ','); ++ if (option) { ++ option = ast_skip_blanks(option + 1); ++ switch (*option) { ++ case 'i': ++ set_it = ast_channel_set_connected_line; ++ break; ++ ++ default: ++ ast_log(LOG_ERROR, "Unknown connectedline option '%s'.\n", option); ++ return 0; ++ } ++ } ++ else { ++ set_it = ast_channel_update_connected_line; ++ } ++ ++ ast_channel_lock(chan); ++ ast_party_connected_line_set_init(&connected, &chan->connected); ++ ast_channel_unlock(chan); ++ ++ value = ast_skip_blanks(value); ++ ++ if (!strncasecmp("all", data, 3)) { ++ char name[256]; ++ char num[256]; ++ ++ ast_callerid_split(value, name, sizeof(name), num, sizeof(num)); ++ connected.id.name = name; ++ connected.id.number = num; ++ set_it(chan, &connected); ++ } else if (!strncasecmp("name", data, 4)) { ++ connected.id.name = ast_strdupa(value); ++ ast_trim_blanks(connected.id.name); ++ set_it(chan, &connected); ++ } else if (!strncasecmp("num", data, 3)) { ++ connected.id.number = ast_strdupa(value); ++ ast_trim_blanks(connected.id.number); ++ set_it(chan, &connected); ++ } else if (!strncasecmp("ton", data, 3)) { ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ connected.id.number_type = atoi(val); ++ set_it(chan, &connected); ++ } else { ++ ast_log(LOG_ERROR, "Unknown connectedline type of number '%s', value unchanged\n", val); ++ } ++ } else if (!strncasecmp("pres", data, 4)) { ++ int pres; ++ ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ pres = atoi(val); ++ } else { ++ pres = ast_parse_caller_presentation(val); ++ } ++ ++ if (pres < 0) { ++ ast_log(LOG_ERROR, "Unknown connectedline number presentation '%s', value unchanged\n", val); ++ } else { ++ connected.id.number_presentation = pres; ++ set_it(chan, &connected); ++ } ++ } else if (!strncasecmp("source", data, 6)) { ++ int source; ++ ++ val = ast_strdupa(value); ++ ast_trim_blanks(val); ++ ++ if (('0' <= val[0]) && (val[0] <= '9')) { ++ source = atoi(val); ++ } else { ++ source = ast_connected_line_source_parse(val); ++ } ++ ++ if (source < 0) { ++ ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val); ++ } else { ++ connected.source = source; ++ set_it(chan, &connected); ++ } ++ } else { ++ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data); ++ } ++ ++ return 0; ++} ++ ++static struct ast_custom_function connectedline_function = { ++ .name = "CONNECTEDLINE", ++ .read = connectedline_read, ++ .write = connectedline_write, ++}; ++ ++static int unload_module(void) ++{ ++ return ast_custom_function_unregister(&connectedline_function); ++} ++ ++static int load_module(void) ++{ ++ return ast_custom_function_register(&connectedline_function) ++ ? AST_MODULE_LOAD_DECLINE ++ : AST_MODULE_LOAD_SUCCESS; ++} ++ ++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Connected Line dialplan function"); + +Property changes on: funcs/func_connectedline.c +___________________________________________________________________ +Added: svn:eol-style + + native +Added: svn:mime-type + + text/plain +Added: svn:keywords + + Author Date Id Revision + + +Property changes on: . +___________________________________________________________________ +Added: automerge + + * +Added: svnmerge-integrated + + /trunk:1-186557 +Added: automerge-email + + rmudgett@digium.com + |