freetdm: make pri tapping actually work - missing audio mix
This commit is contained in:
parent
b485f25f5e
commit
46e9704b04
|
@ -35,10 +35,24 @@
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include "private/ftdm_core.h"
|
#include "private/ftdm_core.h"
|
||||||
|
|
||||||
|
#define PRI_SPAN(p) (((p) >> 8) & 0xff)
|
||||||
|
#define PRI_CHANNEL(p) ((p) & 0xff)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PRITAP_RUNNING = (1 << 0),
|
PRITAP_RUNNING = (1 << 0),
|
||||||
} pritap_flags_t;
|
} pritap_flags_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *callref;
|
||||||
|
ftdm_number_t callingnum;
|
||||||
|
ftdm_number_t callingani;
|
||||||
|
ftdm_number_t callednum;
|
||||||
|
ftdm_channel_t *fchan;
|
||||||
|
char callingname[80];
|
||||||
|
int proceeding:1;
|
||||||
|
int inuse:1;
|
||||||
|
} passive_call_t;
|
||||||
|
|
||||||
typedef struct pritap {
|
typedef struct pritap {
|
||||||
int32_t flags;
|
int32_t flags;
|
||||||
struct pri *pri;
|
struct pri *pri;
|
||||||
|
@ -46,7 +60,8 @@ typedef struct pritap {
|
||||||
ftdm_channel_t *dchan;
|
ftdm_channel_t *dchan;
|
||||||
ftdm_span_t *span;
|
ftdm_span_t *span;
|
||||||
ftdm_span_t *peerspan;
|
ftdm_span_t *peerspan;
|
||||||
struct pritap *pritap;
|
ftdm_mutex_t *pcalls_lock;
|
||||||
|
passive_call_t pcalls[FTDM_MAX_CHANNELS_PHYSICAL_SPAN];
|
||||||
} pritap_t;
|
} pritap_t;
|
||||||
|
|
||||||
static FIO_IO_UNLOAD_FUNCTION(ftdm_pritap_unload)
|
static FIO_IO_UNLOAD_FUNCTION(ftdm_pritap_unload)
|
||||||
|
@ -219,21 +234,26 @@ static ftdm_state_map_t pritap_state_map = {
|
||||||
{
|
{
|
||||||
ZSD_INBOUND,
|
ZSD_INBOUND,
|
||||||
ZSM_UNACCEPTABLE,
|
ZSM_UNACCEPTABLE,
|
||||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
|
||||||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ZSD_INBOUND,
|
ZSD_INBOUND,
|
||||||
ZSM_UNACCEPTABLE,
|
ZSM_UNACCEPTABLE,
|
||||||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
|
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ZSD_INBOUND,
|
ZSD_INBOUND,
|
||||||
ZSM_UNACCEPTABLE,
|
ZSM_UNACCEPTABLE,
|
||||||
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
|
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
|
||||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
|
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||||
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
},
|
||||||
|
{
|
||||||
|
ZSD_INBOUND,
|
||||||
|
ZSM_UNACCEPTABLE,
|
||||||
|
{FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
|
||||||
|
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ZSD_INBOUND,
|
ZSD_INBOUND,
|
||||||
|
@ -242,19 +262,16 @@ static ftdm_state_map_t pritap_state_map = {
|
||||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||||
{
|
{
|
||||||
pritap_t *pritap = ftdmchan->span->signal_data;
|
|
||||||
ftdm_status_t status;
|
ftdm_status_t status;
|
||||||
ftdm_sigmsg_t sig;
|
ftdm_sigmsg_t sig;
|
||||||
q931_call *call = (q931_call *) ftdmchan->call_data;
|
ftdm_channel_t *peerchan = ftdmchan->call_data;
|
||||||
|
|
||||||
|
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state));
|
||||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
|
|
||||||
|
|
||||||
memset(&sig, 0, sizeof(sig));
|
memset(&sig, 0, sizeof(sig));
|
||||||
sig.chan_id = ftdmchan->chan_id;
|
sig.chan_id = ftdmchan->chan_id;
|
||||||
|
@ -264,26 +281,22 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||||
switch (ftdmchan->state) {
|
switch (ftdmchan->state) {
|
||||||
case FTDM_CHANNEL_STATE_DOWN:
|
case FTDM_CHANNEL_STATE_DOWN:
|
||||||
{
|
{
|
||||||
ftdmchan->call_data = NULL;
|
|
||||||
ftdm_channel_done(ftdmchan);
|
ftdm_channel_done(ftdmchan);
|
||||||
|
ftdmchan->call_data = NULL;
|
||||||
|
|
||||||
|
ftdm_channel_done(peerchan);
|
||||||
|
peerchan->call_data = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||||
{
|
|
||||||
pri_progress(pritap->pri, call, ftdmchan->chan_id, 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||||
{
|
case FTDM_CHANNEL_STATE_UP:
|
||||||
pri_proceeding(pritap->pri, call, ftdmchan->chan_id, 1);
|
case FTDM_CHANNEL_STATE_HANGUP:
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_RING:
|
case FTDM_CHANNEL_STATE_RING:
|
||||||
{
|
{
|
||||||
pri_acknowledge(pritap->pri, call, ftdmchan->chan_id, 0);
|
|
||||||
sig.event_id = FTDM_SIGEVENT_START;
|
sig.event_id = FTDM_SIGEVENT_START;
|
||||||
if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
|
if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
|
||||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
||||||
|
@ -291,34 +304,15 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_UP:
|
|
||||||
{
|
|
||||||
pri_answer(pritap->pri, call, 0, 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_HANGUP:
|
|
||||||
{
|
|
||||||
if (call) {
|
|
||||||
pri_hangup(pritap->pri, call, ftdmchan->caller_data.hangup_cause);
|
|
||||||
pri_destroycall(pritap->pri, call);
|
|
||||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
|
||||||
} else {
|
|
||||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FTDM_CHANNEL_STATE_TERMINATING:
|
case FTDM_CHANNEL_STATE_TERMINATING:
|
||||||
{
|
{
|
||||||
sig.event_id = FTDM_SIGEVENT_STOP;
|
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) {
|
||||||
status = ftdm_span_send_signal(ftdmchan->span, &sig);
|
sig.event_id = FTDM_SIGEVENT_STOP;
|
||||||
|
status = ftdm_span_send_signal(ftdmchan->span, &sig);
|
||||||
|
}
|
||||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -385,28 +379,277 @@ static int pri_io_write(struct pri *pri, void *buf, int buflen)
|
||||||
return (int)buflen;
|
return (int)buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tap_pri_get_crv(struct pri *ctrl, q931_call *call)
|
||||||
|
{
|
||||||
|
int callmode = 0;
|
||||||
|
int crv = pri_get_crv(ctrl, call, &callmode);
|
||||||
|
crv <<= 3;
|
||||||
|
crv |= (callmode & 0x7);
|
||||||
|
return crv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static passive_call_t *tap_pri_get_pcall_bycrv(pritap_t *pritap, int crv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int tstcrv;
|
||||||
|
|
||||||
|
ftdm_mutex_lock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
|
||||||
|
tstcrv = pritap->pcalls[i].callref ? tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref) : 0;
|
||||||
|
if (pritap->pcalls[i].callref && tstcrv == crv) {
|
||||||
|
if (!pritap->pcalls[i].inuse) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Found crv %d in slot %d of span %s with call %p but is no longer in use!\n",
|
||||||
|
crv, i, pritap->span->name, pritap->pcalls[i].callref);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_unlock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
return &pritap->pcalls[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_unlock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static passive_call_t *tap_pri_get_pcall(pritap_t *pritap, void *callref)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int crv;
|
||||||
|
|
||||||
|
ftdm_mutex_lock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
|
||||||
|
if (pritap->pcalls[i].callref && !pritap->pcalls[i].inuse) {
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref);
|
||||||
|
/* garbage collection */
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Garbage collecting callref %d/%p from span %s in slot %d\n",
|
||||||
|
crv, pritap->pcalls[i].callref, pritap->span->name, i);
|
||||||
|
pri_passive_destroycall(pritap->pri, pritap->pcalls[i].callref);
|
||||||
|
memset(&pritap->pcalls[i], 0, sizeof(pritap->pcalls[0]));
|
||||||
|
}
|
||||||
|
if (callref == pritap->pcalls[i].callref) {
|
||||||
|
pritap->pcalls[i].inuse = 1;
|
||||||
|
|
||||||
|
ftdm_mutex_unlock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
return &pritap->pcalls[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_unlock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tap_pri_put_pcall(pritap_t *pritap, void *callref)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int crv;
|
||||||
|
int tstcrv;
|
||||||
|
|
||||||
|
if (!callref) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Cannot put pcall for null callref in span %s\n", pritap->span->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_lock(pritap->pcalls_lock);
|
||||||
|
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, callref);
|
||||||
|
for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
|
||||||
|
if (!pritap->pcalls[i].callref) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tstcrv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref);
|
||||||
|
if (tstcrv == crv) {
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "releasing slot %d in span %s used by callref %d/%p\n", i,
|
||||||
|
pritap->span->name, crv, pritap->pcalls[i].callref);
|
||||||
|
if (!pritap->pcalls[i].inuse) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "slot %d in span %s used by callref %d/%p was released already?\n",
|
||||||
|
i, pritap->span->name, crv, pritap->pcalls[i].callref);
|
||||||
|
}
|
||||||
|
pritap->pcalls[i].inuse = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_unlock(pritap->pcalls_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ ftdm_channel_t *tap_pri_get_fchan(pritap_t *pritap, passive_call_t *pcall, int channel)
|
||||||
|
{
|
||||||
|
ftdm_channel_t *fchan = NULL;
|
||||||
|
int chanpos = PRI_CHANNEL(channel);
|
||||||
|
if (!chanpos || chanpos > pritap->span->chan_count) {
|
||||||
|
ftdm_log(FTDM_LOG_CRIT, "Invalid pri tap channel %d requested in span %s\n", channel, pritap->span->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fchan = pritap->span->channels[PRI_CHANNEL(channel)];
|
||||||
|
if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Channel %d requested in span %s is already in use!\n", channel, pritap->span->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftdm_channel_open_chan(fchan) != FTDM_SUCCESS) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Could not open tap channel %d requested in span %s\n", channel, pritap->span->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&fchan->caller_data, 0, sizeof(fchan->caller_data));
|
||||||
|
|
||||||
|
ftdm_set_string(fchan->caller_data.cid_num.digits, pcall->callingnum.digits);
|
||||||
|
if (!ftdm_strlen_zero(pcall->callingname)) {
|
||||||
|
ftdm_set_string(fchan->caller_data.cid_name, pcall->callingname);
|
||||||
|
} else {
|
||||||
|
ftdm_set_string(fchan->caller_data.cid_name, pcall->callingnum.digits);
|
||||||
|
}
|
||||||
|
ftdm_set_string(fchan->caller_data.ani.digits, pcall->callingani.digits);
|
||||||
|
ftdm_set_string(fchan->caller_data.dnis.digits, pcall->callednum.digits);
|
||||||
|
|
||||||
|
return fchan;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
|
static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
|
||||||
{
|
{
|
||||||
ftdm_log(FTDM_LOG_NOTICE, "passive event %s on span %s\n", pri_event2str(e->gen.e), pritap->span->name);
|
passive_call_t *pcall = NULL;
|
||||||
|
passive_call_t *peerpcall = NULL;
|
||||||
|
ftdm_channel_t *fchan = NULL;
|
||||||
|
ftdm_channel_t *peerfchan = NULL;
|
||||||
|
int layer1, transcap = 0;
|
||||||
|
int crv = 0;
|
||||||
|
pritap_t *peertap = pritap->peerspan->signal_data;
|
||||||
|
|
||||||
switch (e->e) {
|
switch (e->e) {
|
||||||
|
|
||||||
case PRI_EVENT_RING:
|
case PRI_EVENT_RING:
|
||||||
|
/* we cannot use ftdm_channel_t because we still dont know which channel will be used
|
||||||
|
* (ie, flexible channel was requested), thus, we need our own list of call references */
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->ring.call);
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Ring on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), crv);
|
||||||
|
pcall = tap_pri_get_pcall_bycrv(pritap, crv);
|
||||||
|
if (pcall) {
|
||||||
|
ftdm_log(FTDM_LOG_WARNING, "There is a call with callref %d already, ignoring duplicated ring event\n", crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pcall = tap_pri_get_pcall(pritap, NULL);
|
||||||
|
if (!pcall) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to get a free passive PRI call slot for callref %d, this is a bug!\n", crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pcall->callref = e->ring.call;
|
||||||
|
ftdm_set_string(pcall->callingnum.digits, e->ring.callingnum);
|
||||||
|
ftdm_set_string(pcall->callingani.digits, e->ring.callingani);
|
||||||
|
ftdm_set_string(pcall->callednum.digits, e->ring.callednum);
|
||||||
|
ftdm_set_string(pcall->callingname, e->ring.callingname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EVENT_PROGRESS:
|
case PRI_EVENT_PROGRESS:
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->ring.call);
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EVENT_PROCEEDING:
|
case PRI_EVENT_PROCEEDING:
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
|
||||||
|
/* at this point we should know the real b chan that will be used and can therefore proceed to notify about the call, but
|
||||||
|
* only if a couple of call tests are passed first */
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Proceeding on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
|
||||||
|
/* check that we already know about this call in the peer PRI (which was the one receiving the PRI_EVENT_RING event) */
|
||||||
|
if (!(pcall = tap_pri_get_pcall_bycrv(peertap, crv))) {
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG,
|
||||||
|
"ignoring proceeding in channel %s:%d:%d for callref %d since we don't know about it",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pcall->proceeding) {
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Ignoring duplicated proceeding with callref %d\n", crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
peerpcall = tap_pri_get_pcall(pritap, NULL);
|
||||||
|
if (!peerpcall) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to get a free peer PRI passive call slot for callref %d in span %s, this is a bug!\n",
|
||||||
|
crv, pritap->span->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
peerpcall->callref = e->proceeding.call;
|
||||||
|
|
||||||
|
/* check that the layer 1 and trans capability are supported */
|
||||||
|
layer1 = pri_get_layer1(peertap->pri, pcall->callref);
|
||||||
|
transcap = pri_get_transcap(peertap->pri, pcall->callref);
|
||||||
|
|
||||||
|
if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) {
|
||||||
|
ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported layer 1 format %d\n", crv, layer1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transcap != PRI_TRANS_CAP_SPEECH && transcap != PRI_TRANS_CAP_3_1K_AUDIO && transcap != PRI_TRANS_CAP_7K_AUDIO) {
|
||||||
|
ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported capability %d\n", crv, transcap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fchan = tap_pri_get_fchan(pritap, pcall, e->proceeding.channel);
|
||||||
|
if (!fchan) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pcall->fchan = fchan;
|
||||||
|
|
||||||
|
peerfchan = tap_pri_get_fchan(peertap, pcall, e->proceeding.channel);
|
||||||
|
if (!peerfchan) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
|
||||||
|
peertap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
peerpcall->fchan = fchan;
|
||||||
|
|
||||||
|
fchan->call_data = peerfchan;
|
||||||
|
peerfchan->call_data = fchan;
|
||||||
|
|
||||||
|
ftdm_set_state_locked(fchan, FTDM_CHANNEL_STATE_RING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EVENT_ANSWER:
|
case PRI_EVENT_ANSWER:
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->answer.call);
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Answer on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
|
||||||
|
if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG,
|
||||||
|
"ignoring answer in channel %s:%d:%d for callref %d since we don't know about it",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ftdm_log_chan(pcall->fchan, FTDM_LOG_NOTICE, "Tapped call was answered in state %s\n", ftdm_channel_state2str(pcall->fchan->state));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EVENT_HANGUP:
|
case PRI_EVENT_HANGUP_REQ:
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->hangup.call);
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Hangup on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
|
||||||
|
|
||||||
|
if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG,
|
||||||
|
"ignoring hangup in channel %s:%d:%d for callref %d since we don't know about it",
|
||||||
|
pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fchan = pcall->fchan;
|
||||||
|
ftdm_set_state_locked(fchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EVENT_HANGUP_ACK:
|
case PRI_EVENT_HANGUP_ACK:
|
||||||
|
crv = tap_pri_get_crv(pritap->pri, e->hangup.call);
|
||||||
|
ftdm_log(FTDM_LOG_DEBUG, "Hangup ack on channel %s:%d:%d with callref %d\n",
|
||||||
|
pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
|
||||||
|
tap_pri_put_pcall(pritap, e->hangup.call);
|
||||||
|
tap_pri_put_pcall(peertap, e->hangup.call);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -502,6 +745,7 @@ static ftdm_status_t ftdm_pritap_stop(ftdm_span_t *span)
|
||||||
ftdm_sleep(100);
|
ftdm_sleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_destroy(&pritap->pcalls_lock);
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +758,8 @@ static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span)
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftdm_mutex_create(&pritap->pcalls_lock);
|
||||||
|
|
||||||
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
|
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
|
||||||
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue