[asterisk-commits] dhubbard: branch dhubbard/pinecowbell r166253 - in /team/dhubbard/pinecowbell...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Dec 21 13:33:51 CST 2008


Author: dhubbard
Date: Sun Dec 21 13:33:50 2008
New Revision: 166253

URL: http://svn.digium.com/view/asterisk?view=rev&rev=166253
Log:
add HAVE_PRI_SERVICE_MESSAGES code from the asterisk/team/issue3450 branch

Modified:
    team/dhubbard/pinecowbell/channels/chan_dahdi.c
    team/dhubbard/pinecowbell/configure
    team/dhubbard/pinecowbell/configure.ac
    team/dhubbard/pinecowbell/include/asterisk/autoconfig.h.in

Modified: team/dhubbard/pinecowbell/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/dhubbard/pinecowbell/channels/chan_dahdi.c?view=diff&rev=166253&r1=166252&r2=166253
==============================================================================
--- team/dhubbard/pinecowbell/channels/chan_dahdi.c (original)
+++ team/dhubbard/pinecowbell/channels/chan_dahdi.c Sun Dec 21 13:33:50 2008
@@ -257,6 +257,20 @@
 #define CALLPROGRESS_FAX_OUTGOING	2
 #define CALLPROGRESS_FAX_INCOMING	4
 #define CALLPROGRESS_FAX		(CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
+
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+/*! \brief Persistent Service State */
+#define SRVST_DBKEY "service-state"
+#define SRVST_TYPE_OOS "O"
+/* the reason for the service state */
+#define SRVST_NOREASON 0
+#define SRVST_NEAREND  (1 << 0)
+#define SRVST_FAREND   (1 << 1)
+#define SRVST_BOTH (SRVST_NEAREND | SRVST_FAREND)
+
+/*! \brief The AstDB family */
+static const char dahdi_db[] = "dahdi/registry";
+#endif
 
 static char defaultcic[64] = "";
 static char defaultozz[64] = "";
@@ -460,6 +474,9 @@
 	int span;
 	int resetting;
 	int resetpos;
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+	unsigned int disable_service_message_support:1;	/*!< Disable SERVICE message support */
+#endif
 #ifdef HAVE_PRI_INBANDDISCONNECT
 	unsigned int inbanddisconnect:1;				/*!< Should we support inband audio after receiving DISCONNECT? */
 #endif
@@ -8702,6 +8719,9 @@
 						pris[span].overlapdial = conf->pri.overlapdial;
 						pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
 						pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+						pris[span].disable_service_message_support = conf->pri.disable_service_message_support;
+#endif
 #ifdef HAVE_PRI_INBANDDISCONNECT
 						pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
 #endif
@@ -8966,10 +8986,24 @@
 		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 */
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+				if (chan_sig == SIG_PRI) {
+					char db_chan_name[20];
+					char db_answer[5];
+
+					snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, tmp->channel);
+					if (ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NOREASON);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+					}
+				}
+#endif
+			} else { 
+				 /* We default to in service on protocols that don't have a reset */
 				tmp->inservice = 1;
+			}
 		}
 	}
 	if (tmp && !here) {
@@ -9019,7 +9053,7 @@
 	return tmp;
 }
 
-static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
+static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched)
 {
 	int res;
 	struct dahdi_params par;
@@ -9037,9 +9071,9 @@
 		*channelmatched = 1;
 	}
 	/* We're at least busy at this point */
-	if (busy) {
+	if (reason) {
 		if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
-			*busy = 1;
+			*reason = AST_CAUSE_BUSY;
 	}
 	/* If do not disturb, definitely not */
 	if (p->dnd)
@@ -9056,10 +9090,27 @@
 #ifdef HAVE_PRI
 		/* Trust PRI */
 		if (p->pri) {
-			if (p->resetting || p->call)
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+			char db_chan_name[20];
+			char db_answer[5];
+			char state;
+			int why = 0;
+						
+			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, p->channel);
+			if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+				sscanf(db_answer, "%c:%d", &state, &why);
+			}
+			if ((p->resetting || p->call) || (why)) {
+				if (why) {
+					*reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+				}
+#else
+			if (p->resetting || p->call) {
+#endif
 				return 0;
-			else
+			} else {
 				return 1;
+			}
 		}
 #endif
 #ifdef HAVE_SS7
