[asterisk-commits] mattf: branch mattf/bug13495 r160762 - in /team/mattf/bug13495: channels/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Dec 3 15:31:23 CST 2008


Author: mattf
Date: Wed Dec  3 15:31:22 2008
New Revision: 160762

URL: http://svn.digium.com/view/asterisk?view=rev&rev=160762
Log:
Commit of chan_dahdi portion of #13495

Modified:
    team/mattf/bug13495/channels/chan_dahdi.c
    team/mattf/bug13495/main/ast_expr2.c
    team/mattf/bug13495/main/ast_expr2.h

Modified: team/mattf/bug13495/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/mattf/bug13495/channels/chan_dahdi.c?view=diff&rev=160762&r1=160761&r2=160762
==============================================================================
--- team/mattf/bug13495/channels/chan_dahdi.c (original)
+++ team/mattf/bug13495/channels/chan_dahdi.c Wed Dec  3 15:31:22 2008
@@ -381,7 +381,11 @@
 
 #define SS7_NAI_DYNAMIC		-1
 
-#define LINKSET_FLAG_EXPLICITACM (1 << 0)
+#define LINKSET_FLAG_EXPLICITACM	(1 << 0)
+#define LINKSET_FLAG_INITIALHWBLO	(1 << 1)
+
+#define SS7_BLOCKED_MAINTENANCE	(1 << 0)
+#define SS7_BLOCKED_HARDWARE	(1 << 1)
 
 struct dahdi_ss7 {
 	pthread_t master;						/*!< Thread of master */
@@ -401,6 +405,7 @@
 	char nationalprefix[10];					/*!< area access code ('0' for european dialplans) */
 	char subscriberprefix[20];					/*!< area access code + area code ('0'+area code for european dialplans) */
 	char unknownprefix[20];						/*!< for unknown dialplans */
+	char networkroutedprefix[20];
 	struct ss7 *ss7;
 	struct dahdi_pvt *pvts[MAX_CHANNELS];				/*!< Member channel pvt structs */
 	int flags;							/*!< Linkset flags */
@@ -638,8 +643,8 @@
 	unsigned int mwisendactive:1; 			/*!< a MWI message sending thread is active */
 	/* Channel state or unavilability flags */
 	unsigned int inservice:1;
-	unsigned int locallyblocked:1;
-	unsigned int remotelyblocked:1;
+	unsigned int locallyblocked:2;
+	unsigned int remotelyblocked:2;
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
 	unsigned int rlt:1;	
 	unsigned int alerting:1;
@@ -649,6 +654,10 @@
 	unsigned int progress:1;
 	unsigned int resetting:1;
 	unsigned int setup_ack:1;
+#endif
+#if HAVE_SS7
+	unsigned int do_hangup; /* what have to do in chan_dahdi */
+	unsigned int called_complete;
 #endif
 	unsigned int use_smdi:1;		/* Whether to use SMDI on this channel */
 	struct mwisend_info mwisend_data;
@@ -754,6 +763,12 @@
 	char gen_dig_number[50];
 	char orig_called_num[50];
 	char redirecting_num[50];
+	unsigned char redirect_counter;
+	unsigned char redirect_info;
+	unsigned char redirect_info_ind;
+	unsigned char redirect_info_orig_reas;
+	unsigned char redirect_info_counter;
+	unsigned char redirect_info_reas;
 	char generic_name[50];
 	unsigned char gen_add_num_plan;
 	unsigned char gen_add_nai;
@@ -773,6 +788,9 @@
 	int cic;							/*!< CIC associated with channel */
 	unsigned int dpc;						/*!< CIC's DPC */
 	unsigned int loopedback:1;
+	char cug_interlock_ni[5];
+	unsigned short cug_interlock_code;
+	unsigned char cug_indicator;
 #endif
 	char begindigit;
 	int muting;
@@ -836,7 +854,8 @@
 			.internationalprefix = "",
 			.nationalprefix = "",
 			.subscriberprefix = "",
-			.unknownprefix = ""
+			.unknownprefix = "",
+			.networkroutedprefix = "",
 		},
 #endif
 		.chan = {
@@ -957,6 +976,9 @@
 #endif
 
 #ifdef HAVE_SS7
+static int ss7_find_alloc_call(struct dahdi_pvt *p);
+static int ss7_do_rsc(struct dahdi_pvt *p);
+
 static inline void ss7_rel(struct dahdi_ss7 *ss7)
 {
 	ast_mutex_unlock(&ss7->lock);
@@ -2160,6 +2182,31 @@
 {
 	return cid_pres & 0x03;
 }
+
+static int ss7_parse_prefix(struct dahdi_pvt *p, const char *number, char *nai)
+{
+	int strip = 0;
+
+	if (strncmp(number, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
+		strip = strlen(p->ss7->internationalprefix);
+		*nai = SS7_NAI_INTERNATIONAL;
+	} else if (strncmp(number, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
+		strip = strlen(p->ss7->nationalprefix);
+		*nai = SS7_NAI_NATIONAL;
+	} else if (strncmp(number, p->ss7->networkroutedprefix, strlen(p->ss7->networkroutedprefix)) == 0) {
+		strip = strlen(p->ss7->networkroutedprefix);
+		*nai = SS7_NAI_NETWORKROUTED;
+	} else if (strncmp(number, p->ss7->unknownprefix, strlen(p->ss7->unknownprefix)) == 0) {
+		strip = strlen(p->ss7->unknownprefix);
+		*nai = SS7_NAI_UNKNOWN;
+	} else if (strncmp(number, p->ss7->subscriberprefix, strlen(p->ss7->subscriberprefix)) == 0) {
+		strip = strlen(p->ss7->subscriberprefix);
+		*nai = SS7_NAI_SUBSCRIBER;
+	} else
+		*nai = SS7_NAI_SUBSCRIBER;
+
+	return strip;
+}
 #endif
 
 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
@@ -2462,6 +2509,16 @@
 		int called_nai_strip;
 		char ss7_calling_nai;
 		int calling_nai_strip;
+		char ss7_orig_called_nai;
+		int orig_called_num_nai_strip;
+		char ss7_redirecting_num_nai;
+		int redirecting_num_nai_strip;
+		unsigned char redirect_info_ind_num;
+		unsigned char redirect_info_orig_reas_num;
+		unsigned char redirect_info_counter_num;
+		unsigned char redirect_info_reas_num;
+		unsigned char ss7_cug_indicator;
+		const char *ss7_redirect_counter;
 		const char *charge_str = NULL;
 		const char *gen_address = NULL;
 		const char *gen_digits = NULL;
@@ -2474,7 +2531,17 @@
 		const char *call_ref_id = NULL;
 		const char *call_ref_pc = NULL;
 		const char *send_far = NULL;
-
+		const char *redirecting_number = NULL;
+		const char *ss7_orig_called_num = NULL;
+		const char *redirect_info_ind = NULL;
+		const char *redirect_info_orig_reas = NULL;
+		const char *redirect_info_counter = NULL;
+		const char *redirect_info_reas = NULL;
+		const char *col_req = NULL;
+		const char *ss7_cug_indicator_str;
+		const char *ss7_cug_interlock_ni;
+		const char *ss7_cug_interlock_code;
+		
 		c = strchr(dest, '/');
 		if (c)
 			c++;
@@ -2504,35 +2571,24 @@
 
 		called_nai_strip = 0;
  		ss7_called_nai = p->ss7->called_nai;
-		if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
- 			if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
- 				called_nai_strip = strlen(p->ss7->internationalprefix);
- 				ss7_called_nai = SS7_NAI_INTERNATIONAL;
- 			} else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
-				called_nai_strip = strlen(p->ss7->nationalprefix);
- 				ss7_called_nai = SS7_NAI_NATIONAL;
- 			} else {
-				ss7_called_nai = SS7_NAI_SUBSCRIBER;
- 			}
- 		}
+
+		if (ss7_called_nai == SS7_NAI_DYNAMIC) /* compute dynamically */
+			called_nai_strip = ss7_parse_prefix(p, c + p->stripmsd, &ss7_called_nai);
+
  		isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
 
 		calling_nai_strip = 0;
 		ss7_calling_nai = p->ss7->calling_nai;
-		if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
-			if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
-				calling_nai_strip = strlen(p->ss7->internationalprefix);
-				ss7_calling_nai = SS7_NAI_INTERNATIONAL;
-			} else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
-				calling_nai_strip = strlen(p->ss7->nationalprefix);
-				ss7_calling_nai = SS7_NAI_NATIONAL;
-			} else {
-				ss7_calling_nai = SS7_NAI_SUBSCRIBER;
-			}
-		}
-		isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
-			p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
-			p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
+
+		if (l && ss7_calling_nai == SS7_NAI_DYNAMIC) /* compute dynamically */
+			calling_nai_strip = ss7_parse_prefix(p, l, &ss7_calling_nai);
+
+		if (ast->cid.cid_pres == AST_PRES_UNAVAILABLE)
+			isup_set_calling(p->ss7call, NULL, 0, SS7_PRESENTATION_ADDR_NOT_AVAILABLE, 3);
+		else
+			isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
+				p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+				p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
 
 		isup_set_oli(p->ss7call, ast->cid.cid_ani2);
 		isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
