[svn-commits] dvossel: branch group/v6-new r267444 - in /team/group/v6-new: ./ channels/ ch...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jun 3 09:44:33 CDT 2010


Author: dvossel
Date: Thu Jun  3 09:44:29 2010
New Revision: 267444

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=267444
Log:
svnmerge merge

Modified:
    team/group/v6-new/   (props changed)
    team/group/v6-new/CHANGES
    team/group/v6-new/channels/Makefile
    team/group/v6-new/channels/chan_dahdi.c
    team/group/v6-new/channels/h323/Makefile.in
    team/group/v6-new/channels/sig_pri.c
    team/group/v6-new/channels/sig_pri.h
    team/group/v6-new/configs/chan_dahdi.conf.sample
    team/group/v6-new/configure
    team/group/v6-new/configure.ac
    team/group/v6-new/include/asterisk/autoconfig.h.in
    team/group/v6-new/include/asterisk/channel.h
    team/group/v6-new/main/Makefile
    team/group/v6-new/main/channel.c
    team/group/v6-new/utils/extconf.c

Propchange: team/group/v6-new/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Jun  3 09:44:29 2010
@@ -1,1 +1,1 @@
-/trunk:1-267139
+/trunk:1-267443

Modified: team/group/v6-new/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/CHANGES?view=diff&rev=267444&r1=267443&r2=267444
==============================================================================
--- team/group/v6-new/CHANGES (original)
+++ team/group/v6-new/CHANGES Thu Jun  3 09:44:29 2010
@@ -61,6 +61,8 @@
    the particular peer. The dialstring format is SIP/peer/exten/host_or_IP.
  * Added directmediapermit/directmediadeny to limit which peers can send direct media
    to each other
+ * Added the 'snom_aoc_enabled' option to turn on support for sending Advice of
+   Charge messages to snom phones.
 
 IAX2 Changes
 -----------
@@ -203,6 +205,11 @@
    prefixing the name of the hash at assignment with the appropriate number of
    underscores, just like variables.
  * GROUP_MATCH_COUNT has been improved to allow regex matching on category
+ * For DAHDI/ISDN channels, the CHANNEL() dialplan function now supports the
+   "no_media_path" option.
+   Returns "0" if there is a B channel associated with the call.
+   Returns "1" if no B channel is associated with the call.  The call is either
+   on hold or is a call waiting call.
 
 Dialplan Variables
 ------------------
@@ -336,6 +343,11 @@
    to eliminate tromboned calls.  A tromboned call goes out an interface and comes
    back into the same interface.  Tromboned calls happen because of call routing,
    call deflection, call forwarding, and call transfer.
+ * Added the ability to send and receive ETSI Advice-Of-Charge messages. 
+ * Added the ability to support call waiting calls.  (The SETUP has no B channel
+   assigned.)
+ * Added Malicious Call ID (MCID) event to the AMI call event class.
+ * Added Message Waiting Indication (MWI) support for ISDN PTMP endpoints (phones).
 
 Asterisk Manager Interface
 --------------------------
@@ -366,6 +378,8 @@
    'sip show peers'.
  * Added Advice-Of-Charge events (AOC-S, AOC-D, and AOC-E) in the new
    aoc event class.
+ * Added Advice-Of-Charge manager action, AOCMessage, for generating AOC-D and
+   AOC-E messages on a channel.
 
 Channel Event Logging
 ---------------------

Modified: team/group/v6-new/channels/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/channels/Makefile?view=diff&rev=267444&r1=267443&r2=267444
==============================================================================
--- team/group/v6-new/channels/Makefile (original)
+++ team/group/v6-new/channels/Makefile Thu Jun  3 09:44:29 2010
@@ -63,8 +63,8 @@
 
 clean::
 	$(MAKE) -C misdn clean