@@ -10888,19 +10939,41 @@
 						ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
 							PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
 					else {
-						ast_verb(3, "B-channel %d/%d restarted on span %d\n",
-								PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						if (pri->pvts[chanpos]->call) {
-							pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
-							pri->pvts[chanpos]->call = NULL;
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+						char db_chan_name[20];
+						char db_answer[5];
+						char state;
+						int why;
+						int skipit = 0;
+						
+						snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, e->restart.channel);
+						if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+							sscanf(db_answer, "%c:%d", &state, &why);
+							if (why) {
+								ast_log(LOG_NOTICE, "channel '%d' is ignoring the PRI_EVENT_RESTART request because it is out-of-service (reason: %d)\n", e->restart.channel, why);
+								skipit = 1;
+							} else {
+								ast_db_del(db_chan_name, SRVST_DBKEY);
+							}
 						}
-						/* Force soft hangup if appropriate */
-						if (pri->pvts[chanpos]->realcall) 
-							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-						else if (pri->pvts[chanpos]->owner)
-							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						if (!skipit) {
+#endif
+							ast_verb(3, "B-channel %d/%d restarted on span %d\n",
+									PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
+							ast_mutex_lock(&pri->pvts[chanpos]->lock);
+							if (pri->pvts[chanpos]->call) {
+								pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
+								pri->pvts[chanpos]->call = NULL;
+							}
+							/* Force soft hangup if appropriate */
+							if (pri->pvts[chanpos]->realcall) 
+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+							else if (pri->pvts[chanpos]->owner)
+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+						}
+#endif
 					}
 				} else {
 					ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
@@ -10974,6 +11047,65 @@
 					}
 				}
 				break;
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+			case PRI_EVENT_SERVICE:
+				chanpos = pri_find_principle(pri, e->service.channel);
+				if (chanpos < 0) {
+					ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
+						e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
+				} else {
+					char db_chan_name[20];
+					char db_answer[5];
+					char state;
+					int ch;
+					int why = -1;
+
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+					ch = pri->pvts[chanpos]->channel;
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+					
+					snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, ch);
+					if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+						sscanf(db_answer, "%c:%d", &state, &why);
+						ast_db_del(db_chan_name, SRVST_DBKEY);
+					}
+					switch (e->service.changestatus) {
+					case 0: /* in-service */
+						if (why > -1) {
+							if (why & SRVST_NEAREND) {
+								snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NEAREND);
+								ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+								ast_debug(2, "channel '%d' service state { near: out-of-service,  far: in-service }\n", ch);
+							}
+						}
+						break;
+					case 2: /* out-of-service */
+						if (why == -1) {
+							why = SRVST_FAREND;
+						} else {
+							why |= SRVST_FAREND;
+						}
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+						break;
+					default:
+						ast_log(LOG_ERROR, "Huh?  changestatus is: %d\n", e->service.changestatus);
+					}
+					ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n",
+						PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus);
+				}
+				break;
+			case PRI_EVENT_SERVICE_ACK:
+				chanpos = pri_find_principle(pri, e->service_ack.channel);
+				if (chanpos < 0) {
+					ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
+						e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
+				} else {
+					ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n",
+						PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
+				}
+				break;
+#endif
 			case PRI_EVENT_RING:
 				crv = NULL;
 				if (e->ring.channel == -1)
@@ -11752,6 +11884,11 @@
 				break;
 			default:
 				pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+				if (!pri->disable_service_message_support) {
+					pri_set_service_message_support(pri->dchans[i], 1);
+				}
+#endif
 		}
 		/* Force overlap dial if we're doing GR-303! */
 		if (pri->switchtype == PRI_SWITCH_GR303_TMC)
