[asterisk-commits] rmudgett: branch rmudgett/sig_ss7 r261099 - /team/rmudgett/sig_ss7/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue May 4 19:14:35 CDT 2010


Author: rmudgett
Date: Tue May  4 19:14:31 2010
New Revision: 261099

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=261099
Log:
Today's progress through the SS7 extraction swamp.

Modified:
    team/rmudgett/sig_ss7/channels/chan_dahdi.c
    team/rmudgett/sig_ss7/channels/sig_ss7.h

Modified: team/rmudgett/sig_ss7/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/sig_ss7/channels/chan_dahdi.c?view=diff&rev=261099&r1=261098&r2=261099
==============================================================================
--- team/rmudgett/sig_ss7/channels/chan_dahdi.c (original)
+++ team/rmudgett/sig_ss7/channels/chan_dahdi.c Tue May  4 19:14:31 2010
@@ -515,6 +515,42 @@
 
 #ifdef HAVE_SS7
 /* BUGBUG sig_ss7 callback functions ----v*/
+#define SIG_SS7_DEADLOCK_AVOIDANCE(p) \
+	do { \
+		sig_ss7_unlock_private(p); \
+		usleep(1); \
+		sig_ss7_lock_private(p); \
+	} while (0)
+
+static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
+{
+	if (p->calls->unlock_private) {
+		p->calls->unlock_private(p->chan_pvt);
+	}
+}
+
+static void sig_ss7_lock_private(struct sig_ss7_chan *p)
+{
+	if (p->calls->lock_private) {
+		p->calls->lock_private(p->chan_pvt);
+	}
+}
+
+void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
+{
+	p->inalarm = in_alarm;
+	if (p->calls->set_alarm) {
+		p->calls->set_alarm(p->chan_pvt, in_alarm);
+	}
+}
+
+static void sig_ss7_set_dialing(struct sig_ss7_chan *p, int is_dialing)
+{
+	if (p->calls->set_dialing) {
+		p->calls->set_dialing(p->chan_pvt, is_dialing);
+	}
+}
+
 /*!
  * \internal
  * \brief Set the caller id information in the parent module.
@@ -583,18 +619,12 @@
 	}
 }
 
-static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
-{
-	if (p->calls->unlock_private) {
-		p->calls->unlock_private(p->chan_pvt);
-	}
-}
-
-static void sig_ss7_lock_private(struct sig_ss7_chan *p)
-{
-	if (p->calls->lock_private) {
-		p->calls->lock_private(p->chan_pvt);
-	}
+static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
+{
+	if (p->calls->set_echocanceller) {
+		return p->calls->set_echocanceller(p->chan_pvt, enable);
+	}
+	return -1;
 }
 
 static void sig_ss7_loopback(struct sig_ss7_chan *p, int enable)
@@ -606,6 +636,7 @@
 		}
 	}
 }
+
 /* BUGBUG sig_ss7 callback functions ----^*/
 
 struct dahdi_ss7 {
@@ -1046,24 +1077,6 @@
 	struct sig_pri_pri *pri;
 	int logicalspan;
 #endif
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
-	/*!
-	 * \brief XXX BOOLEAN Purpose???
-	 * \note Applies to SS7 channels.
-	 */
-	unsigned int rlt:1;
-	/*! \brief TRUE if channel is alerting/ringing */
-	unsigned int alerting:1;
-	/*! \brief TRUE if the call has already gone/hungup */
-	unsigned int alreadyhungup:1;
-	/*!
-	 * \brief TRUE if call is in a proceeding state.
-	 * The call has started working its way through the network.
-	 */
-	unsigned int proceeding:1;
-	/*! \brief TRUE if the call has seen progress through the network. */
-	unsigned int progress:1;
-#endif
 	/*!
 	 * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
 	 * \note Set from the "usesmdi" value read in from chan_dahdi.conf
@@ -3186,6 +3199,7 @@
 	.new_ast_channel = my_new_ss7_ast_channel,
 	.play_tone = my_ss7_play_tone,
 
+	.set_alarm = my_set_alarm,
 	.set_dialing = my_set_dialing,
 	.set_callerid = my_set_callerid,
 	.set_dnid = my_set_dnid,
@@ -3334,14 +3348,14 @@
 #endif	/* defined(HAVE_SS7) */
 
 #if defined(HAVE_SS7)
-static inline int ss7_grab(struct dahdi_pvt *pvt, struct sig_ss7_linkset *ss7)
+static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
 {
 	int res;
 	/* Grab the lock first */
 	do {
 		res = ast_mutex_trylock(&ss7->lock);
 		if (res) {
-			DEADLOCK_AVOIDANCE(&pvt->lock);
+			SIG_SS7_DEADLOCK_AVOIDANCE(pvt);
 		}
 	} while (res);
 	/* Then break the poll */
@@ -3384,21 +3398,28 @@
 	}
 }
 
