From cfac26639039c9b14ae7f6ab025c3cef19219730 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Mon, 12 May 2014 22:45:13 +0000 Subject: [PATCH] libpri: Add control of inband audio progress indication ie to the SETUP_ACKNOWLEDGE message. Added support to the libpri API to control the inband audio available progress indication ie on the SETUP_ACKNOWLEDGE message. * Added the progress indication ie progressmask value to the struct pri_event_setup_ack so the PRI_EVENT_SETUP_ACK event can indicate when a SETUP_ACKNOWLEDGE comes in with inband audio (ie dialtone). * Added pri_setup_ack() so when the SETUP_ACKNOWLEDGE message is sent it can indicate if inband audio is present (ie dialtone). This patch and a corresponding change in Asterisk work together to allow Asterisk to control the inband audio available progress indication ie on the SETUP_ACKNOWLEDGE message when dialtone is present. AST-1338 #close Reported by: Tyler Stewart Review: https://reviewboard.asterisk.org/r/3520/ git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2320 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- libpri.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------ pri.c | 10 ++++++++- pri_q931.h | 2 +- q931.c | 38 ++++++++++++++++++++++--------- 4 files changed, 96 insertions(+), 20 deletions(-) diff --git a/libpri.h b/libpri.h index b1f8a3d..4fb94f2 100644 --- a/libpri.h +++ b/libpri.h @@ -1213,6 +1213,7 @@ typedef struct pri_event_setup_ack { int channel; q931_call *call; struct pri_subcommands *subcmds; + int progressmask; } pri_event_setup_ack; typedef struct pri_event_notify { @@ -1408,8 +1409,17 @@ const char *pri_facility_error2str(int facility_error_code); */ const char *pri_facility_reject2str(int facility_reject_code); -/* Acknowledge a call and place it on the given channel. Set info to non-zero if there - is in-band data available on the channel */ +/*! + * \brief Send the ALERTING message. + * + * \param pri D channel controller. + * \param call Q.931 call leg. + * \param channel Encoded channel id to use. If zero do not change channel id. + * \param info Nonzero to include a progress ie indicating inband audio available (ie ringback). + * + * \retval 0 on success. + * \retval -1 on error. + */ int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info); /* Send a digit in overlap mode */ @@ -1419,12 +1429,44 @@ int pri_information(struct pri *pri, q931_call *call, char digit); /* Send a keypad facility string of digits */ int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits); -/* Answer the incomplete(call without called number) call on the given channel. - Set non-isdn to non-zero if you are not connecting to ISDN equipment */ +/*! + * \brief Send the SETUP_ACKNOWLEDGE message. + * + * \param pri D channel controller. + * \param call Q.931 call leg. + * \param channel Encoded channel id to use. If zero do not change channel id. + * \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN. + * + * \retval 0 on success. + * \retval -1 on error. + */ int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn); -/* Answer(CONNECT) the call on the given channel. - Set non-isdn to non-zero if you are not connecting to ISDN equipment */ +/*! + * \brief Send the SETUP_ACKNOWLEDGE message. + * + * \param ctrl D channel controller. + * \param call Q.931 call leg. + * \param channel Encoded channel id to use. If zero do not change channel id. + * \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN. + * \param inband Nonzero to include a progress ie indicating inband audio available (ie dialtone). + * + * \retval 0 on success. + * \retval -1 on error. + */ +int pri_setup_ack(struct pri *ctrl, q931_call *call, int channel, int nonisdn, int inband); + +/*! + * \brief Send the CONNECT message. + * + * \param pri D channel controller. + * \param call Q.931 call leg. + * \param channel Encoded channel id to use. If zero do not change channel id. + * \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN. + * + * \retval 0 on success. + * \retval -1 on error. + */ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn); /*! @@ -1692,7 +1734,17 @@ int pri_progress(struct pri *pri, q931_call *c, int channel, int info); int pri_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause); #define PRI_PROCEEDING_FULL -/* Send call proceeding */ +/*! + * \brief Send the PROCEEDING message. + * + * \param pri D channel controller. + * \param c Q.931 call leg. + * \param channel Encoded channel id to use. If zero do not change channel id. + * \param info Nonzero to include a progress ie indicating inband audio available. + * + * \retval 0 on success. + * \retval -1 on error. + */ int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info); /* Enable inband progress when a DISCONNECT is received */ diff --git a/pri.c b/pri.c index 340e239..a7c8368 100644 --- a/pri.c +++ b/pri.c @@ -939,7 +939,15 @@ int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisd if (!pri || !pri_is_call_valid(pri, call)) { return -1; } - return q931_setup_ack(pri, call, channel, nonisdn); + return q931_setup_ack(pri, call, channel, nonisdn, 0); +} + +int pri_setup_ack(struct pri *ctrl, q931_call *call, int channel, int nonisdn, int inband) +{ + if (!ctrl || !pri_is_call_valid(ctrl, call)) { + return -1; + } + return q931_setup_ack(ctrl, call, channel, nonisdn, inband); } int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn) diff --git a/pri_q931.h b/pri_q931.h index 3a14b41..2c9f083 100644 --- a/pri_q931.h +++ b/pri_q931.h @@ -468,7 +468,7 @@ extern int q931_notify(struct pri *pri, q931_call *call, int channel, int info); extern int q931_call_proceeding(struct pri *pri, q931_call *call, int channel, int info); -extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int nonisdn); +extern int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn, int inband); extern int q931_information(struct pri *pri, q931_call *call, char digit); diff --git a/q931.c b/q931.c index f729bae..e87f06c 100644 --- a/q931.c +++ b/q931.c @@ -2807,7 +2807,8 @@ static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call * { call->progloc = ie->data[0] & 0xf; call->progcode = (ie->data[0] & 0x60) >> 5; - switch (call->progress = (ie->data[1] & 0x7f)) { + call->progress = (ie->data[1] & 0x7f); + switch (call->progress) { case Q931_PROG_CALL_NOT_E2E_ISDN: call->progressmask |= PRI_PROG_CALL_NOT_E2E_ISDN; break; @@ -3084,7 +3085,9 @@ static void q931_apdu_msg_expire(struct pri *ctrl, struct q931_call *call, int m static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) { - int code, mask; + int code; + int mask; + /* Can't send progress indicator on GR-303 -- EVER! */ if (ctrl->link.next && !ctrl->bri) return 0; @@ -5755,9 +5758,14 @@ int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info) return send_message(ctrl, c, Q931_ALERTING, alerting_ies); } -static int setup_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, -1 }; +static int setup_ack_ies[] = { + Q931_CHANNEL_IDENT, + Q931_IE_FACILITY, + Q931_PROGRESS_INDICATOR, + -1 +}; -int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn) +int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn, int inband) { if (c->ourcallstate == Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE) { /* Cannot send this message when in this state */ @@ -5770,12 +5778,20 @@ int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn) } c->chanflags &= ~FLAG_PREFERRED; c->chanflags |= FLAG_EXCLUSIVE; + + c->progressmask = 0; if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) { - c->progloc = LOC_PRIV_NET_LOCAL_USER; + c->progloc = LOC_PRIV_NET_LOCAL_USER; c->progcode = CODE_CCITT; - c->progressmask = PRI_PROG_CALLED_NOT_ISDN; - } else - c->progressmask = 0; + c->progressmask |= PRI_PROG_CALLED_NOT_ISDN; + } + if (inband) { + /* Inband audio is present (i.e. dialtone) */ + c->progloc = LOC_PRIV_NET_LOCAL_USER; + c->progcode = CODE_CCITT; + c->progressmask |= PRI_PROG_INBAND_AVAILABLE; + } + UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_RECEIVING); c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING; c->alive = 1; @@ -5876,7 +5892,7 @@ int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn) c->chanflags &= ~FLAG_PREFERRED; c->chanflags |= FLAG_EXCLUSIVE; if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) { - c->progloc = LOC_PRIV_NET_LOCAL_USER; + c->progloc = LOC_PRIV_NET_LOCAL_USER; c->progcode = CODE_CCITT; c->progressmask = PRI_PROG_CALLED_NOT_ISDN; } else @@ -7243,6 +7259,7 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca c->useruserinfo[0] = '\0'; c->cause = -1; /* Fall through */ + case Q931_SETUP_ACKNOWLEDGE: case Q931_CALL_PROCEEDING: c->progress = -1; c->progressmask = 0; @@ -7289,8 +7306,6 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca break; case Q931_STATUS_ENQUIRY: break; - case Q931_SETUP_ACKNOWLEDGE: - break; case Q931_NOTIFY: c->notify = -1; q931_party_number_init(&c->redirection_number); @@ -9199,6 +9214,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct ctrl->ev.setup_ack.subcmds = &ctrl->subcmds; ctrl->ev.setup_ack.channel = q931_encode_channel(c); ctrl->ev.setup_ack.call = c->master_call; + ctrl->ev.setup_ack.progressmask = c->progressmask; for (cur = c->apdus; cur; cur = cur->next) { if (!cur->sent && cur->message == Q931_FACILITY) {