[svn-commits] rmudgett: branch rmudgett/call_waiting r251399 - /team/rmudgett/call_waiting/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Mar 8 18:58:12 CST 2010


Author: rmudgett
Date: Mon Mar  8 18:58:08 2010
New Revision: 251399

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=251399
Log:
1) Resolve the channel to use for call waiting when the CONNECT message
comes in.

2) Track the number of outstanding PRI call waiting calls.

3) Simplified channel selection failed reason/cause code.

Modified:
    team/rmudgett/call_waiting/channels/chan_dahdi.c
    team/rmudgett/call_waiting/channels/sig_pri.c
    team/rmudgett/call_waiting/channels/sig_pri.h

Modified: team/rmudgett/call_waiting/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/chan_dahdi.c?view=diff&rev=251399&r1=251398&r2=251399
==============================================================================
--- team/rmudgett/call_waiting/channels/chan_dahdi.c (original)
+++ team/rmudgett/call_waiting/channels/chan_dahdi.c Mon Mar  8 18:58:08 2010
@@ -12202,7 +12202,7 @@
 			int res;
 
 			pvt_chan = p->sig_pvt;
-			res = sig_pri_available(&pvt_chan, reason, is_specific_channel);
+			res = sig_pri_available(&pvt_chan, is_specific_channel);
 			*pvt = pvt_chan->chan_pvt;
 			return res;
 		}
@@ -12570,14 +12570,6 @@
 			&& available(&p, &unavailreason, channelmatched)) {
 			ast_debug(1, "Using channel %d\n", p->channel);
 
-			switch (p->sig) {
-			case SIG_PRI_LIB_HANDLE_CASES:
-				callwait = ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel;
-				break;
-			default:
-				callwait = (p->owner != NULL);
-				break;
-			}
 #ifdef HAVE_OPENR2
 			if (p->mfcr2) {
 				ast_mutex_lock(&p->lock);
@@ -12595,6 +12587,13 @@
 				if (!p) {
 					break;
 				}
+			}
+			switch (p->sig) {
+			case SIG_PRI_LIB_HANDLE_CASES:
+				break;
+			default:
+				callwait = (p->owner != NULL);
+				break;
 			}
 
 			/* Make special notes */
@@ -12633,6 +12632,18 @@
 			}
 			if (!tmp) {
 				p->outgoing = 0;
+#if defined(HAVE_PRI_CALL_WAITING)
+				switch (p->sig) {
+				case SIG_PRI_LIB_HANDLE_CASES:
+					if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
+						((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
+						ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
+					}
+					break;
+				default:
+					break;
+				}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 			} else {
 				snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
 			}
@@ -12656,14 +12667,10 @@
 	}
 	ast_mutex_unlock(&iflock);
 	restart_monitor();
