[svn-commits] rmudgett: branch group/issue14068 r209709 - in /team/group/issue14068: ./ cha...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jul 31 16:47:43 CDT 2009


Author: rmudgett
Date: Fri Jul 31 16:47:31 2009
New Revision: 209709

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=209709
Log:
Merged revisions 203304 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

........
  r203304 | jpeeler | 2009-06-25 14:54:12 -0500 (Thu, 25 Jun 2009) | 6 lines
  
  New signaling module to handle PRI/BRI operations in chan_dahdi
  
  This merge splits the PRI/BRI signaling logic out of chan_dahdi.c into
  sig_pri.c. Functionality in theory should not change (mostly). A few trivial
  changes were made in sig_analog with verbose messages and commenting.
........

Modified:
    team/group/issue14068/   (props changed)
    team/group/issue14068/channels/Makefile
    team/group/issue14068/channels/chan_dahdi.c
    team/group/issue14068/channels/sig_analog.c
    team/group/issue14068/channels/sig_analog.h
    team/group/issue14068/channels/sig_pri.c
    team/group/issue14068/channels/sig_pri.h

Propchange: team/group/issue14068/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Jul 31 16:47:31 2009
@@ -1,1 +1,1 @@
-/trunk:1-203303
+/trunk:1-203304

Modified: team/group/issue14068/channels/Makefile
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/issue14068/channels/Makefile?view=diff&rev=209709&r1=209708&r2=209709
==============================================================================
--- team/group/issue14068/channels/Makefile (original)
+++ team/group/issue14068/channels/Makefile Fri Jul 31 16:47:31 2009
@@ -69,7 +69,7 @@
 	rm -f h323/Makefile
 
 $(if $(filter chan_iax2,$(EMBEDDED_MODS)),modules.link,chan_iax2.so): iax2-parser.o iax2-provision.o
-$(if $(filter chan_dahdi,$(EMBEDDED_MODS)),modules.link,chan_dahdi.so): sig_analog.o
+$(if $(filter chan_dahdi,$(EMBEDDED_MODS)),modules.link,chan_dahdi.so): sig_analog.o sig_pri.o
 
 ifneq ($(filter chan_h323,$(EMBEDDED_MODS)),)
 modules.link: h323/libchanh323.a

Modified: team/group/issue14068/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/issue14068/channels/chan_dahdi.c?view=diff&rev=209709&r1=209708&r2=209709
==============================================================================
--- team/group/issue14068/channels/chan_dahdi.c (original)
+++ team/group/issue14068/channels/chan_dahdi.c Fri Jul 31 16:47:31 2009
@@ -262,9 +262,6 @@
 	.impl = ""
 };
 static struct ast_jb_conf global_jbconf;
-
-/* define this to send PRI user-user information elements */
-#undef SUPPORT_USERUSER
 
 /*!
  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
@@ -1996,7 +1993,7 @@
 }
 #endif
 
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, int startpbx, enum sig_pri_law law, int transfercapability, char *exten)
 {
 	struct dahdi_pvt *p = pvt;
@@ -2027,7 +2024,7 @@
 	}
 	return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, transfercapability);
 }
-#endif
+#endif	/* defined(HAVE_PRI) */
 
 static int unalloc_sub(struct dahdi_pvt *p, int x);
 
@@ -2264,7 +2261,7 @@
 	return ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_HOOK, &x);
 }
 
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 static void my_pri_fixup_chans(void *old_chan, void *new_chan)
 {
 	struct dahdi_pvt *old = old_chan;
@@ -2348,7 +2345,7 @@
 	.new_ast_channel = my_new_pri_ast_channel,
 	.fixup_chans = my_pri_fixup_chans,
 };
-#endif /* HAVE_PRI */
+#endif	/* defined(HAVE_PRI) */
 
 /*!
  * \brief Send MWI state change
@@ -2592,7 +2589,6 @@
 #endif
 }
 
-static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
 #ifdef HAVE_OPENR2
 
 static int dahdi_r2_answer(struct dahdi_pvt *p)
@@ -4161,7 +4157,8 @@
 		ast_mutex_unlock(&p->lock);
 		return -1;
 	}
-#ifdef HAVE_SS7
+
+#if defined(HAVE_SS7)
 	if (p->ss7) {
 		char ss7_called_nai;
 		int called_nai_strip;
@@ -4298,7 +4295,8 @@
 		ast_setstate(ast, AST_STATE_DIALING);
 		ss7_rel(p->ss7);
 	}
-#endif /* HAVE_SS7 */
+#endif	/* defined(HAVE_SS7) */
+
 #ifdef HAVE_OPENR2
 	if (p->mfcr2) {
 		openr2_calling_party_category_t chancat;
@@ -4453,7 +4451,7 @@
 	ast_mutex_unlock(&iflock);
 }
 
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
 
 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
