diff -Naur asterisk-issue8824-2008-12-10/channels/chan_dahdi.c asterisk-issue8824-2008-12-10.new/channels/chan_dahdi.c --- asterisk-issue8824-2008-12-10/channels/chan_dahdi.c 2008-12-10 10:34:28.000000000 +0100 +++ asterisk-issue8824-2008-12-10.new/channels/chan_dahdi.c 2008-12-11 16:06:35.000000000 +0100 @@ -2162,6 +2162,164 @@ } #endif +static int ast_to_pri_reason(enum AST_REDIRECTING_REASON ast_reason) +{ + int pri_reason; + + switch (ast_reason) { + case AST_REDIRECTING_REASON_UNKNOWN: + pri_reason = PRI_REDIR_UNKNOWN; + break; + 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; + default: + pri_reason = PRI_REDIR_UNKNOWN; + break; + } /* end switch */ + + return pri_reason; +} + +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; +} + +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; +} + +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_UNKNOWN: + ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; + break; + case PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER: + ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; + break; + case PRI_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION: + ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION; + break; + case PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER: + ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; + break; + default: + ast_source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; + break; + } /* end switch */ + + return ast_source; +} + +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_UNKNOWN: + pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; + break; + case AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER: + pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; + break; + case AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION: + pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION; + break; + case AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER: + pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; + break; + default: + pri_source = PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; + break; + } /* end switch */ + + return pri_source; +} + static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) { struct dahdi_pvt *p = ast->tech_pvt; @@ -2834,7 +2992,8 @@ 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->redirecting.from.name, ast->redirecting.from.number, ast->redirecting.from.number_type, + ast->redirecting.from.number_presentation, ast_to_pri_reason(ast->redirecting.reason)); #ifdef SUPPORT_USERUSER /* User-user info */ @@ -5837,12 +5996,42 @@ return 0; } +static enum AST_REDIRECTING_REASON pri_to_ast_reason(int pri_reason) +{ + enum AST_REDIRECTING_REASON ast_reason; + + switch (pri_reason) { + case PRI_REDIR_UNKNOWN: + ast_reason = AST_REDIRECTING_REASON_UNKNOWN; + break; + 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; + default: + ast_reason = AST_REDIRECTING_REASON_UNKNOWN; + break; + } /* end switch */ + + return ast_reason; +} + static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen) { struct dahdi_pvt *p = chan->tech_pvt; int res=-1; int idx; int func = DAHDI_FLASH; + struct pri_party_connected_line connected; + struct pri_party_redirecting redirecting; 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); @@ -6068,6 +6257,47 @@ 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 (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); + break; + case AST_CONTROL_REDIRECTING: + ast_debug(1,"Received AST_CONTROL_REDIRECTING on %s\n",chan->name); + if (chan->redirecting.from.number) + ast_copy_string(redirecting.from.number, chan->redirecting.from.number, 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); + break; } } else res = 0; @@ -10968,6 +11198,27 @@ dahdi_queue_frame(pri->pvts[chanpos], &f, pri); } } + if (pri->pvts[chanpos]->owner) { + char dnid[AST_MAX_EXTENSION]; + char rdnis[AST_MAX_EXTENSION]; + if (pri->pvts[chanpos]->owner->exten) { + int pos = strlen(pri->pvts[chanpos]->owner->exten); + if (pos < sizeof(pri->pvts[chanpos]->owner->exten) - 2) + ast_copy_string(&pri->pvts[chanpos]->owner->exten[pos], e->ring.callednum, sizeof(pri->pvts[chanpos]->owner->exten) - strlen(e->ring.callednum)); + } + if (pri->pvts[chanpos]->owner->cid.cid_dnid) { + ast_copy_string(dnid, pri->pvts[chanpos]->owner->cid.cid_dnid, sizeof(dnid)); + strncat (dnid, e->ring.callednum, sizeof(dnid) - strlen(dnid) - 1); + ast_free(pri->pvts[chanpos]->owner->cid.cid_dnid); + pri->pvts[chanpos]->owner->cid.cid_dnid = ast_strdup(dnid); + } + if (pri->pvts[chanpos]->owner->cid.cid_rdnis) { + ast_copy_string(rdnis, pri->pvts[chanpos]->owner->cid.cid_rdnis, sizeof(rdnis)); + strncat (rdnis, e->ring.callednum, sizeof(rdnis) - strlen(rdnis) - 1); + ast_free(pri->pvts[chanpos]->owner->cid.cid_rdnis); + pri->pvts[chanpos]->owner->cid.cid_rdnis = ast_strdup(rdnis); + } + } } ast_mutex_unlock(&pri->pvts[chanpos]->lock); } @@ -11004,6 +11255,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 */ @@ -11025,6 +11277,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) { @@ -11125,6 +11388,9 @@ ast_mutex_unlock(&pri->pvts[chanpos]->lock); + if (c && (redirecting.from.number || redirecting.from.name)) { + ast_party_redirecting_copy(&c->redirecting, &redirecting); + } if (!ast_strlen_zero(e->ring.callingsubaddr)) { pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); } @@ -11170,6 +11436,9 @@ ast_mutex_unlock(&pri->pvts[chanpos]->lock); + if (redirecting.from.number || redirecting.from.name) { + ast_party_redirecting_copy(&c->redirecting, &redirecting); + } if (e->ring.ani2 >= 0) { snprintf(ani2str, 5, "%d", e->ring.ani2); pbx_builtin_setvar_helper(c, "ANI2", ani2str); @@ -11265,6 +11534,20 @@ } #endif + if (e->ringing.calledname[0] || e->ringing.callednum[0]) { + struct ast_party_connected_line connected; + struct ast_channel *owner = pri->pvts[chanpos]->owner; + + /* 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_queue_connected_line_update(owner, &connected); + } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } } @@ -11364,6 +11647,76 @@ } } 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++) { + subcommand *subcmd = &e->facility.subcmds.subcmd[i]; + + switch (subcmd->cmd) { + case CMD_CONNECTEDLINE: + { + struct ast_party_connected_line connected; + cmd_connectedline *cmdcl; + struct ast_channel *owner = pri->pvts[chanpos]->owner; + + /* 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_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; + } + break; + case CMD_REDIRECTING: + { + struct ast_party_redirecting redirecting = {{0,},}; + cmd_redirecting *cmdr; + struct ast_channel *owner = pri->pvts[chanpos]->owner; + + 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_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) { @@ -11375,6 +11728,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 = pri->pvts[chanpos]->owner; + ast_mutex_lock(&pri->pvts[chanpos]->lock); /* Now we can do call progress detection */ @@ -11422,6 +11778,15 @@ } #endif + /* 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_queue_connected_line_update(owner, &connected); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } } @@ -11882,7 +12247,7 @@ } span = atoi(a->argv[5]); if ((span < 1) || (span > NUM_SPANS)) { - ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); + ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS); return CLI_SUCCESS; } if (!pris[span-1].pri) {