-	if [ -f h323/Makefile ]; then $(MAKE) -C h323 clean; fi
 	rm -f sip/*.o sip/*.i
+	rm -f h323/libchanh323.a h323/Makefile.ast h323/*.o h323/*.dep
 
 dist-clean::
 	rm -f h323/Makefile

Modified: team/group/v6-new/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/channels/chan_dahdi.c?view=diff&rev=267444&r1=267443&r2=267444
==============================================================================
--- team/group/v6-new/channels/chan_dahdi.c (original)
+++ team/group/v6-new/channels/chan_dahdi.c Thu Jun  3 09:44:29 2010
@@ -800,7 +800,10 @@
 	unsigned int didtdd:1;				/*!< flag to say its done it once */
 	/*! \brief TRUE if analog type line dialed no digits in Dial() */
 	unsigned int dialednone:1;
-	/*! \brief TRUE if in the process of dialing digits or sending something. */
+	/*!
+	 * \brief TRUE if in the process of dialing digits or sending something.
+	 * \note This is used as a receive squelch for ISDN until connected.
+	 */
 	unsigned int dialing:1;
 	/*! \brief TRUE if the transfer capability of the call is digital. */
 	unsigned int digital:1;
@@ -1075,6 +1078,8 @@
 	 * \note The "group" bitmapped group string read in from chan_dahdi.conf
 	 */
 	ast_group_t group;
+	/*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
+	int law_default;
 	/*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
 	int law;
 	int confno;					/*!< Our conference */
@@ -2232,7 +2237,8 @@
 		p->dsp = NULL;
 	}
 
-	law = DAHDI_LAW_DEFAULT;
+	p->law = p->law_default;
+	law = p->law_default;
 	res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 	if (res < 0)
 		ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
@@ -2391,10 +2397,22 @@
 	int audio;
 	int newlaw = -1;
 
-	/* Set to audio mode at this point */
-	audio = 1;
-	if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
-		ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, audio, strerror(errno));
+	switch (p->sig) {
+	case SIG_PRI_LIB_HANDLE_CASES:
+		if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
+			/* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
+			break;
+		}
+		/* Fall through */
+	default:
+		/* Set to audio mode at this point */
+		audio = 1;
+		if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
+			ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
+				p->channel, audio, strerror(errno));
+		}
+		break;
+	}
 
 	if (law != SIG_PRI_DEFLAW) {
 		dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
@@ -2414,6 +2432,54 @@
 			break;
 	}
 	return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, transfercapability, requestor ? requestor->linkedid : "");
+}
+#endif	/* defined(HAVE_PRI) */
+
+static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Open the PRI channel media path.
+ * \since 1.8
+ *
+ * \param p Channel private control structure.
+ *
+ * \return Nothing
+ */
+static void my_pri_open_media(void *p)
+{
+	struct dahdi_pvt *pvt = p;
+	int res;
+	int dfd;
+	int set_val;
+
+	dfd = pvt->subs[SUB_REAL].dfd;
+
+	/* Open the media path. */
+	set_val = 1;
+	res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
+			pvt->channel, strerror(errno));
+	}
+
+	/* Set correct companding law for this call. */
+	res = dahdi_setlaw(dfd, pvt->law);
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
+	}
+
+	/* Set correct gain for this call. */
+	if (pvt->digital) {
+		res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
+	} else {
+		res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
+			pvt->law);
+	}
+	if (res < 0) {
+		ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
+	}
 }
 #endif	/* defined(HAVE_PRI) */
 
@@ -2734,6 +2800,17 @@
 	new_chan->dsp_features = old_chan->dsp_features;
 	old_chan->dsp = NULL;
 	old_chan->dsp_features = 0;
+
+	/* Transfer flags from the old channel. */
+	new_chan->dialing = old_chan->dialing;
+	new_chan->digital = old_chan->digital;
+	new_chan->outgoing = old_chan->outgoing;
+	old_chan->dialing = 0;
+	old_chan->digital = 0;
+	old_chan->outgoing = 0;
+
+	/* More stuff to transfer to the new channel. */
+	new_chan->law = old_chan->law;
 }
 
 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
@@ -2997,6 +3074,9 @@
 	ast_module_unref(ast_module_info->self);
 }
 