@@ -2580,6 +2636,118 @@
 		send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
 		if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
 			(isup_far(p->ss7->ss7, p->ss7call));
+
+		redirecting_number = pbx_builtin_getvar_helper(ast, "SS7_REDIRECTING_NUMBER");
+
+		if (redirecting_number) {
+			redirecting_num_nai_strip = 0;
+			ss7_redirecting_num_nai = p->ss7->calling_nai;
+			if (ss7_redirecting_num_nai == SS7_NAI_DYNAMIC)
+				redirecting_num_nai_strip = ss7_parse_prefix(p, redirecting_number, &ss7_redirecting_num_nai);
+			isup_set_redirecting_number(p->ss7call, redirecting_number + redirecting_num_nai_strip, ss7_redirecting_num_nai, SS7_PRESENTATION_RESTRICTED, 3);
+		}
+
+		ss7_redirect_counter = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_COUNTER");
+		if (ss7_redirect_counter)
+			isup_set_redirect_counter(p->ss7call, atoi(ss7_redirect_counter));
+
+		ss7_orig_called_num = pbx_builtin_getvar_helper(ast, "SS7_ORIG_CALLED_NUM");
+		if (ss7_orig_called_num) {
+			orig_called_num_nai_strip = 0;
+			ss7_orig_called_nai = p->ss7->called_nai;
+			if (ss7_orig_called_nai == SS7_NAI_DYNAMIC)
+				orig_called_num_nai_strip = ss7_parse_prefix(p, ss7_orig_called_num, &ss7_orig_called_nai);
+			isup_set_orig_called_num(p->ss7call, ss7_orig_called_num + orig_called_num_nai_strip, ss7_orig_called_nai, 
+				SS7_PRESENTATION_RESTRICTED, 3);
+		}
+
+		redirect_info_ind = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_INFO_IND");
+		if (redirect_info_ind && redirect_info_ind[0] != '\0') {
+			if (!strcasecmp(redirect_info_ind, "NO_REDIRECTION"))
+				redirect_info_ind_num = 0;
+			else if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_PRES_ALLOWED"))
+				redirect_info_ind_num = 1;
+			else if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_INFO_RESTRICTED"))
+				redirect_info_ind_num = 2;
+			else if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_ALLOWED"))
+				redirect_info_ind_num = 3;
+			else if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_INFO_RESTRICTED"))
+				redirect_info_ind_num = 4;
+			else if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_PRES_RESTRICTED"))
+				redirect_info_ind_num = 5;
+			else if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_RESTRICTED"))
+				redirect_info_ind_num = 6;
+			else if (!strcasecmp(redirect_info_ind, "SPARE"))
+				redirect_info_ind_num = 7;
+			else
+				redirect_info_ind_num = 0;
+
+			redirect_info_orig_reas = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_INFO_ORIG_REAS");
+			if (redirect_info_orig_reas) {
+				if (!strcasecmp(redirect_info_orig_reas, "UNKNOWN"))
+					redirect_info_orig_reas_num = 0;
+				else if (!strcasecmp(redirect_info_orig_reas, "USER-BUSY"))
+					redirect_info_orig_reas_num = 1;
+				else if (!strcasecmp(redirect_info_orig_reas, "NO-ANSWER"))
+					redirect_info_orig_reas_num = 2;
+				else if (!strcasecmp(redirect_info_orig_reas, "UNCONDITIONAL"))
+					redirect_info_orig_reas_num = 3;
+				else
+					redirect_info_orig_reas_num = 0;
+			} else
+				redirect_info_orig_reas_num = 0;
+
+			redirect_info_counter = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_INFO_COUNTER");
+			if (redirect_info_counter)
+				redirect_info_counter_num = atoi(redirect_info_counter);
+			else
+				redirect_info_counter_num = 5; /* Avoiding call forwarding loops!!! */
+
+			redirect_info_reas = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_INFO_REAS");
+			if (redirect_info_reas) {
+				if (!strcasecmp(redirect_info_reas, "UNKNOWN"))
+					redirect_info_reas_num = 0;
+				else if (!strcasecmp(redirect_info_reas, "USER-BUSY"))
+					redirect_info_reas_num = 1;
+				else if (!strcasecmp(redirect_info_reas, "NO-ANSWER"))
+					redirect_info_reas_num = 2;
+				else if (!strcasecmp(redirect_info_reas, "UNCONDITIONAL"))
+					redirect_info_reas_num = 3;
+				else if (!strcasecmp(redirect_info_reas, "DEFLECTION_DURING_ALERTING"))
+					redirect_info_reas_num = 4;
+				else if (!strcasecmp(redirect_info_reas, "DEFLECTION_IMMEDIATE_RESPONSE"))
+					redirect_info_reas_num = 5;
+				else if (!strcasecmp(redirect_info_reas, "UNAVAILABLE"))
+					redirect_info_reas_num = 6;
+				else
+					redirect_info_reas_num = 0;
+			} else
+				redirect_info_reas_num = 0;
+
+			isup_set_redirectiong_info(p->ss7call, redirect_info_ind_num, redirect_info_orig_reas_num,
+				redirect_info_counter_num, redirect_info_reas_num);
+		}
+
+		col_req = pbx_builtin_getvar_helper(ast, "SS7_COL_REQUEST");
+		if (ast_true(col_req))
+			isup_set_col_req(p->ss7call);
+		
+		ss7_cug_indicator_str = pbx_builtin_getvar_helper(ast, "SS7_CUG_INDICATOR");
+		if (ss7_cug_indicator_str && ss7_cug_indicator_str[0]) {
+			if (!strcasecmp(ss7_cug_indicator_str, "OUTGOING_ALLOWED"))
+				ss7_cug_indicator = ISUP_CUG_OUTGOING_ALLOWED;
+			else if (!strcasecmp(ss7_cug_indicator_str, "OUTGOING_NOT_ALLOWED"))
+				ss7_cug_indicator = ISUP_CUG_OUTGOING_NOT_ALLOWED;
+			else
+				ss7_cug_indicator = ISUP_CUG_NON;
+			
+			if (ss7_cug_indicator != ISUP_CUG_NON) {
+				ss7_cug_interlock_code = pbx_builtin_getvar_helper(ast, "SS7_CUG_INTERLOCK_CODE");
+				ss7_cug_interlock_ni = pbx_builtin_getvar_helper(ast, "SS7_CUG_INTERLOCK_NI");
+				if (ss7_cug_interlock_code && ss7_cug_interlock_ni && strlen(ss7_cug_interlock_ni) == 4)
+					isup_set_cug(p->ss7call, ss7_cug_indicator, ss7_cug_interlock_ni, atoi(ss7_cug_interlock_code));
+			}
+		}
 		
 		ast_channel_unlock(ast);
 