-	if (callwait)
+	if (!tmp) {
 		*cause = AST_CAUSE_BUSY;
-	else if (!tmp) {
-		if (channelmatched) {
-			if (unavailreason)
-				*cause = AST_CAUSE_BUSY;
-		} else if (groupmatched) {
-			*cause = (unavailreason) ? unavailreason : AST_CAUSE_CONGESTION;
+		if (!callwait && groupmatched) {
+			*cause = AST_CAUSE_CONGESTION;
 		}
 	}
 

Modified: team/rmudgett/call_waiting/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/sig_pri.c?view=diff&rev=251399&r1=251398&r2=251399
==============================================================================
--- team/rmudgett/call_waiting/channels/sig_pri.c (original)
+++ team/rmudgett/call_waiting/channels/sig_pri.c Mon Mar  8 18:58:08 2010
@@ -928,15 +928,17 @@
 	int x;
 	int span;
 	int principle;
+	int prioffset;
 
 	if (channel < 0) {
 		/* Channel is not picked yet. */
 		return -1;
 	}
 
-	if (channel & PRI_HELD_CALL) {
+	prioffset = PRI_CHANNEL(channel);
+	if (!prioffset || (channel & PRI_HELD_CALL)) {
 		if (!call) {
-			/* Cannot find a held call without a call. */
+			/* Cannot find a call waiting call or held call without a call. */
 			return -1;
 		}
 		principle = -1;
@@ -961,11 +963,10 @@
 		span = pri->dchan_logical_span[index];
 	}
 
-	channel = PRI_CHANNEL(channel);
 	principle = -1;
 	for (x = 0; x < pri->numchans; x++) {
 		if (pri->pvts[x]
-			&& pri->pvts[x]->prioffset == channel
+			&& pri->pvts[x]->prioffset == prioffset
 			&& pri->pvts[x]->logicalspan == span
 			&& !pri->pvts[x]->no_b_channel) {
 			principle = x;
@@ -1033,6 +1034,10 @@
 		new_chan->setup_ack = old_chan->setup_ack;
 		new_chan->outgoing = old_chan->outgoing;
 		new_chan->digital = old_chan->digital;
+#if defined(HAVE_PRI_CALL_WAITING)
+		new_chan->is_call_waiting = old_chan->is_call_waiting;
+		old_chan->is_call_waiting = 0;
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 		old_chan->alerting = 0;
 		old_chan->alreadyhungup = 0;
 		old_chan->isidlecall = 0;
@@ -1207,9 +1212,6 @@
 			&& pri->pvts[idx]->no_b_channel
 			&& !pri->pvts[idx]->inalarm
 			&& !pri->pvts[idx]->owner) {
-#if defined(HAVE_PRI_CALL_WAITING)
-			pri->pvts[idx]->is_call_waiting = 0;
-#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 			ast_debug(1, "Found empty available no B channel interface\n");
 			return idx;
 		}
@@ -3064,10 +3066,20 @@
 						e->ring.call);
 					break;
 				}
-				if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF)
+				if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
+					/* Any channel requested. */
 					chanpos = pri_find_empty_chan(pri, 1);
-				else
+				} else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
+					/*
+					 * No channel specified.
+					 * We will not accept incoming call waiting calls.
+					 */
+					pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+					break;
+				} else {
+					/* A channel is specified. */
 					chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
+				}
 				/* if no channel specified find one empty */
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
@@ -3581,47 +3593,93 @@
 				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)