+#if defined(HAVE_PRI_CALL_WAITING)
+static void my_pri_init_config(void *priv, struct sig_pri_pri *pri);
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri);
 
 static struct sig_pri_callback dahdi_pri_callbacks =
@@ -3016,11 +3096,15 @@
 	.set_dnid = my_pri_set_dnid,
 	.set_rdnis = my_pri_set_rdnis,
 	.new_nobch_intf = dahdi_new_pri_nobch_channel,
+#if defined(HAVE_PRI_CALL_WAITING)
+	.init_config = my_pri_init_config,
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 	.get_orig_dialstring = my_get_orig_dialstring,
 	.make_cc_dialstring = my_pri_make_cc_dialstring,
 	.update_span_devstate = dahdi_pri_update_span_devstate,
 	.module_ref = my_module_ref,
 	.module_unref = my_module_unref,
+	.open_media = my_pri_open_media,
 };
 #endif	/* defined(HAVE_PRI) */
 
@@ -3155,6 +3239,7 @@
 	.set_needringing = my_set_needringing,
 };
 
+/*! Round robin search locations. */
 static struct dahdi_pvt *round_robin[32];
 
 #if defined(HAVE_SS7)
@@ -4179,7 +4264,7 @@
 	if (slavechannel < 1) {
 		p->confno = zi.confno;
 	}
-	memcpy(&c->curconf, &zi, sizeof(c->curconf));
+	c->curconf = zi;
 	ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
 	return 0;
 }
@@ -4850,13 +4935,8 @@
 
 #ifdef HAVE_PRI
 	if (dahdi_sig_pri_lib_handles(p->sig)) {
-		struct dahdi_params ps;
-
-		memset(&ps, 0, sizeof(ps));
-		if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) {
-			ast_log(LOG_ERROR, "Could not get params\n");
-		}
-		res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW);
+		res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
+			(p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
 		ast_mutex_unlock(&p->lock);
 		return res;
 	}
@@ -5736,7 +5816,8 @@
 		}
 		revert_fax_buffers(p, ast);
 		dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
-		law = DAHDI_LAW_DEFAULT;
+		p->law = p->law_default;
+		law = p->law_default;
 		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 		dahdi_disable_ec(p);
 		update_conf(p);
@@ -5907,7 +5988,8 @@
 
 		revert_fax_buffers(p, ast);
 
-		law = DAHDI_LAW_DEFAULT;
+		p->law = p->law_default;
+		law = p->law_default;
 		res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
 		if (res < 0)
 			ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
@@ -6464,6 +6546,22 @@
 		}
 		ast_mutex_unlock(&p->lock);
 #endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