@@ -3344,7 +3512,7 @@
 		if (p->ss7) {
 			if (p->ss7call) {
 				if (!ss7_grab(p, p->ss7)) {
-					if (!p->alreadyhungup) {
+					if (p->do_hangup == SS7_HANGUP_SEND_REL) {
 						const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
 						int icause = ast->hangupcause ? ast->hangupcause : -1;
 
@@ -3352,11 +3520,30 @@
 							if (atoi(cause))
 								icause = atoi(cause);
 						}
+						if (icause > 255)
+							icause = 16;
+
 						isup_rel(p->ss7->ss7, p->ss7call, icause);
-						ss7_rel(p->ss7);
-						p->alreadyhungup = 1;
-					} else
-						ast_log(LOG_WARNING, "Trying to hangup twice!\n");
+						p->do_hangup = SS7_HANGUP_DO_NOTHING;
+					} else if (p->do_hangup == SS7_HANGUP_SEND_RSC) {
+						ss7_do_rsc(p);
+						p->do_hangup = SS7_HANGUP_DO_NOTHING;
+					} else if (p->do_hangup == SS7_HANGUP_SEND_RLC) {
+						isup_rlc(p->ss7->ss7, p->ss7call);
+						isup_free_call(p->ss7->ss7, p->ss7call);
+						p->ss7call = NULL;
+						p->do_hangup = SS7_HANGUP_DO_NOTHING;
+					} else if (p->do_hangup == SS7_HANGUP_FREE_CALL) {
+						p->do_hangup = SS7_HANGUP_DO_NOTHING;
+						isup_free_call(p->ss7->ss7, p->ss7call);
+						p->ss7call = NULL;
+					} else if (p->do_hangup == SS7_HANGUP_REEVENT_IAM) {
+						isup_event_iam(p->ss7->ss7, p->ss7call, p->dpc);
+						p->do_hangup = SS7_HANGUP_SEND_REL;
+					} else if (p->do_hangup == SS7_HANGUP_DO_NOTHING) {
+						p->ss7call = isup_free_call_if_clear(p->ss7->ss7, p->ss7call);
+					}
+					ss7_rel(p->ss7);
 				} else {
 					ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
 					res = -1;
@@ -3601,6 +3788,27 @@
 #ifdef HAVE_SS7
 	case SIG_SS7:
 		if (!ss7_grab(p, p->ss7)) {
+			const char *connected_num, *connected_pres_str;
+			unsigned char connected_pres;
+			char connected_nai;
+			int connected_strip = 0;
+			
+			connected_num = pbx_builtin_getvar_helper(ast, "SS7_CONNECTED_NUMBER");
+			if (connected_num) {
+				if (p->ss7->called_nai ==  SS7_NAI_DYNAMIC)
+					connected_strip = ss7_parse_prefix(p, connected_num, &connected_nai);
+				else
+					connected_nai = p->ss7->called_nai;
+
+				connected_pres_str = pbx_builtin_getvar_helper(ast, "SS7_CONNECTED_PRES");
+							
+				if (connected_pres_str)
+					connected_pres = cid_pres2ss7pres(ast_parse_caller_presentation(connected_pres_str));
+				else
+					connected_pres = SS7_PRESENTATION_RESTRICTED;
+							
+				isup_set_connected(p->ss7call, connected_num + connected_strip, connected_nai, connected_pres, SS7_SCREENING_NETWORK_PROVIDED);
+			}
 			p->proceeding = 1;
 			res = isup_anm(p->ss7->ss7, p->ss7call);
 			ss7_rel(p->ss7);
@@ -5940,6 +6148,7 @@
 			}
 				
 			if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
+				
 				if (p->ss7->ss7) {
 					ss7_grab(p, p->ss7);
 					isup_acm(p->ss7->ss7, p->ss7call);
@@ -6026,6 +6235,16 @@
 			} else
 #endif
 				ast_moh_start(chan, data, p->mohinterpret);
+#ifdef HAVE_SS7
+			if (p->ss7) {
+				if (!ss7_grab(p, p->ss7)) {
+					if (p->ss7call)
+						isup_sus(p->ss7->ss7, p->ss7call, 0);
+					ss7_rel(p->ss7);
+				} else
+					ast_log(LOG_WARNING, "Unable to grab SS& on linkset %d\n", p->span);
+			}
+#endif
 			break;
 		case AST_CONTROL_UNHOLD:
 #ifdef HAVE_PRI
@@ -6038,6 +6257,16 @@
 			} else
 #endif
 				ast_moh_stop(chan);
+#ifdef HAVE_SS7
+			if (p->ss7) {
+				if (!ss7_grab(p, p->ss7)) {
+					if (p->ss7call)
+						isup_res(p->ss7->ss7, p->ss7call, 0);
+					ss7_rel(p->ss7);
+				} else
+					ast_log(LOG_WARNING, "Unable to grab SS& on linkset %d\n", p->span);
+			}
+#endif
 			break;
 		case AST_CONTROL_RADIO_KEY:
 			if (p->radio) 
@@ -6240,6 +6469,9 @@
 	/* Assume calls are not idle calls unless we're told differently */
 	i->isidlecall = 0;
 	i->alreadyhungup = 0;
+#endif
+#ifdef HAVE_SS7
+	i->do_hangup = SS7_HANGUP_SEND_REL;
 #endif
 	/* clear the fake event in case we posted one before we had ast_channel */
 	i->fake_event = 0;
@@ -8587,13 +8819,14 @@
 				tmp->ss7call = NULL;
 				ss7->pvts[ss7->numchans++] = tmp;
 
-				ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
-				ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
-				ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
-				ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
-
-				linksets[span].called_nai = conf->ss7.called_nai;
-				linksets[span].calling_nai = conf->ss7.calling_nai;
+				ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
+				ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
+				ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
+				ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
+				ast_copy_string(ss7->networkroutedprefix, conf->ss7.networkroutedprefix, sizeof(ss7->networkroutedprefix));
+
+				ss7->called_nai = conf->ss7.called_nai;
+				ss7->calling_nai = conf->ss7.calling_nai;
 			}
 #endif
 #ifdef HAVE_PRI
