From 6e2e38083d4b27185df4d85617ceae45f0961a39 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Fri, 16 May 2014 17:32:44 +0000 Subject: sig_pri.c: Pull the pri_dchannel() PRI_EVENT_RING case into its own function. * Populate the CALLERID(ani2) value (and the special CALLINGANI2 channel variable) with the ANI2 value in addition to the PRI specific ANI2 channel variable. * Made complete snapshot staging with the channel lock held. All channel snapshots need to be done while the channel lock is held. ........ Merged revisions 414050 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 414051 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@414052 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/sig_pri.c | 1003 +++++++++++++++++++++++++--------------------------- 1 file changed, 476 insertions(+), 527 deletions(-) (limited to 'channels/sig_pri.c') diff --git a/channels/sig_pri.c b/channels/sig_pri.c index d153da1db..57c518c88 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1043,8 +1043,8 @@ static struct ast_channel *sig_pri_new_ast_channel(struct sig_pri_chan *p, int s return NULL; } - if (!p->owner) - p->owner = c; + ast_assert(p->owner == NULL || p->owner == c); + p->owner = c; p->isidlecall = 0; p->alreadyhungup = 0; ast_channel_transfercapability_set(c, transfercapability); @@ -5751,6 +5751,479 @@ static void sig_pri_handle_retrieve_rej(struct sig_pri_span *pri, pri_event *ev) } #endif /* defined(HAVE_PRI_CALL_HOLD) */ +/*! + * \internal + * \brief Setup channel variables on the owner. + * + * \param pri PRI span control structure. + * \param chanpos Channel position in the span. + * \param ev SETUP event received. + * + * \note Assumes the pri->lock is already obtained. + * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained. + * + * \return Nothing + */ +static void setup_incoming_channel(struct sig_pri_span *pri, int chanpos, pri_event *ev) +{ + struct ast_channel *owner; + char ani2str[6]; + char calledtonstr[10]; + + sig_pri_lock_owner(pri, chanpos); + owner = pri->pvts[chanpos]->owner; + if (!owner) { + return; + } + + ast_channel_stage_snapshot(owner); + +#if defined(HAVE_PRI_SUBADDR) + if (ev->ring.calling.subaddress.valid) { + /* Set Calling Subaddress */ + sig_pri_set_subaddress(&ast_channel_caller(owner)->id.subaddress, + &ev->ring.calling.subaddress); + if (!ev->ring.calling.subaddress.type + && !ast_strlen_zero((char *) ev->ring.calling.subaddress.data)) { + /* NSAP */ + pbx_builtin_setvar_helper(owner, "CALLINGSUBADDR", + (char *) ev->ring.calling.subaddress.data); + } + } + if (ev->ring.called_subaddress.valid) { + /* Set Called Subaddress */ + sig_pri_set_subaddress(&ast_channel_dialed(owner)->subaddress, + &ev->ring.called_subaddress); + if (!ev->ring.called_subaddress.type + && !ast_strlen_zero((char *) ev->ring.called_subaddress.data)) { + /* NSAP */ + pbx_builtin_setvar_helper(owner, "CALLEDSUBADDR", + (char *) ev->ring.called_subaddress.data); + } + } +#else + if (!ast_strlen_zero(ev->ring.callingsubaddr)) { + pbx_builtin_setvar_helper(owner, "CALLINGSUBADDR", ev->ring.callingsubaddr); + } +#endif /* !defined(HAVE_PRI_SUBADDR) */ + if (ev->ring.ani2 >= 0) { + ast_channel_caller(owner)->ani2 = ev->ring.ani2; + snprintf(ani2str, sizeof(ani2str), "%d", ev->ring.ani2); + pbx_builtin_setvar_helper(owner, "ANI2", ani2str); + } + +#ifdef SUPPORT_USERUSER + if (!ast_strlen_zero(ev->ring.useruserinfo)) { + pbx_builtin_setvar_helper(owner, "USERUSERINFO", ev->ring.useruserinfo); + } +#endif + + snprintf(calledtonstr, sizeof(calledtonstr), "%d", ev->ring.calledplan); + pbx_builtin_setvar_helper(owner, "CALLEDTON", calledtonstr); + ast_channel_dialed(owner)->number.plan = ev->ring.calledplan; + + if (ev->ring.redirectingreason >= 0) { + /* This is now just a status variable. Use REDIRECTING() dialplan function. */ + pbx_builtin_setvar_helper(owner, "PRIREDIRECTREASON", + redirectingreason2str(ev->ring.redirectingreason)); + } +#if defined(HAVE_PRI_REVERSE_CHARGE) + pri->pvts[chanpos]->reverse_charging_indication = ev->ring.reversecharge; +#endif +#if defined(HAVE_PRI_SETUP_KEYPAD) + ast_copy_string(pri->pvts[chanpos]->keypad_digits, + ev->ring.keypad_digits, sizeof(pri->pvts[chanpos]->keypad_digits)); +#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ + + /* + * It's ok to call this with the owner already locked here + * since it will want to do this anyway if there are any + * subcmds. + */ + sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->ring.subcmds, + ev->ring.call); + + ast_channel_stage_snapshot_done(owner); + ast_channel_unlock(owner); +} + +/*! + * \internal + * \brief Handle the incoming SETUP event from libpri. + * + * \param pri PRI span control structure. + * \param e SETUP event received. + * + * \note Assumes the pri->lock is already obtained. + * + * \return Nothing + */ +static void sig_pri_handle_setup(struct sig_pri_span *pri, pri_event *e) +{ + int exten_exists_or_can_exist; + int could_match_more; + int need_dialtone; + int law; + int chanpos = -1; + struct ast_callid *callid = NULL; + struct ast_channel *c; + char plancallingnum[AST_MAX_EXTENSION]; + char plancallingani[AST_MAX_EXTENSION]; + pthread_t threadid; + + if (!ast_strlen_zero(pri->msn_list) + && !sig_pri_msn_match(pri->msn_list, e->ring.callednum)) { + /* The call is not for us so ignore it. */ + ast_verb(3, + "Ignoring call to '%s' on span %d. Its not in the MSN list: %s\n", + e->ring.callednum, pri->span, pri->msn_list); + pri_destroycall(pri->pri, e->ring.call); + goto setup_exit; + } + if (sig_pri_is_cis_call(e->ring.channel)) { + sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds, e->ring.call); + goto setup_exit; + } + chanpos = pri_find_principle_by_call(pri, e->ring.call); + if (-1 < chanpos) { + /* Libpri has already filtered out duplicate SETUPs. */ + ast_log(LOG_WARNING, + "Span %d: Got SETUP with duplicate call ptr (%p). Dropping call.\n", + pri->span, e->ring.call); + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE); + goto setup_exit; + } + if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) { + /* Any channel requested. */ + chanpos = pri_find_empty_chan(pri, 1); + if (-1 < chanpos) { + callid = func_pri_dchannel_new_callid(); + } + } else if (PRI_CHANNEL(e->ring.channel) == 0x00) { + /* No channel specified. */ +#if defined(HAVE_PRI_CALL_WAITING) + if (!pri->allow_call_waiting_calls) +#endif /* defined(HAVE_PRI_CALL_WAITING) */ + { + /* We will not accept incoming call waiting calls. */ + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); + goto setup_exit; + } +#if defined(HAVE_PRI_CALL_WAITING) + chanpos = pri_find_empty_nobch(pri); + if (chanpos < 0) { + /* We could not find/create a call interface. */ + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); + goto setup_exit; + } + + callid = func_pri_dchannel_new_callid(); + + /* Setup the call interface to use. */ + sig_pri_init_config(pri->pvts[chanpos], pri); +#endif /* defined(HAVE_PRI_CALL_WAITING) */ + } else { + /* A channel is specified. */ + callid = func_pri_dchannel_new_callid(); + chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call); + if (chanpos < 0) { + ast_log(LOG_WARNING, + "Span %d: SETUP on unconfigured channel %d/%d\n", + pri->span, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel)); + } else { + switch (pri->pvts[chanpos]->resetting) { + case SIG_PRI_RESET_IDLE: + break; + case SIG_PRI_RESET_ACTIVE: + /* + * The peer may have lost the expected ack or not received the + * RESTART yet. + */ + pri->pvts[chanpos]->resetting = SIG_PRI_RESET_NO_ACK; + break; + case SIG_PRI_RESET_NO_ACK: + /* The peer likely is not going to ack the RESTART. */ + ast_debug(1, + "Span %d: Second SETUP while waiting for RESTART ACKNOWLEDGE on channel %d/%d\n", + pri->span, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel)); + + /* Assume we got the ack. */ + pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE; + if (pri->resetting) { + /* Go on to the next idle channel to RESTART. */ + pri_check_restart(pri); + } + break; + } + if (!sig_pri_is_chan_available(pri->pvts[chanpos])) { + /* This is where we handle initial glare */ + ast_debug(1, + "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n", + pri->span, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel)); + chanpos = -1; + } + } +#if defined(ALWAYS_PICK_CHANNEL) + if (e->ring.flexible) { + chanpos = -1; + } +#endif /* defined(ALWAYS_PICK_CHANNEL) */ + if (chanpos < 0 && e->ring.flexible) { + /* We can try to pick another channel. */ + chanpos = pri_find_empty_chan(pri, 1); + } + } + if (chanpos < 0) { + if (e->ring.flexible) { + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); + } else { + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); + } + goto setup_exit; + } + + sig_pri_lock_private(pri->pvts[chanpos]); + + /* Mark channel as in use so noone else will steal it. */ + pri->pvts[chanpos]->call = e->ring.call; + + /* Use plancallingnum as a scratch buffer since it is initialized next. */ + apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri, + e->ring.redirectingnum, e->ring.callingplanrdnis); + sig_pri_set_rdnis(pri->pvts[chanpos], plancallingnum); + + /* Setup caller-id info */ + apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri, + e->ring.callingnum, e->ring.callingplan); + pri->pvts[chanpos]->cid_ani2 = 0; + if (pri->pvts[chanpos]->use_callerid) { + ast_shrink_phone_number(plancallingnum); + ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, + sizeof(pri->pvts[chanpos]->cid_num)); +#ifdef PRI_ANI + apply_plan_to_existing_number(plancallingani, sizeof(plancallingani), + pri, e->ring.callingani, e->ring.callingplanani); + ast_shrink_phone_number(plancallingani); + ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, + sizeof(pri->pvts[chanpos]->cid_ani)); +#endif + pri->pvts[chanpos]->cid_subaddr[0] = '\0'; +#if defined(HAVE_PRI_SUBADDR) + if (e->ring.calling.subaddress.valid) { + struct ast_party_subaddress calling_subaddress; + + ast_party_subaddress_init(&calling_subaddress); + sig_pri_set_subaddress(&calling_subaddress, + &e->ring.calling.subaddress); + if (calling_subaddress.str) { + ast_copy_string(pri->pvts[chanpos]->cid_subaddr, + calling_subaddress.str, + sizeof(pri->pvts[chanpos]->cid_subaddr)); + } + ast_party_subaddress_free(&calling_subaddress); + } +#endif /* defined(HAVE_PRI_SUBADDR) */ + ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, + sizeof(pri->pvts[chanpos]->cid_name)); + /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ + pri->pvts[chanpos]->cid_ton = e->ring.callingplan; + pri->pvts[chanpos]->callingpres = e->ring.callingpres; + if (e->ring.ani2 >= 0) { + pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; + } + } else { + pri->pvts[chanpos]->cid_num[0] = '\0'; + pri->pvts[chanpos]->cid_subaddr[0] = '\0'; + pri->pvts[chanpos]->cid_ani[0] = '\0'; + pri->pvts[chanpos]->cid_name[0] = '\0'; + pri->pvts[chanpos]->cid_ton = 0; + pri->pvts[chanpos]->callingpres = 0; + } + + /* Setup the user tag for party id's from this device for this call. */ + if (pri->append_msn_to_user_tag) { + snprintf(pri->pvts[chanpos]->user_tag, + sizeof(pri->pvts[chanpos]->user_tag), "%s_%s", + pri->initial_user_tag, + pri->nodetype == PRI_NETWORK + ? plancallingnum : e->ring.callednum); + } else { + ast_copy_string(pri->pvts[chanpos]->user_tag, + pri->initial_user_tag, sizeof(pri->pvts[chanpos]->user_tag)); + } + + sig_pri_set_caller_id(pri->pvts[chanpos]); + + /* Set DNID on all incoming calls -- even immediate */ + sig_pri_set_dnid(pri->pvts[chanpos], e->ring.callednum); + + if (pri->pvts[chanpos]->immediate) { + /* immediate=yes go to s|1 */ + ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); + pri->pvts[chanpos]->exten[0] = 's'; + pri->pvts[chanpos]->exten[1] = '\0'; + } else if (!ast_strlen_zero(e->ring.callednum)) { + /* Get called number */ + ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, + sizeof(pri->pvts[chanpos]->exten)); + } else if (pri->overlapdial) { + pri->pvts[chanpos]->exten[0] = '\0'; + } else { + /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ + pri->pvts[chanpos]->exten[0] = 's'; + pri->pvts[chanpos]->exten[1] = '\0'; + } + /* No number yet, but received "sending complete"? */ + if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { + ast_verb(3, "Going to extension s|1 because of Complete received\n"); + pri->pvts[chanpos]->exten[0] = 's'; + pri->pvts[chanpos]->exten[1] = '\0'; + } + + /* Make sure extension exists (or in overlap dial mode, can exist) */ + exten_exists_or_can_exist = ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) + && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, + pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) + || ast_exists_extension(NULL, pri->pvts[chanpos]->context, + pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num); + if (!exten_exists_or_can_exist) { + ast_verb(3, + "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n", + pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, + pri->pvts[chanpos]->cid_num); + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); + pri->pvts[chanpos]->call = NULL; + pri->pvts[chanpos]->exten[0] = '\0'; + sig_pri_unlock_private(pri->pvts[chanpos]); + sig_pri_span_devstate_changed(pri); + goto setup_exit; + } + + /* Select audio companding mode. */ + switch (e->ring.layer1) { + case PRI_LAYER_1_ALAW: + law = SIG_PRI_ALAW; + break; + case PRI_LAYER_1_ULAW: + law = SIG_PRI_ULAW; + break; + default: + /* This is a data call to us. */ + law = SIG_PRI_DEFLAW; + break; + } + + could_match_more = !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); + + need_dialtone = could_match_more + /* + * Must explicitly check the digital capability this + * way instead of checking the pvt->digital flag + * because the flag hasn't been set yet. + */ + && !(e->ring.ctype & AST_TRANS_CAP_DIGITAL) + && !pri->pvts[chanpos]->no_b_channel + && (!strlen(pri->pvts[chanpos]->exten) + || ast_ignore_pattern(pri->pvts[chanpos]->context, + pri->pvts[chanpos]->exten)); + + if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { + /* Just announce proceeding */ + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); + } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); + } else { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP; +#if defined(HAVE_PRI_SETUP_ACK_INBAND) + pri_setup_ack(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, need_dialtone); +#else /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ + pri_need_more_info(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); +#endif /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ + } + + /* + * Release the PRI lock while we create the channel so other + * threads can send D channel messages. We must also release + * the private lock to prevent deadlock while creating the + * channel. + */ + sig_pri_unlock_private(pri->pvts[chanpos]); + ast_mutex_unlock(&pri->lock); + c = sig_pri_new_ast_channel(pri->pvts[chanpos], + could_match_more ? AST_STATE_RESERVED : AST_STATE_RING, law, e->ring.ctype, + pri->pvts[chanpos]->exten, NULL, NULL); + ast_mutex_lock(&pri->lock); + sig_pri_lock_private(pri->pvts[chanpos]); + + if (c) { + setup_incoming_channel(pri, chanpos, e); + + /* Start PBX */ + if (could_match_more) { +#if !defined(HAVE_PRI_SETUP_ACK_INBAND) + if (need_dialtone) { + /* Indicate that we are providing dialtone. */ + pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */ +#ifdef HAVE_PRI_PROG_W_CAUSE + pri_progress_with_cause(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */ +#else + pri_progress(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); +#endif + } +#endif /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ + + if (!ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, + pri->pvts[chanpos])) { + ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", + plancallingnum, S_OR(pri->pvts[chanpos]->exten, ""), + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, + pri->span); + sig_pri_unlock_private(pri->pvts[chanpos]); + goto setup_exit; + } + } else { + if (!ast_pbx_start(c)) { + ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", + plancallingnum, pri->pvts[chanpos]->exten, + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, + pri->span); + sig_pri_set_echocanceller(pri->pvts[chanpos], 1); + sig_pri_unlock_private(pri->pvts[chanpos]); + goto setup_exit; + } + } + } + ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); + if (c) { + /* Avoid deadlock while destroying channel */ + sig_pri_unlock_private(pri->pvts[chanpos]); + ast_mutex_unlock(&pri->lock); + ast_hangup(c); + ast_mutex_lock(&pri->lock); + } else { + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); + pri->pvts[chanpos]->call = NULL; + sig_pri_unlock_private(pri->pvts[chanpos]); + sig_pri_span_devstate_changed(pri); + } + +setup_exit:; + if (callid) { + ast_callid_unref(callid); + ast_callid_threadassoc_remove(); + } +} + static void *pri_dchannel(void *vpri) { struct sig_pri_span *pri = vpri; @@ -5758,19 +6231,12 @@ static void *pri_dchannel(void *vpri) struct pollfd fds[SIG_PRI_NUM_DCHANS]; int res; int x; - int law; - struct ast_channel *c; struct timeval tv, lowest, *next; int doidling=0; char *cc; time_t t; int i, which=-1; int numdchans; - pthread_t threadid; - char ani2str[6]; - char plancallingnum[AST_MAX_EXTENSION]; - char plancallingani[AST_MAX_EXTENSION]; - char calledtonstr[10]; struct timeval lastidle = { 0, 0 }; pthread_t p; struct ast_channel *idle; @@ -6222,524 +6688,7 @@ static void *pri_dchannel(void *vpri) break; #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */ case PRI_EVENT_RING: - if (!ast_strlen_zero(pri->msn_list) - && !sig_pri_msn_match(pri->msn_list, e->ring.callednum)) { - /* The call is not for us so ignore it. */ - ast_verb(3, - "Ignoring call to '%s' on span %d. Its not in the MSN list: %s\n", - e->ring.callednum, pri->span, pri->msn_list); - pri_destroycall(pri->pri, e->ring.call); - break; - } - if (sig_pri_is_cis_call(e->ring.channel)) { - sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds, - e->ring.call); - break; - } - chanpos = pri_find_principle_by_call(pri, e->ring.call); - if (-1 < chanpos) { - /* Libpri has already filtered out duplicate SETUPs. */ - ast_log(LOG_WARNING, - "Span %d: Got SETUP with duplicate call ptr (%p). Dropping call.\n", - pri->span, e->ring.call); - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE); - break; - } - if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) { - /* Any channel requested. */ - chanpos = pri_find_empty_chan(pri, 1); - if (-1 < chanpos) { - callid = func_pri_dchannel_new_callid(); - } - } else if (PRI_CHANNEL(e->ring.channel) == 0x00) { - /* No channel specified. */ -#if defined(HAVE_PRI_CALL_WAITING) - if (!pri->allow_call_waiting_calls) -#endif /* defined(HAVE_PRI_CALL_WAITING) */ - { - /* We will not accept incoming call waiting calls. */ - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); - break; - } -#if defined(HAVE_PRI_CALL_WAITING) - chanpos = pri_find_empty_nobch(pri); - if (chanpos < 0) { - /* We could not find/create a call interface. */ - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); - break; - } - - callid = func_pri_dchannel_new_callid(); - - /* Setup the call interface to use. */ - sig_pri_init_config(pri->pvts[chanpos], pri); -#endif /* defined(HAVE_PRI_CALL_WAITING) */ - } else { - /* A channel is specified. */ - callid = func_pri_dchannel_new_callid(); - chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call); - if (chanpos < 0) { - ast_log(LOG_WARNING, - "Span %d: SETUP on unconfigured channel %d/%d\n", - pri->span, PRI_SPAN(e->ring.channel), - PRI_CHANNEL(e->ring.channel)); - } else { - switch (pri->pvts[chanpos]->resetting) { - case SIG_PRI_RESET_IDLE: - break; - case SIG_PRI_RESET_ACTIVE: - /* - * The peer may have lost the expected ack or not received the - * RESTART yet. - */ - pri->pvts[chanpos]->resetting = SIG_PRI_RESET_NO_ACK; - break; - case SIG_PRI_RESET_NO_ACK: - /* The peer likely is not going to ack the RESTART. */ - ast_debug(1, - "Span %d: Second SETUP while waiting for RESTART ACKNOWLEDGE on channel %d/%d\n", - pri->span, PRI_SPAN(e->ring.channel), - PRI_CHANNEL(e->ring.channel)); - - /* Assume we got the ack. */ - pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE; - if (pri->resetting) { - /* Go on to the next idle channel to RESTART. */ - pri_check_restart(pri); - } - break; - } - if (!sig_pri_is_chan_available(pri->pvts[chanpos])) { - /* This is where we handle initial glare */ - ast_debug(1, - "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n", - pri->span, PRI_SPAN(e->ring.channel), - PRI_CHANNEL(e->ring.channel)); - chanpos = -1; - } - } -#if defined(ALWAYS_PICK_CHANNEL) - if (e->ring.flexible) { - chanpos = -1; - } -#endif /* defined(ALWAYS_PICK_CHANNEL) */ - if (chanpos < 0 && e->ring.flexible) { - /* We can try to pick another channel. */ - chanpos = pri_find_empty_chan(pri, 1); - } - } - if (chanpos < 0) { - if (e->ring.flexible) { - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); - } else { - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); - } - break; - } - - sig_pri_lock_private(pri->pvts[chanpos]); - - /* Mark channel as in use so noone else will steal it. */ - pri->pvts[chanpos]->call = e->ring.call; - - /* Use plancallingnum as a scratch buffer since it is initialized next. */ - apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri, - e->ring.redirectingnum, e->ring.callingplanrdnis); - sig_pri_set_rdnis(pri->pvts[chanpos], plancallingnum); - - /* Setup caller-id info */ - apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri, - e->ring.callingnum, e->ring.callingplan); - pri->pvts[chanpos]->cid_ani2 = 0; - if (pri->pvts[chanpos]->use_callerid) { - ast_shrink_phone_number(plancallingnum); - ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); -#ifdef PRI_ANI - apply_plan_to_existing_number(plancallingani, sizeof(plancallingani), - pri, e->ring.callingani, e->ring.callingplanani); - ast_shrink_phone_number(plancallingani); - ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, - sizeof(pri->pvts[chanpos]->cid_ani)); -#endif - pri->pvts[chanpos]->cid_subaddr[0] = '\0'; -#if defined(HAVE_PRI_SUBADDR) - if (e->ring.calling.subaddress.valid) { - struct ast_party_subaddress calling_subaddress; - - ast_party_subaddress_init(&calling_subaddress); - sig_pri_set_subaddress(&calling_subaddress, - &e->ring.calling.subaddress); - if (calling_subaddress.str) { - ast_copy_string(pri->pvts[chanpos]->cid_subaddr, - calling_subaddress.str, - sizeof(pri->pvts[chanpos]->cid_subaddr)); - } - ast_party_subaddress_free(&calling_subaddress); - } -#endif /* defined(HAVE_PRI_SUBADDR) */ - ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); - pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ - pri->pvts[chanpos]->callingpres = e->ring.callingpres; - if (e->ring.ani2 >= 0) { - pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; - } - } else { - pri->pvts[chanpos]->cid_num[0] = '\0'; - pri->pvts[chanpos]->cid_subaddr[0] = '\0'; - pri->pvts[chanpos]->cid_ani[0] = '\0'; - pri->pvts[chanpos]->cid_name[0] = '\0'; - pri->pvts[chanpos]->cid_ton = 0; - pri->pvts[chanpos]->callingpres = 0; - } - - /* Setup the user tag for party id's from this device for this call. */ - if (pri->append_msn_to_user_tag) { - snprintf(pri->pvts[chanpos]->user_tag, - sizeof(pri->pvts[chanpos]->user_tag), "%s_%s", - pri->initial_user_tag, - pri->nodetype == PRI_NETWORK - ? plancallingnum : e->ring.callednum); - } else { - ast_copy_string(pri->pvts[chanpos]->user_tag, - pri->initial_user_tag, sizeof(pri->pvts[chanpos]->user_tag)); - } - - sig_pri_set_caller_id(pri->pvts[chanpos]); - - /* Set DNID on all incoming calls -- even immediate */ - sig_pri_set_dnid(pri->pvts[chanpos], e->ring.callednum); - - /* If immediate=yes go to s|1 */ - if (pri->pvts[chanpos]->immediate) { - ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); - pri->pvts[chanpos]->exten[0] = 's'; - pri->pvts[chanpos]->exten[1] = '\0'; - } - /* Get called number */ - else if (!ast_strlen_zero(e->ring.callednum)) { - ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); - } else if (pri->overlapdial) - pri->pvts[chanpos]->exten[0] = '\0'; - else { - /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ - pri->pvts[chanpos]->exten[0] = 's'; - pri->pvts[chanpos]->exten[1] = '\0'; - } - /* No number yet, but received "sending complete"? */ - if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { - ast_verb(3, "Going to extension s|1 because of Complete received\n"); - pri->pvts[chanpos]->exten[0] = 's'; - pri->pvts[chanpos]->exten[1] = '\0'; - } - - /* Make sure extension exists (or in overlap dial mode, can exist) */ - if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || - ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { - int could_match_more; - int need_dialtone; - - /* Select audio companding mode. */ - switch (e->ring.layer1) { - case PRI_LAYER_1_ALAW: - law = SIG_PRI_ALAW; - break; - case PRI_LAYER_1_ULAW: - law = SIG_PRI_ULAW; - break; - default: - /* This is a data call to us. */ - law = SIG_PRI_DEFLAW; - break; - } - - could_match_more = !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); - - need_dialtone = could_match_more - /* - * Must explicitly check the digital capability this - * way instead of checking the pvt->digital flag - * because the flag hasn't been set yet. - */ - && !(e->ring.ctype & AST_TRANS_CAP_DIGITAL) - && !pri->pvts[chanpos]->no_b_channel - && (!strlen(pri->pvts[chanpos]->exten) - || ast_ignore_pattern(pri->pvts[chanpos]->context, - pri->pvts[chanpos]->exten)); - - if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { - /* Just announce proceeding */ - pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; - pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); - } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) { - pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; - pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); - } else { - pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP; -#if defined(HAVE_PRI_SETUP_ACK_INBAND) - pri_setup_ack(pri->pri, e->ring.call, - PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, need_dialtone); -#else /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ - pri_need_more_info(pri->pri, e->ring.call, - PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); -#endif /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ - } - - /* Start PBX */ - if (could_match_more) { - /* - * Release the PRI lock while we create the channel so other - * threads can send D channel messages. We must also release - * the private lock to prevent deadlock while creating the - * channel. - */ - sig_pri_unlock_private(pri->pvts[chanpos]); - ast_mutex_unlock(&pri->lock); - c = sig_pri_new_ast_channel(pri->pvts[chanpos], - AST_STATE_RESERVED, law, e->ring.ctype, - pri->pvts[chanpos]->exten, NULL, NULL); - ast_mutex_lock(&pri->lock); - sig_pri_lock_private(pri->pvts[chanpos]); - if (c) { - ast_channel_stage_snapshot(c); -#if defined(HAVE_PRI_SUBADDR) - if (e->ring.calling.subaddress.valid) { - /* Set Calling Subaddress */ - sig_pri_lock_owner(pri, chanpos); - sig_pri_set_subaddress( - &ast_channel_caller(pri->pvts[chanpos]->owner)->id.subaddress, - &e->ring.calling.subaddress); - if (!e->ring.calling.subaddress.type - && !ast_strlen_zero( - (char *) e->ring.calling.subaddress.data)) { - /* NSAP */ - pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", - (char *) e->ring.calling.subaddress.data); - } - ast_channel_unlock(c); - } - if (e->ring.called_subaddress.valid) { - /* Set Called Subaddress */ - sig_pri_lock_owner(pri, chanpos); - sig_pri_set_subaddress( - &ast_channel_dialed(pri->pvts[chanpos]->owner)->subaddress, - &e->ring.called_subaddress); - if (!e->ring.called_subaddress.type - && !ast_strlen_zero( - (char *) e->ring.called_subaddress.data)) { - /* NSAP */ - pbx_builtin_setvar_helper(c, "CALLEDSUBADDR", - (char *) e->ring.called_subaddress.data); - } - ast_channel_unlock(c); - } -#else - if (!ast_strlen_zero(e->ring.callingsubaddr)) { - pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); - } -#endif /* !defined(HAVE_PRI_SUBADDR) */ - if (e->ring.ani2 >= 0) { - snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); - pbx_builtin_setvar_helper(c, "ANI2", ani2str); - } - -#ifdef SUPPORT_USERUSER - if (!ast_strlen_zero(e->ring.useruserinfo)) { - pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); - } -#endif - - snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); - pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); - ast_channel_lock(c); - ast_channel_dialed(c)->number.plan = e->ring.calledplan; - ast_channel_unlock(c); - - 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)); - } -#if defined(HAVE_PRI_REVERSE_CHARGE) - pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge; -#endif -#if defined(HAVE_PRI_SETUP_KEYPAD) - ast_copy_string(pri->pvts[chanpos]->keypad_digits, - e->ring.keypad_digits, - sizeof(pri->pvts[chanpos]->keypad_digits)); -#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ - - sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds, - e->ring.call); - -#if !defined(HAVE_PRI_SETUP_ACK_INBAND) - if (need_dialtone) { - /* Indicate that we are providing dialtone. */ - pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */ -#ifdef HAVE_PRI_PROG_W_CAUSE - pri_progress_with_cause(pri->pri, e->ring.call, - PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */ -#else - pri_progress(pri->pri, e->ring.call, - PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); -#endif - } -#endif /* !defined(HAVE_PRI_SETUP_ACK_INBAND) */ - ast_channel_stage_snapshot_done(c); - } - if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) { - ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", - plancallingnum, S_OR(pri->pvts[chanpos]->exten, ""), - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); - } else { - ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); - if (c) { - /* Avoid deadlock while destroying channel */ - sig_pri_unlock_private(pri->pvts[chanpos]); - ast_mutex_unlock(&pri->lock); - ast_hangup(c); - ast_mutex_lock(&pri->lock); - } else { - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); - pri->pvts[chanpos]->call = NULL; - sig_pri_unlock_private(pri->pvts[chanpos]); - sig_pri_span_devstate_changed(pri); - } - break; - } - } else { - /* - * Release the PRI lock while we create the channel so other - * threads can send D channel messages. We must also release - * the private lock to prevent deadlock while creating the - * channel. - */ - sig_pri_unlock_private(pri->pvts[chanpos]); - ast_mutex_unlock(&pri->lock); - c = sig_pri_new_ast_channel(pri->pvts[chanpos], - AST_STATE_RING, law, e->ring.ctype, - pri->pvts[chanpos]->exten, NULL, NULL); - ast_mutex_lock(&pri->lock); - sig_pri_lock_private(pri->pvts[chanpos]); - if (c) { - /* - * It is reasonably safe to set the following - * channel variables while the PRI and DAHDI private - * structures are locked. The PBX has not been - * started yet and it is unlikely that any other task - * will do anything with the channel we have just - * created. - */ - ast_channel_stage_snapshot(c); -#if defined(HAVE_PRI_SUBADDR) - if (e->ring.calling.subaddress.valid) { - /* Set Calling Subaddress */ - sig_pri_lock_owner(pri, chanpos); - sig_pri_set_subaddress( - &ast_channel_caller(pri->pvts[chanpos]->owner)->id.subaddress, - &e->ring.calling.subaddress); - if (!e->ring.calling.subaddress.type - && !ast_strlen_zero( - (char *) e->ring.calling.subaddress.data)) { - /* NSAP */ - pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", - (char *) e->ring.calling.subaddress.data); - } - ast_channel_unlock(c); - } - if (e->ring.called_subaddress.valid) { - /* Set Called Subaddress */ - sig_pri_lock_owner(pri, chanpos); - sig_pri_set_subaddress( - &ast_channel_dialed(pri->pvts[chanpos]->owner)->subaddress, - &e->ring.called_subaddress); - if (!e->ring.called_subaddress.type - && !ast_strlen_zero( - (char *) e->ring.called_subaddress.data)) { - /* NSAP */ - pbx_builtin_setvar_helper(c, "CALLEDSUBADDR", - (char *) e->ring.called_subaddress.data); - } - ast_channel_unlock(c); - } -#else - if (!ast_strlen_zero(e->ring.callingsubaddr)) { - pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); - } -#endif /* !defined(HAVE_PRI_SUBADDR) */ - if (e->ring.ani2 >= 0) { - snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); - pbx_builtin_setvar_helper(c, "ANI2", ani2str); - } - -#ifdef SUPPORT_USERUSER - if (!ast_strlen_zero(e->ring.useruserinfo)) { - pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); - } -#endif - - 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)); - } -#if defined(HAVE_PRI_REVERSE_CHARGE) - pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge; -#endif -#if defined(HAVE_PRI_SETUP_KEYPAD) - ast_copy_string(pri->pvts[chanpos]->keypad_digits, - e->ring.keypad_digits, - sizeof(pri->pvts[chanpos]->keypad_digits)); -#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ - - snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); - pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); - ast_channel_lock(c); - ast_channel_dialed(c)->number.plan = e->ring.calledplan; - ast_channel_unlock(c); - - sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds, - e->ring.call); - - ast_channel_stage_snapshot_done(c); - } - if (c && !ast_pbx_start(c)) { - ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", - plancallingnum, pri->pvts[chanpos]->exten, - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); - sig_pri_set_echocanceller(pri->pvts[chanpos], 1); - } else { - ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); - if (c) { - /* Avoid deadlock while destroying channel */ - sig_pri_unlock_private(pri->pvts[chanpos]); - ast_mutex_unlock(&pri->lock); - ast_hangup(c); - ast_mutex_lock(&pri->lock); - } else { - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); - pri->pvts[chanpos]->call = NULL; - sig_pri_unlock_private(pri->pvts[chanpos]); - sig_pri_span_devstate_changed(pri); - } - break; - } - } - } else { - ast_verb(3, - "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n", - pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, - pri->pvts[chanpos]->cid_num); - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); - pri->pvts[chanpos]->call = NULL; - pri->pvts[chanpos]->exten[0] = '\0'; - sig_pri_unlock_private(pri->pvts[chanpos]); - sig_pri_span_devstate_changed(pri); - break; - } - sig_pri_unlock_private(pri->pvts[chanpos]); + sig_pri_handle_setup(pri, e); break; case PRI_EVENT_RINGING: if (sig_pri_is_cis_call(e->ringing.channel)) { -- cgit v1.2.3