-static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
-{
-#ifdef HAVE_SS7
-	struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
-
-	if (data) {
-		switch (p->sig) {
-		case SIG_SS7:
-			ast_mutex_unlock(&ss7->ss7.lock);
+/* BUGBUG move to sig_ss7.c */
+static void sig_ss7_queue_frame(struct sig_ss7_chan *p, struct ast_frame *f, struct sig_ss7_linkset *ss7)
+{
+	/* We must unlock the SS7 to avoid the possibility of a deadlock */
+	ast_mutex_unlock(&ss7->lock);
+	for (;;) {
+		if (p->owner) {
+			if (ast_channel_trylock(p->owner)) {
+				SIG_SS7_DEADLOCK_AVOIDANCE(p);
+			} else {
+				ast_queue_frame(p->owner, f);
+				ast_channel_unlock(p->owner);
+				break;
+			}
+		} else
 			break;
-		default:
-			break;
-		}
-	}
-#endif
+	}
+	ast_mutex_lock(&ss7->lock);
+}
+
+static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
+{
 	for (;;) {
 		if (p->owner) {
 			if (ast_channel_trylock(p->owner)) {
@@ -3411,17 +3432,6 @@
 		} else
 			break;
 	}
-#if defined(HAVE_SS7)
-	if (data) {
-		switch (p->sig) {
-		case SIG_SS7:
-			ast_mutex_lock(&ss7->ss7.lock);
-			break;
-		default:
-			break;
-		}
-	}
-#endif
 }
 
 static void handle_clear_alarms(struct dahdi_pvt *p)
@@ -4980,9 +4990,7 @@
 	struct dahdi_pvt *p = ast->tech_pvt;
 	int x, res, mysig;
 	char dest[256]; /* must be same length as p->dialdest */
-#ifdef HAVE_SS7
-	char *c, *l;
-#endif
+
 	ast_mutex_lock(&p->lock);
 	ast_copy_string(dest, rdest, sizeof(dest));
 	ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
@@ -5031,6 +5039,15 @@
 	}
 #endif
 
+#if defined(HAVE_SS7)
+	if (p->sig == SIG_SS7) {
+		p->digital = IS_DIGITAL(ast->transfercapability);
+		res = sig_ss7_call(p->sig_pvt, ast, rdest);
+		ast_mutex_unlock(&p->lock);
+		return res;
+	}
+#endif	/* defined(HAVE_SS7) */
+
 	/* If this is analog signalling we can exit here */
 	if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
 		p->callwaitrings = 0;
@@ -5045,11 +5062,7 @@
 		/* Special pseudo -- automatically up*/
 		ast_setstate(ast, AST_STATE_UP);
 		break;
-	case SIG_SS7:
 	case SIG_MFCR2:
-		/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
-		p->dialdest[0] = '\0';
-		p->dialing = 1;
 		break;
 	default:
 		ast_debug(1, "not yet implemented\n");
@@ -5057,24 +5070,14 @@
 		return -1;
 	}
 
-#if defined(HAVE_SS7)
-	if (p->ss7) {
-		char ss7_called_nai;
-		int called_nai_strip;
-		char ss7_calling_nai;
-		int calling_nai_strip;
-		const char *charge_str = NULL;
-		const char *gen_address = NULL;
-		const char *gen_digits = NULL;
-		const char *gen_dig_type = NULL;
-		const char *gen_dig_scheme = NULL;
-		const char *gen_name = NULL;
-		const char *jip_digits = NULL;
-		const char *lspi_ident = NULL;
-		const char *rlt_flag = NULL;
-		const char *call_ref_id = NULL;
-		const char *call_ref_pc = NULL;
-		const char *send_far = NULL;
+#ifdef HAVE_OPENR2
+	if (p->mfcr2) {
+		openr2_calling_party_category_t chancat;
+		int callres = 0;
+		char *c, *l;
+
+		/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
+		p->dialdest[0] = '\0';
 
 		c = strchr(dest, '/');
 		if (c) {
@@ -5082,146 +5085,18 @@
 		} else {
 			c = "";
 		}
+		if (!p->hidecallerid) {
+			l = ast->cid.cid_num;
+		} else {
+			l = NULL;
+		}
 		if (strlen(c) < p->stripmsd) {
 			ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
 			ast_mutex_unlock(&p->lock);
 			return -1;
 		}
-
-		if (!p->hidecallerid) {
-			l = ast->connected.id.number;
-		} else {
-			l = NULL;
-		}
-
-		if (ss7_grab(p, p->ss7)) {
-			ast_log(LOG_WARNING, "Failed to grab SS7!\n");
-			ast_mutex_unlock(&p->lock);
-			return -1;
-		}
-		p->digital = IS_DIGITAL(ast->transfercapability);
-		p->ss7call = isup_new_call(p->ss7->ss7);
-
-		if (!p->ss7call) {
-			ss7_rel(p->ss7);
-			ast_mutex_unlock(&p->lock);
-			ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
-			return -1;
-		}
-
-		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;
- 			}
- 		}
- 		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->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
-			p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
-
-		isup_set_oli(p->ss7call, ast->connected.ani2);
-		isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
-
-		ast_channel_lock(ast);
-		/* Set the charge number if it is set */
-		charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
-		if (charge_str)
-			isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
-
-		gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
-		if (gen_address)
-			isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
-
-		gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
-		gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
-		gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
-		if (gen_digits)
-			isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
-
-		gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
-		if (gen_name)
-			isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
-
-		jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
-		if (jip_digits)
-			isup_set_jip_digits(p->ss7call, jip_digits);
-
-		lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
-		if (lspi_ident)
-			isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
-
-		rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
-		if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
-			isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
-		}
-
-		call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
-		call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
-		if (call_ref_id && call_ref_pc) {
-			isup_set_callref(p->ss7call, atoi(call_ref_id),
-					 call_ref_pc ? atoi(call_ref_pc) : 0);
-		}
-
-		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));
-
-		ast_channel_unlock(ast);
-
-		isup_iam(p->ss7->ss7, p->ss7call);
-		ast_setstate(ast, AST_STATE_DIALING);
-		ss7_rel(p->ss7);
-	}
-#endif	/* defined(HAVE_SS7) */
-
-#ifdef HAVE_OPENR2
-	if (p->mfcr2) {
-		openr2_calling_party_category_t chancat;
-		int callres = 0;
-		char *c, *l;
-
-		c = strchr(dest, '/');
-		if (c) {
-			c++;
-		} else {
-			c = "";
-		}
-		if (!p->hidecallerid) {
-			l = ast->cid.cid_num;
-		} else {
-			l = NULL;
-		}
-		if (strlen(c) < p->stripmsd) {
-			ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-			ast_mutex_unlock(&p->lock);
-			return -1;
-		}
 		p->dialing = 1;
-		ast_channel_lock(ast);
 		chancat = dahdi_r2_get_channel_category(ast);
-		ast_channel_unlock(ast);
 		callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
 		if (-1 == callres) {
 			ast_mutex_unlock(&p->lock);
@@ -5869,9 +5744,8 @@
 		return 0;
 	}
 
+	ast_mutex_lock(&p->lock);
 	if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
-		ast_mutex_lock(&p->lock);
-
 		dahdi_confmute(p, 0);
 		restore_gains(p);
 		p->ignoredtmf = 0;
@@ -5887,22 +5761,18 @@
 		p->cid_subaddr[0] = '\0';
 	}
 
-	ast_mutex_lock(&p->lock);
-
-	idx = dahdi_get_index(ast, p, 1);
-
 #ifdef HAVE_PRI
 	if (dahdi_sig_pri_lib_handles(p->sig)) {
-		int law;
-
 		x = 1;
 		ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
 		dahdi_confmute(p, 0);
+		p->muting = 0;
 		restore_gains(p);
 		if (p->dsp) {
 			ast_dsp_free(p->dsp);
 			p->dsp = NULL;
 		}
+		p->ignoredtmf = 0;
 		revert_fax_buffers(p, ast);
 		dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
 		law = DAHDI_LAW_DEFAULT;
@@ -5920,19 +5790,73 @@
 		p->digital = 0;
 		p->faxhandled = 0;
 		p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
-		//p->proceeding = 0;
-		//p->progress = 0;
-		//p->alerting = 0;
 		goto hangup_out;
 	}
 #endif
 
+#if defined(HAVE_SS7)
 	if (p->sig == SIG_SS7) {
 		x = 1;
 		ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
-	}
-
-	x = 0;
+
+		dahdi_confmute(p, 0);
+		p->muting = 0;
+		restore_gains(p);
+		if (p->dsp) {
+			ast_dsp_free(p->dsp);
+			p->dsp = NULL;
+		}
+		p->ignoredtmf = 0;
+
+		/* Real channel, do some fixup */
+		p->subs[SUB_REAL].owner = NULL;
+		p->subs[SUB_REAL].needanswer = 0;
+		p->subs[SUB_REAL].needringing = 0;
+		p->subs[SUB_REAL].needbusy = 0;
+		p->polarity = POLARITY_IDLE;
+		dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
+
+		p->owner = NULL;
+		p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
+		p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
+		p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
+		p->outgoing = 0;
+		p->digital = 0;
+		p->faxhandled = 0;
+		p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
+
+		revert_fax_buffers(p, ast);
+
+		law = DAHDI_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));
+
+		sig_ss7_hangup(p->sig_pvt, ast);
+
+		tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
+		dahdi_disable_ec(p);
+		x = 0;
+		ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
+		ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
+		p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
+		update_conf(p);
+		reset_conf(p);
+
+		/* Restore data mode */
+		x = 0;
+		ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
+
+		if (num_restart_pending == 0)
+			restart_monitor();
+
+		ast->tech_pvt = NULL;
+		goto hangup_out;
+	}
+#endif	/* defined(HAVE_SS7) */
+
+	idx = dahdi_get_index(ast, p, 1);
+
 	dahdi_confmute(p, 0);
 	p->muting = 0;
 	restore_gains(p);
