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 "private/ftdm_core.h"
|
||||
|
||||
#define PRI_SPAN(p) (((p) >> 8) & 0xff)
|
||||
#define PRI_CHANNEL(p) ((p) & 0xff)
|
||||
|
||||
typedef enum {
|
||||
PRITAP_RUNNING = (1 << 0),
|
||||
} 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 {
|
||||
int32_t flags;
|
||||
struct pri *pri;
|
||||
|
@ -46,7 +60,8 @@ typedef struct pritap {
|
|||
ftdm_channel_t *dchan;
|
||||
ftdm_span_t *span;
|
||||
ftdm_span_t *peerspan;
|
||||
struct pritap *pritap;
|
||||
ftdm_mutex_t *pcalls_lock;
|
||||
passive_call_t pcalls[FTDM_MAX_CHANNELS_PHYSICAL_SPAN];
|
||||
} pritap_t;
|
||||
|
||||
static FIO_IO_UNLOAD_FUNCTION(ftdm_pritap_unload)
|
||||
|
@ -219,21 +234,26 @@ static ftdm_state_map_t pritap_state_map = {
|
|||
{
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_DOWN, FTDM_END},
|
||||
},
|
||||
{
|
||||
ZSD_INBOUND,
|
||||
ZSM_UNACCEPTABLE,
|
||||
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
|
||||
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
|
||||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 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,
|
||||
|
@ -242,19 +262,16 @@ static ftdm_state_map_t pritap_state_map = {
|
|||
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
pritap_t *pritap = ftdmchan->span->signal_data;
|
||||
ftdm_status_t status;
|
||||
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", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
sig.chan_id = ftdmchan->chan_id;
|
||||
|
@ -264,26 +281,22 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
|||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
{
|
||||
ftdmchan->call_data = NULL;
|
||||
ftdm_channel_done(ftdmchan);
|
||||
ftdmchan->call_data = NULL;
|
||||
|
||||
ftdm_channel_done(peerchan);
|
||||
peerchan->call_data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
{
|
||||
pri_progress(pritap->pri, call, ftdmchan->chan_id, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
{
|
||||
pri_proceeding(pritap->pri, call, ftdmchan->chan_id, 1);
|
||||
}
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
case FTDM_CHANNEL_STATE_HANGUP:
|
||||
break;
|
||||
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
{
|
||||
pri_acknowledge(pritap->pri, call, ftdmchan->chan_id, 0);
|
||||
sig.event_id = FTDM_SIGEVENT_START;
|
||||
if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
||||
|
@ -291,34 +304,15 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
|
|||
}
|
||||
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:
|
||||
{
|
||||
sig.event_id = FTDM_SIGEVENT_STOP;
|
||||
status = ftdm_span_send_signal(ftdmchan->span, &sig);
|
||||
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) {
|
||||
sig.event_id = FTDM_SIGEVENT_STOP;
|
||||
status = ftdm_span_send_signal(ftdmchan->span, &sig);
|
||||
}
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -385,28 +379,277 @@ static int pri_io_write(struct pri *pri, void *buf, 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)
|
||||
{
|
||||
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) {
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
|
@ -502,6 +745,7 @@ static ftdm_status_t ftdm_pritap_stop(ftdm_span_t *span)
|
|||
ftdm_sleep(100);
|
||||
}
|
||||
|
||||
ftdm_mutex_destroy(&pritap->pcalls_lock);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -514,6 +758,8 @@ static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span)
|
|||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
ftdm_mutex_create(&pritap->pcalls_lock);
|
||||
|
||||
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
|
||||
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
||||
|
||||
|
|
Loading…
Reference in New Issue