+	} else if (!strcasecmp(data, "no_media_path")) {
+		ast_mutex_lock(&p->lock);
+		switch (p->sig) {
+		case SIG_PRI_LIB_HANDLE_CASES:
+			/*
+			 * TRUE if the call is on hold or is call waiting because
+			 * there is no media path available.
+			 */
+			snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
+			break;
+		default:
+			*buf = '\0';
+			res = -1;
+			break;
+		}
+		ast_mutex_unlock(&p->lock);
 #endif	/* defined(HAVE_PRI) */
 	} else {
 		*buf = '\0';
@@ -8871,12 +8969,10 @@
 {
 	struct ast_channel *tmp;
 	format_t deflaw;
-	int res;
 	int x;
 	int features;
 	struct ast_str *chan_name;
 	struct ast_variable *v;
-	struct dahdi_params ps;
 
 	if (i->subs[idx].owner) {
 		ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
@@ -8907,21 +9003,29 @@
 	}
 #endif	/* defined(HAVE_PRI) */
 	ast_channel_cc_params_init(tmp, i->cc_params);
-	memset(&ps, 0, sizeof(ps));
-	res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
-	if (res) {
-		ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
-		ps.curlaw = DAHDI_LAW_MULAW;
-	}
-	if (ps.curlaw == DAHDI_LAW_ALAW)
-		deflaw = AST_FORMAT_ALAW;
-	else
-		deflaw = AST_FORMAT_ULAW;
 	if (law) {
-		if (law == DAHDI_LAW_ALAW)
+		i->law = law;
+		if (law == DAHDI_LAW_ALAW) {
 			deflaw = AST_FORMAT_ALAW;
-		else
+		} else {
 			deflaw = AST_FORMAT_ULAW;
+		}
+	} else {
+		switch (i->sig) {
+		case SIG_PRI_LIB_HANDLE_CASES:
+			/* Make sure companding law is known. */
+			i->law = (i->law_default == DAHDI_LAW_ALAW)
+				? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
+			break;
+		default:
+			i->law = i->law_default;
+			break;
+		}
+		if (i->law_default == DAHDI_LAW_ALAW) {
+			deflaw = AST_FORMAT_ALAW;
+		} else {
+			deflaw = AST_FORMAT_ULAW;
+		}
 	}
 	ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
 	tmp->nativeformats = deflaw;
@@ -11538,6 +11642,7 @@
 					destroy_dahdi_pvt(tmp);
 					return NULL;
 				}
+				tmp->law_default = p.curlaw;
 				tmp->law = p.curlaw;
 				tmp->span = p.spanno;
 				span = p.spanno - 1;
@@ -11777,6 +11882,12 @@
 						pris[span].pri.cc_qsig_signaling_link_rsp =
 							conf->pri.pri.cc_qsig_signaling_link_rsp;
 #endif	/* defined(HAVE_PRI_CCSS) */
+#if defined(HAVE_PRI_CALL_WAITING)
+						pris[span].pri.max_call_waiting_calls =
+							conf->pri.pri.max_call_waiting_calls;
+						pris[span].pri.allow_call_waiting_calls =
+							conf->pri.pri.allow_call_waiting_calls;
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 						pris[span].pri.transfer = conf->chan.transfer;
 						pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
 #if defined(HAVE_PRI_AOC_EVENTS)
@@ -11784,6 +11895,11 @@
 						pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 						ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
+#if defined(HAVE_PRI_MWI)
+						ast_copy_string(pris[span].pri.mwi_mailboxes,
+							conf->pri.pri.mwi_mailboxes,
+							sizeof(pris[span].pri.mwi_mailboxes));
+#endif	/* defined(HAVE_PRI_MWI) */
 						ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
 						ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
 						ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
@@ -11796,6 +11912,20 @@
 						for (x = 0; x < PRI_MAX_TIMERS; x++) {
 							pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
 						}
+
+#if defined(HAVE_PRI_CALL_WAITING)
+						/* Channel initial config parameters. */
+						pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
+						pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
+						pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
+						pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
+						pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
+						pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
+						pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
+						pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
+						ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
+						ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 					} else {
 						ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
 						destroy_dahdi_pvt(tmp);
@@ -12266,8 +12396,10 @@
 	return 1;
 }
 
