[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