@@ -6062,13 +5986,6 @@
 		p->digital = 0;
 		p->faxhandled = 0;
 		p->pulsedial = 0;
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
-		p->proceeding = 0;
-		p->dialing = 0;
-		p->progress = 0;
-		p->alerting = 0;
-		p->rlt = 0;
-#endif
 		if (p->dsp) {
 			ast_dsp_free(p->dsp);
 			p->dsp = NULL;
@@ -6081,30 +5998,6 @@
 		if (res < 0)
 			ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
 		/* Perform low level hangup if no owner left */
-#ifdef HAVE_SS7
-		if (p->ss7) {
-			if (p->ss7call) {
-				if (!ss7_grab(p, p->ss7)) {
-					if (!p->alreadyhungup) {
-						const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
-						int icause = ast->hangupcause ? ast->hangupcause : -1;
-
-						if (cause) {
-							if (atoi(cause))
-								icause = atoi(cause);
-						}
-						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");
-				} else {
-					ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
-					res = -1;
-				}
-			}
-		}
-#endif
 #ifdef HAVE_OPENR2
 		if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
 			ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
@@ -7591,6 +7484,11 @@
 			sig_pri_chan_alarm_notify(p->sig_pvt, 0);
 			break;
 #endif	/* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+		case SIG_SS7:
+			sig_ss7_set_alarm(p->sig_pvt, 1);
+			break;
+#endif	/* defined(HAVE_SS7) */
 		default:
 			p->inalarm = 1;
 			break;
@@ -7923,6 +7821,11 @@
 			sig_pri_chan_alarm_notify(p->sig_pvt, 1);
 			break;
 #endif	/* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+		case SIG_SS7:
+			sig_ss7_set_alarm(p->sig_pvt, 0);
+			break;
+#endif	/* defined(HAVE_SS7) */
 		default:
 			p->inalarm = 0;
 			break;
@@ -10928,6 +10831,11 @@
 			sig_pri_chan_alarm_notify(i->sig_pvt, 1);
 			break;
 #endif	/* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+		case SIG_SS7:
+			sig_ss7_set_alarm(i->sig_pvt, 0);
+			break;
+#endif	/* defined(HAVE_SS7) */
 		default:
 			i->inalarm = 0;
 			break;
@@ -10941,6 +10849,11 @@
 			sig_pri_chan_alarm_notify(i->sig_pvt, 0);
 			break;
 #endif	/* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+		case SIG_SS7:
+			sig_ss7_set_alarm(i->sig_pvt, 1);
+			break;
+#endif	/* defined(HAVE_SS7) */
 		default:
 			i->inalarm = 1;
 			break;
@@ -12242,6 +12155,11 @@
 					sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
 					break;
 #endif
+#if defined(HAVE_SS7)
+				case SIG_SS7:
+					sig_ss7_set_alarm(tmp->sig_pvt, 1);
+					break;
+#endif	/* defined(HAVE_SS7) */
 				default:
 					tmp->inalarm = 1;
 					break;
@@ -12430,14 +12348,18 @@
 	if (analog_lib_handles(p->sig, p->radio, p->oprmode))
 		return analog_available(p->sig_pvt);
 
-#ifdef HAVE_PRI
 	switch (p->sig) {
+#if defined(HAVE_PRI)
 	case SIG_PRI_LIB_HANDLE_CASES:
 		return sig_pri_available(p->sig_pvt);
+#endif	/* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+	case SIG_SS7:
+		return sig_ss7_available(p->sig_pvt);
+#endif	/* defined(HAVE_SS7) */
 	default:
 		break;
 	}
-#endif
 
 	if (p->locallyblocked || p->remotelyblocked) {
 		return 0;
@@ -12445,16 +12367,6 @@
 
 	/* If no owner definitely available */
 	if (!p->owner) {
-#ifdef HAVE_SS7
-		/* Trust SS7 */
-		if (p->ss7) {
-			if (p->ss7call) {
-				return 0;
-			} else {
-				return 1;
-			}
-		}
-#endif
 #ifdef HAVE_OPENR2
 		/* Trust MFC/R2 */
 		if (p->mfcr2) {
@@ -13211,7 +13123,7 @@
 	} else
 		ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
 
-	dahdi_enable_ec(p);
+	sig_ss7_set_echocanceller(p, 1);
 
 	/* We only reference these variables in the context of the ss7_linkset function
 	 * when receiving either and IAM or a COT message.  Since they are only accessed
@@ -13442,9 +13354,10 @@
 				ast_verbose("--- SS7 Down ---\n");
 				linkset->state = LINKSET_STATE_DOWN;
 				for (i = 0; i < linkset->numchans; i++) {
-					struct dahdi_pvt *p = linkset->pvts[i];
-					if (p)
-						p->inalarm = 1;
+					p = linkset->pvts[i];
+					if (p) {
+						sig_ss7_set_alarm(p, 1);
+					}
 				}
 				break;
 			case MTP2_LINK_UP:
@@ -13471,9 +13384,9 @@
 					{
 						struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
 						ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
-						dahdi_queue_frame(p, &f, linkset);
+						sig_ss7_queue_frame(p, &f, linkset);
 						p->progress = 1;
-						p->dialing = 0;
+						sig_ss7_set_dialing(p, 0);
 						if (p->dsp && p->dsp_features) {
 							ast_dsp_set_features(p->dsp, p->dsp_features);
 							p->dsp_features = 0;
@@ -13559,6 +13472,13 @@
 				} else
 					p->cid_num[0] = 0;
 
+				/* Set DNID */
+				if (!ast_strlen_zero(e->iam.called_party_num)) {
+					ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset,
+						e->iam.called_party_num, e->iam.called_nai);
+					sig_ss7_set_dnid(p, p->exten);
+				}
+
 				if (p->immediate) {
 					p->exten[0] = 's';
 					p->exten[1] = '\0';
@@ -13566,10 +13486,12 @@
 					char *st;
 					ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
 					st = strchr(p->exten, '#');
-					if (st)
+					if (st) {
 						*st = '\0';
-					} else
-						p->exten[0] = '\0';
+					}
+				} else {
+					p->exten[0] = '\0';
+				}
 
 				p->cid_ani[0] = '\0';
 				if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
@@ -13593,10 +13515,6 @@
 				ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
 				ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
 				p->calling_party_cat = e->iam.calling_party_cat;
-
-				/* Set DNID */
-				if (!ast_strlen_zero(e->iam.called_party_num))
-					ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
 
 				if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
 
@@ -13673,8 +13591,9 @@
 				if (p->owner) {
 					p->owner->hangupcause = e->rel.cause;
 					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-				} else if (!p->restartpending)
+				} else {
 					ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
+				}
 
 				/* End the loopback if we have one */
 				sig_ss7_loopback(p, 0);
@@ -13702,9 +13621,9 @@
 					}
 
 					sig_ss7_lock_private(p);