-static int available(struct dahdi_pvt *p)
-{
+static int available(struct dahdi_pvt **pvt, int is_specific_channel)
+{
+	struct dahdi_pvt *p = *pvt;
+
 	if (p->inalarm)
 		return 0;
 
@@ -12277,7 +12409,15 @@
 #ifdef HAVE_PRI
 	switch (p->sig) {
 	case SIG_PRI_LIB_HANDLE_CASES:
-		return sig_pri_available(p->sig_pvt);
+		{
+			struct sig_pri_chan *pvt_chan;
+			int res;
+
+			pvt_chan = p->sig_pvt;
+			res = sig_pri_available(&pvt_chan, is_specific_channel);
+			*pvt = pvt_chan->chan_pvt;
+			return res;
+		}
 	default:
 		break;
 	}
@@ -12314,6 +12454,38 @@
 
 	return 0;
 }
+
+#if defined(HAVE_PRI)
+#if defined(HAVE_PRI_CALL_WAITING)
+/*!
+ * \internal
+ * \brief Init the private channel configuration using the span controller.
+ * \since 1.8
+ *
+ * \param priv Channel to init the configuration.
+ * \param pri sig_pri PRI control structure.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void my_pri_init_config(void *priv, struct sig_pri_pri *pri)
+{
+	struct dahdi_pvt *pvt = priv;
+
+	pvt->stripmsd = pri->ch_cfg.stripmsd;
+	pvt->hidecallerid = pri->ch_cfg.hidecallerid;
+	pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
+	pvt->immediate = pri->ch_cfg.immediate;
+	pvt->priexclusive = pri->ch_cfg.priexclusive;
+	pvt->priindication_oob = pri->ch_cfg.priindication_oob;
+	pvt->use_callerid = pri->ch_cfg.use_callerid;
+	pvt->use_callingpres = pri->ch_cfg.use_callingpres;
+	ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
+	ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
+}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+#endif	/* defined(HAVE_PRI) */
 
 #if defined(HAVE_PRI)
 /*!
@@ -12381,7 +12553,15 @@
 	}
 	chan->no_b_channel = 1;
 
+	/*
+	 * Pseudo channel companding law.
+	 * Needed for outgoing call waiting calls.
+	 * XXX May need to make this determined by switchtype or user option.
+	 */
+	pvt->law_default = DAHDI_LAW_ALAW;
+
 	pvt->sig = pri->sig;
+	pvt->outsigmod = -1;
 	pvt->pri = pri;
 	pvt->sig_pvt = chan;
 	pri->pvts[pvt_idx] = chan;
@@ -12577,13 +12757,18 @@
 			} else
 				p = iflist;
 		} else {
+			if (ARRAY_LEN(round_robin) <= x) {
+				ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
+					x, data);
+				return NULL;
+			}
 			if (args.group[0] == 'R') {
 				param->backwards = 1;
-				p = round_robin[x]?round_robin[x]->prev:ifend;
+				p = round_robin[x] ? round_robin[x]->prev : ifend;
 				if (!p)
 					p = ifend;
 			} else {
-				p = round_robin[x]?round_robin[x]->next:iflist;
+				p = round_robin[x] ? round_robin[x]->next : iflist;
 				if (!p)
 					p = iflist;
 			}
@@ -12643,7 +12828,7 @@
 			round_robin[start.rr_starting_point] = p;
 
 		if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
-			&& available(p)) {
+			&& available(&p, channelmatched)) {
 			ast_debug(1, "Using channel %d\n", p->channel);
 
 			callwait = (p->owner != NULL);
@@ -12702,6 +12887,20 @@
 			}
 			if (!tmp) {
 				p->outgoing = 0;
+#if defined(HAVE_PRI)
+#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) */
+#endif	/* defined(HAVE_PRI) */
 			} else {
 				snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
 			}
@@ -15090,7 +15289,7 @@
 			ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
 			ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
 			ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
-			ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
+			ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
 			ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
 			ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
 			ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
@@ -16392,6 +16591,7 @@
 		for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
 			dahdi_close_pri_fd(&(pris[i]), j);
 		}
+		sig_pri_stop_pri(&pris[i].pri);
 	}
 #if defined(HAVE_PRI_CCSS)
 	ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
@@ -17246,6 +17446,21 @@
 					confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
 				}
 #endif	/* defined(HAVE_PRI_CCSS) */