@@ -8965,9 +9198,11 @@
 		tmp->sendcalleridafter = conf->chan.sendcalleridafter;
 		if (!here) {
 			tmp->locallyblocked = tmp->remotelyblocked = 0;
-			if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
+			if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) {
 				tmp->inservice = 0;
-			else /* We default to in service on protocols that don't have a reset */
+				if (chan_sig == SIG_SS7 && tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO)
+					tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
+			} else /* We default to in service on protocols that don't have a reset */
 				tmp->inservice = 1;
 		}
 	}
@@ -9064,7 +9299,7 @@
 #ifdef HAVE_SS7
 		/* Trust SS7 */
 		if (p->ss7) {
-			if (p->ss7call)
+			if (p->ss7call || !p->inservice)
 				return 0;
 			else
 				return 1;
@@ -9446,6 +9681,28 @@
 	return winner;
 }
 
+static void ss7_check_range(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char *state)
+{
+	int cic;
+	
+	for (cic = startcic; cic <= endcic; cic++)
+		if (state[cic - startcic] && ss7_find_cic(linkset, cic, dpc) == -1)
+			state[cic - startcic] = 0;
+}
+
+static int ss7_find_cic_range(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
+{
+	int x, found = 0;
+	
+	for (x = 0; x < linkset->numchans; x++)
+		if (linkset->pvts[x] && (linkset->pvts[x]->dpc == dpc && linkset->pvts[x]->cic >= startcic && linkset->pvts[x]->cic <= endcic))
+			found++;
+	if (found == endcic - startcic + 1)
+		return  1;
+	else
+		return 0;
+}
+
 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
 {
 	unsigned char status[32];
@@ -9478,33 +9735,52 @@
 	
 }
 
-static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
-{
-	int i;
-
-	for (i = 0; i < linkset->numchans; i++) {
-		if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
-			ast_mutex_lock(&linkset->pvts[i]->lock);
-			if (linkset->pvts[i]->owner)
-				linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-			ast_mutex_unlock(&linkset->pvts[i]->lock);
-		}
-	}
-}
-
-static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
-{
-	int i;
-
+static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block, int remotely, int type)
+{
+	int i, offset = 0;
 	for (i = 0; i < linkset->numchans; i++) {
 		if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
 			if (state) {
-				if (state[i])
-					linkset->pvts[i]->remotelyblocked = block;
-			} else
-				linkset->pvts[i]->remotelyblocked = block;
-		}
-	}
+				if (state[offset]) {
+					if (linkset->pvts[i]->cic != startcic)
+						ast_mutex_lock(&linkset->pvts[i]->lock);
+
+					if (block) {
+						if (remotely)
+							linkset->pvts[i]->remotelyblocked |= type;
+						else
+							linkset->pvts[i]->locallyblocked |= type;
+					} else {
+						if (remotely)
+							linkset->pvts[i]->remotelyblocked &= ~type;
+						else
+							linkset->pvts[i]->locallyblocked &= ~type;
+					}
+
+					if (linkset->pvts[i]->owner && linkset->pvts[i]->owner->_state == AST_STATE_DIALING && !linkset->pvts[i]->proceeding) {
+						linkset->pvts[i]->owner->hangupcause = SS7_CAUSE_TRY_AGAIN;
+						linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+					}
+
+					if (linkset->pvts[i]->cic != startcic)
+						ast_mutex_unlock(&linkset->pvts[i]->lock);
+				}
+				offset++;
+			} else {
+				if (block) {
+					if (remotely)
+						linkset->pvts[i]->remotelyblocked |= type;
+					else
+						linkset->pvts[i]->locallyblocked |= type;
+				} else {
+					if (remotely)
+						linkset->pvts[i]->remotelyblocked &= ~type;
+					else
+						linkset->pvts[i]->locallyblocked &= ~type;
+				}
+			}
+		}
+	} /* for */
 }
 
 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