+				if (pri->pvts[chanpos]->is_call_waiting) {
+					if (pri->pvts[chanpos]->no_b_channel) {
+						int new_chanpos;
+
+						/*
+						 * Need to find a free channel now or
+						 * kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
+						 */
+						new_chanpos = pri_find_empty_chan(pri, 1);
+						if (new_chanpos < 0) {
+							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);
+							pri->pvts[chanpos]->alreadyhungup = 1;
+							pri_hangup(pri->pri, e->answer.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+							if (pri->pvts[chanpos]->owner) {
+								pri->pvts[chanpos]->owner->hangupcause = PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+								switch (pri->pvts[chanpos]->owner->_state) {
+								case AST_STATE_BUSY:
+								case AST_STATE_UP:
+									ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+									break;
+								default:
+									pri_queue_control(pri->pvts[chanpos], AST_CONTROL_CONGESTION, pri);
+									break;
+								}
+							} else {
+								pri->pvts[chanpos]->is_call_waiting = 0;
+								pri->pvts[chanpos]->call = NULL;
+								ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
+							}
+							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;
+						}
+					}
+					pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
 				} else {
-#if defined(HAVE_PRI_CALL_WAITING)
-/* BUGBUG need to handle the channel indication as in a SETUP: Specified, no alternative; specified, alternate acceptable; any channel; not present.  */
-					if (PRI_CHANNEL(e->answer.channel)) {
-						/* We already have a channel so do normal CONNECT_ACKNOWLEDGE. */
-						pri_connect_ack(pri->pri, e->answer.call, 0);
-					} else {
-/* BUGBUG need to find a free channel now or kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION. */
+					/* Call is normal so do normal CONNECT_ACKNOWLEDGE. */
+					pri_connect_ack(pri->pri, e->answer.call, 0);
+				}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+				sig_pri_lock_private(pri->pvts[chanpos]);
+
+				if (pri->pvts[chanpos]->is_call_waiting) {
+					pri->pvts[chanpos]->is_call_waiting = 0;
+					ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
+					sig_pri_span_devstate_changed(pri);
+				}
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
+					e->answer.subcmds, e->answer.call);
+				pri_queue_control(pri->pvts[chanpos], AST_CONTROL_ANSWER, pri);
+				/* 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)) {
+					struct ast_channel *owner;
+
+					sig_pri_lock_owner(pri, chanpos);
+					owner = pri->pvts[chanpos]->owner;
+					if (owner) {
+						pbx_builtin_setvar_helper(owner, "USERUSERINFO",
+							e->answer.useruserinfo);
+						ast_channel_unlock(owner);
 					}
-#endif	/* defined(HAVE_PRI_CALL_WAITING) */
-					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);
-					} else {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
-							e->answer.subcmds, e->answer.call);
-						pri_queue_control(pri->pvts[chanpos], AST_CONTROL_ANSWER, pri);
-						/* 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)) {
-							struct ast_channel *owner;
-
-							sig_pri_lock_owner(pri, chanpos);
-							owner = pri->pvts[chanpos]->owner;
-							if (owner) {
-								pbx_builtin_setvar_helper(owner, "USERUSERINFO",
-									e->answer.useruserinfo);
-								ast_channel_unlock(owner);
-							}
-						}
+				}
 #endif
 
-						sig_pri_unlock_private(pri->pvts[chanpos]);
-					}
-				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_HANGUP:
 				if (sig_pri_is_cis_call(e->hangup.channel)) {
@@ -4055,6 +4113,12 @@
 	p->owner = NULL;
 	p->outgoing = 0;
 	sig_pri_set_digital(p, 0);	/* push up to parent for EC*/
+#if defined(HAVE_PRI_CALL_WAITING)
+	if (p->is_call_waiting) {
+		p->is_call_waiting = 0;
+		ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
+	}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 	p->proceeding = 0;
 	p->progress = 0;
 	p->alerting = 0;
@@ -4845,7 +4909,7 @@
 			cw = pri->pvts[idx];
 			cw->is_call_waiting = 1;
 			sig_pri_init_config(cw, pri);
-			++pri->num_call_waiting_calls;
+			ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, 1);
 		}
 	}
 	ast_mutex_unlock(&pri->lock);
@@ -4853,7 +4917,7 @@
 }
 #endif	/* defined(HAVE_PRI_CALL_WAITING) */
 
-int sig_pri_available(struct sig_pri_chan **pvt, int *reason, int is_specific_channel)
+int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
 {
 	struct sig_pri_chan *p = *pvt;
 
@@ -4875,11 +4939,6 @@
 		sig_pri_available_check(p)) {
 		return 1;
 	}
-#if defined(HAVE_PRI_SERVICE_MESSAGES)
-	if (p->service_status) {
-		*reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
-	}
-#endif	/* defined(HAVE_PRI_SERVICE_MESSAGES) */
 
 #if defined(HAVE_PRI_CALL_WAITING)
 	if (!is_specific_channel) {

Modified: team/rmudgett/call_waiting/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/sig_pri.h?view=diff&rev=251399&r1=251398&r2=251399
==============================================================================
--- team/rmudgett/call_waiting/channels/sig_pri.h (original)
+++ team/rmudgett/call_waiting/channels/sig_pri.h Mon Mar  8 18:58:08 2010
@@ -384,7 +384,7 @@
 
 int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast);
 
-int sig_pri_available(struct sig_pri_chan **pvt, int *reason, int is_specific_channel);
+int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel);
 
 void sig_pri_init_pri(struct sig_pri_pri *pri);
 




More information about the svn-commits mailing list