-					dahdi_queue_frame(p, &f, linkset);
+					sig_ss7_queue_frame(p, &f, linkset);
 					p->proceeding = 1;
-					p->dialing = 0;
+					sig_ss7_set_dialing(p, 0);
 					/* Send alerting if subscriber is free */
 					if (e->acm.called_party_status_ind == 1) {
 						p->alerting = 1;
@@ -13816,7 +13735,7 @@
 						ast_dsp_set_features(p->dsp, p->dsp_features);
 						p->dsp_features = 0;
 					}
-					dahdi_enable_ec(p);
+					sig_ss7_set_echocanceller(p, 1);
 					sig_ss7_unlock_private(p);
 				}
 				break;
@@ -15828,7 +15747,7 @@
 	}
 	for (i = 0; i < strlen(number); i++) {
 		struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
-		dahdi_queue_frame(p, &f, NULL);
+		dahdi_queue_frame(p, &f);
 	}
 	astman_send_ack(s, m, "DAHDIDialOffhook");
 	return 0;
@@ -18189,6 +18108,229 @@
 	return 0;
 }
 /* BUGBUG sig_ss7 API functions ----v*/
+
+/*!
+ * \brief Determine if the specified channel is available for an outgoing call.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ *
+ * \retval TRUE if the channel is available.
+ */
+int sig_ss7_available(struct sig_ss7_chan *p)
+{
+	if (!p->ss7) {
+		/* Something is wrong here.  A SS7 channel without the ss7 pointer? */
+		return 0;
+	}
+
+	if (!p->inalarm && !p->owner && !p->ss7call
+		&& !p->locallyblocked && !p->remotelyblocked) {
+		return 1;
+	}
+
+	return 0;
+}
+
+/*!
+ * \brief Dial out using the specified SS7 channel.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ * \param ast Asterisk channel sructure pointer.
+ * \param rdest Dialstring.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
+{
+	char ss7_called_nai;
+	int called_nai_strip;
+	char ss7_calling_nai;
+	int calling_nai_strip;
+	const char *charge_str = NULL;
+	const char *gen_address = NULL;
+	const char *gen_digits = NULL;
+	const char *gen_dig_type = NULL;
+	const char *gen_dig_scheme = NULL;
+	const char *gen_name = NULL;
+	const char *jip_digits = NULL;
+	const char *lspi_ident = NULL;
+	const char *rlt_flag = NULL;
+	const char *call_ref_id = NULL;
+	const char *call_ref_pc = NULL;
+	const char *send_far = NULL;
+	char *c;
+	char *l;
+	char dest[256];
+
+	ast_copy_string(dest, rdest, sizeof(dest));
+
+	c = strchr(dest, '/');
+	if (c) {
+		c++;
+	} else {
+		c = "";
+	}
+	if (strlen(c) < p->stripmsd) {
+		ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
+		return -1;
+	}
+
+	if (!p->hidecallerid) {
+		l = ast->connected.id.number;
+	} else {
+		l = NULL;
+	}
+
+	if (ss7_grab(p, p->ss7)) {
+		ast_log(LOG_WARNING, "Failed to grab SS7!\n");
+		return -1;
+	}
+
+	p->ss7call = isup_new_call(p->ss7->ss7);
+	if (!p->ss7call) {
+		ss7_rel(p->ss7);
+		ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
+		return -1;
+	}
+
+	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;
+		}
+	}
+	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->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+		p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
+
+	isup_set_oli(p->ss7call, ast->connected.ani2);
+	isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
+
+	/* Set the charge number if it is set */
+	charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
+	if (charge_str)
+		isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
+
+	gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
+	if (gen_address)
+		isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
+
+	gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
+	gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
+	gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
+	if (gen_digits)
+		isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
+
+	gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
+	if (gen_name)
+		isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
+
+	jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
+	if (jip_digits)
+		isup_set_jip_digits(p->ss7call, jip_digits);
+
+	lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
+	if (lspi_ident)
+		isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
+
+	rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
+	if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
+		isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
+	}
+
+	call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
+	call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
+	if (call_ref_id && call_ref_pc) {
+		isup_set_callref(p->ss7call, atoi(call_ref_id),
+				 call_ref_pc ? atoi(call_ref_pc) : 0);
+	}
+
+	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));
+
+	isup_iam(p->ss7->ss7, p->ss7call);
+	sig_ss7_set_dialing(p, 1);
+	ast_setstate(ast, AST_STATE_DIALING);
+	ss7_rel(p->ss7);
+}
+
+
+/*!
+ * \brief SS7 hangup channel.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ * \param ast Asterisk channel sructure pointer.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
+{
+	int res = 0;
+
+	if (!ast->tech_pvt) {
+		ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
+		return 0;
+	}
+
+	sig_ss7_set_dialing(p, 0);
+	p->proceeding = 0;
+	p->progress = 0;
+	p->alerting = 0;
+	p->rlt = 0;
+	p->exten[0] = '\0';
+	/* Perform low level hangup if no owner left */
+	if (p->ss7call) {
+		if (!ss7_grab(p, p->ss7)) {
+			if (!p->alreadyhungup) {
+				const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
+				int icause = ast->hangupcause ? ast->hangupcause : -1;
+
+				if (cause) {
+					if (atoi(cause))
+						icause = atoi(cause);
+				}
+				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");
+		} else {
+			ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
+			res = -1;
+		}
+	}
+
+	return res;
+}
+
 /* BUGBUG sig_ss7 API functions ----^*/
 
 

