[asterisk-commits] rmudgett: branch rmudgett/call_waiting r251134 - /team/rmudgett/call_waiting/...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Mar 5 17:37:54 CST 2010
Author: rmudgett
Date: Fri Mar 5 17:37:50 2010
New Revision: 251134
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=251134
Log:
1) Rework HAVE_PRI_SERVICE_MESSAGES to not use the active values directly
from the database. Database access is likely expensive. Database access
now only happens on initialization, destruction, and when the B channel is
taken in or out of service. (This change is not related to call waiting
but it would cause the search for a call waiting interface to be very
expensive and slow down D channel message servicing.)
2) Change chan_dahdi channel search to "find" a call waiting interface if
no B channels are available on a span that has call waiting enabled.
3) Sorted the span controller channel private pointer array just like the
chan_dahdi interface list. B channels are now found in the expected order
for incoming calls if the channels were declared out of order in
chan_dahdi.conf. (This change is no longer required for call waiting.)
Modified:
team/rmudgett/call_waiting/channels/chan_dahdi.c
team/rmudgett/call_waiting/channels/sig_pri.c
team/rmudgett/call_waiting/channels/sig_pri.h
Modified: team/rmudgett/call_waiting/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/chan_dahdi.c?view=diff&rev=251134&r1=251133&r2=251134
==============================================================================
--- team/rmudgett/call_waiting/channels/chan_dahdi.c (original)
+++ team/rmudgett/call_waiting/channels/chan_dahdi.c Fri Mar 5 17:37:50 2010
@@ -981,7 +981,6 @@
#if defined(HAVE_PRI)
struct sig_pri_pri *pri;
- int prioffset;
int logicalspan;
#endif
#if defined(HAVE_PRI) || defined(HAVE_SS7)
@@ -3123,6 +3122,7 @@
.get_orig_dialstring = my_get_orig_dialstring,
};
+/*! Round robin search locations. */
static struct dahdi_pvt *round_robin[32];
#if defined(HAVE_SS7)
@@ -5360,9 +5360,11 @@
p = iflist;
chan = p->channel;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
{
- char db_chan_name[20], db_answer[5], state;
+ char db_chan_name[20];
+ char db_answer[5];
+ char state;
int why = -1;
snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
@@ -5374,7 +5376,7 @@
ast_db_del(db_chan_name, SRVST_DBKEY);
}
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
/* Free associated memory */
destroy_dahdi_pvt(p);
ast_verb(3, "Unregistered channel %d\n", chan);
@@ -11668,9 +11670,9 @@
pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
#ifdef HAVE_PRI_INBANDDISCONNECT
pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
#endif
@@ -11705,11 +11707,19 @@
pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
}
- if (si.spanno != span + 1) { /* in another trunkgroup */
- tmp->prioffset = pris[span].pri.numchans;
- } else {
- tmp->prioffset = p.chanpos;
- }
+#if defined(HAVE_PRI_CALL_WAITING)
+ /* Channel initial config parameters. */
+ pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
+ pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
+ pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
+ pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
+ pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
+ pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
+ pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
+ pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
+ ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
+ ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
} else {
ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
destroy_dahdi_pvt(tmp);
@@ -12012,17 +12022,32 @@
case SIG_PRI_LIB_HANDLE_CASES:
case SIG_SS7:
tmp->inservice = 0;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
if (chan_sig == SIG_PRI) {
- char db_chan_name[20], db_answer[5];
-
+ char db_chan_name[20];
+ char db_answer[5];
+
+ /*
+ * Initialize the active out-of-service status
+ * and delete any record if the feature is not enabled.
+ */
snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, 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_INITIALIZED);
- ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+ unsigned *why;
+
+ why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
+ if (tmp->pri->enable_service_message_support) {
+ char state;
+
+ sscanf(db_answer, "%1c:%30u", &state, why);
+ }
+ if (!*why) {
+ ast_db_del(db_chan_name, SRVST_DBKEY);
+ }
}
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
break;
default:
/* We default to in service on protocols that don't have a reset */
@@ -12154,8 +12179,10 @@
return 1;
}
-static int available(struct dahdi_pvt *p, int *reason)
-{
+static int available(struct dahdi_pvt **pvt, int *reason, int is_specific_channel)
+{
+ struct dahdi_pvt *p = *pvt;
+
if (p->inalarm)
return 0;
@@ -12165,7 +12192,15 @@
#ifdef HAVE_PRI
switch (p->sig) {
case SIG_PRI_LIB_HANDLE_CASES:
- return sig_pri_available(p->sig_pvt, reason);
+ {
+ struct sig_pri_chan *pvt_chan;
+ int res;
+
+ pvt_chan = p->sig_pvt;
+ res = sig_pri_available(&pvt_chan, reason, is_specific_channel);
+ *pvt = pvt_chan->chan_pvt;
+ return res;
+ }
default:
break;
}
@@ -12456,13 +12491,18 @@
} else
p = iflist;
} else {
+ if (ARRAY_LEN(round_robin) <= x) {
+ ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
+ x, data);
+ return NULL;
+ }
if (args.group[0] == 'R') {
param->backwards = 1;
- p = round_robin[x]?round_robin[x]->prev:ifend;
+ p = round_robin[x] ? round_robin[x]->prev : ifend;
if (!p)
p = ifend;
} else {
- p = round_robin[x]?round_robin[x]->next:iflist;
+ p = round_robin[x] ? round_robin[x]->next : iflist;
if (!p)
p = iflist;
}
@@ -12522,10 +12562,17 @@
round_robin[start.rr_starting_point] = p;
if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
- && available(p, &unavailreason)) {
+ && available(&p, &unavailreason, channelmatched)) {
ast_debug(1, "Using channel %d\n", p->channel);
- callwait = (p->owner != NULL);
+ switch (p->sig) {
+ case SIG_PRI_LIB_HANDLE_CASES:
+ callwait = ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel;
+ break;
+ default:
+ callwait = (p->owner != NULL);
+ break;
+ }
#ifdef HAVE_OPENR2
if (p->mfcr2) {
ast_mutex_lock(&p->lock);
@@ -13986,16 +14033,15 @@
}
#endif /* defined(HAVE_PRI) */
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(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;
+ unsigned *why;
int channel;
int trunkgroup;
int x, y, fd = a->fd;
int interfaceid = 0;
char *c;
- char state;
char db_chan_name[20], db_answer[5];
struct dahdi_pvt *tmp;
struct dahdi_pri *pri;
@@ -14047,38 +14093,32 @@
ast_mutex_lock(&iflock);
for (tmp = iflist; tmp; tmp = tmp->next) {
if (tmp->pri && tmp->channel == channel) {
+ ast_mutex_unlock(&iflock);
+ ast_mutex_lock(&tmp->pri->lock);
if (!tmp->pri->enable_service_message_support) {
- ast_mutex_unlock(&iflock);
+ ast_mutex_unlock(&tmp->pri->lock);
ast_cli(fd,
"\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
"\tNote only 4ESS and 5ESS switch types are supported.\n\n");
return CLI_SUCCESS;
}
- why = -1;
snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
- if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
- sscanf(db_answer, "%1c:%30d", &state, &why);
- ast_db_del(db_chan_name, SRVST_DBKEY);
- }
+ why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
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);
- }
+ /* Near end wants to be in service now. */
+ *why &= ~SRVST_NEAREND;
+ snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
+ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+ if (!*why) {
+ ast_db_del(db_chan_name, SRVST_DBKEY);
}
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);
+ /* Near end wants to be out-of-service now. */
+ *why |= SRVST_NEAREND;
+ snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
break;
/* case 3: -- continuity */
@@ -14087,8 +14127,6 @@
ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
break;
}
- ast_mutex_unlock(&iflock);
- ast_mutex_lock(&tmp->pri->lock);
pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
ast_mutex_unlock(&tmp->pri->lock);
return CLI_SUCCESS;
@@ -14133,7 +14171,7 @@
}
return handle_pri_service_generic(e, cmd, a, 2);
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
#if defined(HAVE_PRI)
static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -14263,10 +14301,10 @@
#if defined(HAVE_PRI)
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
+#if defined(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
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
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"),
@@ -17030,14 +17068,14 @@
#endif
} else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
} else if (!strcasecmp(v->name, "service_message_support")) {
/* assuming switchtype for this channel group has been configured already */
if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E) && ast_true(v->value))
confp->pri.pri.enable_service_message_support = 1;
else
confp->pri.pri.enable_service_message_support = 0;
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
#ifdef HAVE_PRI_INBANDDISCONNECT
} else if (!strcasecmp(v->name, "inbanddisconnect")) {
confp->pri.pri.inbanddisconnect = ast_true(v->value);
@@ -17452,6 +17490,60 @@
/*!
* \internal
+ * \brief qsort comparison function.
+ * \since 1.8
+ *
+ * \param left Ptr to sig_pri_chan ptr to compare.
+ * \param right Ptr to sig_pri_chan ptr to compare.
+ *
+ * \retval <0 if left < right.
+ * \retval =0 if left == right.
+ * \retval >0 if left > right.
+ */
+static int dahdi_cmp_pri_chans(const void *left, const void *right)
+{
+ const struct sig_pri_chan *chan_left;
+ const struct sig_pri_chan *chan_right;
+ const struct dahdi_pvt *pvt_left;
+ const struct dahdi_pvt *pvt_right;
+
+ chan_left = *(struct sig_pri_chan **) left;
+ chan_right = *(struct sig_pri_chan **) right;
+ if (!chan_left) {
+ if (!chan_right) {
+ return 0;
+ }
+ return 1;
+ }
+ if (!chan_right) {
+ return -1;
+ }
+ pvt_left = (struct dahdi_pvt *) chan_left->chan_pvt;
+ pvt_right = (struct dahdi_pvt *) chan_right->chan_pvt;
+
+ return pvt_left->channel - pvt_right->channel;
+}
+
+/*!
+ * \internal
+ * \brief Sort the PRI B channel private pointer array.
+ * \since 1.8
+ *
+ * \param pri PRI Span controlling structure.
+ *
+ * \details
+ * Since the chan_dahdi.conf file can declare channels in any order, we need to sort
+ * the private channel pointer array.
+ *
+ * \return Nothing
+ */
+static void dahdi_sort_pri_chans(struct sig_pri_pri *pri)
+{
+ qsort(&pri->pvts, pri->numchans, sizeof(pri->pvts[0]), dahdi_cmp_pri_chans);
+}
+
+/*!
+ * \internal
* \brief Deep copy struct dahdi_chan_conf.
* \since 1.8
*
@@ -17531,7 +17623,7 @@
}
}
- /* It's a little silly to lock it, but we mind as well just to be sure */
+ /* It's a little silly to lock it, but we might as well just to be sure */
ast_mutex_lock(&iflock);
#ifdef HAVE_PRI
if (reload != 1) {
@@ -17670,6 +17762,7 @@
int x;
for (x = 0; x < NUM_SPANS; x++) {
if (pris[x].pri.pvts[0]) {
+ dahdi_sort_pri_chans(&pris[x].pri);
prepare_pri(pris + x);
if (sig_pri_start_pri(&pris[x].pri)) {
ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
Modified: team/rmudgett/call_waiting/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/sig_pri.c?view=diff&rev=251134&r1=251133&r2=251134
==============================================================================
--- team/rmudgett/call_waiting/channels/sig_pri.c (original)
+++ team/rmudgett/call_waiting/channels/sig_pri.c Fri Mar 5 17:37:50 2010
@@ -1125,9 +1125,9 @@
/*! \note Assumes the pri->lock is already obtained. */
static int pri_check_restart(struct sig_pri_pri *pri)
{
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
tryanotherpos:
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
do {
pri->resetpos++;
} while (pri->resetpos < pri->numchans
@@ -1136,23 +1136,16 @@
|| pri->pvts[pri->resetpos]->call
|| pri->pvts[pri->resetpos]->resetting));
if (pri->resetpos < pri->numchans) {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
- char db_chan_name[20], db_answer[5], state;
- int why;
-
- /* check if the channel is out of service */
- snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->span, pri->pvts[pri->resetpos]->channel);
-
- /* if so, try next channel */
- if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
- sscanf(db_answer, "%1c:%30d", &state, &why);
- if (why) {
- ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), not sending RESTART\n", pri->span,
- pri->pvts[pri->resetpos]->channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
- goto tryanotherpos;
- }
- }
-#endif
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ unsigned why;
+
+ why = pri->pvts[pri->resetpos]->service_status;
+ if (why) {
+ ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), not sending RESTART\n", pri->span,
+ pri->pvts[pri->resetpos]->channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
+ goto tryanotherpos;
+ }
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
/* Mark the channel as resetting and restart it */
pri->pvts[pri->resetpos]->resetting = 1;
@@ -1214,6 +1207,9 @@
&& pri->pvts[idx]->no_b_channel
&& !pri->pvts[idx]->inalarm
&& !pri->pvts[idx]->owner) {
+#if defined(HAVE_PRI_CALL_WAITING)
+ pri->pvts[idx]->is_call_waiting = 0;
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
ast_debug(1, "Found empty available no B channel interface\n");
return idx;
}
@@ -2886,35 +2882,28 @@
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 {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
- char db_chan_name[20], db_answer[5], state;
- int why, skipit = 0;
-
- snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->span, pri->pvts[chanpos]->channel);
- if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
- sscanf(db_answer, "%1c:%30d", &state, &why);
- if (why) {
- ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), ignoring RESTART\n", pri->span,
- PRI_CHANNEL(e->restart.channel), (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
- skipit = 1;
- } else {
- ast_db_del(db_chan_name, SRVST_DBKEY);
- }
+ int skipit = 0;
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ unsigned why;
+
+ why = pri->pvts[chanpos]->service_status;
+ if (why) {
+ ast_log(LOG_NOTICE,
+ "span '%d' channel '%d' out-of-service (reason: %s), ignoring RESTART\n",
+ pri->span, PRI_CHANNEL(e->restart.channel),
+ (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
+ skipit = 1;
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
sig_pri_lock_private(pri->pvts[chanpos]);
-#ifdef HAVE_PRI_SERVICE_MESSAGES
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);
if (pri->pvts[chanpos]->call) {
pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
pri->pvts[chanpos]->call = NULL;
}
-#ifdef HAVE_PRI_SERVICE_MESSAGES
}
-#endif
/* Force soft hangup if appropriate */
if (pri->pvts[chanpos]->owner)
ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
@@ -3004,43 +2993,42 @@
}
}
break;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
case PRI_EVENT_SERVICE:
chanpos = pri_find_principle(pri, e->service.channel, NULL);
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], db_answer[5], state;
- int ch, why = -1;
+ char db_chan_name[20];
+ char db_answer[5];
+ int ch;
+ unsigned *why;
ch = pri->pvts[chanpos]->channel;
snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->span, ch);
- if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
- sscanf(db_answer, "%1c:%30d", &state, &why);
- ast_db_del(db_chan_name, SRVST_DBKEY);
- }
+ why = &pri->pvts[chanpos]->service_status;
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);
- }
+ /* Far end wants to be in service now. */
+ *why &= ~SRVST_FAREND;
+ snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS,
+ *why);
+ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
+ if (!*why) {
+ ast_db_del(db_chan_name, SRVST_DBKEY);
}
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);
+ /* Far end wants to be out-of-service now. */
+ *why |= SRVST_FAREND;
+ snprintf(db_answer, sizeof(db_answer), "%s:%u", 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);
+ break;
}
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);
@@ -3056,7 +3044,7 @@
PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
}
break;
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
case PRI_EVENT_RING:
if (!ast_strlen_zero(pri->msn_list)
&& !sig_pri_msn_match(pri->msn_list, e->ring.callednum)) {
@@ -4323,14 +4311,25 @@
sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability)); /* push up to parent for EC */
- /* Should the picked channel be used exclusively? */
- if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
- exclusive = 1;
- } else {
- exclusive = 0;
- }
-
- pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
+#if defined(HAVE_PRI_CALL_WAITING)
+ if (p->is_call_waiting) {
+ /*
+ * Indicate that this is a call waiting call.
+ * i.e., Normal call but with no B channel.
+ */
+ pri_sr_set_channel(sr, 0, 0, 1);
+ } else
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
+ {
+ /* Should the picked channel be used exclusively? */
+ if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
+ exclusive = 1;
+ } else {
+ exclusive = 0;
+ }
+ pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
+ }
+
pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
(p->digital ? -1 : layer1));
@@ -4754,32 +4753,130 @@
return res;
}
-int sig_pri_available(struct sig_pri_chan *p, int *reason)
-{
- /* If no owner and interface has a B channel then likely available */
- if (!p->owner && !p->no_b_channel && p->pri) {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
- char db_chan_name[20], db_answer[5], state;
- int why = 0;
-
- snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->pri->span, p->channel);
- if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
- sscanf(db_answer, "%1c:%30d", &state, &why);
- }
- if (p->resetting || p->call || why) {
- if (why) {
- *reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+/*!
+ * \internal
+ * \brief Simple check if the channel is available to use.
+ * \since 1.8
+ *
+ * \param pvt Private channel control structure.
+ *
+ * \retval 0 Interface not available.
+ * \retval 1 Interface is available.
+ */
+static int sig_pri_available_check(struct sig_pri_chan *pvt)
+{
+ /*
+ * If no owner, interface has a B channel, not resetting, not already with call,
+ * not in alarm, and in-service then available.
+ */
+ if (!pvt->owner && !pvt->no_b_channel && !pvt->resetting && !pvt->call
+ && !pvt->inalarm) {
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ if (pvt->service_status) {
+ return 0;
+ }
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
+ return 1;
+ }
+ return 0;
+}
+
+#if defined(HAVE_PRI_CALL_WAITING)
+/*!
+ * \internal
+ * \brief Init the channel configuration using the span controller.
+ * \since 1.8
+ *
+ * \param pvt Channel to init the configuration.
+ * \param pri sig_pri PRI control structure.
+ *
+ * \return Nothing
+ */
+static void sig_pri_init_config(struct sig_pri_chan *pvt, struct sig_pri_pri *pri)
+{
+ pvt->stripmsd = pri->ch_cfg.stripmsd;
+ pvt->hidecallerid = pri->ch_cfg.hidecallerid;
+ pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
+ pvt->immediate = pri->ch_cfg.immediate;
+ pvt->priexclusive = pri->ch_cfg.priexclusive;
+ pvt->priindication_oob = pri->ch_cfg.priindication_oob;
+ pvt->use_callerid = pri->ch_cfg.use_callerid;
+ pvt->use_callingpres = pri->ch_cfg.use_callingpres;
+ ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
+ ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
+}
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
+
+#if defined(HAVE_PRI_CALL_WAITING)
+/*!
+ * \internal
+ * \brief Get an available call waiting interface.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ *
+ * \retval cw Call waiting interface to use.
+ * \retval NULL if no call waiting interface available.
+ */
+static struct sig_pri_chan *sig_pri_cw_available(struct sig_pri_pri *pri)
+{
+ struct sig_pri_chan *cw;
+ int idx;
+
+ cw = NULL;
+ ast_mutex_lock(&pri->lock);
+ if (pri->num_call_waiting_calls < pri->max_call_waiting_calls) {
+ for (idx = 0; idx < pri->numchans; ++idx) {
+ if (pri->pvts[idx] && sig_pri_available_check(pri->pvts[idx])) {
+ /* There is another channel that is available on this span. */
+ ast_mutex_unlock(&pri->lock);
+ return cw;
}
- return 0;
- }
-#else
- if (p->resetting || p->call) {
- return 0;
- }
-#endif
+ }
+ idx = pri_find_empty_nobch(pri);
+ if (0 <= idx) {
+ /* Setup the call waiting interface to use. */
+ cw = pri->pvts[idx];
+ cw->is_call_waiting = 1;
+ sig_pri_init_config(cw, pri);
+ ++pri->num_call_waiting_calls;
+ }
+ }
+ ast_mutex_unlock(&pri->lock);
+ return cw;
+}
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
+
+int sig_pri_available(struct sig_pri_chan **pvt, int *reason, int is_specific_channel)
+{
+ struct sig_pri_chan *p = *pvt;
+
+ if (!p->pri) {
+ /* Something is wrong here. A PRI channel without the pri pointer? */
+ return 0;
+ }
+
+ if (sig_pri_available_check(p)) {
return 1;
}
-
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ if (p->service_status) {
+ *reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ }
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
+
+#if defined(HAVE_PRI_CALL_WAITING)
+ if (!is_specific_channel) {
+ struct sig_pri_chan *cw;
+
+ cw = sig_pri_cw_available(p->pri);
+ if (cw) {
+ /* We have a call waiting interface to use instead. */
+ *pvt = cw;
+ return 1;
+ }
+ }
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
return 0;
}
@@ -4828,11 +4925,11 @@
break;
default:
pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
if (pri->enable_service_message_support) {
pri_set_service_message_support(pri->dchans[i], 1);
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
break;
}
@@ -5063,7 +5160,7 @@
return res;
}
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
int pri_maintenance_bservice(struct pri *pri, struct sig_pri_chan *p, int changestatus)
{
int channel = PVT_TO_CHANNEL(p);
@@ -5071,7 +5168,7 @@
return pri_maintenance_service(pri, span, channel, changestatus);
}
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
{
Modified: team/rmudgett/call_waiting/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/call_waiting/channels/sig_pri.h?view=diff&rev=251134&r1=251133&r2=251134
==============================================================================
--- team/rmudgett/call_waiting/channels/sig_pri.h (original)
+++ team/rmudgett/call_waiting/channels/sig_pri.h Fri Mar 5 17:37:50 2010
@@ -143,7 +143,7 @@
#define DAHDI_OVERLAPDIAL_INCOMING 2
#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
/*! \brief Persistent Service State */
#define SRVST_DBKEY "service-state"
/*! \brief The out-of-service SERVICE state */
@@ -163,22 +163,21 @@
/*! \brief The AstDB family */
static const char dahdi_db[] = "dahdi/registry";
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
struct sig_pri_chan {
/* Options to be set by user */
unsigned int hidecallerid:1;
unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
unsigned int immediate:1; /*!< Answer before getting digits? */
- unsigned int inalarm:1;
unsigned int priexclusive:1; /*!< Whether or not to override and use exculsive mode for channel selection */
unsigned int priindication_oob:1;
unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
char context[AST_MAX_CONTEXT];
- int channel; /*!< Channel Number or CRV */
char mohinterpret[MAX_MUSICCLASS];
int stripmsd;
+ int channel; /*!< Channel Number or CRV */
/* Options to be checked by user */
int cid_ani2; /*!< Automatic Number Identification number (Alternate PRI caller ID number) */
@@ -198,6 +197,7 @@
char keypad_digits[AST_MAX_EXTENSION];
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
+ unsigned int inalarm:1;
unsigned int alerting:1; /*!< TRUE if channel is alerting/ringing */
unsigned int alreadyhungup:1; /*!< TRUE if the call has already gone/hungup */
unsigned int isidlecall:1; /*!< TRUE if this is an idle call */
@@ -210,6 +210,10 @@
unsigned int digital:1;
/*! \brief TRUE if this interface has no B channel. (call hold and call waiting) */
unsigned int no_b_channel:1;
+#if defined(HAVE_PRI_CALL_WAITING)
+ /*! \brief TRUE if this is a call waiting call */
+ unsigned int is_call_waiting:1;
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
struct ast_channel *owner;
@@ -219,10 +223,21 @@
int prioffset; /*!< channel number in span */
int logicalspan; /*!< logical span number within trunk group */
int mastertrunkgroup; /*!< what trunk group is our master */
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
+ /*! \brief Active SRVST_DBKEY out-of-service status value. */
+ unsigned service_status;
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
struct sig_pri_callback *calls;
void *chan_pvt; /*!< Private structure of the user of this module. */
#if defined(HAVE_PRI_REVERSE_CHARGE)
+ /*!
+ * \brief Reverse charging indication
+ * \details
+ * -1 - No reverse charging,
+ * 1 - Reverse charging,
+ * 0,2-7 - Reserved for future use
+ */
int reverse_charging_indication;
#endif
};
@@ -237,9 +252,9 @@
int facilityenable; /*!< Enable facility IEs */
int dchan_logical_span[NUM_DCHANS]; /*!< Logical offset the DCHAN sits in */
int fds[NUM_DCHANS]; /*!< FD's for d-channels */
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
unsigned int enable_service_message_support:1; /*!< enable SERVICE message support */
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
#ifdef HAVE_PRI_INBANDDISCONNECT
unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
#endif
@@ -277,6 +292,20 @@
*/
int max_call_waiting_calls;
#endif /* defined(HAVE_PRI_CALL_WAITING) */
+#if defined(HAVE_PRI_CALL_WAITING)
+ struct {
+ int stripmsd;
+ unsigned int hidecallerid:1;
+ unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
+ unsigned int immediate:1; /*!< Answer before getting digits? */
+ unsigned int priexclusive:1; /*!< Whether or not to override and use exculsive mode for channel selection */
+ unsigned int priindication_oob:1;
+ unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
+ unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
+ char context[AST_MAX_CONTEXT];
+ char mohinterpret[MAX_MUSICCLASS];
+ } ch_cfg;
+#endif /* defined(HAVE_PRI_CALL_WAITING) */
#if defined(HAVE_PRI_CALL_WAITING)
/*!
@@ -355,7 +384,7 @@
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast);
-int sig_pri_available(struct sig_pri_chan *p, int *reason);
+int sig_pri_available(struct sig_pri_chan **pvt, int *reason, int is_specific_channel);
void sig_pri_init_pri(struct sig_pri_pri *pri);
@@ -385,9 +414,9 @@
int pri_send_keypad_facility_exec(struct sig_pri_chan *p, const char *digits);
int pri_send_callrerouting_facility_exec(struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason);
-#ifdef HAVE_PRI_SERVICE_MESSAGES
+#if defined(HAVE_PRI_SERVICE_MESSAGES)
int pri_maintenance_bservice(struct pri *pri, struct sig_pri_chan *p, int changestatus);
-#endif
+#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan);
More information about the asterisk-commits
mailing list