diff options
author | Richard Mudgett <rmudgett@digium.com> | 2012-02-02 20:18:11 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2012-02-02 20:18:11 +0000 |
commit | 63c5eaee4331d55e87b44f532f4c132e46bd7f5e (patch) | |
tree | f8f58c07e01971e64a7613140da21ceff62e36b9 /channels | |
parent | 0f4489dc0f76b92d95592cc0b726cb98f781881e (diff) |
Restore the 'w' modifier support for ISDN spans. Dial(DAHDI/g0/1234w888)
This feature also causes the sending complete ie to be sent for switch
types that do not automatically send the ie. (EuroISDN/ETSI)
The main difference between dialing Dial(DAHDI/g0/1234w888) and
Dial(DAHDI/g0/1234,,D(888)) is the sending of the sending complete ie.
(closes issue ASTERISK-19176)
Reported by: rmudgett
Tested by: rmudgett
........
Merged revisions 353867 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 353868 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@353872 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_dahdi.c | 57 | ||||
-rw-r--r-- | channels/sig_pri.c | 98 | ||||
-rw-r--r-- | channels/sig_pri.h | 6 |
3 files changed, 152 insertions, 9 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 6cfa81d61..cde55d0c7 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -2681,6 +2681,39 @@ static void my_pri_open_media(void *p) } #endif /* defined(HAVE_PRI) */ +#if defined(HAVE_PRI) +/*! + * \internal + * \brief Ask DAHDI to dial the given dial string. + * \since 1.8.11 + * + * \param p Channel private control structure. + * \param dial_string String to pass to DAHDI to dial. + * + * \note The channel private lock needs to be held when calling. + * + * \return Nothing + */ +static void my_pri_dial_digits(void *p, const char *dial_string) +{ + struct dahdi_dialoperation zo = { + .op = DAHDI_DIAL_OP_APPEND, + }; + struct dahdi_pvt *pvt = p; + int res; + + snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string); + ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr); + res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo); + if (res) { + ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n", + pvt->channel, dial_string, strerror(errno)); + } else { + pvt->dialing = 1; + } +} +#endif /* defined(HAVE_PRI) */ + static int unalloc_sub(struct dahdi_pvt *p, int x); static int my_unallocate_sub(void *pvt, enum analog_sub analogsub) @@ -3380,6 +3413,7 @@ static struct sig_pri_callback dahdi_pri_callbacks = .update_span_devstate = dahdi_pri_update_span_devstate, .module_ref = my_module_ref, .module_unref = my_module_unref, + .dial_digits = my_pri_dial_digits, .open_media = my_pri_open_media, .ami_channel_event = my_ami_channel_event, }; @@ -7975,6 +8009,29 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) tone_zone_play_tone(p->subs[idx].dfd, -1); break; case DAHDI_EVENT_DIALCOMPLETE: + /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */ +#if defined(HAVE_PRI) + if (dahdi_sig_pri_lib_handles(p->sig)) { + if (p->inalarm) { + break; + } + if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) { + ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n", + ast_channel_name(ast), strerror(errno)); + return NULL; + } + if (x) { + /* Still dialing in DAHDI driver */ + break; + } + /* + * The ast channel is locked and the private may be locked more + * than once. + */ + sig_pri_dial_complete(p->sig_pvt, ast); + break; + } +#endif /* defined(HAVE_PRI) */ #ifdef HAVE_OPENR2 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { /* we don't need to do anything for this event for R2 signaling diff --git a/channels/sig_pri.c b/channels/sig_pri.c index c9c96be55..bfdcb1084 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -137,6 +137,8 @@ static const char *sig_pri_call_level2str(enum sig_pri_call_level level) return "Proceeding"; case SIG_PRI_CALL_LEVEL_ALERTING: return "Alerting"; + case SIG_PRI_CALL_LEVEL_DEFER_DIAL: + return "DeferDial"; case SIG_PRI_CALL_LEVEL_CONNECT: return "Connect"; } @@ -214,6 +216,13 @@ static void sig_pri_make_cc_dialstring(struct sig_pri_chan *p, char *buf, size_t } #endif /* defined(HAVE_PRI_CCSS) */ +static void sig_pri_dial_digits(struct sig_pri_chan *p, const char *dial_string) +{ + if (p->calls->dial_digits) { + p->calls->dial_digits(p->chan_pvt, dial_string); + } +} + /*! * \internal * \brief Reevaluate the PRI span device state. @@ -1459,6 +1468,7 @@ static int pri_fixup_principle(struct sig_pri_span *pri, int principle, q931_cal #if defined(HAVE_PRI_SETUP_KEYPAD) strcpy(new_chan->keypad_digits, old_chan->keypad_digits); #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ + strcpy(new_chan->deferred_digits, old_chan->deferred_digits); strcpy(new_chan->moh_suggested, old_chan->moh_suggested); new_chan->moh_state = old_chan->moh_state; old_chan->moh_state = SIG_PRI_MOH_STATE_IDLE; @@ -6567,14 +6577,28 @@ static void *pri_dchannel(void *vpri) #endif /* defined(HAVE_PRI_CALL_WAITING) */ sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.subcmds, e->answer.call); - if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_CONNECT) { - pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + if (!ast_strlen_zero(pri->pvts[chanpos]->deferred_digits)) { + /* We have some 'w' deferred digits to dial now. */ + ast_verb(3, + "Span %d: Channel %d/%d dialing deferred digit string: %s\n", + pri->span, pri->pvts[chanpos]->logicalspan, + pri->pvts[chanpos]->prioffset, + pri->pvts[chanpos]->deferred_digits); + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_DEFER_DIAL) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_DEFER_DIAL; + } + sig_pri_dial_digits(pri->pvts[chanpos], + pri->pvts[chanpos]->deferred_digits); + } else { + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_CONNECT) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + } + sig_pri_open_media(pri->pvts[chanpos]); + pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER); + sig_pri_set_dialing(pri->pvts[chanpos], 0); + /* Enable echo cancellation if it's not on already */ + sig_pri_set_echocanceller(pri->pvts[chanpos], 1); } - sig_pri_open_media(pri->pvts[chanpos]); - pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER); - /* Enable echo cancellation if it's not on already */ - sig_pri_set_dialing(pri->pvts[chanpos], 0); - sig_pri_set_echocanceller(pri->pvts[chanpos], 1); #ifdef SUPPORT_USERUSER if (!ast_strlen_zero(e->answer.useruserinfo)) { @@ -7331,7 +7355,14 @@ void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdes if (strlen(number) < p->stripmsd) { number = ""; } else { + char *deferred; + number += p->stripmsd; + deferred = strchr(number, 'w'); + if (deferred) { + /* Remove any 'w' deferred digits. */ + *deferred = '\0'; + } while (isalpha(*number)) { ++number; } @@ -7447,7 +7478,6 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd } dialed_subaddress.str = s; dialed_subaddress.valid = 1; - s = NULL; } l = NULL; @@ -7476,6 +7506,21 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); return -1; } + + /* Extract any 'w' deferred digits. */ + s = strchr(c + p->stripmsd, 'w'); + if (s) { + *s++ = '\0'; + ast_copy_string(p->deferred_digits, s, sizeof(p->deferred_digits)); + /* + * Since we have a 'w', this means that there will not be any + * more normal dialed digits. Therefore, the sending complete + * ie needs to be sent with any normal digits. + */ + } else { + p->deferred_digits[0] = '\0'; + } + pri_grab(p, p->pri); if (!(p->call = pri_new_call(p->pri->pri))) { ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); @@ -7483,7 +7528,8 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd return -1; } if (!(sr = pri_sr_new())) { - ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); + ast_log(LOG_WARNING, "Failed to allocate setup request on channel %d\n", + p->channel); pri_destroycall(p->pri->pri, p->call); p->call = NULL; pri_rel(p->pri); @@ -8258,6 +8304,40 @@ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char return 1; } +/*! + * \brief DTMF dial string complete. + * \since 1.8.11 + * + * \param pvt sig_pri private channel structure. + * \param ast Asterisk channel + * + * \note Channel and private lock are already held. + * + * \return Nothing + */ +void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast) +{ + /* If we just completed 'w' deferred dialing digits, we need to answer now. */ + if (pvt->call_level == SIG_PRI_CALL_LEVEL_DEFER_DIAL) { + pvt->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + + sig_pri_open_media(pvt); + { + struct ast_frame f = {AST_FRAME_CONTROL, }; + + if (pvt->calls->queue_control) { + pvt->calls->queue_control(pvt->chan_pvt, AST_CONTROL_ANSWER); + } + + f.subclass.integer = AST_CONTROL_ANSWER; + ast_queue_frame(ast, &f); + } + sig_pri_set_dialing(pvt, 0); + /* Enable echo cancellation if it's not on already */ + sig_pri_set_echocanceller(pvt, 1); + } +} + #if defined(HAVE_PRI_MWI) /*! * \internal diff --git a/channels/sig_pri.h b/channels/sig_pri.h index e10e4c7c3..dc9f5789a 100644 --- a/channels/sig_pri.h +++ b/channels/sig_pri.h @@ -156,6 +156,8 @@ enum sig_pri_call_level { SIG_PRI_CALL_LEVEL_PROCEEDING, /*! Called party is being alerted of the call. (ALERTING) */ SIG_PRI_CALL_LEVEL_ALERTING, + /*! Call is dialing 'w' deferred digits. (CONNECT) */ + SIG_PRI_CALL_LEVEL_DEFER_DIAL, /*! Call is connected/answered. (CONNECT) */ SIG_PRI_CALL_LEVEL_CONNECT, }; @@ -199,6 +201,7 @@ struct sig_pri_callback { const char *(* const get_orig_dialstring)(void *pvt); void (* const make_cc_dialstring)(void *pvt, char *buf, size_t buf_size); void (* const update_span_devstate)(struct sig_pri_span *pri); + void (* const dial_digits)(void *pvt, const char *dial_string); void (* const open_media)(void *pvt); @@ -290,6 +293,8 @@ struct sig_pri_chan { /*! \brief Keypad digits that came in with the SETUP message. */ char keypad_digits[AST_MAX_EXTENSION]; #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */ + /*! 'w' deferred dialing digits. */ + char deferred_digits[AST_MAX_EXTENSION]; /*! Music class suggested with AST_CONTROL_HOLD. */ char moh_suggested[MAX_MUSICCLASS]; enum sig_pri_moh_state moh_state; @@ -605,6 +610,7 @@ void sig_pri_init_pri(struct sig_pri_span *pri); /* If return 0, it means this function was able to handle it (pre setup digits). If non zero, the user of this * functions should handle it normally (generate inband DTMF) */ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit); +void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast); void sig_pri_stop_pri(struct sig_pri_span *pri); int sig_pri_start_pri(struct sig_pri_span *pri); |