@@ -7590,6 +7588,7 @@
 	int res=-1;
 	int idx;
 	int func = DAHDI_FLASH;
+
 	ast_mutex_lock(&p->lock);
 	idx = dahdi_get_index(chan, p, 0);
 	ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
@@ -12229,7 +12228,7 @@
 }
 #endif	/* defined(HAVE_PRI) */
 
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 static int prepare_pri(struct dahdi_pri *pri)
 {
 	int i, res, x;
@@ -12285,7 +12284,9 @@
 	}
 	return 0;
 }
-
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
 {
 	int which, span;
@@ -12304,7 +12305,9 @@
 	}
 	return ret;
 }
-
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
 static char *complete_span_4(const char *line, const char *word, int pos, int state)
 {
 	return complete_span_helper(line,word,pos,state,3);
@@ -12554,7 +12557,7 @@
 }
 #endif
 
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int span;
@@ -12580,7 +12583,7 @@
 	}
 	return CLI_SUCCESS;
 }
-#endif
+#endif	/* defined(HAVE_PRI) */
 
 #if defined(HAVE_PRI)
 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Modified: team/group/issue14068/channels/sig_analog.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/issue14068/channels/sig_analog.c?view=diff&rev=209709&r1=209708&r2=209709
==============================================================================
--- team/group/issue14068/channels/sig_analog.c (original)
+++ team/group/issue14068/channels/sig_analog.c Fri Jul 31 16:47:31 2009
@@ -774,11 +774,10 @@
 			p->lastcid_name[0] = '\0';
 
 		if (p->use_callerid) {
-			//p->callwaitcas = 0;
+			p->callwaitcas = 0;
 			p->cid.cid_name = p->lastcid_name;
 			p->cid.cid_num = p->lastcid_num;
 		}
-
 
 		ast_setstate(ast, AST_STATE_RINGING);
 		index = analog_get_index(ast, p, 0);
@@ -1087,9 +1086,7 @@
 	analog_stop_callwait(p);
 	ast->tech_pvt = NULL;
 
-	if (option_verbose > 2) {
-		ast_verbose(VERBOSE_PREFIX_3 "Hanging up on '%s'\n", ast->name);
-	}
+	ast_verb(3, "Hanging up on '%s'\n", ast->name);
 
 	return 0;
 }
@@ -1557,8 +1554,7 @@
 			}
 			goto quit;
 		} else {
-			if (option_verbose > 2)
-				ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
+			ast_verb(3, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
 			sleep(2);
 			res = analog_play_tone(p, index, ANALOG_TONE_INFO);
 			if (res < 0)
@@ -1608,8 +1604,7 @@
 					if (getforward) {
 						/* Record this as the forwarding extension */
 						ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
+						ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
 						res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 						if (res)
 							break;
@@ -1654,8 +1649,7 @@
 				ast_hangup(chan);
 				goto quit;
 			} else if (p->callwaiting && !strcmp(exten, "*70")) {
-				if (option_verbose > 2) 
-					ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
+				ast_verb(3, "Disabling call waiting on %s\n", chan->name);
 				/* Disable call waiting if enabled */
 				p->callwaiting = 0;
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
@@ -1695,8 +1689,7 @@
 					goto quit;
 				}
 			} else if (!p->hidecallerid && !strcmp(exten, "*67")) {
-				if (option_verbose > 2) 
-					ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
+				ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
 				/* Disable Caller*ID if enabled */
 				p->hidecallerid = 1;
 				if (chan->cid.cid_num)
@@ -1723,13 +1716,10 @@
 				break;
 			} else if (!strcmp(exten, "*78")) {
 				/* Do not disturb */
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
-#if 0
+				ast_verb(3, "Enabled DND on channel %d\n", p->channel);
 				manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-					      "Channel: %s/%d\r\n"
-					      "Status: enabled\r\n", dahdi_chan_name, p->channel);
-#endif
+					      "Channel: DAHDI/%d\r\n"
+					      "Status: enabled\r\n", p->channel);
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 				p->dnd = 1;
 				getforward = 0;
@@ -1737,13 +1727,10 @@
 				len = 0;
 			} else if (!strcmp(exten, "*79")) {
 				/* Do not disturb */
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
-#if 0
+				ast_verb(3, "Disabled DND on channel %d\n", p->channel);
 				manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-					      "Channel: %s/%d\r\n"
-					      "Status: disabled\r\n", dahdi_chan_name, p->channel);
-#endif
+					      "Channel: DAHDI/%d\r\n"
+					      "Status: disabled\r\n", p->channel);
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 				p->dnd = 0;
 				getforward = 0;