+#if defined(HAVE_PRI_CALL_WAITING)
+			} else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
+				confp->pri.pri.max_call_waiting_calls = atoi(v->value);
+				if (confp->pri.pri.max_call_waiting_calls < 0) {
+					/* Negative values are not allowed. */
+					confp->pri.pri.max_call_waiting_calls = 0;
+				}
+			} else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
+				confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+#if defined(HAVE_PRI_MWI)
+			} else if (!strcasecmp(v->name, "mwi_mailboxes")) {
+				ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
+					sizeof(confp->pri.pri.mwi_mailboxes));
+#endif	/* defined(HAVE_PRI_MWI) */
 #endif /* HAVE_PRI */
 #ifdef HAVE_SS7
 			} else if (!strcasecmp(v->name, "ss7type")) {

Modified: team/group/v6-new/channels/h323/Makefile.in
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/channels/h323/Makefile.in?view=diff&rev=267444&r1=267443&r2=267444
==============================================================================
--- team/group/v6-new/channels/h323/Makefile.in (original)
+++ team/group/v6-new/channels/h323/Makefile.in Thu Jun  3 09:44:29 2010
@@ -47,4 +47,3 @@
 	@if [ -r $@ ] && cmp -s $@ $@.tmp; then rm -f $@.tmp; else mv -f $@.tmp $@; fi
 
 clean::
-	rm -f $(TARGET) $(OBJS) Makefile.ast *.dep

Modified: team/group/v6-new/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/group/v6-new/channels/sig_pri.c?view=diff&rev=267444&r1=267443&r2=267444
==============================================================================
--- team/group/v6-new/channels/sig_pri.c (original)
+++ team/group/v6-new/channels/sig_pri.c Thu Jun  3 09:44:29 2010
@@ -814,6 +814,26 @@
 	return c;
 }
 
+/*!
+ * \internal
+ * \brief Open the PRI channel media path.
+ * \since 1.8
+ *
+ * \param p Channel private control structure.
+ *
+ * \return Nothing
+ */
+static void sig_pri_open_media(struct sig_pri_chan *p)
+{
+	if (p->no_b_channel) {
+		return;
+	}
+
+	if (p->calls->open_media) {
+		p->calls->open_media(p->chan_pvt);
+	}
+}
+
 struct ast_channel *sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_channel *requestor, int transfercapability)
 {
 	struct ast_channel *ast;
@@ -982,15 +1002,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;
@@ -1015,11 +1037,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;
@@ -1079,6 +1100,11 @@
 		old_chan->call = NULL;
 
 		/* Transfer flags from the old channel. */
+#if defined(HAVE_PRI_AOC_EVENTS)
+		new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
+		new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
+		new_chan->holding_aoce = old_chan->holding_aoce;
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 		new_chan->alerting = old_chan->alerting;
 		new_chan->alreadyhungup = old_chan->alreadyhungup;
 		new_chan->isidlecall = old_chan->isidlecall;
@@ -1087,17 +1113,14 @@
 		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;
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
+
 #if defined(HAVE_PRI_AOC_EVENTS)
-		new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
-		new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
-		new_chan->holding_aoce = old_chan->holding_aoce;
-		new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
-		new_chan->aoc_e = old_chan->aoc_e;
-
-		old_chan->holding_aoce = 0;
 		old_chan->aoc_s_request_invoke_id_valid = 0;
 		old_chan->waiting_for_aoce = 0;
-		memset(&old_chan->aoc_e, 0, sizeof(&old_chan->aoc_e));
+		old_chan->holding_aoce = 0;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 		old_chan->alerting = 0;
 		old_chan->alreadyhungup = 0;
@@ -1107,6 +1130,9 @@
 		old_chan->setup_ack = 0;
 		old_chan->outgoing = 0;
 		old_chan->digital = 0;
+#if defined(HAVE_PRI_CALL_WAITING)
+		old_chan->is_call_waiting = 0;
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 
 		/* More stuff to transfer to the new channel. */
 #if defined(HAVE_PRI_REVERSE_CHARGE)
@@ -1115,6 +1141,10 @@
 #if defined(HAVE_PRI_SETUP_KEYPAD)
 		strcpy(new_chan->keypad_digits, old_chan->keypad_digits);
 #endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
+#if defined(HAVE_PRI_AOC_EVENTS)
+		new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
+		new_chan->aoc_e = old_chan->aoc_e;
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 
 		if (new_chan->no_b_channel) {
 			/* Copy the real channel configuration to the no B channel interface. */
@@ -1222,6 +1252,38 @@
 	}
 	return 0;
 }