@@ -11916,6 +12053,150 @@
 	return CLI_SUCCESS;
 }
 
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
+{
+	int why;
+	int channel;
+	int trunkgroup;
+	int x, y, fd = a->fd;
+	int interfaceid = 0;
+	char *c;
+	char state;
+	char db_answer[5];
+	char db_chan_name[20];
+	struct dahdi_pvt *start, *tmp = NULL;
+	struct dahdi_pri *pri = NULL;
+	ast_mutex_t *lock;
+	
+	lock = &iflock;
+	start = iflist;
+
+	if (a->argc < 5 || a->argc > 6)
+		return CLI_SHOWUSAGE;
+	if ((c = strchr(a->argv[4], ':'))) {
+		if (sscanf(a->argv[4], "%d:%d", &trunkgroup, &channel) != 2)
+			return CLI_SHOWUSAGE;
+		if ((trunkgroup < 1) || (channel < 1))
+			return CLI_SHOWUSAGE;
+		for (x=0;x<NUM_SPANS;x++) {
+			if (pris[x].trunkgroup == trunkgroup) {
+				pri = pris + x;
+				break;
+			}
+		}
+		if (pri) {
+			start = pri->crvs;
+			lock = &pri->lock;
+		} else {
+			ast_cli(fd, "No such trunk group %d\n", trunkgroup);
+			return CLI_FAILURE;
+		}
+	} else
+		channel = atoi(a->argv[4]);
+	
+	if (a->argc == 6)
+		interfaceid = atoi(a->argv[5]);
+
+	/* either servicing a D-Channel */
+	for (x = 0; x < NUM_SPANS; x++) {
+		for (y = 0; y < NUM_DCHANS; y++) {
+			if (pris[x].dchannels[y] == channel) {
+				pri = pris + x;
+				pri_maintenance_service(pri->pri, interfaceid, -1, changestatus);
+				return CLI_SUCCESS;
+			}
+		}
+	}
+
+	/* or servicing a B-Channel */
+	ast_mutex_lock(lock);
+	tmp = start;
+	while (tmp) {
+		if (tmp->pri && tmp->channel == channel) {
+			if (tmp->pri->disable_service_message_support) {
+				ast_cli(fd, "\n\tThis operation is disabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n\n");
+				return CLI_SUCCESS;
+			}
+			why = -1;
+			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d", dahdi_db, channel);
+			if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+				sscanf(db_answer, "%c:%d", &state, &why);
+				ast_db_del(db_chan_name, SRVST_DBKEY);
+			}
+			switch(changestatus) {
+			case 0: /* enable */
+				if (why > -1) {
+					if (why & SRVST_FAREND) {
+						why = SRVST_FAREND;
+						snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+						ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+						ast_debug(2, "channel '%d' service state { near: in-service,  far: out-of-service }\n", channel);
+					}
+				}
+				break;
+			/* case 1:  -- loop */
+			case 2: /* disable */
+				if (why == -1) {
+					why = SRVST_NEAREND;
+				} else {
+					why |= SRVST_NEAREND;
+				}
+				snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
+				ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+				break;
+			/* case 3:  -- continuity */
+			/* case 4:  -- shutdown */
+			default:
+				ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
+			}
+			pri_maintenance_service(tmp->pri->pri, PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp), changestatus);
+			ast_mutex_unlock(lock);
+			return CLI_SUCCESS;
+		}
+		tmp = tmp->next;
+	}
+	ast_mutex_unlock(lock);
+
+	ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
+	return CLI_FAILURE;
+}
+
+static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:	
+		e->command = "pri service enable channel";
+		e->usage = 
+			"Usage: pri service enable channel <channel> [<interface id>]\n"
+			"       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
+			"	to restore a channel to service, with optional interface id\n"
+			"	as agreed upon with remote switch operator\n";
+		return NULL;
+	case CLI_GENERATE:	
+		return NULL;
+	}
+	return handle_pri_service_generic(e, cmd, a, 0);
+}
+
+static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:	
+		e->command = "pri service disable channel";
+		e->usage = 
+			"Usage: pri service disable channel <chan num> [<interface id>]\n"
+			"	Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
+			"	to remove a channel from service, with optional interface id\n"
+			"	as agreed upon with remote switch operator\n";
+		return NULL;
+	case CLI_GENERATE:	
+		return NULL;
+	}
+	return handle_pri_service_generic(e, cmd, a, 2);
+}
+#endif
+
 static void build_status(char *s, size_t len, int status, int active)
 {
 	if (!s || len < 1) {
@@ -12081,6 +12362,10 @@
 
 static struct ast_cli_entry dahdi_pri_cli[] = {
 	AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+ 	AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
+ 	AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
+#endif
 	AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
 	AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
 	AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
@@ -14424,6 +14709,10 @@
 #endif
 			} else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
 				confp->pri.discardremoteholdretrieval = ast_true(v->value);
+#ifdef HAVE_PRI_SERVICE_MESSAGES
+			} else if (!strcasecmp(v->name, "service_message_support")) {
+				confp->pri.disable_service_message_support = ast_false(v->value);
+#endif
 #ifdef HAVE_PRI_INBANDDISCONNECT
 			} else if (!strcasecmp(v->name, "inbanddisconnect")) {
 				confp->pri.inbanddisconnect = ast_true(v->value);

Modified: team/dhubbard/pinecowbell/configure.ac
URL: http://svn.digium.com/view/asterisk/team/dhubbard/pinecowbell/configure.ac?view=diff&rev=166253&r1=166252&r2=166253
==============================================================================
--- team/dhubbard/pinecowbell/configure.ac (original)
+++ team/dhubbard/pinecowbell/configure.ac Sun Dec 21 13:33:50 2008
@@ -1393,6 +1393,8 @@
 
 AST_EXT_LIB_CHECK([PRI_INBANDDISCONNECT], [pri], [pri_set_inbanddisconnect], [libpri.h])
 
+AST_EXT_LIB_CHECK([PRI_SERVICE_MESSAGES], [pri], [pri_maintenance_service], [libpri.h])
+
 AST_EXT_LIB_CHECK([RESAMPLE], [resample], [resample_open], [libresample.h], [-lm])
 
 AST_C_COMPILE_CHECK([SPANDSP], [

Modified: team/dhubbard/pinecowbell/include/asterisk/autoconfig.h.in
URL: http://svn.digium.com/view/asterisk/team/dhubbard/pinecowbell/include/asterisk/autoconfig.h.in?view=diff&rev=166253&r1=166252&r2=166253
==============================================================================
--- team/dhubbard/pinecowbell/include/asterisk/autoconfig.h.in (original)
+++ team/dhubbard/pinecowbell/include/asterisk/autoconfig.h.in Sun Dec 21 13:33:50 2008
@@ -643,6 +643,12 @@
 
 /* Define to indicate the ${PRI_PROG_W_CAUSE_DESCRIP} library version */
 #undef HAVE_PRI_PROG_W_CAUSE_VERSION
+
+/* Define this to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library */
+#undef HAVE_PRI_SERVICE_MESSAGES
+
+/* Define to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library version */
+#undef HAVE_PRI_SERVICE_MESSAGES_VERSION
 
 /* Define to indicate the ${PRI_DESCRIP} library version */
 #undef HAVE_PRI_VERSION




More information about the asterisk-commits mailing list