@@ -9520,11 +9796,13 @@
 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
 {
 	int i, startcic = -1, endcic, dpc;
+	struct dahdi_pvt *p;
 
 	if (linkset->numchans <= 0)
 		return;
 
 	startcic = linkset->pvts[0]->cic;
+	p = linkset->pvts[0];
 	/* DB: CIC's DPC fix */
 	dpc = linkset->pvts[0]->dpc;
 
@@ -9534,12 +9812,16 @@
 		} else {
 			endcic = linkset->pvts[i]->cic;
 			ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
-			isup_grs(linkset->ss7, startcic, endcic, dpc);
+			if (!ss7_find_alloc_call(p))
+				ast_log(LOG_ERROR, "Unable allocate new ss7call\n");
+			else
+				isup_grs(linkset->ss7, p->ss7call, endcic);
 
 			/* DB: CIC's DPC fix */
 			if (linkset->pvts[i+1]) {
 				startcic = linkset->pvts[i+1]->cic;
 				dpc = linkset->pvts[i+1]->dpc;
+				p = linkset->pvts[i+1];
 			}
 		}
 	}
@@ -9554,6 +9836,79 @@
 		}
 		p->loopedback = enable;
 	}
+}
+
+/* call me with locked p !!! */
+static int ss7_do_rsc(struct dahdi_pvt *p)
+{
+	if (!p || !p->ss7call)
+		return 0;
+
+	isup_rsc(p->ss7->ss7, p->ss7call);
+
+	if (p->locallyblocked == SS7_BLOCKED_MAINTENANCE)
+		isup_blo(p->ss7->ss7, p->ss7call);
+	else
+		p->locallyblocked = 0;
+
+	return 1;
+}
+
+/* call me with locked p !!! */
+static int ss7_start_rsc(struct dahdi_pvt *p)
+{
+	if (!p)
+		return 0;
+
+	if (!ss7_find_alloc_call(p))
+		return 0;
+
+	p->remotelyblocked = 0;
+	p->inservice = 0;
+	dahdi_loopback(p, 0);
+
+	if (p->owner) {
+		p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+		p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+		p->do_hangup = SS7_HANGUP_SEND_RSC;
+		return 1;
+	} else 
+		ss7_do_rsc(p);
+	
+	return 1;
+}
+
+static int ss7_clear_channels(struct dahdi_pvt *p, int endcic, int do_hangup)
+{
+	int i, chanpos, clean = 1;
+	struct dahdi_pvt *p_cur;
+
+	if (!p || !p->ss7call)
+		return 0;
+
+	for (i = p->cic; i <= endcic; i++)	{
+		chanpos = ss7_find_cic(p->ss7, i, p->dpc);
+		p_cur = p->ss7->pvts[chanpos];
+
+		if (p_cur != p)
+			ast_mutex_lock(&p_cur->lock);
+
+		p_cur->inservice = 0;
+
+		if (p_cur->owner) {
+			p_cur->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+			p_cur->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+			p_cur->do_hangup = do_hangup;
+			clean = 0;
+		} else if (p_cur->ss7call && p != p_cur) {
+			isup_free_call(p_cur->ss7->ss7, p_cur->ss7call);
+			p_cur->ss7call = NULL;
+		}
+		if (p_cur != p)
+			ast_mutex_unlock(&p_cur->lock);
+	}
+
+	return clean;
 }
 
 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