+
+#if defined(HAVE_PRI_CALL_WAITING)
+/*!
+ * \internal
+ * \brief Init the private channel configuration using the span controller.
+ * \since 1.8
+ *
+ * \param pvt Channel to init the configuration.
+ * \param pri sig_pri PRI control structure.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_init_config(struct sig_pri_chan *pvt, struct sig_pri_pri *pri)
+{
+	pvt->stripmsd = pri->ch_cfg.stripmsd;
+	pvt->hidecallerid = pri->ch_cfg.hidecallerid;
+	pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
+	pvt->immediate = pri->ch_cfg.immediate;
+	pvt->priexclusive = pri->ch_cfg.priexclusive;
+	pvt->priindication_oob = pri->ch_cfg.priindication_oob;
+	pvt->use_callerid = pri->ch_cfg.use_callerid;
+	pvt->use_callingpres = pri->ch_cfg.use_callingpres;
+	ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
+	ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
+
+	if (pri->calls->init_config) {
+		pri->calls->init_config(pvt->chan_pvt, pri);
+	}
+}
+#endif	/* defined(HAVE_PRI_CALL_WAITING) */
 
 static int pri_find_empty_chan(struct sig_pri_pri *pri, int backwards)
 {
@@ -1581,6 +1643,98 @@
 	/* Did not match any pattern in the list. */
 	return 0;
 }
+
+#if defined(HAVE_PRI_MCID)
+/*!
+ * \internal
+ * \brief Append the given party id to the event string.
+ * \since 1.8
+ *
+ * \param msg Event message string being built.
+ * \param prefix Prefix to add to the party id lines.
+ * \param party Party information to encode.
+ *
+ * \return Nothing
+ */
+static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, struct ast_party_id *party)
+{
+	ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix,
+		party->number_presentation,
+		ast_describe_caller_presentation(party->number_presentation));
+	ast_str_append(msg, 0, "%sNum: %s\r\n", prefix, S_OR(party->number, ""));
+	ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number_type);
+	ast_str_append(msg, 0, "%sName: %s\r\n", prefix, S_OR(party->name, ""));
+#if defined(HAVE_PRI_SUBADDR)
+	if (party->subaddress.valid) {
+		static const char subaddress[] = "Subaddr";
+
+		ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress,
+			S_OR(party->subaddress.str, ""));
+		ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress,
+			party->subaddress.type);
+		ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress,
+			party->subaddress.odd_even_indicator);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+}
+#endif	/* defined(HAVE_PRI_MCID) */
+
+#if defined(HAVE_PRI_MCID)
+/*!
+ * \internal
+ * \brief Handle the MCID event.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param mcid MCID event parameters.
+ * \param owner Asterisk channel associated with the call.
+ * NULL if Asterisk no longer has the ast_channel struct.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the owner channel lock is already obtained if still present.
+ *
+ * \return Nothing
+ */
+static void sig_pri_mcid_event(struct sig_pri_pri *pri, const struct pri_subcmd_mcid_req *mcid, struct ast_channel *owner)
+{
+	struct ast_channel *chans[1];
+	struct ast_str *msg;
+	struct ast_party_id party;
+
+	msg = ast_str_create(4096);
+	if (!msg) {
+		return;
+	}
+
+	if (owner) {
+		/* The owner channel is present. */
+		ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
+		ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
+
+		sig_pri_event_party_id(&msg, "CallerID", &owner->connected.id);
+	} else {
+		/*
+		 * Since we no longer have an owner channel,
+		 * we have to use the caller information supplied by libpri.
+		 */
+		ast_party_id_init(&party);
+		sig_pri_party_id_convert(&party, &mcid->originator, pri);
+		sig_pri_event_party_id(&msg, "CallerID", &party);
+		ast_party_id_free(&party);
+	}
+
+	/* Always use libpri's called party information. */
+	ast_party_id_init(&party);
+	sig_pri_party_id_convert(&party, &mcid->answerer, pri);
+	sig_pri_event_party_id(&msg, "ConnectedID", &party);
+	ast_party_id_free(&party);
+
+	chans[0] = owner;
+	ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s",
+		ast_str_buffer(msg));
+	ast_free(msg);
+}
+#endif	/* defined(HAVE_PRI_MCID) */
 
 #if defined(HAVE_PRI_CALL_HOLD) || defined(HAVE_PRI_TRANSFER)
 /*!
@@ -3519,7 +3673,8 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
-				sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
+				sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner,
+					(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
 				ast_channel_unlock(owner);
 			}
 			break;
@@ -3530,7 +3685,8 @@
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
 				/* Queue AST_CONTROL_AOC frame on channel */
