[asterisk-commits] rmudgett: branch rmudgett/bch_shift_v1.8 r311486 - /team/rmudgett/bch_shift_v...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 21 12:57:46 CDT 2011
Author: rmudgett
Date: Mon Mar 21 12:57:42 2011
New Revision: 311486
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311486
Log:
Initial work before testing.
Modified:
team/rmudgett/bch_shift_v1.8/channels/chan_dahdi.c
team/rmudgett/bch_shift_v1.8/channels/sig_pri.c
Modified: team/rmudgett/bch_shift_v1.8/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.8/channels/chan_dahdi.c?view=diff&rev=311486&r1=311485&r2=311486
==============================================================================
--- team/rmudgett/bch_shift_v1.8/channels/chan_dahdi.c (original)
+++ team/rmudgett/bch_shift_v1.8/channels/chan_dahdi.c Mon Mar 21 12:57:42 2011
@@ -8710,14 +8710,27 @@
static struct ast_frame *dahdi_read(struct ast_channel *ast)
{
- struct dahdi_pvt *p = ast->tech_pvt;
+ struct dahdi_pvt *p;
int res;
int idx;
void *readbuf;
struct ast_frame *f;
+ /*
+ * For analog channels, we must do deadlock avoidance because
+ * analog ports can have more than one Asterisk channel using
+ * the same private structure.
+ */
+ p = ast->tech_pvt;
while (ast_mutex_trylock(&p->lock)) {
CHANNEL_DEADLOCK_AVOIDANCE(ast);
+
+ /*
+ * For PRI channels, we must refresh the private pointer because
+ * the call could move to another B channel while the Asterisk
+ * channel is unlocked.
+ */
+ p = ast->tech_pvt;
}
idx = dahdi_get_index(ast, p, 0);
Modified: team/rmudgett/bch_shift_v1.8/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.8/channels/sig_pri.c?view=diff&rev=311486&r1=311485&r2=311486
==============================================================================
--- team/rmudgett/bch_shift_v1.8/channels/sig_pri.c (original)
+++ team/rmudgett/bch_shift_v1.8/channels/sig_pri.c Mon Mar 21 12:57:42 2011
@@ -1101,6 +1101,70 @@
/*!
* \internal
+ * \brief Find the channel associated with the libpri call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_principle_by_call(struct sig_pri_span *pri, q931_call *call)
+{
+ int idx;
+
+ if (!call) {
+ /* Cannot find a call without a call. */
+ return -1;
+ }
+ for (idx = 0; idx < pri->numchans; ++idx) {
+ if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
+ /* Found the principle */
+ return idx;
+ }
+ }
+ return -1;
+}
+
+/*!
+ * \internal
+ * \brief Kill the call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ * \param cause Reason call was killed.
+ *
+ * \note Assumes the pvt->pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_kill_call(struct sig_pri_span *pri, q931_call *call, int cause)
+{
+ int chanpos;
+
+ chanpos = pri_find_principle_by_call(pri, call);
+ if (chanpos < 0) {
+ pri_hangup(pri->pri, call, cause);
+ return;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ if (!pri->pvts[chanpos]->owner) {
+ pri_hangup(pri->pri, call, cause);
+ pri->pvts[chanpos]->call = NULL;
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ return;
+ }
+ pri->pvts[chanpos]->owner->hangupcause = cause;
+ pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+}
+
+/*!
+ * \internal
* \brief Find the private structure for the libpri call.
*
* \param pri PRI span control structure.
@@ -1325,6 +1389,52 @@
return -1;
}
+/*!
+ * \internal
+ * \brief Find and fixup the private structure associated with the libpri call.
+ *
+ * \param pri PRI span control structure.
+ * \param channel LibPRI encoded channel ID.
+ * \param call LibPRI opaque call pointer.
+ *
+ * \details
+ * This is a combination of pri_find_principle() and pri_fixup_principle()
+ * to reduce code redundancy and to make handling several PRI_EVENT_xxx's
+ * consistent for the current architecture.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_fixup_principle(struct sig_pri_span *pri, int channel, q931_call *call)
+{
+ int chanpos;
+
+ chanpos = pri_find_principle(pri, channel, call);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
+ pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+ sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
+ return -1;
+ }
+ chanpos = pri_fixup_principle(pri, chanpos, call);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
+ pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+ /*
+ * Using Q.931 section 5.2.3.1 b) as the reason for picking
+ * PRI_CAUSE_CHANNEL_UNACCEPTABLE. Receiving a
+ * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
+ * that channel (which is not specified by Q.931) and kill some
+ * other call which would be bad.
+ */
+ sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
+ return -1;
+ }
+ return chanpos;
+}
+
static char * redirectingreason2str(int redirectingreason)
{
switch (redirectingreason) {
@@ -1502,34 +1612,6 @@
idx = -1;
}
return idx;
-}
-#endif /* defined(HAVE_PRI_CALL_HOLD) */
-
-#if defined(HAVE_PRI_CALL_HOLD)
-/*!
- * \internal
- * \brief Find the channel associated with the libpri call.
- * \since 1.8
- *
- * \param pri PRI span control structure.
- * \param call LibPRI opaque call pointer to find.
- *
- * \note Assumes the pri->lock is already obtained.
- *
- * \retval array-index into private pointer array on success.
- * \retval -1 on error.
- */
-static int pri_find_pri_call(struct sig_pri_span *pri, q931_call *call)
-{
- int idx;
-
- for (idx = 0; idx < pri->numchans; ++idx) {
- if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
- /* Found the channel */
- return idx;
- }
- }
- return -1;
}
#endif /* defined(HAVE_PRI_CALL_HOLD) */
@@ -2062,8 +2144,8 @@
c2.held = call_2_held;
call_2 = &c2;
- call_1->chanpos = pri_find_pri_call(pri, call_1->pri);
- call_2->chanpos = pri_find_pri_call(pri, call_2->pri);
+ call_1->chanpos = pri_find_principle_by_call(pri, call_1->pri);
+ call_2->chanpos = pri_find_principle_by_call(pri, call_2->pri);
if (call_1->chanpos < 0 || call_2->chanpos < 0) {
/* Calls not found in span control. */
if (rsp_callback) {
@@ -4161,11 +4243,9 @@
struct ast_channel *bridged;
struct ast_channel *owner;
- chanpos_old = pri_find_principle(pri, ev->hold.channel, ev->hold.call);
+ chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
if (chanpos_old < 0) {
- ast_log(LOG_WARNING,
- "Received HOLD on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(ev->hold.channel), PRI_CHANNEL(ev->hold.channel), pri->span);
+ ast_log(LOG_WARNING, "Span %d: Received HOLD for unknown call.\n", pri->span);
return -1;
}
if (pri->pvts[chanpos_old]->no_b_channel) {
@@ -4238,9 +4318,14 @@
{
int chanpos;
- if (!(ev->retrieve.channel & PRI_HELD_CALL)
- || pri_find_principle(pri, ev->retrieve.channel, ev->retrieve.call) < 0) {
+ if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
/* The call is not currently held. */
+ pri_retrieve_rej(pri->pri, ev->retrieve.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ return;
+ }
+ if (pri_find_principle_by_call(pri, ev->retrieve.call) < 0) {
+ ast_log(LOG_WARNING, "Span %d: Received RETRIEVE for unknown call.\n", pri->span);
pri_retrieve_rej(pri->pri, ev->retrieve.call,
PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
return;
@@ -4251,7 +4336,7 @@
chanpos = pri_find_principle(pri,
ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
if (ev->retrieve.flexible
- && (chanpos < 0 || pri->pvts[chanpos]->owner)) {
+ && (chanpos < 0 || pri->pvts[chanpos]->owner || pri->pvts[chanpos]->call)) {
/*
* Channel selection is flexible and the requested channel
* is bad or already in use. Pick another channel.
@@ -4310,6 +4395,7 @@
int nextidle = -1;
int haveidles;
int activeidles;
+ unsigned int len;
gettimeofday(&lastidle, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
@@ -4603,33 +4689,29 @@
e->digit.call);
break;
}
- chanpos = pri_find_principle(pri, e->digit.channel, e->digit.call);
+ chanpos = pri_find_principle_by_call(pri, e->digit.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
- e->digit.subcmds, e->digit.call);
- /* 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) {
- /* how to do that */
- int digitlen = strlen(e->digit.digits);
- int i;
-
- for (i = 0; i < digitlen; i++) {
- struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
-
- pri_queue_frame(pri, chanpos, &f);
- }
- }
- sig_pri_unlock_private(pri->pvts[chanpos]);
+ ast_log(LOG_WARNING,
+ "Span %d: Received keypad digits for unknown call.\n", pri->span);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
+ e->digit.subcmds, e->digit.call);
+ /* 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]->owner) {
+ /* how to do that */
+ int digitlen = strlen(e->digit.digits);
+ int i;
+
+ for (i = 0; i < digitlen; i++) {
+ struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
+
+ pri_queue_frame(pri, chanpos, &f);
}
}
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_INFO_RECEIVED:
@@ -4638,33 +4720,29 @@
e->ring.call);
break;
}
- chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
+ chanpos = pri_find_principle_by_call(pri, e->ring.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
- e->ring.subcmds, e->ring.call);
- /* 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) {
- /* how to do that */
- int digitlen = strlen(e->ring.callednum);
- int i;
-
- for (i = 0; i < digitlen; i++) {
- struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
-
- pri_queue_frame(pri, chanpos, &f);
- }
- }
- sig_pri_unlock_private(pri->pvts[chanpos]);
+ ast_log(LOG_WARNING,
+ "Span %d: Received INFORMATION for unknown call.\n", pri->span);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
+ e->ring.subcmds, e->ring.call);
+ /* 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]->owner) {
+ /* how to do that */
+ int digitlen = strlen(e->ring.callednum);
+ int i;
+
+ for (i = 0; i < digitlen; i++) {
+ struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
+
+ pri_queue_frame(pri, chanpos, &f);
}
}
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
#if defined(HAVE_PRI_SERVICE_MESSAGES)
case PRI_EVENT_SERVICE:
@@ -4763,6 +4841,17 @@
} else {
/* A channel is specified. */
chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
+/*!
+ * Define to make always pick a channel if allowed. Useful for
+ * testing channel shifting.
+ */
+//#define ALWAYS_PICK_CHANNEL 1
+#define ALWAYS_PICK_CHANNEL 1 //BUGBUG
+#if defined(ALWAYS_PICK_CHANNEL)
+ if (e->ring.flexible) {
+ chanpos = pri_find_empty_chan(pri, 1);
+ }
+#endif /* defined(ALWAYS_PICK_CHANNEL) */
}
/* if no channel specified find one empty */
if (chanpos < 0) {
@@ -5137,55 +5226,47 @@
e->ringing.call);
break;
}
- chanpos = pri_find_principle(pri, e->ringing.channel, e->ringing.call);
+ chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
+ e->ringing.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
- PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
- } else {
- sig_pri_lock_private(pri->pvts[chanpos]);
-
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
- e->ringing.subcmds, e->ringing.call);
- sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
- sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
- pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
- if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
- pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
- }
-
- if (
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
+ e->ringing.subcmds, e->ringing.call);
+ sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
+ sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
+ pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
+ if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
+ pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
+ }
+
+ if (
#ifdef PRI_PROGRESS_MASK
- e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
+ e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
- e->ringing.progress == 8
+ e->ringing.progress == 8
#endif
- ) {
- sig_pri_open_media(pri->pvts[chanpos]);
- }
-
+ ) {
+ sig_pri_open_media(pri->pvts[chanpos]);
+ }
#ifdef SUPPORT_USERUSER
- if (!ast_strlen_zero(e->ringing.useruserinfo)) {
- struct ast_channel *owner;
-
- sig_pri_lock_owner(pri, chanpos);
- owner = pri->pvts[chanpos]->owner;
- if (owner) {
- pbx_builtin_setvar_helper(owner, "USERUSERINFO",
- e->ringing.useruserinfo);
- ast_channel_unlock(owner);
- }
- }
+ if (!ast_strlen_zero(e->ringing.useruserinfo)) {
+ struct ast_channel *owner;
+
+ sig_pri_lock_owner(pri, chanpos);
+ owner = pri->pvts[chanpos]->owner;
+ if (owner) {
+ pbx_builtin_setvar_helper(owner, "USERUSERINFO",
+ e->ringing.useruserinfo);
+ ast_channel_unlock(owner);
+ }
+ }
#endif
- sig_pri_unlock_private(pri->pvts[chanpos]);
- }
- }
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_PROGRESS:
if (sig_pri_is_cis_call(e->proceeding.channel)) {
@@ -5193,44 +5274,48 @@
e->proceeding.call);
break;
}
- chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
- e->proceeding.subcmds, e->proceeding.call);
-
- if (e->proceeding.cause > -1) {
- ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
-
- /* Work around broken, out of spec USER_BUSY cause in a progress message */
- if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
- if (pri->pvts[chanpos]->owner) {
- ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-
- pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
- pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
- }
+ chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+ e->proceeding.call);
+ if (chanpos < 0) {
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
+ e->proceeding.subcmds, e->proceeding.call);
+
+ if (e->proceeding.cause > -1) {
+ ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
+
+ /* Work around broken, out of spec USER_BUSY cause in a progress message */
+ if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
+ if (pri->pvts[chanpos]->owner) {
+ ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
+
+ pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
+ pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
}
}
-
- if (!pri->pvts[chanpos]->progress
- && !pri->pvts[chanpos]->no_b_channel
+ }
+
+ if (!pri->pvts[chanpos]->progress
+ && !pri->pvts[chanpos]->no_b_channel
#ifdef PRI_PROGRESS_MASK
- && (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+ && (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
#else
- && e->proceeding.progress == 8
+ && e->proceeding.progress == 8
#endif
- ) {
- /* Bring voice path up */
- ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
- pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
- pri->pvts[chanpos]->progress = 1;
- sig_pri_set_dialing(pri->pvts[chanpos], 0);
- sig_pri_open_media(pri->pvts[chanpos]);
- }
- sig_pri_unlock_private(pri->pvts[chanpos]);
- }
+ ) {
+ /* Bring voice path up */
+ ast_debug(1,
+ "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
+ pri->span);
+ pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
+ pri->pvts[chanpos]->progress = 1;
+ sig_pri_set_dialing(pri->pvts[chanpos], 0);
+ sig_pri_open_media(pri->pvts[chanpos]);
+ }
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_PROCEEDING:
if (sig_pri_is_cis_call(e->proceeding.channel)) {
@@ -5238,33 +5323,37 @@
e->proceeding.call);
break;
}
- chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
- e->proceeding.subcmds, e->proceeding.call);
- if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
- pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
- ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
- pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
- }
- if (!pri->pvts[chanpos]->progress
- && !pri->pvts[chanpos]->no_b_channel
+ chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+ e->proceeding.call);
+ if (chanpos < 0) {
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
+ e->proceeding.subcmds, e->proceeding.call);
+ if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
+ pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
+ ast_debug(1,
+ "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
+ pri->span);
+ pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
+ }
+ if (!pri->pvts[chanpos]->progress
+ && !pri->pvts[chanpos]->no_b_channel
#ifdef PRI_PROGRESS_MASK
- && (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+ && (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
#else
- && e->proceeding.progress == 8
+ && e->proceeding.progress == 8
#endif
- ) {
- /* Bring voice path up */
- pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
- pri->pvts[chanpos]->progress = 1;
- sig_pri_set_dialing(pri->pvts[chanpos], 0);
- sig_pri_open_media(pri->pvts[chanpos]);
- }
- sig_pri_unlock_private(pri->pvts[chanpos]);
- }
+ ) {
+ /* Bring voice path up */
+ pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
+ pri->pvts[chanpos]->progress = 1;
+ sig_pri_set_dialing(pri->pvts[chanpos], 0);
+ sig_pri_open_media(pri->pvts[chanpos]);
+ }
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_FACILITY:
if (!e->facility.call || sig_pri_is_cis_call(e->facility.channel)) {
@@ -5278,27 +5367,21 @@
#endif /* !defined(HAVE_PRI_CALL_REROUTING) */
break;
}
- chanpos = pri_find_principle(pri, e->facility.channel, e->facility.call);
+ chanpos = pri_find_principle_by_call(pri, e->facility.call);
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 {
- sig_pri_lock_private(pri->pvts[chanpos]);
+ ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
+ pri->span);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
#if defined(HAVE_PRI_CALL_REROUTING)
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
- e->facility.subcmds, e->facility.subcall);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+ e->facility.subcmds, e->facility.subcall);
#else
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
- e->facility.subcmds, e->facility.call);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+ e->facility.subcmds, e->facility.call);
#endif /* !defined(HAVE_PRI_CALL_REROUTING) */
- sig_pri_unlock_private(pri->pvts[chanpos]);
- }
- }
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_ANSWER:
if (sig_pri_is_cis_call(e->answer.channel)) {
@@ -5310,16 +5393,8 @@
e->answer.call);
break;
}
- chanpos = pri_find_principle(pri, e->answer.channel, e->answer.call);
+ chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
- break;
- }
- chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
- if (chanpos < 0) {
- 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);
break;
}
#if defined(HAVE_PRI_CALL_WAITING)
@@ -5332,11 +5407,23 @@
* kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
*/
new_chanpos = pri_find_empty_chan(pri, 1);
+ if (0 <= new_chanpos) {
+ new_chanpos = pri_fixup_principle(pri, new_chanpos,
+ e->answer.call);
+ }
if (new_chanpos < 0) {
+ /*
+ * Either no channel was available or someone stole
+ * the channel!
+ */
+ ast_verb(3,
+ "Span %d: Channel not available for call waiting call.\n",
+ pri->span);
sig_pri_lock_private(pri->pvts[chanpos]);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
e->answer.subcmds, e->answer.call);
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+ sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
pri->pvts[chanpos]->owner->hangupcause = PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION;
switch (pri->pvts[chanpos]->owner->_state) {
@@ -5348,6 +5435,7 @@
pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
}
+ ast_channel_unlock(pri->pvts[chanpos]->owner);
} else {
pri->pvts[chanpos]->is_call_waiting = 0;
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
@@ -5357,13 +5445,7 @@
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
}
- chanpos = pri_fixup_principle(pri, new_chanpos, e->answer.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING,
- "Unable to move call waiting call channel on span %d\n",
- pri->span);
- break;
- }
+ chanpos = new_chanpos;
}
pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
} else {
@@ -5414,19 +5496,9 @@
e->connect_ack.call);
break;
}
- chanpos = pri_find_principle(pri, e->connect_ack.channel,
+ chanpos = pri_find_fixup_principle(pri, e->connect_ack.channel,
e->connect_ack.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Connect ACK on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->connect_ack.channel),
- PRI_CHANNEL(e->connect_ack.channel), pri->span);
- break;
- }
- chanpos = pri_fixup_principle(pri, chanpos, e->connect_ack.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Connect ACK requested on channel %d/%d not in use on span %d\n",
- PRI_SPAN(e->connect_ack.channel),
- PRI_CHANNEL(e->connect_ack.channel), pri->span);
break;
}
@@ -5445,130 +5517,119 @@
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
- chanpos = pri_find_principle(pri, e->hangup.channel, e->hangup.call);
+ chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
/*
* Continue hanging up the call even though
- * it is on an unconfigured channel.
+ * we do not remember it (if we ever did).
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
- e->hangup.subcmds, e->hangup.call);
- if (!pri->pvts[chanpos]->alreadyhungup) {
- /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
- pri->pvts[chanpos]->alreadyhungup = 1;
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
+ e->hangup.subcmds, e->hangup.call);
+ if (!pri->pvts[chanpos]->alreadyhungup) {
+ /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
+ pri->pvts[chanpos]->alreadyhungup = 1;
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+ break;
+ default:
+ break;
+ }
+ if (pri->pvts[chanpos]->owner) {
+ int do_hangup = 0;
+ /* Queue a BUSY instead of a hangup if our cause is appropriate */
+ pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+ switch (pri->pvts[chanpos]->owner->_state) {
+ case AST_STATE_BUSY:
+ case AST_STATE_UP:
+ do_hangup = 1;
+ break;
+ default:
+ if (!pri->pvts[chanpos]->outgoing) {
+ /*
+ * The incoming call leg hung up before getting
+ * connected so just hangup the call.
+ */
+ do_hangup = 1;
+ break;
+ }
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
+ pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
default:
+ do_hangup = 1;
break;
}
- if (pri->pvts[chanpos]->owner) {
- int do_hangup = 0;
- /* Queue a BUSY instead of a hangup if our cause is appropriate */
- pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (pri->pvts[chanpos]->owner->_state) {
- case AST_STATE_BUSY:
- case AST_STATE_UP:
- do_hangup = 1;
- break;
- default:
- if (!pri->pvts[chanpos]->outgoing) {
- /*
- * The incoming call leg hung up before getting
- * connected so just hangup the call.
- */
- do_hangup = 1;
- break;
- }
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- case PRI_CAUSE_SWITCH_CONGESTION:
- case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
- pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
- break;
- default:
- do_hangup = 1;
- break;
- }
- break;
- }
-
- if (do_hangup) {
+ break;
+ }
+
+ if (do_hangup) {
#if defined(HAVE_PRI_AOC_EVENTS)
- if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
- /* If a AOC-E msg was sent during the release, we must use a
- * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
- pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
- } else {
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- }
+ if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
+ /* If a AOC-E msg was sent during the release, we must use a
+ * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
+ pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+ } else {
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
#else
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
- }
- } else {
- /*
- * Continue hanging up the call even though
- * we do not have an owner.
- */
- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
- pri->pvts[chanpos]->call = NULL;
- }
- ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
- } else {
- /* Continue hanging up the call. */
- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
- pri->pvts[chanpos]->call = NULL;
}
- if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
- ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
- pri->pvts[chanpos]->resetting = 1;
- }
- if (e->hangup.aoc_units > -1)
- ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-
-#ifdef SUPPORT_USERUSER
- if (!ast_strlen_zero(e->hangup.useruserinfo)) {
- struct ast_channel *owner;
-
- sig_pri_lock_owner(pri, chanpos);
- owner = pri->pvts[chanpos]->owner;
- if (owner) {
- pbx_builtin_setvar_helper(owner, "USERUSERINFO",
- e->hangup.useruserinfo);
- ast_channel_unlock(owner);
- }
- }
-#endif
-
- sig_pri_unlock_private(pri->pvts[chanpos]);
} else {
/*
* Continue hanging up the call even though
- * we do not remember it (if we ever did).
+ * we do not have an owner.
*/
- pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
+ pri->pvts[chanpos]->call = NULL;
}
- }
+ ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
+ } else {
+ /* Continue hanging up the call. */
+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
+ pri->pvts[chanpos]->call = NULL;
+ }
+ if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+ ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
+ pri->pvts[chanpos]->resetting = 1;
+ }
+ if (e->hangup.aoc_units > -1)
+ ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
+
+#ifdef SUPPORT_USERUSER
+ if (!ast_strlen_zero(e->hangup.useruserinfo)) {
+ struct ast_channel *owner;
+
+ sig_pri_lock_owner(pri, chanpos);
+ owner = pri->pvts[chanpos]->owner;
+ if (owner) {
+ pbx_builtin_setvar_helper(owner, "USERUSERINFO",
+ e->hangup.useruserinfo);
+ ast_channel_unlock(owner);
+ }
+ }
+#endif
+
+ sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_HANGUP_REQ:
if (sig_pri_is_cis_call(e->hangup.channel)) {
@@ -5577,136 +5638,125 @@
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
- chanpos = pri_find_principle(pri, e->hangup.channel, e->hangup.call);
+ chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
/*
* Continue hanging up the call even though
- * it is on an unconfigured channel.
+ * we do not remember it (if we ever did).
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
- if (chanpos > -1) {
- sig_pri_lock_private(pri->pvts[chanpos]);
- sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
- e->hangup.subcmds, e->hangup.call);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
+ e->hangup.subcmds, e->hangup.call);
#if defined(HAVE_PRI_CALL_HOLD)
- if (e->hangup.call_active && e->hangup.call_held
- && pri->hold_disconnect_transfer) {
- /* We are to transfer the call instead of simply hanging up. */
- sig_pri_unlock_private(pri->pvts[chanpos]);
- if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
- e->hangup.call_active, 0, NULL, NULL)) {
- break;
- }
- sig_pri_lock_private(pri->pvts[chanpos]);
+ if (e->hangup.call_active && e->hangup.call_held
+ && pri->hold_disconnect_transfer) {
+ /* We are to transfer the call instead of simply hanging up. */
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
+ e->hangup.call_active, 0, NULL, NULL)) {
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ }
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+ break;
+ default:
+ break;
+ }
+ if (pri->pvts[chanpos]->owner) {
+ int do_hangup = 0;
+
+ pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+ switch (pri->pvts[chanpos]->owner->_state) {
+ case AST_STATE_BUSY:
+ case AST_STATE_UP:
+ do_hangup = 1;
+ break;
+ default:
+ if (!pri->pvts[chanpos]->outgoing) {
+ /*
+ * The incoming call leg hung up before getting
+ * connected so just hangup the call.
+ */
+ do_hangup = 1;
+ break;
}
-#endif /* defined(HAVE_PRI_CALL_HOLD) */
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
+ pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
default:
+ do_hangup = 1;
break;
}
- if (pri->pvts[chanpos]->owner) {
- int do_hangup = 0;
-
- pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (pri->pvts[chanpos]->owner->_state) {
- case AST_STATE_BUSY:
- case AST_STATE_UP:
- do_hangup = 1;
- break;
- default:
- if (!pri->pvts[chanpos]->outgoing) {
- /*
- * The incoming call leg hung up before getting
- * connected so just hangup the call.
- */
- do_hangup = 1;
- break;
- }
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
[... 322 lines stripped ...]
More information about the asterisk-commits
mailing list