[asterisk-commits] moy: branch moy/dahdi-tap-trunk r220585 - /team/moy/dahdi-tap-trunk/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat Sep 26 02:13:41 CDT 2009
Author: moy
Date: Sat Sep 26 02:13:37 2009
New Revision: 220585
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=220585
Log:
initial code to support tapping channels
Modified:
team/moy/dahdi-tap-trunk/channels/chan_dahdi.c
team/moy/dahdi-tap-trunk/channels/sig_pri.c
team/moy/dahdi-tap-trunk/channels/sig_pri.h
Modified: team/moy/dahdi-tap-trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-trunk/channels/chan_dahdi.c?view=diff&rev=220585&r1=220584&r2=220585
==============================================================================
--- team/moy/dahdi-tap-trunk/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-trunk/channels/chan_dahdi.c Sat Sep 26 02:13:37 2009
@@ -248,6 +248,10 @@
</description>
</manager>
***/
+
+#define TAP_PEER_NONE 0
+#define TAP_PEER_NEXT 1
+#define TAP_PEER_PREV 2
#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
@@ -1253,6 +1257,9 @@
/*! \brief TRUE if confrence is muted. */
int muting;
void *sig_pvt;
+ struct dahdi_pvt *tappingpeer; /*!< Peer channel that has the other side of the call audio */
+ int tappingconf; /*!< DAHDI Conference number used for tapping */
+ int tappingfd; /*!< DAHDI Conference fd the mixed audio is read from */
};
static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
@@ -1316,6 +1323,7 @@
.privateprefix = "",
.unknownprefix = "",
.resetinterval = -1,
+ .tappingpeerpos = TAP_PEER_NONE,
},
#endif
#ifdef HAVE_SS7
@@ -2306,6 +2314,14 @@
struct dahdi_pvt *p = pvt;
int audio;
int newlaw = -1;
+
+ struct sig_pri_chan *pchan = p->sig_pvt;
+ struct sig_pri_pri *pri = pchan->pri;
+
+ if (pri->tappingpeer) {
+ p->tappingpeer = pchan->tappingpeer->chan_pvt;
+ ((struct dahdi_pvt *)pchan->tappingpeer->chan_pvt)->tappingpeer = p;
+ }
/* Set to audio mode at this point */
audio = 1;
@@ -5208,6 +5224,21 @@
if (p->sig == SIG_SS7) {
x = 1;
ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
+ }
+
+ if (p->tappingpeer) {
+ struct dahdi_confinfo pinfo;
+ memset(&pinfo, 0, sizeof(pinfo));
+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF);
+ memset(&pinfo, 0, sizeof(pinfo));
+ ioctl(p->tappingpeer->subs[SUB_REAL].dfd, DAHDI_SETCONF);
+ memset(&pinfo, 0, sizeof(pinfo));
+ ioctl(p->tappingfd, DAHDI_SETCONF);
+ dahdi_close(p->tappingfd);
+ p->tappingfd = -1;
+ p->tappingpeer->tappingpeer = NULL;
+ p->tappingpeer->owner = NULL;
+ p->tappingpeer = NULL;
}
x = 0;
@@ -7776,40 +7807,54 @@
}
readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
CHECK_BLOCKING(ast);
- res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+#define CHECK_READ_RESULT(res) if (res < 0) { \
+ f = NULL; \
+ if (res == -1) { \
+ if (errno == EAGAIN) { \
+ /* Return "NULL" frame if there is nobody there */ \
+ ast_mutex_unlock(&p->lock); \
+ return &p->subs[idx].f; \
+ } else if (errno == ELAST) { \
+ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { \
+ struct analog_pvt *analog_p = p->sig_pvt; \
+ f = analog_exception(analog_p, ast); \
+ } else { \
+ f = __dahdi_exception(ast); \
+ } \
+ } else \
+ ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); \
+ } \
+ ast_mutex_unlock(&p->lock); \
+ return f; \
+ } \
+ if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { \
+ ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); \
+ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { \
+ struct analog_pvt *analog_p = p->sig_pvt; \
+ f = analog_exception(analog_p, ast); \
+ } else { \
+ f = __dahdi_exception(ast); \
+ } \
+ ast_mutex_unlock(&p->lock); \
+ return f; \
+ }
+ /* if we have a tap peer we must read the mixed audio */
+ if (p->tappingpeer) {
+ /* passive channel reading */
+ /* first read from the 2 involved dahdi channels just to consume their frames */
+ res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+ CHECK_READ_RESULT(res);
+ res = read(p->tappingpeer->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+ CHECK_READ_RESULT(res);
+ /* now read the mixed audio that will be returned to the core */
+ res = read(p->tappingfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+ } else {
+ /* no tapping peer, normal reading */
+ res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+ }
ast_clear_flag(ast, AST_FLAG_BLOCKING);
/* Check for hangup */
- if (res < 0) {
- f = NULL;
- if (res == -1) {
- if (errno == EAGAIN) {
- /* Return "NULL" frame if there is nobody there */
- ast_mutex_unlock(&p->lock);
- return &p->subs[idx].f;
- } else if (errno == ELAST) {
- if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
- struct analog_pvt *analog_p = p->sig_pvt;
- f = analog_exception(analog_p, ast);
- } else {
- f = __dahdi_exception(ast);
- }
- } else
- ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
- }
- ast_mutex_unlock(&p->lock);
- return f;
- }
- if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
- ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
- if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
- struct analog_pvt *analog_p = p->sig_pvt;
- f = analog_exception(analog_p, ast);
- } else {
- f = __dahdi_exception(ast);
- }
- ast_mutex_unlock(&p->lock);
- return f;
- }
+ CHECK_READ_RESULT(res);
if (p->tdd) { /* if in TDD mode, see if we receive that */
int c;
@@ -7996,6 +8041,11 @@
return -1;
}
+ /* ignore writes to tapping channels */
+ if (p->tappingpeer) {
+ return 0;
+ }
+
/* Write a frame of (presumably voice) data */
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype != AST_FRAME_IMAGE)
@@ -8198,7 +8248,7 @@
struct ast_channel *tmp;
int deflaw;
int res;
- int x,y;
+ int x,y,fd;
int features;
struct ast_str *chan_name;
struct ast_variable *v;
@@ -8368,6 +8418,54 @@
for (v = i->vars ; v ; v = v->next)
pbx_builtin_setvar_helper(tmp, v->name, v->value);
+ if (i->tappingpeer) {
+ struct dahdi_confinfo dahdic = { 0, };
+ /* create the mixing conference
+ * some DAHDI_SETCONF interface rules to keep in mind
+ * confno == -1 means create new conference with the given confmode
+ * confno and confmode == 0 means remove the channel from its conference */
+ dahdic.chan = 0; /* means use current channel (the one the fd belongs to)*/
+ dahdic.confno = -1; /* -1 means create new conference */
+ dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER | DAHDI_CONF_PSEUDO_LISTENER;
+ fd = dahdi_open("/dev/dahdi/pseudo");
+ if (fd < 0 || ioctl(fd, DAHDI_SETCONF, &dahdic)) {
+ ast_log(LOG_ERROR, "Unable to create dahdi conference for tapping\n");
+ ast_hangup(tmp);
+ i->owner = NULL;
+ return NULL;
+ }
+ i->tappingconf = dahdic.confno;
+ i->tappingfd = fd;
+
+ /* add both parties to the conference */
+ dahdic.chan = 0;
+ dahdic.confno = i->tappingconf;
+ dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
+ if (ioctl(i->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+ ast_log(LOG_ERROR, "Unable to add chan to conference for tapping devices: %s\n", strerror(errno));
+ ast_hangup(tmp);
+ i->owner = NULL;
+ return NULL;
+ }
+ dahdic.chan = 0;
+ dahdic.confno = i->tappingconf;
+ dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
+ if (ioctl(i->tappingpeer->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+ ast_log(LOG_ERROR, "Unable to add peer chan to conference for tapping devices: %s\n", strerror(errno));
+ ast_hangup(tmp);
+ i->owner = NULL;
+ return NULL;
+ }
+ ast_log(LOG_DEBUG, "Created tapping conference %d with fd %d between dahdi chans %d and %d for ast channel %s\n",
+ i->tappingconf,
+ i->tappingfd,
+ i->channel,
+ i->tappingpeer->channel,
+ tmp->name);
+ i->tappingpeer->owner = i->owner;
+
+ }
+
if (startpbx) {
#ifdef HAVE_OPENR2
if (i->mfcr2call) {
@@ -8378,6 +8476,9 @@
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
ast_hangup(tmp);
i->owner = NULL;
+ if (i->tappingpeer) {
+ i->tappingpeer->owner = NULL;
+ }
return NULL;
}
}
@@ -11001,6 +11102,23 @@
pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
+ if (conf->pri.pri.tappingpeerpos == TAP_PEER_NEXT) {
+ if (span < (ARRAY_LEN(pris) - 1)) {
+ pris[span].pri.tappingpeerpos = TAP_PEER_NEXT;
+ pris[span].pri.tappingpeer = &pris[span+1].pri;
+ pris[span+1].pri.tappingpeer = &pris[span].pri;
+ } else {
+ ast_log(LOG_ERROR, "Ignoring tappingpeerpos 'next' for span %d, max spans exceeded.\n", span + 1);
+ }
+ } else if (conf->pri.pri.tappingpeerpos == TAP_PEER_PREV) {
+ if (span > 0) {
+ ast_log(LOG_ERROR, "Ignoring tappingpeerpos 'prev' for span %d, there is no previous span.\n", span + 1);
+ } else {
+ pris[span].pri.tappingpeerpos = TAP_PEER_PREV;
+ pris[span].pri.tappingpeer = &pris[span-1].pri;
+ pris[span-1].pri.tappingpeer = &pris[span].pri;
+ }
+ }
#ifdef HAVE_PRI_SERVICE_MESSAGES
pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
#endif
@@ -11429,7 +11547,7 @@
*channelmatched = 1;
}
- if (p->inalarm)
+ if (p->inalarm || p->tappingpeer)
return 0;
if (analog_lib_handles(p->sig, p->radio, p->oprmode))
@@ -15879,6 +15997,17 @@
#endif /* PRI_GETSET_TIMERS */
} else if (!strcasecmp(v->name, "facilityenable")) {
confp->pri.pri.facilityenable = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "tappingpeerpos")) {
+ if (!strcasecmp(v->name, "prev")) {
+ confp->pri.pri.tappingpeerpos = TAP_PEER_PREV;
+ } else if (!strcasecmp(v->name, "next")) {
+ confp->pri.pri.tappingpeerpos = TAP_PEER_NEXT;
+ } else {
+ confp->pri.pri.tappingpeerpos = TAP_PEER_NONE;
+ ast_log(LOG_ERROR, "'%s' is not a valid tappingpeerpos value at line %d. "
+ "(tappingpeerpos must be either 'prev' or 'next')\n",
+ v->value, v->lineno);
+ }
#endif /* HAVE_PRI */
#ifdef HAVE_SS7
} else if (!strcasecmp(v->name, "ss7type")) {
Modified: team/moy/dahdi-tap-trunk/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-trunk/channels/sig_pri.c?view=diff&rev=220585&r1=220584&r2=220585
==============================================================================
--- team/moy/dahdi-tap-trunk/channels/sig_pri.c (original)
+++ team/moy/dahdi-tap-trunk/channels/sig_pri.c Sat Sep 26 02:13:37 2009
@@ -1225,6 +1225,306 @@
break;
}
}
+}
+
+/* Not thread-safe, we assume nobody else is looking for a tap call slot at the same time in this pri */
+static struct dahdi_tapcall *pri_get_tap_call(struct sig_pri_pri *pri, void *callref)
+{
+ int i;
+ for (i = 0; i < ARRAY_LEN(pri->tapcalls); i++) {
+ if (callref == pri->tapcalls[i].callref) {
+ return &pri->tapcalls[i];
+ }
+ }
+ return NULL;
+}
+
+static struct dahdi_tapcall *pri_get_tap_call_by_crv(struct sig_pri_pri *pri, int crv)
+{
+ int i;
+ int tstcrv;
+ for (i = 0; i < ARRAY_LEN(pri->tapcalls); i++) {
+ tstcrv = pri->tapcalls[i].callref ? pri_get_crv(pri->pri, pri->tapcalls[i].callref, NULL) : 0;
+ if (pri->tapcalls[i].callref && tstcrv == crv) {
+ return &pri->tapcalls[i];
+ }
+ }
+ return NULL;
+}
+
+static void pri_put_pcall(struct sig_pri_pri *pri, void *callref)
+{
+ int i;
+ for (i = 0; i < ARRAY_LEN(pri->tapcalls); i++) {
+ if (callref == pri->tapcalls[i].callref) {
+ memset(&pri->tapcalls[i], 0, sizeof(pri->tapcalls[0]));
+ }
+ }
+}
+
+static void handle_pri_tapping_event(struct sig_pri_pri *pri, pri_event *e)
+{
+ int chanpos, peerpos, law, layer1, transcap;
+ struct dahdi_tapcall *tapcall = NULL;
+ struct ast_channel *c = NULL;
+ struct sig_pri_pri *peerpri = pri->tappingpeer;
+
+ if (!peerpri) {
+ ast_log(LOG_ERROR, "Ignoring tap PRI event on span %d, no peer span found!\n", pri->span);
+ return;
+ }
+
+ switch (e->e) {
+
+ case PRI_EVENT_RING:
+ ast_log(LOG_DEBUG, "Ring on channel %d of span %d with callref %d\n", e->ring.channel, pri->span, e->ring.cref);
+ /* we cannot use any pri->pvts data structure because we still dont know which channel will be used and therefore cant get
+ * chanpos (ie, flexible channel was requested), thus, we need our own list of call references */
+ tapcall = pri_get_tap_call(pri, NULL);
+ if (!tapcall) {
+ ast_log(LOG_ERROR, "Failed to get a free PRI tap call slot, this is a bug!\n");
+ break;
+ }
+ tapcall->callref = e->ring.call;
+ ast_copy_string(tapcall->callingnum, e->ring.callingnum, sizeof(tapcall->callingnum));
+ ast_copy_string(tapcall->callingani, e->ring.callingani, sizeof(tapcall->callingani));
+ ast_copy_string(tapcall->callingname, e->ring.callingname, sizeof(tapcall->callingname));
+ ast_copy_string(tapcall->callednum, e->ring.callednum, sizeof(tapcall->callednum));
+ break;
+
+ case PRI_EVENT_PROGRESS:
+ ast_log(LOG_DEBUG, "Progress on channel %d of span %d\n", e->proceeding.channel, pri->span);
+ break;
+
+ case PRI_EVENT_PROCEEDING:
+ ast_log(LOG_DEBUG, "Proceed on channel %d of span %d\n", e->proceeding.channel, pri->span);
+ /* at this point we should know the real b chan that will be used and can therefore proceed to setup the ast channels, but
+ * only if a couple of call tests are passed */
+
+ /* check that we already know about this call in the peer PRI (which was the one receiving the PRI_EVENT_RING event) */
+ if (!(tapcall = pri_get_tap_call_by_crv(peerpri, pri_get_crv(pri->pri, e->proceeding.call, NULL)))) {
+ ast_log(LOG_ERROR,
+ "BUG, we got proceeding in channel number %d/%d on span %d for call reference %d "
+ "but we never got PRI_EVENT_RING for that call on peer span %d?\n",
+ PRI_SPAN(e->proceeding.channel),
+ PRI_CHANNEL(e->proceeding.channel),
+ pri->span, e->proceeding.cref, peerpri->span);
+ break;
+ }
+ /* check that the layer 1 and trans capability are supported */
+ layer1 = pri_get_layer1(peerpri->pri, tapcall->callref);
+ transcap = pri_get_transcap(peerpri->pri, tapcall->callref);
+
+ if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) {
+ ast_log(LOG_NOTICE, "Not monitoring call with unsupported layer 1 format %d\n", layer1);
+ break;
+ }
+ if (transcap != PRI_TRANS_CAP_SPEECH) {
+ ast_log(LOG_NOTICE, "Not monitoring call with unsupported capability %d\n", transcap);
+ break;
+ }
+
+ /* check for valid channels in both the current span and the peer span */
+ chanpos = pri_find_principle(pri, e->proceeding.channel);
+ if (chanpos < 0) {
+ ast_log(LOG_ERROR, "Proceeding requested on odd/unavailable channel number %d/%d on span %d\n",
+ PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
+ break;
+ }
+
+ peerpos = pri_find_principle(peerpri, e->proceeding.channel);
+ if (peerpos < 0) {
+ ast_log(LOG_ERROR, "Proceeding requested on odd/unavailable peer channel number %d/%d on span %d\n",
+ PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
+ break;
+ }
+
+ /* save the call reference */
+ pri->pvts[chanpos]->call = e->proceeding.call;
+ peerpri->pvts[peerpos]->call = e->proceeding.call;
+
+ /* Set calling and callee information */
+ ast_copy_string(pri->pvts[chanpos]->cid_num, tapcall->callingnum, sizeof(pri->pvts[chanpos]->cid_num));
+ ast_shrink_phone_number(pri->pvts[chanpos]->cid_num);
+#ifdef PRI_ANI
+ if (!ast_strlen_zero(tapcall->callingani)) {
+ ast_copy_string(pri->pvts[chanpos]->cid_ani, tapcall->callingani, sizeof(pri->pvts[chanpos]->cid_ani));
+ ast_shrink_phone_number(pri->pvts[chanpos]->cid_ani);
+ } else {
+ pri->pvts[chanpos]->cid_ani[0] = '\0';
+ }
+#endif
+ ast_copy_string(pri->pvts[chanpos]->cid_name, tapcall->callingname, sizeof(pri->pvts[chanpos]->cid_name));
+
+ if (!ast_strlen_zero(tapcall->callednum)) {
+ ast_copy_string(pri->pvts[chanpos]->exten, tapcall->callednum, sizeof(pri->pvts[chanpos]->exten));
+ } else if (pri->overlapdial)
+ pri->pvts[chanpos]->exten[0] = '\0';
+ else {
+ /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
+ pri->pvts[chanpos]->exten[0] = 's';
+ pri->pvts[chanpos]->exten[1] = '\0';
+ }
+
+ /* set the tapping peers in both pri pvts */
+ peerpri->pvts[peerpos]->tappingpeer = pri->pvts[chanpos];
+ pri->pvts[chanpos]->tappingpeer = peerpri->pvts[peerpos];
+
+ /* create the actual ast_channel but dont start a pbx just yet */
+ law = layer1 == PRI_LAYER_1_ULAW ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW;
+ ast_mutex_unlock(&pri->lock);
+ c = sig_pri_new_ast_channel(pri->pvts[chanpos], AST_STATE_RING, 0, law, AST_TRANS_CAP_SPEECH, pri->pvts[chanpos]->exten, NULL);
+ ast_mutex_lock(&pri->lock);
+ if (!c) {
+ ast_log(LOG_ERROR, "Failed to create channel for PRI call on channel %d/%d on span %d\n",
+ PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
+ peerpri->pvts[peerpos]->tappingpeer = NULL;
+ pri->pvts[chanpos]->tappingpeer = NULL;
+ break;
+ }
+ /* the owner for the peer channel will be the same, both dahdi pvt structures will share the owner */
+ peerpri->pvts[peerpos]->owner = c;
+
+ /* from now on, reading from the conference has the mix of both tapped channels, we can now launch the pbx thread */
+ if (ast_pbx_start(c) != AST_PBX_SUCCESS) {
+ ast_log(LOG_ERROR, "Failed to launch PBX thread for passive channel %s\n", c->name);
+ ast_hangup(c);
+ }
+ break;
+
+ case PRI_EVENT_ANSWER:
+ ast_log(LOG_DEBUG, "Answer on channel %d of span %d\n", e->proceeding.channel, pri->span);
+
+ /* get the chan pos for the answered channel and check we have an owner already */
+ chanpos = pri_find_principle(pri, e->answer.channel);
+ if (chanpos < 0) {
+ ast_log(LOG_ERROR, "Answer requested on odd/unavailable channel number %d/%d on span %d\n",
+ PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+ break;
+ }
+
+ if (!pri->pvts[chanpos]->owner) {
+ /* this may be a valid condition if the user hangup the ast channel before the tapped line is answered */
+ ast_log(LOG_NOTICE, "Ignoring answer in tapped channel number %d/%d on span %d, no owner found\n",
+ PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+ break;
+ }
+
+ /* set the owner state as UP */
+ c = pri->pvts[chanpos]->owner;
+ ast_channel_lock(c);
+ if (c->_state == AST_STATE_RING) {
+ ast_setstate(c, AST_STATE_UP);
+ }
+ ast_channel_unlock(c);
+ break;
+
+ case PRI_EVENT_HANGUP:
+
+ ast_log(LOG_DEBUG, "Hangup on channel %d of span %d\n", e->hangup.channel, pri->span);
+ chanpos = pri_find_principle(pri, e->hangup.channel);
+ if (chanpos < 0) {
+ ast_log(LOG_ERROR, "Hangup requested on odd/unavailable channel number %d/%d on span %d\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ break;
+ }
+ /* first put back the passive call slot, if any was used, since
+ * regardless of whethere there is owner or not, this resource must be freed */
+ pri_put_pcall(pri, e->hangup.call);
+
+ if (!pri->pvts[chanpos]->owner) {
+ /* this may be a valid condition if the user hangup the ast channel before the tapped line is terminated */
+ ast_log(LOG_NOTICE, "Ignoring hangup in tapped channel number %d/%d on span %d, no owner found\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ break;
+ }
+ ast_queue_hangup(pri->pvts[chanpos]->owner);
+
+ chanpos = pri_find_principle(peerpri, e->hangup.channel);
+ if (chanpos < 0) {
+ ast_log(LOG_ERROR, "Hangup requested on odd/unavailable channel number %d/%d on peer span %d\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), peerpri->span);
+ break;
+ }
+
+ if (!peerpri->pvts[chanpos]->owner) {
+ /* invalid, since the owner is the same for both pvts, the owner should be here too */
+ ast_log(LOG_ERROR, "No owner on hangup in channel number %d/%d on peer span %d!!!??\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), peerpri->span);
+ break;
+ }
+ ast_queue_hangup(peerpri->pvts[chanpos]->owner);
+
+ break;
+
+ case PRI_EVENT_HANGUP_ACK:
+
+ ast_log(LOG_DEBUG, "Hangup ack on channel %d of span %d\n", e->hangup.channel, pri->span);
+ /* put back the passive call slot, if any was used */
+ pri_put_pcall(pri, e->hangup.call);
+ break;
+
+ default:
+ ast_log(LOG_NOTICE, "Ignoring passive event %s on span %d\n", pri_event2str(e->gen.e), pri->span);
+ break;
+ }
+}
+
+static void *pri_tapping_dchannel(void *vpri)
+{
+ struct sig_pri_pri *pri = vpri;
+ pri_event *e;
+ struct pollfd fds[NUM_DCHANS];
+ int res, i, numdchans, which;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+ for (;;) {
+ for (i = 0; i < NUM_DCHANS; i++) {
+ if (!pri->dchans[i])
+ break;
+ fds[i].fd = pri->fds[i];
+ fds[i].events = POLLIN | POLLPRI;
+ fds[i].revents = 0;
+ }
+ numdchans = i;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_testcancel();
+ e = NULL;
+ res = poll(fds, numdchans, -1);
+ pthread_testcancel();
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+ if (res == -1 && errno != EINTR) {
+ ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
+ break;
+ } else if (res == -1) {
+ ast_log(LOG_DEBUG, "pri_event got EINT, continuing ...\n");
+ continue;
+ }
+
+ ast_mutex_lock(&pri->lock);
+ for (which = 0; which < NUM_DCHANS; which++) {
+ if (!pri->dchans[which]) {
+ break;
+ }
+ if (fds[which].revents & POLLPRI) {
+ sig_pri_handle_dchan_exception(pri, which);
+ } else if (fds[which].revents & POLLIN) {
+ e = pri_read_event(pri->dchans[which]);
+ if (e && pri->debug) {
+ pri_dump_event(pri->dchans[which], e);
+ }
+ if (e) {
+ handle_pri_tapping_event(pri, e);
+ }
+ }
+ }
+ ast_mutex_unlock(&pri->lock);
+ }
+ ast_log(LOG_NOTICE, "Finishing tapping PRI loop for span %d\n", pri->span);
+ return NULL;
}
static void *pri_dchannel(void *vpri)
@@ -2407,6 +2707,10 @@
p->alerting = 0;
p->setup_ack = 0;
p->exten[0] = '\0';
+ if (p->tappingpeer) {
+ p->tappingpeer->tappingpeer = NULL;
+ p->tappingpeer = NULL;
+ }
sig_pri_set_dialing(p, 0);
if (!p->call) {
@@ -2998,7 +3302,7 @@
/* Assume primary is the one we use */
pri->pri = pri->dchans[0];
pri->resetpos = -1;
- if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
+ if (ast_pthread_create_background(&pri->master, NULL, pri->tappingpeer ? pri_tapping_dchannel : pri_dchannel, pri)) {
for (i = 0; i < NUM_DCHANS; i++) {
if (!pri->dchans[i])
break;
Modified: team/moy/dahdi-tap-trunk/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-trunk/channels/sig_pri.h?view=diff&rev=220585&r1=220584&r2=220585
==============================================================================
--- team/moy/dahdi-tap-trunk/channels/sig_pri.h (original)
+++ team/moy/dahdi-tap-trunk/channels/sig_pri.h Sat Sep 26 02:13:37 2009
@@ -116,6 +116,16 @@
static const char dahdi_db[] = "dahdi/registry";
#endif
+/* Passive call structure.
+ * As of now just valid for pri but eventually may be reused for other protocols with monitoring support */
+struct dahdi_tapcall {
+ void *callref;
+ char callingnum[AST_MAX_EXTENSION];
+ char callingani[AST_MAX_EXTENSION];
+ char callingname[AST_MAX_EXTENSION];
+ char callednum[AST_MAX_EXTENSION];
+};
+
struct sig_pri_chan {
/* Options to be set by user */
unsigned int hidecallerid:1;
@@ -170,6 +180,7 @@
#if defined(HAVE_PRI_REVERSE_CHARGE)
int reverse_charging_indication;
#endif
+ struct sig_pri_chan *tappingpeer; /*!< Peer tapping pri chan structure */
};
struct sig_pri_pri {
@@ -222,6 +233,10 @@
ast_mutex_t lock; /*!< libpri access Mutex */
time_t lastreset; /*!< time when unused channels were last reset */
struct sig_pri_callback *calls;
+ /* TODO: allocate this structures on demand only when the pri is flagged as passive */
+ struct dahdi_tapcall tapcalls[MAX_CHANNELS]; /*!< Tap calls if any. */
+ struct sig_pri_pri *tappingpeer; /*!< Peer PRI tapping structure. */
+ int tappingpeerpos; /*!< Relative tapping peer position. */
};
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1);
More information about the asterisk-commits
mailing list