@@ -1755,8 +1742,7 @@
 				memset(exten, 0, sizeof(exten));
 				len = 0;
 			} else if (p->cancallforward && !strcmp(exten, "*73")) {
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
+				ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 				memset(p->call_forward, 0, sizeof(p->call_forward));
 				getforward = 0;
@@ -1768,12 +1754,10 @@
 				/* This is a three way call, the main call being a real channel,
 					and we're parking the first call. */
 				ast_masq_park_call(ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner), chan, 0, NULL);
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
+				ast_verb(3, "Parking call to '%s'\n", chan->name);
 				break;
 			} else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
-				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
+				ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
 				res = ast_db_put("blacklist", p->lastcid_num, "1");
 				if (!res) {
 					res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
@@ -1781,8 +1765,7 @@
 					len = 0;
 				}
 			} else if (p->hidecallerid && !strcmp(exten, "*82")) {
-				if (option_verbose > 2) 
-					ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
+				ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
 				/* Enable Caller*ID if enabled */
 				p->hidecallerid = 0;
 				if (chan->cid.cid_num)
@@ -2241,8 +2224,7 @@
 	switch (res) {
 #ifdef ANALOG_EVENT_EC_DISABLED
 	case ANALOG_EVENT_EC_DISABLED:
-		if (option_verbose > 2) 
-			ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
+		ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
 		p->echocanon = 0;
 		break;
 #endif
@@ -2310,8 +2292,7 @@
 				if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
 					/* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
 					analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
-					if (option_verbose > 2) 
-						ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
+					ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
 					analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
 					analog_stop_callwait(p);
 					p->owner = NULL;
@@ -2680,8 +2661,7 @@
 						if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
 							cdr3way = 1;
  						
-						if (option_verbose > 2)	
-							ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
+						ast_verb(3, "Started three way call on channel %d\n", p->channel);
 						/* Start music on hold if appropriate */
 						if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
 							ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD,
@@ -2703,8 +2683,7 @@
 						p->owner = p->subs[ANALOG_SUB_REAL].owner;
 					}
 					/* Drop the last call and stop the conference */
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
+					ast_verb(3, "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
 					ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
 					p->subs[ANALOG_SUB_REAL].inthreeway = 0;
 					p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
@@ -2724,8 +2703,7 @@
 						if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
 							cdr3way = 1;
 
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name, p->subs[ANALOG_SUB_REAL].owner->name);
+						ast_verb(3, "Building conference on call on %s and %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name, p->subs[ANALOG_SUB_REAL].owner->name);
 						/* Put them in the threeway, and flip */
 						p->subs[ANALOG_SUB_THREEWAY].inthreeway = 1;
 						p->subs[ANALOG_SUB_REAL].inthreeway = 1;
@@ -2742,8 +2720,7 @@
 							analog_play_tone(p, ANALOG_SUB_THREEWAY, ANALOG_TONE_RINGTONE);
 						}
 					} else {
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
+						ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
 						analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
 						ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
 						p->owner = p->subs[ANALOG_SUB_REAL].owner;
@@ -2938,8 +2915,7 @@
 		case ANALOG_EVENT_ONHOOK:
 			analog_set_echocanceller(p, 0);
 			if (p->owner) {
-				if (option_verbose > 2) 
-					ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
+				ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
 				analog_ring(p);
 				analog_stop_callwait(p);
 			} else
@@ -2962,8 +2938,7 @@
 		case ANALOG_EVENT_WINKFLASH:
 			gettimeofday(&p->flashtime, NULL);
 			if (p->owner) {
-				if (option_verbose > 2) 
-					ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
+				ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
 				if (p->owner->_state != AST_STATE_UP) {
 					/* Answer if necessary */
 					usedindex = analog_get_index(p->owner, p, 0);

Modified: team/group/issue14068/channels/sig_analog.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/issue14068/channels/sig_analog.h?view=diff&rev=209709&r1=209708&r2=209709
==============================================================================
--- team/group/issue14068/channels/sig_analog.h (original)
+++ team/group/issue14068/channels/sig_analog.h Fri Jul 31 16:47:31 2009
@@ -248,12 +248,12 @@
 	/* XXX: All variables after this are internal */
 	unsigned int callwaiting:1;
 	unsigned int dialednone:1;
-	unsigned int dialing:1;
+	unsigned int dialing:1;			/*!< TRUE if in the process of dialing digits or sending something */
 	unsigned int dnd:1;
 	unsigned int echobreak:1;
 	unsigned int hidecallerid:1;
 	unsigned int outgoing:1;
-	unsigned int pulsedial:1;			/*!< whether a pulse dial phone is detected */
+	unsigned int pulsedial:1;		/*!< TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
 
 	char callwait_num[AST_MAX_EXTENSION];
 	char callwait_name[AST_MAX_EXTENSION];
@@ -277,13 +277,13 @@
 	void *ss_astchan;
 
 	/* All variables after this are definitely going to be audited */
-	unsigned int inalarm:1; //
-	unsigned int unknown_alarm:1;//
+	unsigned int inalarm:1;
+	unsigned int unknown_alarm:1;
 
 	int callwaitcas;
 
 #if 0
-	int ringt; //
+	int ringt;
 	int ringt_base;
 #endif
 };

Modified: team/group/issue14068/channels/sig_pri.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/issue14068/channels/sig_pri.c?view=diff&rev=209709&r1=209708&r2=209709
==============================================================================
--- team/group/issue14068/channels/sig_pri.c (original)
+++ team/group/issue14068/channels/sig_pri.c Fri Jul 31 16:47:31 2009
@@ -48,6 +48,9 @@
 
 #include "sig_pri.h"
 
+/* define this to send PRI user-user information elements */
+#undef SUPPORT_USERUSER
+
 static int pri_matchdigittimeout = 3000;
 
 static int pri_gendigittimeout = 8000;
@@ -62,7 +65,7 @@
 
 #define DCHAN_AVAILABLE	(DCHAN_NOTINALARM | DCHAN_UP)
 
-#define PRI_DEADLOCK_AVOIDANCE(lock) \
+#define PRI_DEADLOCK_AVOIDANCE(p) \
 	do { \
 		sig_pri_unlock_private(p); \
 		usleep(1); \
@@ -119,6 +122,275 @@
 	/* Then break the poll */
 	pthread_kill(pri->master, SIGURG);
 	return 0;
+}
+
+static enum AST_REDIRECTING_REASON pri_to_ast_reason(int pri_reason)
+{
+	enum AST_REDIRECTING_REASON ast_reason;
+
+	switch (pri_reason) {
+	case PRI_REDIR_FORWARD_ON_BUSY:
+		ast_reason = AST_REDIRECTING_REASON_USER_BUSY;
+		break;
+	case PRI_REDIR_FORWARD_ON_NO_REPLY:
+		ast_reason = AST_REDIRECTING_REASON_NO_ANSWER;
+		break;
+	case PRI_REDIR_DEFLECTION:
+		ast_reason = AST_REDIRECTING_REASON_DEFLECTION;
+		break;
+	case PRI_REDIR_UNCONDITIONAL:
+		ast_reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
+		break;
+	case PRI_REDIR_UNKNOWN:
+	default:
+		ast_reason = AST_REDIRECTING_REASON_UNKNOWN;
+		break;
+	}
+
+	return ast_reason;
+}
+
+static int ast_to_pri_reason(enum AST_REDIRECTING_REASON ast_reason)
+{
+	int pri_reason;
+
+	switch (ast_reason) {
+	case AST_REDIRECTING_REASON_USER_BUSY:
+		pri_reason = PRI_REDIR_FORWARD_ON_BUSY;
+		break;
+	case AST_REDIRECTING_REASON_NO_ANSWER:
+		pri_reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
+		break;
+	case AST_REDIRECTING_REASON_UNCONDITIONAL:
+		pri_reason = PRI_REDIR_UNCONDITIONAL;
+		break;
+	case AST_REDIRECTING_REASON_DEFLECTION:
+		pri_reason = PRI_REDIR_DEFLECTION;
+		break;
+	case AST_REDIRECTING_REASON_UNKNOWN:
+	default:
+		pri_reason = PRI_REDIR_UNKNOWN;
+		break;
+	}
+
+	return pri_reason;
+}
+
+static int pri_to_ast_presentation(int pri_presentation)
+{
+	int ast_presentation;
+
+	switch (pri_presentation) {
+	case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+		ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		break;
+	case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+		ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+		break;
+	case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+		ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN;
+		break;
+	case PRES_ALLOWED_NETWORK_NUMBER:
+		ast_presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
+		break;
+	case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+		ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+		break;
+	case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+		ast_presentation = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+		break;
+	case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+		ast_presentation = AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN;
+		break;
+	case PRES_PROHIB_NETWORK_NUMBER:
+		ast_presentation = AST_PRES_PROHIB_NETWORK_NUMBER;
+		break;
+	case PRES_NUMBER_NOT_AVAILABLE:
+		ast_presentation = AST_PRES_NUMBER_NOT_AVAILABLE;
+		break;
+	default:
+		ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+		break;
+	}
+
+	return ast_presentation;
+}
+
+static int ast_to_pri_presentation(int ast_presentation)
+{
+	int pri_presentation;
+
+	switch (ast_presentation) {
+	case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+		pri_presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		break;
+	case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+		pri_presentation = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+		break;
+	case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+		pri_presentation = PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN;
+		break;
+	case AST_PRES_ALLOWED_NETWORK_NUMBER:
+		pri_presentation = PRES_ALLOWED_NETWORK_NUMBER;
+		break;
+	case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+		pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+		break;
+	case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+		pri_presentation = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+		break;
+	case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+		pri_presentation = PRES_PROHIB_USER_NUMBER_FAILED_SCREEN;
+		break;
+	case AST_PRES_PROHIB_NETWORK_NUMBER:
+		pri_presentation = PRES_PROHIB_NETWORK_NUMBER;
+		break;
+	case AST_PRES_NUMBER_NOT_AVAILABLE:
+		pri_presentation = PRES_NUMBER_NOT_AVAILABLE;
+		break;
+	default:
+		pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+		break;
+	}
+
+	return pri_presentation;
+}
+
+/*!
+ * \internal
+ * \brief Determine the overall presentation value for the given party.
+ * \since 1.6.3
+ *
+ * \param id Party to determine the overall presentation value.
+ *
+ * \return Overall presentation value for the given party converted to ast values.
+ */
+static int overall_ast_presentation(const struct pri_party_id *id)
+{
+	int number_priority;
+	int number_value;
+	int number_screening;
+	int name_priority;
+	int name_value;
+
+	/* Determine name presentation priority. */
+	if (!id->name.valid) {
+		name_value = PRI_PRES_UNAVAILABLE;
+		name_priority = 3;
+	} else {
+		name_value = id->name.presentation & PRI_PRES_RESTRICTION;
+		switch (name_value) {
+		case PRI_PRES_RESTRICTED:
+			name_priority = 0;
+			break;
+		case PRI_PRES_ALLOWED:
+			name_priority = 1;
+			break;
+		case PRI_PRES_UNAVAILABLE:
+			name_priority = 2;
+			break;
+		default:
+			name_value = PRI_PRES_UNAVAILABLE;
+			name_priority = 3;
+			break;
+		}
+	}
+
+	/* Determine number presentation priority. */
+	if (!id->number.valid) {
+		number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
+		number_value = PRI_PRES_UNAVAILABLE;
+		number_priority = 3;
+	} else {
+		number_screening = id->number.presentation & PRI_PRES_NUMBER_TYPE;
+		number_value = id->number.presentation & PRI_PRES_RESTRICTION;
+		switch (number_value) {
+		case PRI_PRES_RESTRICTED:
+			number_priority = 0;
+			break;
+		case PRI_PRES_ALLOWED:
+			number_priority = 1;
+			break;
+		case PRI_PRES_UNAVAILABLE:
+			number_priority = 2;
+			break;
+		default:
+			number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
+			number_value = PRI_PRES_UNAVAILABLE;
+			number_priority = 3;
+			break;
+		}
+	}
+
+	/* Select the wining presentation value. */
+	if (name_priority < number_priority) {
+		number_value = name_value;
+	}
+
+	return pri_to_ast_presentation(number_value | number_screening);
+}
+
+/*!
+ * \internal
+ * \brief Fill in the PRI party id from the given asterisk party id.
+ * \since 1.6.3
+ *
+ * \param pri_id PRI party id structure.
+ * \param ast_id Asterisk party id structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes that pri_id has been previously memset to zero.
+ */
+static void sig_pri_party_id_from_ast(struct pri_party_id *pri_id, const struct ast_party_id *ast_id)
+{
+	int presentation;
+
+	presentation = ast_to_pri_presentation(ast_id->number_presentation);
+	if (!ast_strlen_zero(ast_id->name)) {
+		pri_id->name.valid = 1;
+		pri_id->name.presentation = presentation;
+		pri_id->name.char_set = PRI_CHAR_SET_ISO8859_1;
+		ast_copy_string(pri_id->name.str, ast_id->name, sizeof(pri_id->name.str));
+	}
+	if (!ast_strlen_zero(ast_id->number)) {
+		pri_id->number.valid = 1;
+		pri_id->number.presentation = presentation;
+		pri_id->number.plan = ast_id->number_type;
+		ast_copy_string(pri_id->number.str, ast_id->number, sizeof(pri_id->number.str));
+	}
+}
+
+/*!
+ * \internal
+ * \brief Update the PRI redirecting information for the current call.
+ * \since 1.6.3
+ *
+ * \param pvt sig_pri private channel structure.
+ * \param ast Asterisk channel
+ *
+ * \return Nothing
+ *
+ * \note Assumes that the PRI lock is already obtained.
+ */
+static void sig_pri_redirecting_update(struct sig_pri_chan *pvt, struct ast_channel *ast)
+{
+	struct pri_party_redirecting pri_redirecting;
+	struct ast_party_redirecting ast_redirecting;
+
+	/* Gather asterisk redirecting data */
+	ast_redirecting = ast->redirecting;
+	ast_redirecting.from.number = ast->cid.cid_rdnis;
+
+/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
+
+	memset(&pri_redirecting, 0, sizeof(pri_redirecting));
+	sig_pri_party_id_from_ast(&pri_redirecting.from, &ast_redirecting.from);
+	sig_pri_party_id_from_ast(&pri_redirecting.to, &ast_redirecting.to);
+	pri_redirecting.count = ast_redirecting.count;
+	pri_redirecting.reason = ast_to_pri_reason(ast_redirecting.reason);
+
+	pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
 }
 
 static int sig_pri_set_echocanceller(struct sig_pri_chan *p, int enable)
@@ -232,29 +504,6 @@
 			pri->fds[oldslot], pri->fds[newslot]);
 	pri->pri = pri->dchans[newslot];
 	return 0;
-}
-static void pri_update_cid(struct sig_pri_chan *p, struct sig_pri_pri *pri)
-{
-	/* We must unlock the PRI to avoid the possibility of a deadlock */
-	if (pri)
-		ast_mutex_unlock(&pri->lock);
-	for (;;) {
-		if (p->owner) {
-			if (ast_channel_trylock(p->owner)) {
-				PRI_DEADLOCK_AVOIDANCE(p);
-			} else {
-				ast_set_callerid(p->owner, S_OR(p->lastcid_num, NULL),
-							S_OR(p->lastcid_name, NULL),
-							S_OR(p->lastcid_num, NULL)
-							);
-				ast_channel_unlock(p->owner);
-				break;
-			}
-		} else
-			break;
-	}
-	if (pri)
-		ast_mutex_lock(&pri->lock);
 }
 
 static void pri_queue_frame(struct sig_pri_chan *p, struct ast_frame *f, struct sig_pri_pri *pri)