Modified: team/rmudgett/sig_ss7/channels/sig_ss7.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/sig_ss7/channels/sig_ss7.h?view=diff&rev=261099&r1=261098&r2=261099
==============================================================================
--- team/rmudgett/sig_ss7/channels/sig_ss7.h (original)
+++ team/rmudgett/sig_ss7/channels/sig_ss7.h Tue May  4 19:14:31 2010
@@ -97,7 +97,8 @@
 	struct ast_channel * (* const new_ast_channel)(void *pvt, int state, int startpbx, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor);
 	int (* const play_tone)(void *pvt, enum sig_ss7_tone tone);
 
-	void (* const set_dialing)(void *pvt, int flag);
+	void (* const set_alarm)(void *pvt, int in_alarm);
+	void (* const set_dialing)(void *pvt, int is_dialing);
 	void (* const set_callerid)(void *pvt, const struct ast_party_caller *caller);
 	void (* const set_dnid)(void *pvt, const char *dnid);
 	void (* const set_rdnis)(void *pvt, const char *rdnis);
@@ -112,6 +113,37 @@
 	/*! \brief Opaque libss7 call control structure */
 	struct isup_call *ss7call;
 
+	/* Options to be set by user */
+	/*!
+	 * \brief Number of most significant digits/characters to strip from the dialed number.
+	 * \note Feature is deprecated.  Use dialplan logic.
+	 */
+	int stripmsd;
+	/*!
+	 * \brief TRUE if the outgoing caller ID is blocked/hidden.
+	 */
+	unsigned int hidecallerid:1;
+	/*! \brief TRUE if caller ID is used on this channel. */
+	unsigned int use_callerid:1;
+	/*!
+	 * \brief TRUE if we will use the calling presentation setting
+	 * from the Asterisk channel for outgoing calls.
+	 */
+	unsigned int use_callingpres:1;
+	unsigned int immediate:1;			/*!< Answer before getting digits? */
+
+	/* Options to be checked by user */
+	int cid_ani2;						/*!< Automatic Number Identification number (Alternate PRI caller ID number) */
+	int cid_ton;					/*!< Type Of Number (TON) */
+	int callingpres;				/*!< The value of calling presentation that we're going to use when placing a PRI call */
+	char cid_num[AST_MAX_EXTENSION];
+	char cid_subaddr[AST_MAX_EXTENSION];/*!< BUGBUG SS7 may not support. */
+	char cid_name[AST_MAX_EXTENSION];
+	char cid_ani[AST_MAX_EXTENSION];
+	char exten[AST_MAX_EXTENSION];
+
+	/* Options to be set by user */
+	char context[AST_MAX_CONTEXT];
 	char charge_number[50];
 	char gen_add_number[50];
 	char gen_dig_number[50];