-				sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
+				sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner,
+					(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
 				ast_channel_unlock(owner);
 			}
 			break;
@@ -3540,7 +3696,8 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			/* Queue AST_CONTROL_AOC frame */
-			sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
+			sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner,
+				(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
 			if (owner) {
 				ast_channel_unlock(owner);
 			}
@@ -3551,25 +3708,45 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
-				sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos], call_rsp);
+				sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos],
+					call_rsp);
 				ast_channel_unlock(owner);
 			}
 			break;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
 #if defined(HAVE_PRI_AOC_EVENTS)
 		case PRI_SUBCMD_AOC_CHARGING_REQ_RSP:
-			/* An AOC request response may contain an AOC-S rate list.  If this is the case handle this just like we
-			 * would an incoming AOC-S msg */
+			/*
+			 * An AOC request response may contain an AOC-S rate list.
+			 * If this is the case handle this just like we
+			 * would an incoming AOC-S msg.
+			 */
 			if (subcmd->u.aoc_request_response.valid_aoc_s) {
 				sig_pri_lock_owner(pri, chanpos);
 				owner = pri->pvts[chanpos]->owner;
 				if (owner) {
-					sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
+					sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner,
+						(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
 					ast_channel_unlock(owner);
 				}
 			}
 			break;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+#if defined(HAVE_PRI_MCID)
+		case PRI_SUBCMD_MCID_REQ:
+			sig_pri_lock_owner(pri, chanpos);
+			owner = pri->pvts[chanpos]->owner;
+			sig_pri_mcid_event(pri, &subcmd->u.mcid_req, owner);
+			if (owner) {
+				ast_channel_unlock(owner);
+			}
+			break;
+#endif	/* defined(HAVE_PRI_MCID) */
+#if defined(HAVE_PRI_MCID)
+		case PRI_SUBCMD_MCID_RSP:
+			/* Ignore for now. */
+			break;
+#endif	/* defined(HAVE_PRI_MCID) */
 		default:
 			ast_debug(2,
 				"Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n",
@@ -4175,10 +4352,33 @@
 						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. */
+#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_INCOMPATIBLE_DESTINATION);
+						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;
+					}
+					/* 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. */
 					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",
@@ -4571,43 +4771,33 @@
 					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]->progress)
+
+					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
 #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
 						) {
-						int subclass;
-
-						subclass = AST_CONTROL_PROGRESS;
-						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;
-									subclass = AST_CONTROL_BUSY;
-								}
-							}
-						}
-
+						/* 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, subclass);
-						if (
-#ifdef PRI_PROGRESS_MASK
-							e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
-							e->proceeding.progress == 8
-#endif
-							) {
-							/* Bring voice path up */
-							pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
-						}
+						pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
 						pri->pvts[chanpos]->progress = 1;
 						sig_pri_set_dialing(pri->pvts[chanpos], 0);
 					}
@@ -4629,17 +4819,19 @@
 						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]->proceeding = 1;
+					}
+					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]->proceeding = 1;
+						) {
+						/* 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_unlock_private(pri->pvts[chanpos]);
@@ -4689,39 +4881,127 @@
 				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);
+							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, chanpos, AST_CONTROL_CONGESTION);
+									break;
+								}
+							} else {
+								pri->pvts[chanpos]->is_call_waiting = 0;
+								ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
+								pri_hangup(pri->pri, e->answer.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+								pri->pvts[chanpos]->call = NULL;
+							}
+							sig_pri_unlock_private(pri->pvts[chanpos]);
+							break;
+						}
+						chanpos = pri_fixup_principle(pri, new_chanpos, e->answer.call);
+						if (chanpos < 0) {

[... 1077 lines stripped ...]



More information about the svn-commits mailing list