@@ -610,6 +859,188 @@
 	pri->dchanavail[index] |= DCHAN_NOTINALARM;
 	if (!before_start_pri)
 		pri_restart(pri->dchans[index]);
+}
+
+/*!
+ * \internal
+ * \brief Obtain the sig_pri owner channel lock if the owner exists.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_lock_owner(struct sig_pri_pri *pri, int chanpos)
+{
+	for (;;) {
+		if (!pri->pvts[chanpos]->owner) {
+			/* There is no owner lock to get. */
+			break;
+		}
+		if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
+			/* We got the lock */
+			break;
+		}
+		/* We must unlock the PRI to avoid the possibility of a deadlock */
+		ast_mutex_unlock(&pri->lock);
+		PRI_DEADLOCK_AVOIDANCE(pri->pvts[chanpos]);
+		ast_mutex_lock(&pri->lock);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Handle the call associated PRI subcommand events.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
+ * \param event_id PRI event id
+ * \param channel PRI encoded span/channel
+ * \param subcmds Subcommands to process if any. (Could be NULL).
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int event_id,
+	int channel, const struct pri_subcommands *subcmds)
+{
+	int index;
+	struct ast_channel *owner;
+
+	if (!subcmds) {
+		return;
+	}
+	for (index = 0; index < subcmds->counter_subcmd; ++index) {
+		const struct pri_subcommand *subcmd = &subcmds->subcmd[index];
+
+		switch (subcmd->cmd) {
+		case PRI_SUBCMD_CONNECTED_LINE:
+			sig_pri_lock_owner(pri, chanpos);
+			owner = pri->pvts[chanpos]->owner;
+			if (owner) {
+				struct ast_party_connected_line ast_connected;
+				const struct pri_party_connected_line *pri_connected;
+				int caller_id_update;
+				char connected_number[AST_MAX_EXTENSION];
+
+				caller_id_update = 0;
+
+				/* Extract the connected line information */
+				ast_party_connected_line_init(&ast_connected);
+				pri_connected = &subcmd->u.connected_line;
+				if (pri_connected->id.name.valid) {
+					ast_connected.id.name = (char *) pri_connected->id.name.str;
+
+					caller_id_update = 1;
+				}
+				if (pri_connected->id.number.valid) {
+					apply_plan_to_number(connected_number, sizeof(connected_number), pri,
+						pri_connected->id.number.str,
+						pri_connected->id.number.plan);
+					ast_connected.id.number = connected_number;
+					ast_connected.id.number_type = pri_connected->id.number.plan;
+
+					caller_id_update = 1;
+				} else {
+					ast_connected.id.number = "";
+				}
+				if (pri_connected->id.name.valid
+					|| pri_connected->id.number.valid) {
+					ast_connected.id.number_presentation =
+						overall_ast_presentation(&pri_connected->id);
+				}
+				ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+
+				if (caller_id_update) {
+					ast_set_callerid(owner, S_OR(ast_connected.id.number, NULL),
+						S_OR(ast_connected.id.name, NULL),
+						S_OR(ast_connected.id.number, NULL));
+				}
+
+				/* Update the connected line information on the other channel */
+				if (event_id != PRI_EVENT_RING) {
+					/* This connected_line update was not from a SETUP message. */
+					ast_channel_queue_connected_line_update(owner, &ast_connected);
+				}
+
+				ast_channel_unlock(owner);
+			}
+			break;
+		case PRI_SUBCMD_REDIRECTING:
+			sig_pri_lock_owner(pri, chanpos);
+			owner = pri->pvts[chanpos]->owner;
+			if (owner) {
+				struct ast_party_redirecting ast_redirecting;
+				const struct pri_party_redirecting *pri_redirecting;
+				char from_number[AST_MAX_EXTENSION];
+				char to_number[AST_MAX_EXTENSION];
+
+				ast_party_redirecting_set_init(&ast_redirecting, &owner->redirecting);
+
+				pri_redirecting = &subcmd->u.redirecting;
+
+				/* ast_redirecting.from */
+				if (pri_redirecting->from.name.valid) {
+					ast_redirecting.from.name = (char *) pri_redirecting->from.name.str;
+				}
+				if (pri_redirecting->from.number.valid) {
+					apply_plan_to_number(from_number, sizeof(from_number), pri,
+						pri_redirecting->from.number.str,
+						pri_redirecting->from.number.plan);
+					ast_redirecting.from.number = from_number;
+					ast_redirecting.from.number_type = pri_redirecting->from.number.plan;
+				}
+				if (pri_redirecting->from.name.valid
+					|| pri_redirecting->from.number.valid) {
+					ast_redirecting.from.number_presentation =
+						overall_ast_presentation(&pri_redirecting->from);
+				}
+
+				/* ast_redirecting.to */
+				if (pri_redirecting->to.name.valid) {
+					ast_redirecting.to.name = (char *) pri_redirecting->to.name.str;
+				}
+				if (pri_redirecting->to.number.valid) {
+					apply_plan_to_number(to_number, sizeof(to_number), pri,
+						pri_redirecting->to.number.str, pri_redirecting->to.number.plan);
+					ast_redirecting.to.number = to_number;
+					ast_redirecting.to.number_type = pri_redirecting->to.number.plan;
+				}
+				if (pri_redirecting->to.name.valid
+					|| pri_redirecting->to.number.valid) {
+					ast_redirecting.to.number_presentation =
+						overall_ast_presentation(&pri_redirecting->from);
+				}
+
+				ast_redirecting.count = pri_redirecting->count;
+				ast_redirecting.reason = pri_to_ast_reason(pri_redirecting->reason);
+
+/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
+
+				ast_channel_set_redirecting(owner, &ast_redirecting);
+				if (event_id != PRI_EVENT_RING) {
+					/* This redirection was not from a SETUP message. */
+					ast_channel_queue_redirecting_update(owner, &ast_redirecting);
+				}
+
+				ast_channel_unlock(owner);
+			}
+			break;
+		default:
+			ast_log(LOG_WARNING,
+				"Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n",
+				subcmd->cmd, pri_event2str(event_id), PRI_SPAN(channel),
+				PRI_CHANNEL(channel), pri->span);
+			break;
+		}
+	}
 }
 
 static void *pri_dchannel(void *vpri)