@@ -9564,6 +9919,7 @@
 	int law = 1;
 	struct ast_channel *c;
 	char tmp[256];
+	char *strp;
 
 	if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
 		ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
@@ -9583,12 +9939,13 @@
 	}
 
 	ast_mutex_unlock(&linkset->lock);
-	c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
+	c = dahdi_new(p, AST_STATE_RING, 0, SUB_REAL, law, 0); /* The startpbx is sometimes faster than we set up the variables!!! */
 
 	if (!c) {
 		ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
 		/* Holding this lock is assumed entering the function */
 		ast_mutex_lock(&linkset->lock);
+		isup_rel(p->ss7->ss7, p->ss7call, AST_CAUSE_SWITCH_CONGESTION);
 		return;
 	} else
 		ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
@@ -9668,8 +10025,127 @@
 		/* Clear this after we set it */
 		p->generic_name[0] = 0;
 	}
-
+	if (p->redirect_counter) {
+		char redirect_counter_str[8];
+		sprintf(redirect_counter_str, "%u", p->redirect_counter);
+		pbx_builtin_setvar_helper(c, "SS7_REDIRECT_COUNTER", redirect_counter_str);
+		/* Clear this after we set it */
+		p->redirect_counter = 0;
+	}
+	if (p->redirect_info) {
+		switch (p->redirect_info_ind) {
+		case 0:
+			strp = "NO_REDIRECTION";
+			break;
+		case 1:
+			strp = "CALL_REROUTED_PRES_ALLOWED";
+			break;
+		case 2:
+			strp = "CALL_REROUTED_INFO_RESTRICTED";
+			break;
+		case 3:
+			strp = "CALL_DIVERTED_PRES_ALLOWED";
+			break;
+		case 4:
+			strp = "CALL_DIVERTED_INFO_RESTRICTED";
+			break;
+		case 5:
+			strp = "CALL_REROUTED_PRES_RESTRICTED";
+			break;
+		case 6:
+			strp = "CALL_DIVERTED_PRES_RESTRICTED";
+			break;
+		case 7:
+			strp = "SPARE";
+			break;
+		default:
+			strp = "NO_REDIRECTION";
+		}
+		pbx_builtin_setvar_helper(c, "SS7_REDIRECT_INFO_IND", strp);
+	
+		switch (p->redirect_info_orig_reas) {
+		case 0:
+			strp = "UNKNOWN";
+			break;
+		case 1:
+			strp = "USER-BUSY";
+			break;
+		case 2:
+			strp = "NO-ANSWER";
+			break;
+		case 3:
+			strp = "UNCONDITIONAL";
+			break;
+		default:
+			strp = "UNKNOWN";
+		}
+		pbx_builtin_setvar_helper(c, "SS7_REDIRECT_INFO_ORIG_REAS", strp);
+
+	switch (p->redirect_info_reas) {
+		case 0:
+			strp = "UNKNOWN";
+			break;
+		case 1:
+			strp = "USER-BUSY";
+			break;
+		case 2:
+			strp = "NO-ANSWER";
+			break;
+		case 3:
+			strp = "UNCONDITIONAL";
+			break;
+		case 4:
+			strp = "DEFLECTION_DURING_ALERTING";
+			break;
+		case 5:
+			strp = "DEFLECTION_IMMEDIATE_RESPONSE";
+			break;
+		case 6:
+			strp = "UNAVAILABLE";
+			break;
+		default:
+			strp = "UNKNOWN";
+			break;
+		}
+		pbx_builtin_setvar_helper(c, "SS7_REDIRECT_INFO_REAS", strp);
+
+		snprintf(tmp, sizeof(tmp), "%d", p->redirect_info_counter);
+		pbx_builtin_setvar_helper(c, "SS7_REDIRECT_INFO_COUNTER", tmp);
+	}
+	if (p->cug_indicator != ISUP_CUG_NON) {
+		sprintf(tmp, "%d", p->cug_interlock_code);
+		pbx_builtin_setvar_helper(c, "SS7_CUG_INTERLOCK_CODE", tmp);
+
+		switch (p->cug_indicator) {
+		case ISUP_CUG_NON:
+			strp = "NON_CUG";
+			break;
+		case ISUP_CUG_OUTGOING_ALLOWED:
+			strp = "OUTGOING_ALLOWED";
+			break;
+		case ISUP_CUG_OUTGOING_NOT_ALLOWED:
+			strp = "OUTGOING_NOT_ALLOWED";
+			break;
+		default:
+			strp = "SPARE";
+		}
+		pbx_builtin_setvar_helper(c, "SS7_CUG_INDICATOR", strp);
+		
+		if (p->cug_interlock_ni)
+			pbx_builtin_setvar_helper(c, "SS7_CUG_INTERLOCK_NI", p->cug_interlock_ni);
+
+		p->cug_indicator = ISUP_CUG_NON;
+	}
+	
 	ast_mutex_lock(&p->lock);
+
+	/* STARTPBX !!! */
+	if (ast_pbx_start(c)) {
+		ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
+		c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; /* The ast_hangup() is dangerous here!!! */
+		c->_softhangup |= AST_SOFTHANGUP_DEV;
+	}
+
 	ast_mutex_lock(&linkset->lock);
 }
 
@@ -9688,14 +10164,38 @@
 	case SS7_NAI_UNKNOWN:
 		snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
 		break;
+	case SS7_NAI_NETWORKROUTED:
+		snprintf(buf, size, "%s%s", ss7->networkroutedprefix, number);
+		break;
 	default:
 		snprintf(buf, size, "%s", number);
 		break;
 	}
 }
+
 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
 {
     return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
+}
+
+static void ss7_process_connected(struct dahdi_pvt *p, char *connected_num, unsigned char connected_nai,
+		unsigned char connected_presentation_ind, unsigned char connected_screening_ind)
+{
+	struct ast_channel *c;
+	char buf[AST_MAX_EXTENSION];
+	
+	if (!p->owner)
+		return;
+	
+	c = p->owner;
+	if (!ast_strlen_zero(connected_num)) {
+		ss7_apply_plan_to_number(buf, sizeof(buf), p->ss7, connected_num, connected_nai);
+		pbx_builtin_setvar_helper(c, "SS7_CONNECTED_NUMBER", buf);
+	}
+	
+	pbx_builtin_setvar_helper(c, "SS7_CONNECTED_PRES",
+			ast_named_caller_presentation(ss7_pres_scr2cid_pres(connected_presentation_ind, connected_screening_ind)));
+	
 }
 
 static void *ss7_linkset(void *data)
@@ -9705,12 +10205,14 @@
 	struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
 	struct ss7 *ss7 = linkset->ss7;
 	ss7_event *e = NULL;
-	struct dahdi_pvt *p;
+	struct dahdi_pvt *p_cur, *p = NULL; /* just shut up gcc 4.1 */
 	int chanpos;
 	struct pollfd pollers[NUM_DCHANS];
 	int cic;
 	unsigned int dpc;
+	unsigned char state[255], mb_state[255];
 	int nextms = 0;
+	int mbcount;
 
 	ss7_start(ss7);
 
@@ -9730,7 +10232,9 @@
 			}
 			nextms = tv.tv_sec * 1000;
 			nextms += tv.tv_usec / 1000;
-		}
+		} else 
+			nextms = -1;
+
 		ast_mutex_unlock(&linkset->lock);
 
 		for (i = 0; i < linkset->numsigchans; i++) {
@@ -9746,7 +10250,6 @@
 			ast_mutex_lock(&linkset->lock);
 			ss7_schedule_run(ss7);
 			ast_mutex_unlock(&linkset->lock);
-			continue;
 		}
 
 		ast_mutex_lock(&linkset->lock);
@@ -9810,8 +10313,11 @@
 				linkset->state = LINKSET_STATE_DOWN;
 				for (i = 0; i < linkset->numchans; i++) {
 					struct dahdi_pvt *p = linkset->pvts[i];
-					if (p)
-						p->inalarm = 1;
+					if (p) {
+						p->inservice = 0;
+						if (linkset->flags & LINKSET_FLAG_INITIALHWBLO)
+							p->remotelyblocked |= SS7_BLOCKED_HARDWARE;
+					}
 				}
 				break;
 			case MTP2_LINK_UP:
@@ -9822,12 +10328,14 @@
 				break;
 			case ISUP_EVENT_CPG:
 				chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
-				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
+				if (chanpos < 0) { /* Never will be true */
+					ast_log(LOG_WARNING, "CPG on unconfigured CIC %d PC %d\n", e->cpg.cic, e->cpg.opc);
+					isup_free_call(ss7, e->cpg.call);
 					break;
 				}
 				p = linkset->pvts[chanpos];
 				ast_mutex_lock(&p->lock);
+
 				switch (e->cpg.event) {
 				case CPG_EVENT_ALERTING:
 					p->alerting = 1;
@@ -9841,8 +10349,8 @@
 						dahdi_queue_frame(p, &f, linkset);
 						p->progress = 1;
 						if (p->dsp && p->dsp_features) {
-						        ast_dsp_set_features(p->dsp, p->dsp_features);
-						        p->dsp_features = 0;
+							ast_dsp_set_features(p->dsp, p->dsp_features);
+							p->dsp_features = 0;
 						}
 					}
 					break;
@@ -9856,63 +10364,190 @@
 				ast_verbose("Resetting CIC %d\n", e->rsc.cic);
 				chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
+					ast_log(LOG_WARNING, "RSC on unconfigured CIC %d PC %d\n", e->rsc.cic, e->rsc.opc);
+					isup_free_call(ss7, e->rsc.call);
 					break;
 				}
 				p = linkset->pvts[chanpos];
 				ast_mutex_lock(&p->lock);
+				p->ss7call = e->rsc.call;
 				p->inservice = 1;
 				p->remotelyblocked = 0;
 				dpc = p->dpc;
+				if (p->locallyblocked == SS7_BLOCKED_MAINTENANCE)
+					isup_blo(ss7, e->rsc.call);
+				else if (p->locallyblocked == SS7_BLOCKED_HARDWARE)
+					p->locallyblocked = 0;
+				
 				isup_set_call_dpc(e->rsc.call, dpc);
-				if (p->ss7call)
-					p->ss7call = NULL;
-				if (p->owner)
+
+				if (p->owner) {
 					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+					p->do_hangup = SS7_HANGUP_SEND_RLC;
+					if (e->rsc.got_sent_msg != ISUP_SENT_IAM) {
+						/* Q.784 6.2.3 */
+						p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+					} else {
+						p->owner->hangupcause = SS7_CAUSE_TRY_AGAIN;
+					}
+				} else {
+					isup_rlc(ss7, e->rsc.call);
+					p->ss7call = isup_free_call_if_clear(ss7, e->rsc.call);
+				}
+				/* End the loopback if we have one */
+				dahdi_loopback(p, 0);
 				ast_mutex_unlock(&p->lock);
-				isup_rlc(ss7, e->rsc.call);
 				break;
 			case ISUP_EVENT_GRS:
-				ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
+				if (!ss7_find_cic_range(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc)) {
+					ast_log(LOG_WARNING, "GRS on unconfigured range CIC %d - %d PC %d\n", e->grs.startcic, e->grs.endcic, e->grs.opc);
+					chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
+					if (chanpos > -1) {
+						p = linkset->pvts[chanpos];
+						ast_mutex_lock(&p->lock);
+						p->ss7call = isup_free_call_if_clear(ss7, e->grs.call);
+						ast_mutex_unlock(&p->lock);
+					} else
+						isup_free_call(ss7, e->grs.call);
+					break;
+				}
+
 				chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
-				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
-					break;
-				}
 				p = linkset->pvts[chanpos];
-				isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
-				ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
-				ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
+				ast_mutex_lock(&p->lock);
+				p->ss7call = e->grs.call;
+
+				ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0, 1, 							
+					SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE); 
+
+				mbcount = 0;
+				for (i = 0; i <= e->grs.endcic - p->cic; i++)	{
+					chanpos = ss7_find_cic(p->ss7, i + p->cic, p->dpc);
+					p_cur = p->ss7->pvts[chanpos];
+					if (p != p_cur)
+						ast_mutex_lock(&p_cur->lock);
+
+					if (p_cur->locallyblocked & SS7_BLOCKED_HARDWARE)
+						state[i] = 1;
+					else
+						state[i] = 0;
+
+					if (p_cur->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
+						mb_state[i] = 1;
+						mbcount++;
+					} else
+						mb_state[i] = 0;
+
+					if (p_cur->owner) {
+						p_cur->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+						if (p_cur->owner->_state == AST_STATE_DIALING && !linkset->pvts[i]->proceeding)
+							p_cur->owner->hangupcause = SS7_CAUSE_TRY_AGAIN;
+						else
+							p_cur->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+						p_cur->do_hangup = SS7_HANGUP_FREE_CALL;
+					} else if (p->ss7call && p != p_cur) { /* clear any session */
+						isup_free_call(ss7, p_cur->ss7call);
+						p_cur->ss7call = NULL;
+					}
+
+					p_cur->inservice = 1;
+
+					if (p != p_cur)
+						ast_mutex_unlock(&p_cur->lock);
+				}
+
+				if (mbcount)
+					isup_cgb(ss7, p->ss7call, e->grs.endcic, mb_state, 0);
+	
+				isup_gra(ss7, p->ss7call, e->grs.endcic, state);
+				if (!p->owner)
+					p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
+				ast_mutex_unlock(&p->lock);
 				break;
 			case ISUP_EVENT_CQM:
 				ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
 				ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
+				chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
+				if (chanpos > -1) {
+					p = linkset->pvts[chanpos];
+					ast_mutex_lock(&p->lock);
+					if (!p->owner)
+						p->ss7call = isup_free_call_if_clear(ss7, e->cqm.call);
+					ast_mutex_unlock(&p->lock);
+				}
 				break;
 			case ISUP_EVENT_GRA:
-				ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
-				ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
-				ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
+				if (!ss7_find_cic_range(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc)) { /* Never will be true */
+					ast_log(LOG_WARNING, "GRA on unconfigured range CIC %d - %d PC %d\n", e->gra.startcic, e->gra.endcic, e->gra.opc);
+					isup_free_call(ss7, e->gra.call);
+					break;
+				}
+				chanpos = ss7_find_cic(linkset, e->gra.startcic, e->gra.opc);
+				p = linkset->pvts[chanpos];
+				ast_mutex_lock(&p->lock);
+				p->ss7call = e->gra.call;
+
+				ast_verbose("Got reset acknowledgement from CIC %d to %d DPC: %d\n", e->gra.startcic, e->gra.endcic, e->gra.opc);
+      				ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
+				ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status,
+					1, 1, SS7_BLOCKED_HARDWARE);
+
+				p->ss7call = isup_free_call_if_clear(ss7, p->ss7call); /* we may sent a CDB with GRS! */
+				ast_mutex_unlock(&p->lock);
 				break;
+			case ISUP_EVENT_SAM:
+				chanpos = ss7_find_cic(linkset, e->sam.cic, e->sam.opc);
+				if (chanpos < 0) {
+					ast_log(LOG_WARNING, "SAM on unconfigured CIC %d PC %d\n", e->sam.cic, e->sam.opc);
+					isup_free_call(ss7, e->sam.call);
+					break;
+				}
+				p = linkset->pvts[chanpos];
+				ast_mutex_lock(&p->lock);
+				if (p->owner) {
+					ast_log(LOG_WARNING, "SAM on CIC %d PC %d already have call\n", e->sam.cic, e->sam.opc);
+					ast_mutex_unlock(&p->lock);
+					break;
+				}
+				p->called_complete = 0;
+				if (!ast_strlen_zero(e->sam.called_party_num)) {
+					char *st;
+					strncat(p->exten, e->sam.called_party_num, sizeof(p->exten) - strlen(p->exten));
+					st = strchr(p->exten, '#');
+					if (st) {
+						*st = '\0';
+						p->called_complete = 1;
+					}
+				} else
+					p->exten[0] = '\0';
+				goto ss7_start_switch;
 			case ISUP_EVENT_IAM:
  				ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
 				chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
-					isup_rel(ss7, e->iam.call, -1);
+					ast_log(LOG_WARNING, "IAM on unconfigured CIC %d PC %d\n", e->iam.cic, e->iam.opc);
+					isup_free_call(ss7, e->iam.call);
 					break;
 				}
 				p = linkset->pvts[chanpos];
 				ast_mutex_lock(&p->lock);
+				p->ss7call = e->iam.call;
+				if (p->locallyblocked) {

[... 2295 lines stripped ...]



More information about the asterisk-commits mailing list