[asterisk-commits] rmudgett: branch rmudgett/sig_ss7 r261447 - /team/rmudgett/sig_ss7/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 5 19:03:57 CDT 2010
Author: rmudgett
Date: Wed May 5 19:03:53 2010
New Revision: 261447
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=261447
Log:
More progress through the SS7 swamp.
Modified:
team/rmudgett/sig_ss7/channels/chan_dahdi.c
team/rmudgett/sig_ss7/channels/sig_pri.c
team/rmudgett/sig_ss7/channels/sig_pri.h
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=261447&r1=261446&r2=261447
==============================================================================
--- team/rmudgett/sig_ss7/channels/chan_dahdi.c (original)
+++ team/rmudgett/sig_ss7/channels/chan_dahdi.c Wed May 5 19:03:53 2010
@@ -550,6 +550,12 @@
p->calls->set_dialing(p->chan_pvt, is_dialing);
}
}
+static void sig_ss7_set_digital(struct sig_ss7_chan *p, int is_digital)
+{
+ if (p->calls->set_digital) {
+ p->calls->set_digital(p->chan_pvt, is_digital);
+ }
+}
/*!
* \internal
@@ -562,7 +568,6 @@
*/
static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
{
-#if 0
struct ast_party_caller caller;
if (p->calls->set_callerid) {
@@ -581,7 +586,6 @@
caller.ani2 = p->cid_ani2;
p->calls->set_callerid(p->chan_pvt, &caller);
}
-#endif
/* BUGBUG sig_ss7_set_caller_id() not written */
}
@@ -619,6 +623,18 @@
}
}
+static int sig_ss7_play_tone(struct sig_ss7_chan *p, enum sig_ss7_tone tone)
+{
+ int res;
+
+ if (p->calls->play_tone) {
+ res = p->calls->play_tone(p->chan_pvt, tone);
+ } else {
+ res = -1;
+ }
+ return res;
+}
+
static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
{
if (p->calls->set_echocanceller) {
@@ -635,6 +651,30 @@
p->calls->set_loopback(p->chan_pvt, enable);
}
}
+}
+
+static struct ast_channel *sig_ss7_new_ast_channel(struct sig_ss7_chan *p, int state, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
+{
+ struct ast_channel *ast;
+
+ if (p->calls->new_ast_channel) {
+ ast = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
+ } else {
+ return NULL;
+ }
+
+ if (!p->owner) {
+ p->owner = ast;
+ }
+ p->alreadyhungup = 0;
+ ast->transfercapability = transfercapability;
+ pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY",
+ ast_transfercapability2str(transfercapability));
+ if (transfercapability & AST_TRANS_CAP_DIGITAL) {
+ sig_ss7_set_digital(p, 1);
+ }
+
+ return ast;
}
/* BUGBUG sig_ss7 callback functions ----^*/
@@ -2166,14 +2206,14 @@
p->dialing = is_dialing;
}
-#if defined(HAVE_PRI)
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
static void my_set_digital(void *pvt, int is_digital)
{
struct dahdi_pvt *p = pvt;
p->digital = is_digital;
}
-#endif /* defined(HAVE_PRI) */
+#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
static void my_set_ringtimeout(void *pvt, int ringt)
{
@@ -2406,14 +2446,14 @@
return;
}
-static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability, const char *linkedid);
+static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
{
struct dahdi_pvt *p = pvt;
int dsub = analogsub_to_dahdisub(sub);
- return dahdi_new(p, state, startpbx, dsub, 0, 0, requestor ? requestor->linkedid : "");
+ return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
}
#if defined(HAVE_PRI) || defined(HAVE_SS7)
@@ -2428,7 +2468,7 @@
#endif
#if defined(HAVE_PRI)
-static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, int startpbx, enum sig_pri_law law, int transfercapability, char *exten, const struct ast_channel *requestor)
+static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
{
struct dahdi_pvt *p = pvt;
int audio;
@@ -2456,7 +2496,7 @@
newlaw = DAHDI_LAW_MULAW;
break;
}
- return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, transfercapability, requestor ? requestor->linkedid : "");
+ return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
}
#endif /* defined(HAVE_PRI) */
@@ -3109,7 +3149,6 @@
*
* \param pvt Private channel structure.
* \param state Initial state of new channel.
- * \param startpbx TRUE if PBS is started
* \param law Combanding law to use.
* \param exten Dialplan extension for incoming call.
* \param requestor Channel requesting this new channel.
@@ -3117,7 +3156,7 @@
* \retval ast_channel on success.
* \retval NULL on error.
*/
-static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, int startpbx, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
+static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
{
struct dahdi_pvt *p = pvt;
int audio;
@@ -3147,8 +3186,7 @@
newlaw = DAHDI_LAW_MULAW;
break;
}
- return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, 0,
- requestor ? requestor->linkedid : "");
+ return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
/*! \todo BUGBUG my_new_ss7_ast_channel() not written */
}
@@ -3201,6 +3239,7 @@
.set_alarm = my_set_alarm,
.set_dialing = my_set_dialing,
+ .set_digital = my_set_digital,
.set_callerid = my_set_callerid,
.set_dnid = my_set_dnid,
.set_rdnis = my_set_rdnis,
@@ -3607,7 +3646,7 @@
}
if (!p->mfcr2_accept_on_offer) {
/* The user wants us to start the PBX thread right away without accepting the call first */
- c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0, NULL);
+ c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
if (c) {
/* Done here, don't disable reading now since we still need to generate MF tones to accept
the call or reject it and detect the tone off condition of the other end, all of this
@@ -3657,7 +3696,7 @@
}
return;
}
- c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0, NULL);
+ c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
if (c) {
/* chan_dahdi will take care of reading from now on in the PBX thread, tell the
library to forget about it */
@@ -5041,7 +5080,6 @@
#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;
@@ -5326,6 +5364,38 @@
}
#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+/*!
+ * \internal
+ * \brief Unlink the channel interface from the SS7 private pointer array.
+ * \since 1.8
+ *
+ * \param pvt chan_dahdi private interface structure to unlink.
+ *
+ * \return Nothing
+ */
+static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
+{
+ unsigned idx;
+ struct sig_ss7_linkset *ss7;
+
+ ss7 = pvt->ss7;
+ if (!ss7) {
+ /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
+ return;
+ }
+ ast_mutex_lock(&ss7->lock);
+ for (idx = 0; idx < ss7->numchans; ++idx) {
+ if (ss7->pvts[idx] == pvt->sig_pvt) {
+ ss7->pvts[idx] = NULL;
+ ast_mutex_unlock(&ss7->lock);
+ return;
+ }
+ }
+ ast_mutex_unlock(&ss7->lock);
+}
+#endif /* defined(HAVE_SS7) */
+
static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
{
if (cur->next && cur->next->span == cur->span) {
@@ -5352,6 +5422,9 @@
#if defined(HAVE_PRI)
dahdi_unlink_pri_pvt(p);
#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+ dahdi_unlink_ss7_pvt(p);
+#endif /* defined(HAVE_SS7) */
switch (pvt->which_iflist) {
case DAHDI_IFLIST_NONE:
break;
@@ -5371,11 +5444,20 @@
if (analog_lib_handles(p->sig, 0, 0)) {
analog_delete(p->sig_pvt);
}
+ switch (p->sig) {
#if defined(HAVE_PRI)
- if (dahdi_sig_pri_lib_handles(p->sig)) {
+ case SIG_PRI_LIB_HANDLE_CASES:
sig_pri_chan_delete(p->sig_pvt);
- }
+ break;
#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+ case SIG_SS7:
+ sig_ss7_chan_delete(p->sig_pvt);
+ break;
+#endif /* defined(HAVE_SS7) */
+ default:
+ break;
+ }
}
if (p->cidspill) {
ast_free(p->cidspill);
@@ -6124,7 +6206,7 @@
struct dahdi_pvt *p = ast->tech_pvt;
int res = 0;
int idx;
- ast_setstate(ast, AST_STATE_UP);
+ ast_setstate(ast, AST_STATE_UP);/* BUGBUG this is redundantly set by the analog and PRI submodules! */
ast_mutex_lock(&p->lock);
idx = dahdi_get_index(ast, p, 0);
if (idx < 0)
@@ -6142,24 +6224,16 @@
}
switch (p->sig) {
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
case SIG_PRI_LIB_HANDLE_CASES:
res = sig_pri_answer(p->sig_pvt, ast);
- ast_mutex_unlock(&p->lock);
- return res;
-#endif
-#ifdef HAVE_SS7
+ break;
+#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
case SIG_SS7:
- if (!ss7_grab(p, p->ss7)) {
- p->proceeding = 1;
- res = isup_anm(p->ss7->ss7, p->ss7call);
- ss7_rel(p->ss7);
- } else {
- ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
- res = -1;
- }
+ res = sig_ss7_answer(p->sig_pvt, ast);
break;
-#endif
+#endif /* defined(HAVE_SS7) */
#ifdef HAVE_OPENR2
case SIG_MFCR2:
if (!p->mfcr2_call_accepted) {
@@ -6185,6 +6259,7 @@
default:
ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
res = -1;
+ break;
}
ast_mutex_unlock(&p->lock);
return res;
@@ -7352,20 +7427,19 @@
if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
if (dahdi_sig_pri_lib_handles(p->sig)
&& !((struct sig_pri_chan *) p->sig_pvt)->proceeding
&& p->pri
&& (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* absorb event */
- } else {
-#endif
+ } else
+#endif /* defined(HAVE_PRI) */
+ {
dahdi_confmute(p, 0);
p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
p->subs[idx].f.subclass.integer = res & 0xff;
-#ifdef HAVE_PRI
- }
-#endif
+ }
dahdi_handle_dtmfup(ast, idx, &f);
return f;
}
@@ -7924,7 +7998,7 @@
goto winkflashdone;
}
/* Make new channel */
- chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0, 0);
+ chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
if (p->dahditrcallerid) {
if (!p->origcid_num)
p->origcid_num = ast_strdup(p->cid_num);
@@ -8755,8 +8829,23 @@
int func = DAHDI_FLASH;
ast_mutex_lock(&p->lock);
- idx = dahdi_get_index(chan, p, 0);
ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
+ switch (p->sig) {
+#if defined(HAVE_PRI)
+ case SIG_PRI_LIB_HANDLE_CASES:
+ res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
+ ast_mutex_unlock(&p->lock);
+ return res;
+#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+ case SIG_SS7:
+ res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
+ ast_mutex_unlock(&p->lock);
+ return res;
+#endif /* defined(HAVE_SS7) */
+ default:
+ break;
+ }
#ifdef HAVE_OPENR2
if (p->mfcr2 && !p->mfcr2_call_accepted) {
ast_mutex_unlock(&p->lock);
@@ -8765,37 +8854,13 @@
return 0;
}
#endif
-#ifdef HAVE_PRI
- switch (p->sig) {
- case SIG_PRI_LIB_HANDLE_CASES:
- res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
- ast_mutex_unlock(&p->lock);
- return res;
- default:
- break;
- }
-#endif
+ idx = dahdi_get_index(chan, p, 0);
if (idx == SUB_REAL) {
switch (condition) {
case AST_CONTROL_BUSY:
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
break;
case AST_CONTROL_RINGING:
-#ifdef HAVE_SS7
- if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
- if (p->ss7->ss7) {
- ss7_grab(p, p->ss7);
-
- if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
- p->rlt = 1;
- if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
- isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
- p->alerting = 1;
- ss7_rel(p->ss7);
- }
- }
-#endif
-
res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
if (chan->_state != AST_STATE_UP) {
@@ -8808,41 +8873,11 @@
break;
case AST_CONTROL_PROCEEDING:
ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
-#ifdef HAVE_SS7
- /* This IF sends the FAR for an answered ALEG call */
- if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
- if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
- p->rlt = 1;
- }
-
- if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
- if (p->ss7->ss7) {
- ss7_grab(p, p->ss7);
- isup_acm(p->ss7->ss7, p->ss7call);
- p->proceeding = 1;
- ss7_rel(p->ss7);
-
- }
- }
-#endif
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_PROGRESS:
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
-#ifdef HAVE_SS7
- if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
- if (p->ss7->ss7) {
- ss7_grab(p, p->ss7);
- isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
- p->progress = 1;
- ss7_rel(p->ss7);
- /* enable echo canceler here on SS7 calls */
- dahdi_enable_ec(p);
-
- }
- }
-#endif
/* don't continue in ast_indicate */
res = 0;
break;
@@ -8885,8 +8920,9 @@
res = tone_zone_play_tone(p->subs[idx].dfd, -1);
break;
}
- } else
+ } else {
res = 0;
+ }
ast_mutex_unlock(&p->lock);
return res;
}
@@ -8939,7 +8975,7 @@
return chan_name;
}
-static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability, const char *linkedid)
+static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
{
struct ast_channel *tmp;
format_t deflaw;
@@ -9102,13 +9138,6 @@
tmp->cid.cid_pres = i->callingpres;
tmp->cid.cid_ton = i->cid_ton;
tmp->cid.cid_ani2 = i->cid_ani2;
-#if defined(HAVE_SS7)
- tmp->transfercapability = transfercapability;
- pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
- if (transfercapability & AST_TRANS_CAP_DIGITAL)
- i->digital = 1;
- i->alreadyhungup = 0;
-#endif
/* clear the fake event in case we posted one before we had ast_channel */
i->fake_event = 0;
/* Assure there is no confmute on this channel */
@@ -10422,7 +10451,7 @@
restore_gains(mtd->pvt);
mtd->pvt->ringt = mtd->pvt->ringt_base;
- if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0, NULL))) {
+ if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
int result;
if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
@@ -10750,7 +10779,7 @@
dahdi_enable_ec(i);
/* The channel is immediately up. Start right away */
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
- chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
if (!chan) {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
@@ -10759,7 +10788,7 @@
}
} else {
/* Check for callerid, digits, etc */
- chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
if (chan) {
if (has_voicemail(i))
res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
@@ -10800,9 +10829,9 @@
case SIG_SF:
/* Check for callerid, digits, etc */
if (i->cid_start == CID_START_POLARITY_IN) {
- chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
} else {
- chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
}
if (!chan) {
@@ -10923,7 +10952,7 @@
ast_verb(2, "Starting post polarity "
"CID detection on channel %d\n",
i->channel);
- chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
} else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
@@ -11184,7 +11213,7 @@
doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
i->dtmfcid_holdoff_state = 1;
} else {
- chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL);
+ chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
} else {
@@ -11544,10 +11573,13 @@
int x;
struct analog_pvt *analog_p = NULL;
struct dahdi_params p;
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
struct dahdi_spaninfo si;
- struct sig_pri_chan *pchan = NULL;
-#endif
+ struct sig_pri_chan *pri_chan = NULL;
+#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+ struct sig_ss7_chan *ss7_chan = NULL;
+#endif /* defined(HAVE_SS7) */
/* Search channel interface list to see if it already exists. */
for (tmp = iflist; tmp; tmp = tmp->next) {
@@ -11635,10 +11667,11 @@
}
tmp->sig_pvt = analog_p;
}
-#ifdef HAVE_SS7
+#if defined(HAVE_SS7)
if (chan_sig == SIG_SS7) {
struct dahdi_ss7 *ss7;
int clear = 0;
+
if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
destroy_dahdi_pvt(tmp);
@@ -11651,20 +11684,27 @@
destroy_dahdi_pvt(tmp);
return NULL;
}
+ ss7->ss7.span = cur_linkset;
if (cur_cicbeginswith < 0) {
ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
destroy_dahdi_pvt(tmp);
return NULL;
}
-
- tmp->cic = cur_cicbeginswith++;
+ ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
+ if (!ss7_chan) {
+ destroy_dahdi_pvt(tmp);
+ return NULL;
+ }
+ tmp->sig_pvt = ss7_chan;
+ tmp->ss7 = &ss7->ss7;
+
+ ss7_chan->channel = tmp->channel;
+ ss7_chan->cic = cur_cicbeginswith++;
/* DB: Add CIC's DPC information */
- tmp->dpc = cur_defaultdpc;
-
- tmp->ss7 = &ss7->ss7;
- tmp->ss7call = NULL;
- ss7->ss7.pvts[ss7->ss7.numchans++] = tmp;
+ ss7_chan->dpc = cur_defaultdpc;
+
+ ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
@@ -11674,7 +11714,7 @@
ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
}
-#endif
+#endif /* defined(HAVE_SS7) */
#ifdef HAVE_OPENR2
if (chan_sig == SIG_MFCR2) {
struct dahdi_mfcr2 *r2_link;
@@ -11810,12 +11850,12 @@
}
ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
- pchan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
- if (!pchan) {
+ pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
+ if (!pri_chan) {
destroy_dahdi_pvt(tmp);
return NULL;
}
- tmp->sig_pvt = pchan;
+ tmp->sig_pvt = pri_chan;
tmp->pri = &pris[span].pri;
if (!tmp->pri->cc_params) {
@@ -12223,7 +12263,52 @@
}
}
- if (!dahdi_sig_pri_lib_handles(tmp->sig)) {
+ switch (tmp->sig) {
+#if defined(HAVE_PRI)
+ case SIG_PRI_LIB_HANDLE_CASES:
+ if (pri_chan) {
+ pri_chan->channel = tmp->channel;
+ pri_chan->hidecallerid = tmp->hidecallerid;
+ pri_chan->hidecalleridname = tmp->hidecalleridname;
+ pri_chan->immediate = tmp->immediate;
+ pri_chan->inalarm = tmp->inalarm;
+ pri_chan->priexclusive = tmp->priexclusive;
+ pri_chan->priindication_oob = tmp->priindication_oob;
+ pri_chan->use_callerid = tmp->use_callerid;
+ pri_chan->use_callingpres = tmp->use_callingpres;
+ ast_copy_string(pri_chan->context, tmp->context,
+ sizeof(pri_chan->context));
+ ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
+ sizeof(pri_chan->mohinterpret));
+ pri_chan->stripmsd = tmp->stripmsd;
+ }
+ break;
+#endif /* defined(HAVE_PRI) */
+#if defined(HAVE_SS7)
+ case SIG_SS7:
+ if (ss7_chan) {
+/* BUGBUG check that all fields that need initialization are initialized */
+/* BUGBUG check that all fields that need synchronization between upper and submodule are synced with callbacks. */
+ ss7_chan->inalarm = tmp->inalarm;
+/* BUGBUG the following three flags need callbacks for syncing with the upper layer. */
+ ss7_chan->locallyblocked = tmp->locallyblocked;
+ ss7_chan->remotelyblocked = tmp->remotelyblocked;
+ ss7_chan->inservice = tmp->inservice;
+
+ ss7_chan->stripmsd = tmp->stripmsd;
+ ss7_chan->hidecallerid = tmp->hidecallerid;
+ ss7_chan->use_callerid = tmp->use_callerid;
+ ss7_chan->use_callingpres = tmp->use_callingpres;
+ ss7_chan->immediate = tmp->immediate;
+ ast_copy_string(ss7_chan->context, tmp->context,
+ sizeof(ss7_chan->context));
+ ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
+ sizeof(ss7_chan->mohinterpret));
+ }
+ break;
+#endif /* defined(HAVE_SS7) */
+ default:
+ /* The only sig submodule left should be sig_analog. */
analog_p = tmp->sig_pvt;
if (analog_p) {
analog_p->channel = tmp->channel;
@@ -12247,17 +12332,18 @@
analog_p->cid_signalling = conf->chan.cid_signalling;
analog_p->stripmsd = conf->chan.stripmsd;
switch (conf->chan.cid_start) {
- case CID_START_POLARITY:
- analog_p->cid_start = ANALOG_CID_START_POLARITY;
- break;
- case CID_START_POLARITY_IN:
- analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
- break;
- case CID_START_DTMF_NOALERT:
- analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
- break;
- default:
- analog_p->cid_start = ANALOG_CID_START_RING;
+ case CID_START_POLARITY:
+ analog_p->cid_start = ANALOG_CID_START_POLARITY;
+ break;
+ case CID_START_POLARITY_IN:
+ analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
+ break;
+ case CID_START_DTMF_NOALERT:
+ analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
+ break;
+ default:
+ analog_p->cid_start = ANALOG_CID_START_RING;
+ break;
}
analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
analog_p->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
@@ -12283,22 +12369,9 @@
analog_config_complete(analog_p);
}
+ break;
}
#if defined(HAVE_PRI)
- else if (pchan != NULL) {
- pchan->channel = tmp->channel;
- pchan->hidecallerid = tmp->hidecallerid;
- pchan->hidecalleridname = tmp->hidecalleridname;
- pchan->immediate = tmp->immediate;
- pchan->inalarm = tmp->inalarm;
- pchan->priexclusive = tmp->priexclusive;
- pchan->priindication_oob = tmp->priindication_oob;
- pchan->use_callerid = tmp->use_callerid;
- pchan->use_callingpres = tmp->use_callingpres;
- ast_copy_string(pchan->context, tmp->context, sizeof(pchan->context));
- ast_copy_string(pchan->mohinterpret, tmp->mohinterpret, sizeof(pchan->mohinterpret));
- pchan->stripmsd = tmp->stripmsd;
- }
if (tmp->channel == CHAN_PSEUDO) {
/*
* Save off pseudo channel buffer policy values for dynamic creation of
@@ -12762,8 +12835,12 @@
sizeof(p->dnid));
tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
#endif
+#if defined(HAVE_SS7)
+ } else if (p->sig == SIG_SS7) {
+ tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
+#endif /* defined(HAVE_SS7) */
} else {
- tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, transcapdigital, requestor ? requestor->linkedid : "");
+ tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
}
if (!tmp) {
p->outgoing = 0;
@@ -13120,7 +13197,9 @@
}
ast_mutex_unlock(&linkset->lock);
- c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0, NULL);
+ /* BUGBUG do not call dahdi_new() with the startpbx flag set here! MUST FIX */
+ /* BUGBUG convert code here to use sig_ss7_new_ast_channel() */
+ c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, NULL);
if (!c) {
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
/* Holding this lock is assumed entering the function */
@@ -18143,7 +18222,7 @@
* \since 1.8
*
* \param p Signaling private structure pointer.
- * \param ast Asterisk channel sructure pointer.
+ * \param ast Asterisk channel structure pointer.
* \param rdest Dialstring.
*
* \retval 0 on success.
@@ -18292,7 +18371,7 @@
* \since 1.8
*
* \param p Signaling private structure pointer.
- * \param ast Asterisk channel sructure pointer.
+ * \param ast Asterisk channel structure pointer.
*
* \retval 0 on success.
* \retval -1 on error.
@@ -18337,6 +18416,189 @@
return res;
}
+/*!
+ * \brief SS7 answer channel.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ * \param ast Asterisk channel structure pointer.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
+{
+ int res;
+
+ if (!ss7_grab(p, p->ss7)) {
+ p->proceeding = 1;
+ res = isup_anm(p->ss7->ss7, p->ss7call);
+ ss7_rel(p->ss7);
+ } else {
+ ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->ss7->span);
+ res = -1;
+ }
+ return res;
+}
+
+/*!
+ * \brief SS7 answer channel.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ * \param chan Asterisk channel structure pointer.
+ * \param condition AST control frame subtype.
+ * \param data AST control frame payload contents.
+ * \param datalen Length of payload contents.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error or indication condition not handled.
+ */
+int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
+{
+ int res = -1;
+
+ switch (condition) {
+ case AST_CONTROL_BUSY:
+ res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
+ break;
+ case AST_CONTROL_RINGING:
+ if ((!p->alerting) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
+ if (p->ss7->ss7) {
+ ss7_grab(p, p->ss7);
+
+ if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
+ p->rlt = 1;
+ if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
+ isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
+ p->alerting = 1;
+ ss7_rel(p->ss7);
+ }
+ }
+
+ res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
+
+ if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) {
+ ast_setstate(chan, AST_STATE_RINGING);
+ }
+ break;
+ case AST_CONTROL_PROCEEDING:
+ ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
+ /* This IF sends the FAR for an answered ALEG call */
+ if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
+ if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
+ p->rlt = 1;
+ }
+
+ if (!p->proceeding && p->ss7 && !p->outgoing) {
+ if (p->ss7->ss7) {
+ ss7_grab(p, p->ss7);
+ isup_acm(p->ss7->ss7, p->ss7call);
+ p->proceeding = 1;
+ ss7_rel(p->ss7);
+ }
+ }
+ /* don't continue in ast_indicate */
+ res = 0;
+ break;
+ case AST_CONTROL_PROGRESS:
+ ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
+ if (!p->progress && p->ss7 && !p->outgoing) {
+ if (p->ss7->ss7) {
+ ss7_grab(p, p->ss7);
+ isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
+ p->progress = 1;
+ ss7_rel(p->ss7);
+ /* enable echo canceler here on SS7 calls */
+ sig_ss7_set_echocanceller(p, 1);
+ }
+ }
+ /* don't continue in ast_indicate */
+ res = 0;
+ break;
+ case AST_CONTROL_CONGESTION:
+ chan->hangupcause = AST_CAUSE_CONGESTION;
+ break;
+ case AST_CONTROL_HOLD:
+ ast_moh_start(chan, data, p->mohinterpret);
+ break;
+ case AST_CONTROL_UNHOLD:
+ ast_moh_stop(chan);
+ break;
+ case AST_CONTROL_SRCUPDATE:
+ res = 0;
+ break;
+ case -1:
+ res = sig_ss7_play_tone(p, -1);
+ break;
+ }
+ return res;
+}
+
+/*!
+ * \brief SS7 channel request.
+ * \since 1.8
+ *
+ * \param p Signaling private structure pointer.
+ * \param law Companding law preferred
+ * \param requestor Asterisk channel requesting a channel to dial (Can be NULL)
+ * \param transfercapability
+ *
+ * \retval ast_channel on success.
+ * \retval NULL on error.
+ */
+struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability)
+{
+ struct ast_channel *ast;
+
+ p->outgoing = 1;
+ ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
+ if (!ast) {
+ p->outgoing = 0;
+ }
+ return ast;
+}
+
+/*!
+ * \brief Delete the sig_ss7 private channel structure.
+ * \since 1.8
+ *
+ * \param doomed sig_ss7 private channel structure to delete.
+ *
+ * \return Nothing
+ */
+void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
+{
+ ast_free(doomed);
+}
+
+/*!
+ * \brief Create a new sig_ss7 private channel structure.
+ * \since 1.8
+ *
+ * \param pvt_data Upper layer private data structure.
+ * \param callback Callbacks to the upper layer.
+ * \param ss7 Controlling linkset for the channel.
+ *
+ * \retval sig_ss7_chan on success.
+ * \retval NULL on error.
+ */
+struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7)
+{
+ struct sig_ss7_chan *pvt;
+
+ pvt = ast_calloc(1, sizeof(*pvt));
+ if (!pvt) {
+ return pvt;
+ }
+
+ pvt->calls = callback;
+ pvt->chan_pvt = pvt_data;
+ pvt->ss7 = ss7;
+
+ return pvt;
+}
+
/* BUGBUG sig_ss7 API functions ----^*/
Modified: team/rmudgett/sig_ss7/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/sig_ss7/channels/sig_pri.c?view=diff&rev=261447&r1=261446&r2=261447
==============================================================================
--- team/rmudgett/sig_ss7/channels/sig_pri.c (original)
+++ team/rmudgett/sig_ss7/channels/sig_pri.c Wed May 5 19:03:53 2010
@@ -785,12 +785,12 @@
return -1;
}
-static struct ast_channel *sig_pri_new_ast_channel(struct sig_pri_chan *p, int state, int startpbx, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
+static struct ast_channel *sig_pri_new_ast_channel(struct sig_pri_chan *p, int state, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
{
struct ast_channel *c;
if (p->calls->new_ast_channel)
- c = p->calls->new_ast_channel(p->chan_pvt, state, startpbx, ulaw, transfercapability, exten, requestor);
+ c = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
else
return NULL;
@@ -798,9 +798,10 @@
p->owner = c;
p->isidlecall = 0;
p->alreadyhungup = 0;
+ c->transfercapability = transfercapability;
+ pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY",
+ ast_transfercapability2str(transfercapability));
if (transfercapability & AST_TRANS_CAP_DIGITAL) {
- c->transfercapability = transfercapability;
- pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
sig_pri_set_digital(p, 1);
}
if (p->pri && !pri_grab(p, p->pri)) {
@@ -820,7 +821,7 @@
ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
p->outgoing = 1;
- ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, 0, law, transfercapability, p->exten, requestor);
+ ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
if (!ast) {
p->outgoing = 0;
}
@@ -3202,7 +3203,7 @@
*/
ast_mutex_unlock(&pri->lock);
c = sig_pri_new_ast_channel(pri->pvts[chanpos],
- AST_STATE_RESERVED, 0,
+ AST_STATE_RESERVED,
(e->ring.layer1 == PRI_LAYER_1_ALAW)
? SIG_PRI_ALAW : SIG_PRI_ULAW,
e->ring.ctype, pri->pvts[chanpos]->exten, NULL);
@@ -3295,7 +3296,7 @@
*/
ast_mutex_unlock(&pri->lock);
c = sig_pri_new_ast_channel(pri->pvts[chanpos],
- AST_STATE_RING, 0,
+ AST_STATE_RING,
(e->ring.layer1 == PRI_LAYER_1_ALAW)
? SIG_PRI_ALAW : SIG_PRI_ULAW, e->ring.ctype,
pri->pvts[chanpos]->exten, NULL);
Modified: team/rmudgett/sig_ss7/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/sig_ss7/channels/sig_pri.h?view=diff&rev=261447&r1=261446&r2=261447
==============================================================================
--- team/rmudgett/sig_ss7/channels/sig_pri.h (original)
+++ team/rmudgett/sig_ss7/channels/sig_pri.h Wed May 5 19:03:53 2010
@@ -97,7 +97,7 @@
int (* const train_echocanceller)(void *pvt);
int (* const dsp_reset_and_flush_digits)(void *pvt);
- struct ast_channel * (* const new_ast_channel)(void *pvt, int state, int startpbx, enum sig_pri_law law, int transfercapability, char *exten, const struct ast_channel *chan);
+ struct ast_channel * (* const new_ast_channel)(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *chan);
void (* const fixup_chans)(void *old_chan, void *new_chan);
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=261447&r1=261446&r2=261447
==============================================================================
--- team/rmudgett/sig_ss7/channels/sig_ss7.h (original)
+++ team/rmudgett/sig_ss7/channels/sig_ss7.h Wed May 5 19:03:53 2010
@@ -94,11 +94,12 @@
int (* const set_echocanceller)(void *pvt, int enable);
void (* const set_loopback)(void *pvt, int enable);
- 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);
+ struct ast_channel * (* const new_ast_channel)(void *pvt, int state, 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_alarm)(void *pvt, int in_alarm);
void (* const set_dialing)(void *pvt, int is_dialing);
+ void (* const set_digital)(void *pvt, int is_digital);
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);
@@ -144,6 +145,7 @@
/* Options to be set by user */
char context[AST_MAX_CONTEXT];
+ char mohinterpret[MAX_MUSICCLASS];
char charge_number[50];
char gen_add_number[50];
char gen_dig_number[50];
@@ -164,11 +166,10 @@
unsigned int call_ref_ident;
unsigned int call_ref_pc;
unsigned char calling_party_cat;
+
int cic; /*!< CIC associated with channel */
unsigned int dpc; /*!< CIC's DPC */
int channel; /*!< Channel Number */
-
- unsigned int loopedback:1;
/*!
* \brief TRUE if channel is out of reset and ready
@@ -195,37 +196,46 @@
unsigned int alreadyhungup:1;
/*! \brief XXX BOOLEAN Purpose??? */
unsigned int rlt:1;
+
+ unsigned int loopedback:1;
};
struct sig_ss7_linkset {
pthread_t master; /*!< Thread of master */
ast_mutex_t lock; /*!< libss7 access lock */
+ struct sig_ss7_callback *calls;
+ struct ss7 *ss7;
+ struct sig_ss7_chan *pvts[SIG_SS7_MAX_CHANNELS];/*!< Member channel pvt structs */
int fds[SIG_SS7_NUM_DCHANS];
int numsigchans;
int linkstate[SIG_SS7_NUM_DCHANS];
int numchans;
- int type;
+ int span; /*!< span number put into user output messages */
enum {
LINKSET_STATE_DOWN = 0,
LINKSET_STATE_UP
} state;
+
+ /* Options to be set by user */
+ int flags; /*!< Linkset flags (LINKSET_FLAG_EXPLICITACM) */
+ int type; /*!< SS7 type ITU/ANSI. Used for companding selection. */
char called_nai; /*!< Called Nature of Address Indicator */
char calling_nai; /*!< Calling Nature of Address Indicator */
char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
char subscriberprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
char unknownprefix[20]; /*!< for unknown dialplans */
- struct ss7 *ss7;
- struct sig_ss7_chan *pvts[SIG_SS7_MAX_CHANNELS];/*!< Member channel pvt structs */
- int flags; /*!< Linkset flags */
-
- 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);
+int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast);
+int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen);
+struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability);
+void sig_ss7_chan_delete(struct sig_ss7_chan *doomed);
+struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7);
/* ------------------------------------------------------------------- */
More information about the asterisk-commits
mailing list