@@ -935,18 +1366,20 @@
 					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);
 						/* 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) {
+						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);
-							char digit;
-							int i;					
-							for (i = 0; i < digitlen; i++) {	
-								digit = e->digit.digits[i];
-								{
-									struct ast_frame f = { AST_FRAME_DTMF, digit, };
-									pri_queue_frame(pri->pvts[chanpos], &f, pri);
-								}
+							int i;
+
+							for (i = 0; i < digitlen; i++) {
+								struct ast_frame f = { AST_FRAME_DTMF, e->digit.digits[i], };
+
+								pri_queue_frame(pri->pvts[chanpos], &f, pri);
 							}
 						}
 						sig_pri_unlock_private(pri->pvts[chanpos]);
@@ -963,18 +1396,44 @@
 					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);
 						/* 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) {
+						if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+							&& pri->pvts[chanpos]->call == e->ring.call
+							&& pri->pvts[chanpos]->owner) {
 							/* how to do that */
+							struct ast_channel *owner;
 							int digitlen = strlen(e->ring.callednum);
-							char digit;
-							int i;					
-							for (i = 0; i < digitlen; i++) {	
-								digit = e->ring.callednum[i];
-								{
-									struct ast_frame f = { AST_FRAME_DTMF, digit, };
-									pri_queue_frame(pri->pvts[chanpos], &f, pri);
+							int i;
+
+							for (i = 0; i < digitlen; i++) {
+								struct ast_frame f = { AST_FRAME_DTMF, e->ring.callednum[i], };
+
+								pri_queue_frame(pri->pvts[chanpos], &f, pri);
+							}
+							sig_pri_lock_owner(pri, chanpos);
+							owner = pri->pvts[chanpos]->owner;
+							if (owner) {
+								char dnid[AST_MAX_EXTENSION];
+
+								/*
+								 * Append the received info digits to the end of
+								 * the exten and dnid strings
+								 */
+								strncat(owner->exten, e->ring.callednum,
+									(sizeof(owner->exten) - 1) - strlen(owner->exten));
+								if (owner->cid.cid_dnid) {
+									ast_copy_string(dnid, owner->cid.cid_dnid,
+										sizeof(dnid));
+									ast_free(owner->cid.cid_dnid);
+								} else {
+									dnid[0] = 0;
 								}
+								strncat(dnid, e->ring.callednum,
+									(sizeof(dnid) - 1) - strlen(dnid));
+								owner->cid.cid_dnid = ast_strdup(dnid);
+								ast_channel_unlock(owner);
 							}
 						}
 						sig_pri_unlock_private(pri->pvts[chanpos]);
@@ -1052,6 +1511,7 @@
 						if (pri->pvts[chanpos]->call == e->ring.call) {
 							ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
 								PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
+							sig_pri_unlock_private(pri->pvts[chanpos]);
 							break;
 						} else {
 							/* This is where we handle initial glare */
@@ -1091,7 +1551,7 @@
 						pri->pvts[chanpos]->cid_ton = 0;
 					}
 					apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
-							     e->ring.redirectingnum, e->ring.callingplanrdnis);
+						e->ring.redirectingnum, e->ring.callingplanrdnis);
 					/* If immediate=yes go to s|1 */
 					if (pri->pvts[chanpos]->immediate) {
 						ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
@@ -1101,7 +1561,6 @@
 					/* Get called number */
 					else if (!ast_strlen_zero(e->ring.callednum)) {
 						ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
 					} else if (pri->overlapdial)
 						pri->pvts[chanpos]->exten[0] = '\0';
 					else {
@@ -1110,8 +1569,7 @@
 						pri->pvts[chanpos]->exten[1] = '\0';
 					}
 					/* Set DNID on all incoming calls -- even immediate */
-					if (!ast_strlen_zero(e->ring.callednum))
-						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
+					ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
 					/* No number yet, but received "sending complete"? */
 					if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
 						ast_verb(3, "Going to extension s|1 because of Complete received\n");
@@ -1136,37 +1594,42 @@
 						pri->pvts[chanpos]->callingpres = e->ring.callingpres;
 					
 						/* Start PBX */
-						if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-							/* Release the PRI lock while we create the channel */
+						if (!e->ring.complete
+							&& (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+							&& ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
+							/*
+							 * Release the PRI lock while we create the channel
+							 * so other threads can send D channel messages.
+							 */
 							ast_mutex_unlock(&pri->lock);
-
 							c = sig_pri_new_ast_channel(pri->pvts[chanpos], AST_STATE_RESERVED, 0, (e->ring.layer1 = PRI_LAYER_1_ALAW) ? SIG_PRI_ALAW : SIG_PRI_ULAW, e->ring.ctype, pri->pvts[chanpos]->exten);
-
-							sig_pri_unlock_private(pri->pvts[chanpos]);
-
-							if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
+							ast_mutex_lock(&pri->lock);
+							if (c) {
+								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
+									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
+								}
+								if (e->ring.ani2 >= 0) {
+									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
+									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+									pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
+								}
+
+#ifdef SUPPORT_USERUSER
+								if (!ast_strlen_zero(e->ring.useruserinfo)) {
+									pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
+								}
+#endif
+
+								snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
+								pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
+								if (e->ring.redirectingreason >= 0) {
+									/* This is now just a status variable.  Use REDIRECTING() dialplan function. */
+									pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
+								}
+
+								sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
+									e->ring.subcmds);
 							}
-							if (e->ring.ani2 >= 0) {
-								snprintf(ani2str, 5, "%.2d", e->ring.ani2);
-								pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-								pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
-							}
-
-#ifdef SUPPORT_USERUSER
-							if (!ast_strlen_zero(e->ring.useruserinfo)) {

[... 570 lines stripped ...]



More information about the svn-commits mailing list