@@ -132,7 +164,6 @@
 	unsigned int call_ref_ident;
 	unsigned int call_ref_pc;
 	unsigned char calling_party_cat;
-	int transcap;
 	int cic;							/*!< CIC associated with channel */
 	unsigned int dpc;						/*!< CIC's DPC */
 	int channel;					/*!< Channel Number */
@@ -151,6 +182,19 @@
 
 	unsigned int inalarm:1;
 	unsigned int outgoing:1;
+	/*!
+	 * \brief TRUE if call is in a proceeding state.
+	 * The call has started working its way through the network.
+	 */
+	unsigned int proceeding:1;
+	/*! \brief TRUE if the call has seen progress through the network. */
+	unsigned int progress:1;
+	/*! \brief TRUE if channel is alerting/ringing */
+	unsigned int alerting:1;
+	/*! \brief TRUE if the call has already gone/hungup */
+	unsigned int alreadyhungup:1;
+	/*! \brief XXX BOOLEAN Purpose??? */
+	unsigned int rlt:1;
 };
 
 struct sig_ss7_linkset {
@@ -178,6 +222,11 @@
 	struct sig_ss7_callback *calls;
 };
 
+void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm);
+int sig_ss7_available(struct sig_ss7_chan *p);
+int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest);
+int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast);
+
 
 /* ------------------------------------------------------------------- */
 




More information about the asterisk-commits mailing list