mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-11 14:51:53 +00:00
Merge branch 'master' into v1.4.beta
This commit is contained in:
@@ -719,14 +719,14 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
|
||||
name = switch_channel_get_name(channel);
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
|
||||
chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
|
||||
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
@@ -760,7 +760,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -768,7 +768,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk);
|
||||
|
||||
if (status == FTDM_FAIL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -776,7 +776,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) {
|
||||
total_to -= chunk;
|
||||
if (total_to <= 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -789,9 +789,9 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
|
||||
len = tech_pvt->read_frame.buflen;
|
||||
if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@@ -812,7 +812,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
for (p = dtmf; p && *p; p++) {
|
||||
if (is_dtmf(*p)) {
|
||||
_dtmf.digit = *p;
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id);
|
||||
switch_channel_queue_dtmf(channel, &_dtmf);
|
||||
}
|
||||
}
|
||||
@@ -821,7 +821,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
@@ -844,7 +844,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
|
||||
name = switch_channel_get_name(channel);
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
@@ -852,7 +852,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
}
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -879,15 +879,15 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10);
|
||||
|
||||
if (!(wflags & FTDM_WRITE)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Dropping frame! (write not ready) in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
len = frame->datalen;
|
||||
if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG,
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel),
|
||||
SWITCH_LOG_ERROR, "Too many I/O write errors on channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
@@ -898,7 +898,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
@@ -1239,7 +1239,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t
|
||||
tech_init(hdata->tech_pvt, hdata->new_session, fchan, caller_data);
|
||||
|
||||
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
|
||||
switch_channel_set_name(channel, name);
|
||||
switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan));
|
||||
switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
|
||||
@@ -1267,7 +1267,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t
|
||||
return FTDM_BREAK;
|
||||
}
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2294,7 +2294,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
|
||||
case FTDM_SIGEVENT_COLLECTED_DIGIT: /* Analog E&M */
|
||||
{
|
||||
int span_id = ftdm_channel_get_span_id(sigmsg->channel);
|
||||
@@ -2336,6 +2335,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
|
||||
/* span signaling status changed ... nothing to do here .. */
|
||||
break;
|
||||
default:
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
struct tm * localtime_r(const time_t *clock, struct tm *result);
|
||||
#endif
|
||||
|
||||
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status);
|
||||
|
||||
/* check if the given file is a wave file and skip the header if it is */
|
||||
#define WAVE_CHUNK_ID "RIFF"
|
||||
#define WAVE_FMT "WAVEfmt "
|
||||
@@ -196,6 +198,23 @@ static ftdm_status_t ftdm_analog_em_start(ftdm_span_t *span)
|
||||
return ftdm_thread_create_detached(ftdm_analog_em_run, span);
|
||||
}
|
||||
|
||||
static void ftdm_analog_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
|
||||
{
|
||||
ftdm_sigmsg_t sig;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
sig.chan_id = ftdmchan->chan_id;
|
||||
sig.span_id = ftdmchan->span_id;
|
||||
sig.channel = ftdmchan;
|
||||
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
|
||||
sig.ev_data.sigstatus.status = status;
|
||||
if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Stops EM span thread (monitor)
|
||||
* \param span Span to monitor
|
||||
@@ -206,6 +225,7 @@ static ftdm_status_t ftdm_analog_em_stop(ftdm_span_t *span)
|
||||
ftdm_analog_em_data_t *analog_data = span->signal_data;
|
||||
ftdm_clear_flag(analog_data, FTDM_ANALOG_EM_RUNNING);
|
||||
ftdm_sleep(100);
|
||||
analog_em_set_span_sig_status(span, FTDM_SIG_STATE_SUSPENDED);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -215,10 +235,16 @@ static ftdm_status_t ftdm_analog_em_stop(ftdm_span_t *span)
|
||||
* \param status Pointer to set signalling status
|
||||
* \return Success or failure
|
||||
*/
|
||||
|
||||
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status)
|
||||
{
|
||||
ftdm_unused_arg(ftdmchan);
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
*status = FTDM_SIG_STATE_DOWN;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
|
||||
*status = FTDM_SIG_STATE_SUSPENDED;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
*status = FTDM_SIG_STATE_UP;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
@@ -229,11 +255,82 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status)
|
||||
* \param status Pointer to set signalling status
|
||||
* \return Success or failure
|
||||
*/
|
||||
|
||||
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status)
|
||||
{
|
||||
ftdm_unused_arg(span);
|
||||
*status = FTDM_SIG_STATE_UP;
|
||||
ftdm_iterator_t *citer = NULL;
|
||||
ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||
if (!chaniter) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
/* if ALL channels are in alarm, report DOWN, UP otherwise. */
|
||||
*status = FTDM_SIG_STATE_DOWN;
|
||||
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
|
||||
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
|
||||
ftdm_channel_lock(fchan);
|
||||
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
|
||||
*status = FTDM_SIG_STATE_UP;
|
||||
ftdm_channel_unlock(fchan);
|
||||
break;
|
||||
} else {
|
||||
*status = FTDM_SIG_STATE_SUSPENDED;
|
||||
}
|
||||
}
|
||||
ftdm_channel_unlock(fchan);
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
|
||||
{
|
||||
switch (status) {
|
||||
case FTDM_SIG_STATE_DOWN:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot bring channel down, perhaps you want to try '%s'\n", ftdm_signaling_status2str(FTDM_SIG_STATE_SUSPENDED));
|
||||
return FTDM_FAIL;
|
||||
case FTDM_SIG_STATE_SUSPENDED:
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
|
||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
|
||||
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
|
||||
}
|
||||
break;
|
||||
case FTDM_SIG_STATE_UP:
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
|
||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status)
|
||||
{
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *citer = NULL;
|
||||
|
||||
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||
if (!chaniter) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
/* iterate over all channels, setting them to the requested state */
|
||||
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
|
||||
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
|
||||
/* we set channel's state through analog_em_set_channel_sig_status(), since it already takes care of notifying the user when appropriate */
|
||||
ftdm_channel_lock(fchan);
|
||||
if ((analog_em_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
|
||||
}
|
||||
ftdm_channel_unlock(fchan);
|
||||
}
|
||||
ftdm_iterator_free(chaniter);
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -334,6 +431,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
|
||||
span->outgoing_call = analog_em_outgoing_call;
|
||||
span->get_channel_sig_status = analog_em_get_channel_sig_status;
|
||||
span->get_span_sig_status = analog_em_get_span_sig_status;
|
||||
span->set_channel_sig_status = analog_em_set_channel_sig_status;
|
||||
span->set_span_sig_status = analog_em_set_span_sig_status;
|
||||
ftdm_span_load_tones(span, tonemap);
|
||||
if (immediate_ringback || !ftdm_strlen_zero(ringback_file)) {
|
||||
analog_data->immediate_ringback = FTDM_TRUE;
|
||||
@@ -384,7 +483,9 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_sigmsg_t sig;
|
||||
int cas_bits = 0;
|
||||
uint32_t cas_answer = 0;
|
||||
uint32_t cas_hangup = 0;
|
||||
int cas_answer_ms = 500;
|
||||
int cas_hangup_ms = 500;
|
||||
FILE *ringback_f = NULL;
|
||||
ftdm_bool_t digits_sent = FTDM_FALSE;
|
||||
|
||||
@@ -542,6 +643,23 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
{
|
||||
ftdm_sleep(interval);
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_UP && cas_answer) {
|
||||
cas_bits = 0;
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits);
|
||||
if (!(state_counter % 5000)) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "CAS bits: 0x%X\n", cas_bits);
|
||||
}
|
||||
if (cas_bits == 0x0) {
|
||||
cas_hangup += interval;
|
||||
if (cas_hangup >= cas_hangup_ms) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Hanging up on CAS hangup signal persistence\n");
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
||||
}
|
||||
} else if (cas_hangup) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Resetting cas hangup to 0: 0x%X!\n", cas_bits);
|
||||
cas_hangup = 0;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -859,6 +977,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
|
||||
ftdm_mutex_lock(event->channel->mutex);
|
||||
locked++;
|
||||
|
||||
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_SUSPENDED)) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Ignoring event %s on channel %d:%d in state %s, channel is suspended\n",
|
||||
ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch(event->enum_id) {
|
||||
case FTDM_OOB_ONHOOK:
|
||||
{
|
||||
@@ -893,6 +1017,9 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (locked) {
|
||||
ftdm_mutex_unlock(event->channel->mutex);
|
||||
}
|
||||
@@ -911,6 +1038,7 @@ static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj)
|
||||
|
||||
ftdm_unused_arg(me);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM thread starting.\n");
|
||||
analog_em_set_span_sig_status(span, FTDM_SIG_STATE_UP);
|
||||
|
||||
while(ftdm_running() && ftdm_test_flag(analog_data, FTDM_ANALOG_EM_RUNNING)) {
|
||||
int waitms = 10;
|
||||
|
||||
@@ -1 +1 @@
|
||||
Tue Oct 22 16:25:25 CDT 2013
|
||||
Fri Oct 25 23:51:29 CDT 2013
|
||||
|
||||
@@ -2094,6 +2094,10 @@ void tport_close(tport_t *self)
|
||||
SU_DEBUG_5(("%s(%p): " TPN_FORMAT "\n",
|
||||
__func__, (void *)self, TPN_ARGS(self->tp_name)));
|
||||
|
||||
if (self->tp_refs == -1) {
|
||||
self->tp_refs = 0;
|
||||
}
|
||||
|
||||
if (self->tp_closed || !tport_is_secondary(self))
|
||||
return;
|
||||
|
||||
|
||||
@@ -324,9 +324,11 @@ AX_CHECK_EXPORT_CAPABILITY([$host],
|
||||
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
AC_CACHE_CHECK([whether compiler supports -Wunused-but-set-variable], [ac_cv_gcc_unused_but_set_variable], [
|
||||
CFLAGS="$CFLAGS -Wunused-but-set-variable"
|
||||
AC_TRY_COMPILE([],[return 0;],[ac_cv_gcc_unused_but_set_variable=yes],[ac_cv_gcc_unused_but_set_variable=no])
|
||||
])
|
||||
# We need to add -Werror here or clang doesn't fail (it just warns), even though it doesn't understand the
|
||||
# -Wunused-but-set-variable tag
|
||||
CFLAGS="$CFLAGS -Werror -Wunused-but-set-variable"
|
||||
AC_TRY_COMPILE([],[return 0;],[ac_cv_gcc_unused_but_set_variable=yes],[ac_cv_gcc_unused_but_set_variable=no])
|
||||
])
|
||||
AC_MSG_RESULT($ac_cv_gcc_unused_but_set_variable)
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int
|
||||
" emms;\n"
|
||||
: "=a" (z)
|
||||
: "S" (x), "D" (y), "a" (n)
|
||||
: "cc"
|
||||
: "cc", "rdx", "mm0", "mm1", "mm2"
|
||||
);
|
||||
#elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
|
||||
__asm__ __volatile__(
|
||||
@@ -245,7 +245,7 @@ SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int
|
||||
" emms;\n"
|
||||
: "=a" (z)
|
||||
: "S" (x), "D" (y), "a" (n)
|
||||
: "cc"
|
||||
: "cc", "edx", "mm0", "mm1", "mm2"
|
||||
);
|
||||
#else
|
||||
int i;
|
||||
@@ -436,7 +436,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
|
||||
" emms;\n"
|
||||
: "=a" (max)
|
||||
: "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
|
||||
: "ecx"
|
||||
: "ecx", "mm0", "mm1", "mm2", "mm3", "mm4"
|
||||
);
|
||||
#elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
|
||||
static const int32_t lower_bound = 0x80008000;
|
||||
@@ -589,7 +589,7 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
|
||||
" emms;\n"
|
||||
: "=a" (max)
|
||||
: "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
|
||||
: "ecx"
|
||||
: "ecx", "mm0", "mm1", "mm2", "mm3", "mm4"
|
||||
);
|
||||
#else
|
||||
int i;
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef struct profile_node_s {
|
||||
switch_memory_pool_t *pool;
|
||||
struct switch_caller_profile *next;
|
||||
switch_call_direction_t direction;
|
||||
switch_call_direction_t logical_direction;
|
||||
profile_node_t *soft;
|
||||
char *uuid_str;
|
||||
char *clone_of;
|
||||
|
||||
@@ -633,6 +633,7 @@ SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *app, switch_cha
|
||||
SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel);
|
||||
SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel);
|
||||
SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel);
|
||||
SWITCH_DECLARE(switch_call_direction_t) switch_channel_logical_direction(switch_channel_t *channel);
|
||||
SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction);
|
||||
|
||||
SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel);
|
||||
|
||||
@@ -82,18 +82,34 @@ typedef struct device_uuid_node_s {
|
||||
switch_channel_callstate_t callstate;
|
||||
switch_hold_record_t *hold_record;
|
||||
switch_caller_profile_t *hup_profile;
|
||||
switch_call_direction_t direction;
|
||||
struct switch_device_record_s *parent;
|
||||
struct device_uuid_node_s *next;
|
||||
} switch_device_node_t;
|
||||
|
||||
typedef struct switch_device_stats_s {
|
||||
uint32_t total;
|
||||
uint32_t total_in;
|
||||
uint32_t total_out;
|
||||
uint32_t offhook;
|
||||
uint32_t offhook_in;
|
||||
uint32_t offhook_out;
|
||||
uint32_t active;
|
||||
uint32_t active_in;
|
||||
uint32_t active_out;
|
||||
uint32_t held;
|
||||
uint32_t held_in;
|
||||
uint32_t held_out;
|
||||
uint32_t hup;
|
||||
uint32_t hup_in;
|
||||
uint32_t hup_out;
|
||||
uint32_t ringing;
|
||||
uint32_t ringing_in;
|
||||
uint32_t ringing_out;
|
||||
uint32_t early;
|
||||
uint32_t early_in;
|
||||
uint32_t early_out;
|
||||
uint32_t ring_wait;
|
||||
} switch_device_stats_t;
|
||||
|
||||
|
||||
@@ -102,15 +118,22 @@ typedef struct switch_device_record_s {
|
||||
char *uuid;
|
||||
int refs;
|
||||
switch_device_stats_t stats;
|
||||
switch_device_stats_t last_stats;
|
||||
switch_device_state_t state;
|
||||
switch_device_state_t last_state;
|
||||
switch_time_t active_start;
|
||||
switch_time_t active_stop;
|
||||
switch_time_t last_call_time;
|
||||
switch_time_t ring_start;
|
||||
switch_time_t ring_stop;
|
||||
switch_time_t hold_start;
|
||||
switch_time_t hold_stop;
|
||||
switch_time_t call_start;
|
||||
struct device_uuid_node_s *uuid_list;
|
||||
struct device_uuid_node_s *uuid_tail;
|
||||
switch_mutex_t *mutex;
|
||||
switch_memory_pool_t *pool;
|
||||
void *user_data;
|
||||
} switch_device_record_t;
|
||||
|
||||
typedef void(*switch_device_state_function_t)(switch_core_session_t *session, switch_channel_callstate_t callstate, switch_device_record_t *drec);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
* Bret McDanel <trixter AT 0xdecafbad dot com>
|
||||
* Joseph Sullivan <jossulli@amazon.com>
|
||||
* Raymond Chandler <intralanman@freeswitch.org>
|
||||
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
|
||||
*
|
||||
* switch_types.h -- Data Types
|
||||
*
|
||||
@@ -666,6 +667,7 @@ typedef enum {
|
||||
SWITCH_RTP_FLAG_RTCP_MUX,
|
||||
SWITCH_RTP_FLAG_KILL_JB,
|
||||
SWITCH_RTP_FLAG_VIDEO_BREAK,
|
||||
SWITCH_RTP_FLAG_PAUSE,
|
||||
SWITCH_RTP_FLAG_INVALID
|
||||
} switch_rtp_flag_t;
|
||||
|
||||
@@ -968,6 +970,7 @@ typedef enum {
|
||||
SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE,
|
||||
SWITCH_MESSAGE_INDICATE_STUN_ERROR,
|
||||
SWITCH_MESSAGE_INDICATE_MEDIA_RENEG,
|
||||
SWITCH_MESSAGE_REFER_EVENT,
|
||||
SWITCH_MESSAGE_ANSWER_EVENT,
|
||||
SWITCH_MESSAGE_PROGRESS_EVENT,
|
||||
SWITCH_MESSAGE_RING_EVENT,
|
||||
@@ -1137,6 +1140,7 @@ typedef enum {
|
||||
CCS_EARLY,
|
||||
CCS_ACTIVE,
|
||||
CCS_HELD,
|
||||
CCS_RING_WAIT,
|
||||
CCS_HANGUP,
|
||||
CCS_UNHOLD
|
||||
} switch_channel_callstate_t;
|
||||
|
||||
@@ -37,11 +37,17 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if UINTPTR_MAX == 0xffffffffffffffff
|
||||
#define _fs__bits "64bit"
|
||||
#else
|
||||
#define _fs__bits "32bit"
|
||||
#endif
|
||||
|
||||
#define SWITCH_VERSION_MAJOR "@SWITCH_VERSION_MAJOR@"
|
||||
#define SWITCH_VERSION_MINOR "@SWITCH_VERSION_MINOR@"
|
||||
#define SWITCH_VERSION_MICRO "@SWITCH_VERSION_MICRO@"
|
||||
#define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@"
|
||||
#define SWITCH_VERSION_REVISION_HUMAN "@SWITCH_VERSION_REVISION_HUMAN@"
|
||||
#define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@" "~" _fs__bits
|
||||
#define SWITCH_VERSION_REVISION_HUMAN "@SWITCH_VERSION_REVISION_HUMAN@" " " _fs__bits
|
||||
#define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION
|
||||
#define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " " SWITCH_VERSION_REVISION_HUMAN
|
||||
|
||||
|
||||
@@ -6085,9 +6085,257 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_JSON_API(json_channel_data_function)
|
||||
{
|
||||
cJSON *reply, *data = cJSON_GetObjectItem(json, "data");
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
const char *uuid = cJSON_GetObjectCstr(data, "uuid");
|
||||
switch_core_session_t *tsession;
|
||||
|
||||
|
||||
reply = cJSON_CreateObject();
|
||||
*json_reply = reply;
|
||||
|
||||
if (zstr(uuid)) {
|
||||
cJSON_AddItemToObject(reply, "response", cJSON_CreateString("INVALID INPUT"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if ((tsession = switch_core_session_locate(uuid))) {
|
||||
cJSON *jevent;
|
||||
|
||||
if (switch_ivr_generate_json_cdr(tsession, &jevent, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
|
||||
cJSON_AddItemToObject(reply, "channelData", jevent);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(tsession);
|
||||
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
cJSON_AddItemToObject(reply, "response", cJSON_CreateString("Session does not exist"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_JSON_API(json_execute_function)
|
||||
{
|
||||
cJSON *reply, *data = cJSON_GetObjectItem(json, "data");
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
const char *uuid = cJSON_GetObjectCstr(data, "uuid");
|
||||
const char *app = cJSON_GetObjectCstr(data, "app");
|
||||
const char *arg = cJSON_GetObjectCstr(data, "arg");
|
||||
const char *einline = cJSON_GetObjectCstr(data, "inline");
|
||||
const char *edata = cJSON_GetObjectCstr(data, "extendedData");
|
||||
switch_core_session_t *tsession;
|
||||
|
||||
|
||||
reply = cJSON_CreateObject();
|
||||
*json_reply = reply;
|
||||
|
||||
if (!(uuid && app)) {
|
||||
cJSON_AddItemToObject(reply, "response", cJSON_CreateString("INVALID INPUT"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if ((tsession = switch_core_session_locate(uuid))) {
|
||||
if (switch_true(edata)) {
|
||||
cJSON *jevent = NULL;
|
||||
|
||||
if (switch_ivr_generate_json_cdr(tsession, &jevent, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
|
||||
cJSON_AddItemToObject(reply, "channelData", jevent);
|
||||
}
|
||||
} else {
|
||||
cJSON_AddItemToObject(reply, "channelName", cJSON_CreateString(switch_core_session_get_name(tsession)));
|
||||
}
|
||||
|
||||
if (switch_true(einline)) {
|
||||
switch_core_session_execute_application(tsession, app, arg);
|
||||
} else {
|
||||
switch_core_session_execute_application_async(tsession, app, arg);
|
||||
}
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
switch_core_session_rwunlock(tsession);
|
||||
|
||||
} else {
|
||||
cJSON_AddItemToObject(reply, "response", cJSON_CreateString("Session does not exist"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
end:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_JSON_API(json_api_function)
|
||||
{
|
||||
cJSON *data, *cmd, *arg, *reply;
|
||||
switch_stream_handle_t stream = { 0 };
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
data = cJSON_GetObjectItem(json, "data");
|
||||
|
||||
cmd = cJSON_GetObjectItem(data, "cmd");
|
||||
arg = cJSON_GetObjectItem(data, "arg");
|
||||
|
||||
if (cmd && !cmd->valuestring) {
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
if (arg && !arg->valuestring) {
|
||||
arg = NULL;
|
||||
}
|
||||
|
||||
reply = cJSON_CreateObject();
|
||||
|
||||
SWITCH_STANDARD_STREAM(stream);
|
||||
|
||||
if (cmd && (status = switch_api_execute(cmd->valuestring, arg ? arg->valuestring : NULL, session, &stream)) == SWITCH_STATUS_SUCCESS) {
|
||||
cJSON_AddItemToObject(reply, "message", cJSON_CreateString((char *) stream.data));
|
||||
} else {
|
||||
cJSON_AddItemToObject(reply, "message", cJSON_CreateString("INVALID CALL"));
|
||||
}
|
||||
|
||||
switch_safe_free(stream.data);
|
||||
|
||||
*json_reply = reply;
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
#include <switch_version.h>
|
||||
SWITCH_STANDARD_JSON_API(json_status_function)
|
||||
{
|
||||
cJSON *o, *oo, *reply = cJSON_CreateObject();
|
||||
switch_core_time_duration_t duration = { 0 };
|
||||
int sps = 0, last_sps = 0, max_sps = 0, max_sps_fivemin = 0;
|
||||
int sessions_peak = 0, sessions_peak_fivemin = 0; /* Max Concurrent Sessions buffers */
|
||||
switch_size_t cur = 0, max = 0;
|
||||
|
||||
switch_core_measure_time(switch_core_uptime(), &duration);
|
||||
|
||||
switch_core_session_ctl(SCSC_SESSIONS_PEAK, &sessions_peak);
|
||||
switch_core_session_ctl(SCSC_SESSIONS_PEAK_FIVEMIN, &sessions_peak_fivemin);
|
||||
switch_core_session_ctl(SCSC_LAST_SPS, &last_sps);
|
||||
switch_core_session_ctl(SCSC_SPS, &sps);
|
||||
switch_core_session_ctl(SCSC_SPS_PEAK, &max_sps);
|
||||
switch_core_session_ctl(SCSC_SPS_PEAK_FIVEMIN, &max_sps_fivemin);
|
||||
|
||||
cJSON_AddItemToObject(reply, "systemStatus", cJSON_CreateString(switch_core_ready() ? "ready" : "not ready"));
|
||||
|
||||
o = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(o, "years", cJSON_CreateNumber(duration.yr));
|
||||
cJSON_AddItemToObject(o, "days", cJSON_CreateNumber(duration.day));
|
||||
cJSON_AddItemToObject(o, "hours", cJSON_CreateNumber(duration.hr));
|
||||
cJSON_AddItemToObject(o, "minutes", cJSON_CreateNumber(duration.min));
|
||||
cJSON_AddItemToObject(o, "seconds", cJSON_CreateNumber(duration.sec));
|
||||
cJSON_AddItemToObject(o, "milliseconds", cJSON_CreateNumber(duration.ms));
|
||||
cJSON_AddItemToObject(o, "microseconds", cJSON_CreateNumber(duration.mms));
|
||||
|
||||
cJSON_AddItemToObject(reply, "uptime", o);
|
||||
cJSON_AddItemToObject(reply, "version", cJSON_CreateString(SWITCH_VERSION_FULL_HUMAN));
|
||||
|
||||
o = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(reply, "sessions", o);
|
||||
|
||||
oo = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(o, "count", oo);
|
||||
|
||||
cJSON_AddItemToObject(oo, "total", cJSON_CreateNumber(switch_core_session_id() - 1));
|
||||
cJSON_AddItemToObject(oo, "active", cJSON_CreateNumber(switch_core_session_count()));
|
||||
cJSON_AddItemToObject(oo, "peak", cJSON_CreateNumber(sessions_peak));
|
||||
cJSON_AddItemToObject(oo, "peak5Min", cJSON_CreateNumber(sessions_peak_fivemin));
|
||||
cJSON_AddItemToObject(oo, "limit", cJSON_CreateNumber(switch_core_session_limit(0)));
|
||||
|
||||
|
||||
|
||||
oo = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(o, "rate", oo);
|
||||
cJSON_AddItemToObject(oo, "current", cJSON_CreateNumber(last_sps));
|
||||
cJSON_AddItemToObject(oo, "max", cJSON_CreateNumber(sps));
|
||||
cJSON_AddItemToObject(oo, "peak", cJSON_CreateNumber(max_sps));
|
||||
cJSON_AddItemToObject(oo, "peak5Min", cJSON_CreateNumber(max_sps_fivemin));
|
||||
|
||||
|
||||
o = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(reply, "idleCPU", o);
|
||||
|
||||
cJSON_AddItemToObject(o, "used", cJSON_CreateNumber(switch_core_min_idle_cpu(-1.0)));
|
||||
cJSON_AddItemToObject(o, "allowed", cJSON_CreateNumber(switch_core_idle_cpu()));
|
||||
|
||||
|
||||
if (switch_core_get_stacksizes(&cur, &max) == SWITCH_STATUS_SUCCESS) {
|
||||
o = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(reply, "stackSizeKB", o);
|
||||
|
||||
cJSON_AddItemToObject(o, "current", cJSON_CreateNumber(cur / 1024));
|
||||
cJSON_AddItemToObject(o, "max", cJSON_CreateNumber(max / 1024));
|
||||
}
|
||||
|
||||
|
||||
*json_reply = reply;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(json_function)
|
||||
{
|
||||
cJSON *jcmd = NULL, *format = NULL;
|
||||
const char *message = "";
|
||||
char *response = NULL;
|
||||
|
||||
if (zstr(cmd)) {
|
||||
message = "No JSON supplied.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
jcmd = cJSON_Parse(cmd);
|
||||
|
||||
if (!jcmd) {
|
||||
message = "Parse error.";
|
||||
goto err;
|
||||
}
|
||||
|
||||
format = cJSON_GetObjectItem(jcmd, "format");
|
||||
|
||||
switch_json_api_execute(jcmd, session, NULL);
|
||||
|
||||
|
||||
if (format && format->valuestring && !strcasecmp(format->valuestring, "pretty")) {
|
||||
response = cJSON_Print(jcmd);
|
||||
} else {
|
||||
response = cJSON_PrintUnformatted(jcmd);
|
||||
}
|
||||
|
||||
stream->write_function(stream, "%s\n", switch_str_nil(response));
|
||||
|
||||
switch_safe_free(response);
|
||||
|
||||
cJSON_Delete(jcmd);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
|
||||
stream->write_function(stream, "-ERR %s\n", message);
|
||||
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
{
|
||||
switch_api_interface_t *commands_api_interface;
|
||||
switch_json_api_interface_t *json_api_interface;
|
||||
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
switch_thread_rwlock_create(&bgapi_rwlock, pool);
|
||||
@@ -6219,6 +6467,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
SWITCH_ADD_API(commands_api_interface, "xml_locate", "Find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
|
||||
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
|
||||
SWITCH_ADD_API(commands_api_interface, "file_exists", "Check if a file exists on server", file_exists_function, "<file>");
|
||||
SWITCH_ADD_API(commands_api_interface, "json", "JSON API", json_function, "JSON");
|
||||
|
||||
|
||||
SWITCH_ADD_JSON_API(json_api_interface, "status", "JSON status API", json_status_function, "");
|
||||
SWITCH_ADD_JSON_API(json_api_interface, "fsapi", "JSON FSAPI Gateway", json_api_function, "");
|
||||
SWITCH_ADD_JSON_API(json_api_interface, "execute", "JSON session execute application", json_execute_function, "");
|
||||
SWITCH_ADD_JSON_API(json_api_interface, "channelData", "JSON channel data application", json_channel_data_function, "");
|
||||
|
||||
|
||||
|
||||
switch_console_set_complete("add alias add");
|
||||
switch_console_set_complete("add alias del");
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
* Joao Mesquita <jmesquita@gmail.com>
|
||||
* Raymond Chandler <intralanman@freeswitch.org>
|
||||
* Seven Du <dujinfang@gmail.com>
|
||||
* Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
|
||||
*
|
||||
* mod_conference.c -- Software Conference Bridge
|
||||
*
|
||||
@@ -100,6 +101,7 @@ static struct {
|
||||
uint32_t id_pool;
|
||||
int32_t running;
|
||||
uint32_t threads;
|
||||
switch_event_channel_id_t event_channel_id;
|
||||
} globals;
|
||||
|
||||
/* forward declaration for conference_obj and caller_control */
|
||||
@@ -115,6 +117,7 @@ typedef struct conference_cdr_node_s {
|
||||
uint32_t flags;
|
||||
uint32_t id;
|
||||
conference_member_t *member;
|
||||
switch_event_t *var_event;
|
||||
struct conference_cdr_node_s *next;
|
||||
} conference_cdr_node_t;
|
||||
|
||||
@@ -204,7 +207,9 @@ typedef enum {
|
||||
CFLAG_ENDCONF_FORCED = (1 << 16),
|
||||
CFLAG_RFC4579 = (1 << 17),
|
||||
CFLAG_FLOOR_CHANGE = (1 << 18),
|
||||
CFLAG_VID_FLOOR_LOCK = (1 << 19)
|
||||
CFLAG_VID_FLOOR_LOCK = (1 << 19),
|
||||
CFLAG_JSON_EVENTS = (1 << 20),
|
||||
CFLAG_LIVEARRAY_SYNC = (1 << 21)
|
||||
} conf_flag_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -300,6 +305,8 @@ typedef struct conference_record {
|
||||
/* Conference Object */
|
||||
typedef struct conference_obj {
|
||||
char *name;
|
||||
char *la_name;
|
||||
char *la_event_channel;
|
||||
char *desc;
|
||||
char *timer_name;
|
||||
char *tts_engine;
|
||||
@@ -338,6 +345,7 @@ typedef struct conference_obj {
|
||||
char *domain;
|
||||
char *caller_controls;
|
||||
char *moderator_controls;
|
||||
switch_live_array_t *la;
|
||||
uint32_t flags;
|
||||
member_flag_t mflags;
|
||||
switch_call_cause_t bridge_hangup_cause;
|
||||
@@ -466,6 +474,8 @@ struct conference_member {
|
||||
char *kicked_sound;
|
||||
switch_queue_t *dtmf_queue;
|
||||
switch_thread_t *input_thread;
|
||||
cJSON *json;
|
||||
cJSON *status_field;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -564,6 +574,9 @@ static switch_status_t conf_api_sub_clear_vid_floor(conference_obj_t *conference
|
||||
|
||||
static void conference_cdr_del(conference_member_t *member)
|
||||
{
|
||||
if (member->channel) {
|
||||
switch_channel_get_variables(member->channel, &member->cdr_node->var_event);
|
||||
}
|
||||
member->cdr_node->leave_time = switch_epoch_time_now(NULL);
|
||||
member->cdr_node->flags = member->flags;
|
||||
member->cdr_node->member = NULL;
|
||||
@@ -1086,6 +1099,218 @@ static void conference_cdr_render(conference_obj_t *conference)
|
||||
switch_xml_free(cdr);
|
||||
}
|
||||
|
||||
static cJSON *conference_json_render(conference_obj_t *conference, cJSON *req)
|
||||
{
|
||||
char tmp[30];
|
||||
const char *domain; const char *name;
|
||||
char *dup_domain = NULL;
|
||||
char *uri;
|
||||
conference_cdr_node_t *np;
|
||||
char *tmpp = tmp;
|
||||
cJSON *json = cJSON_CreateObject(), *jusers = NULL, *jold_users = NULL, *juser = NULL, *jvars = NULL;
|
||||
|
||||
switch_assert(json);
|
||||
|
||||
switch_mutex_lock(conference->mutex);
|
||||
switch_snprintf(tmp, sizeof(tmp), "%u", conference->doc_version);
|
||||
conference->doc_version++;
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
|
||||
if (!(name = conference->name)) {
|
||||
name = "conference";
|
||||
}
|
||||
|
||||
if (!(domain = conference->domain)) {
|
||||
dup_domain = switch_core_get_domain(SWITCH_TRUE);
|
||||
if (!(domain = dup_domain)) {
|
||||
domain = "cluecon.com";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uri = switch_mprintf("%s@%s", name, domain);
|
||||
json_add_child_string(json, "entity", uri);
|
||||
json_add_child_string(json, "conferenceDescription", conference->desc ? conference->desc : "FreeSWITCH Conference");
|
||||
json_add_child_string(json, "conferenceState", "active");
|
||||
switch_snprintf(tmp, sizeof(tmp), "%u", conference->count);
|
||||
json_add_child_string(json, "userCount", tmp);
|
||||
|
||||
jusers = json_add_child_array(json, "users");
|
||||
jold_users = json_add_child_array(json, "oldUsers");
|
||||
|
||||
switch_mutex_lock(conference->member_mutex);
|
||||
|
||||
for (np = conference->cdr_nodes; np; np = np->next) {
|
||||
char *user_uri = NULL;
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_time_exp_t tm;
|
||||
switch_size_t retsize;
|
||||
const char *fmt = "%Y-%m-%dT%H:%M:%S%z";
|
||||
char *p;
|
||||
|
||||
if (np->record_path || !np->cp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (!np->cp || (np->member && !np->member->session) || np->leave_time) { /* for now we'll remove participants when they leave */
|
||||
//continue;
|
||||
//}
|
||||
|
||||
if (np->member && np->member->session) {
|
||||
channel = switch_core_session_get_channel(np->member->session);
|
||||
}
|
||||
|
||||
juser = cJSON_CreateObject();
|
||||
|
||||
if (channel) {
|
||||
const char *uri = switch_channel_get_variable_dup(channel, "conference_invite_uri", SWITCH_FALSE, -1);
|
||||
|
||||
if (uri) {
|
||||
user_uri = strdup(uri);
|
||||
}
|
||||
}
|
||||
|
||||
if (np->cp) {
|
||||
|
||||
if (!user_uri) {
|
||||
user_uri = switch_mprintf("%s@%s", np->cp->caller_id_number, domain);
|
||||
}
|
||||
|
||||
json_add_child_string(juser, "entity", user_uri);
|
||||
json_add_child_string(juser, "displayText", np->cp->caller_id_name);
|
||||
}
|
||||
|
||||
//if (np->record_path) {
|
||||
//json_add_child_string(juser, "recordingPATH", np->record_path);
|
||||
//}
|
||||
|
||||
json_add_child_string(juser, "status", np->leave_time ? "disconnected" : "connected");
|
||||
|
||||
switch_time_exp_lt(&tm, (switch_time_t) conference->start_time * 1000000);
|
||||
switch_strftime_nocheck(tmp, &retsize, sizeof(tmp), fmt, &tm);
|
||||
p = end_of_p(tmpp) -1;
|
||||
snprintf(p, 4, ":00");
|
||||
|
||||
json_add_child_string(juser, "joinTime", tmpp);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%u", np->id);
|
||||
json_add_child_string(juser, "memberId", tmp);
|
||||
|
||||
jvars = cJSON_CreateObject();
|
||||
|
||||
if (!np->member && np->var_event) {
|
||||
switch_json_add_presence_data_cols(np->var_event, jvars, "PD-");
|
||||
} else if (np->member) {
|
||||
const char *var;
|
||||
const char *prefix = NULL;
|
||||
switch_event_t *var_event = NULL;
|
||||
switch_event_header_t *hp;
|
||||
int all = 0;
|
||||
|
||||
switch_channel_get_variables(channel, &var_event);
|
||||
|
||||
if ((prefix = switch_event_get_header(var_event, "json_conf_var_prefix"))) {
|
||||
all = strcasecmp(prefix, "__all__");
|
||||
} else {
|
||||
prefix = "json_";
|
||||
}
|
||||
|
||||
for(hp = var_event->headers; hp; hp = hp->next) {
|
||||
if (all || !strncasecmp(hp->name, prefix, strlen(prefix))) {
|
||||
json_add_child_string(jvars, hp->name, hp->value);
|
||||
}
|
||||
}
|
||||
|
||||
switch_json_add_presence_data_cols(var_event, jvars, "PD-");
|
||||
|
||||
switch_event_destroy(&var_event);
|
||||
|
||||
if ((var = switch_channel_get_variable(channel, "rtp_use_ssrc"))) {
|
||||
json_add_child_string(juser, "rtpAudioSSRC", var);
|
||||
}
|
||||
|
||||
json_add_child_string(juser, "rtpAudioDirection", switch_channel_test_flag(channel, CF_HOLD) ? "sendonly" : "sendrecv");
|
||||
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
||||
if ((var = switch_channel_get_variable(channel, "rtp_use_video_ssrc"))) {
|
||||
json_add_child_string(juser, "rtpVideoSSRC", var);
|
||||
}
|
||||
|
||||
json_add_child_string(juser, "rtpVideoDirection", switch_channel_test_flag(channel, CF_HOLD) ? "sendonly" : "sendrecv");
|
||||
}
|
||||
}
|
||||
|
||||
if (jvars) {
|
||||
json_add_child_obj(juser, "variables", jvars);
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray(np->leave_time ? jold_users : jusers, juser);
|
||||
|
||||
switch_safe_free(user_uri);
|
||||
}
|
||||
|
||||
switch_mutex_unlock(conference->member_mutex);
|
||||
|
||||
switch_safe_free(dup_domain);
|
||||
switch_safe_free(uri);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static void conference_la_event_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id)
|
||||
{
|
||||
switch_live_array_parse_json(json, globals.event_channel_id);
|
||||
}
|
||||
|
||||
static void conference_event_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id)
|
||||
{
|
||||
char *domain = NULL, *name = NULL;
|
||||
conference_obj_t *conference = NULL;
|
||||
cJSON *data, *reply = NULL, *conf_desc = NULL;
|
||||
const char *action = NULL;
|
||||
|
||||
if ((data = cJSON_GetObjectItem(json, "data"))) {
|
||||
action = cJSON_GetObjectCstr(data, "action");
|
||||
}
|
||||
|
||||
if (!action) action = "";
|
||||
|
||||
reply = cJSON_Duplicate(json, 1);
|
||||
cJSON_DeleteItemFromObject(reply, "data");
|
||||
|
||||
if ((name = strchr(event_channel, '.'))) {
|
||||
char *tmp = strdup(name + 1);
|
||||
switch_assert(tmp);
|
||||
name = tmp;
|
||||
|
||||
if ((domain = strchr(name, '@'))) {
|
||||
*domain++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(action, "bootstrap")) {
|
||||
if (!zstr(name) && (conference = conference_find(name, domain))) {
|
||||
conf_desc = conference_json_render(conference, json);
|
||||
} else {
|
||||
conf_desc = cJSON_CreateObject();
|
||||
json_add_child_string(conf_desc, "conferenceDescription", "FreeSWITCH Conference");
|
||||
json_add_child_string(conf_desc, "conferenceState", "inactive");
|
||||
json_add_child_array(conf_desc, "users");
|
||||
json_add_child_array(conf_desc, "oldUsers");
|
||||
}
|
||||
} else {
|
||||
conf_desc = cJSON_CreateObject();
|
||||
json_add_child_string(conf_desc, "error", "Invalid action");
|
||||
}
|
||||
|
||||
json_add_child_string(conf_desc, "action", "conferenceDescription");
|
||||
|
||||
cJSON_AddItemToObject(reply, "data", conf_desc);
|
||||
|
||||
switch_event_channel_broadcast(event_channel, &reply, modname, globals.event_channel_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t conference_add_event_data(conference_obj_t *conference, switch_event_t *event)
|
||||
@@ -1340,6 +1565,42 @@ static switch_status_t member_del_relationship(conference_member_t *member, uint
|
||||
return status;
|
||||
}
|
||||
|
||||
static void send_json_event(conference_obj_t *conference)
|
||||
{
|
||||
cJSON *event, *conf_desc = NULL;
|
||||
char *name = NULL, *domain = NULL, *dup_domain = NULL;
|
||||
char *event_channel = NULL;
|
||||
|
||||
if (!switch_test_flag(conference, CFLAG_JSON_EVENTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
conf_desc = conference_json_render(conference, NULL);
|
||||
|
||||
if (!(name = conference->name)) {
|
||||
name = "conference";
|
||||
}
|
||||
|
||||
if (!(domain = conference->domain)) {
|
||||
dup_domain = switch_core_get_domain(SWITCH_TRUE);
|
||||
if (!(domain = dup_domain)) {
|
||||
domain = "cluecon.com";
|
||||
}
|
||||
}
|
||||
|
||||
event_channel = switch_mprintf("conference.%q@%q", name, domain);
|
||||
|
||||
event = cJSON_CreateObject();
|
||||
|
||||
json_add_child_string(event, "eventChannel", event_channel);
|
||||
cJSON_AddItemToObject(event, "data", conf_desc);
|
||||
|
||||
switch_event_channel_broadcast(event_channel, &event, modname, globals.event_channel_id);
|
||||
|
||||
switch_safe_free(dup_domain);
|
||||
switch_safe_free(event_channel);
|
||||
}
|
||||
|
||||
static void send_rfc_event(conference_obj_t *conference)
|
||||
{
|
||||
switch_event_t *event;
|
||||
@@ -1422,6 +1683,73 @@ static void send_conference_notify(conference_obj_t *conference, const char *sta
|
||||
|
||||
}
|
||||
|
||||
static void member_update_status_field(conference_member_t *member)
|
||||
{
|
||||
char *str, *vstr = "", display[128] = "";
|
||||
|
||||
if (!member->conference->la) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch_live_array_lock(member->conference->la);
|
||||
|
||||
if (!switch_test_flag(member, MFLAG_CAN_SPEAK)) {
|
||||
str = "MUTE";
|
||||
} else if (switch_channel_test_flag(member->channel, CF_HOLD)) {
|
||||
str = "HOLD";
|
||||
} else if (member == member->conference->floor_holder) {
|
||||
if (switch_test_flag(member, MFLAG_TALKING)) {
|
||||
str = "TALKING (FLOOR)";
|
||||
} else {
|
||||
str = "FLOOR";
|
||||
}
|
||||
} else if (switch_test_flag(member, MFLAG_TALKING)) {
|
||||
str = "TALKING";
|
||||
} else {
|
||||
str = "ACTIVE";
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(member->channel, CF_VIDEO)) {
|
||||
vstr = " VIDEO";
|
||||
if (member == member->conference->video_floor_holder) {
|
||||
vstr = " VIDEO (FLOOR)";
|
||||
}
|
||||
}
|
||||
|
||||
switch_snprintf(display, sizeof(display), "%s%s", str, vstr);
|
||||
|
||||
|
||||
free(member->status_field->valuestring);
|
||||
member->status_field->valuestring = strdup(display);
|
||||
|
||||
switch_live_array_add(member->conference->la, switch_core_session_get_uuid(member->session), -1, &member->json, SWITCH_FALSE);
|
||||
switch_live_array_unlock(member->conference->la);
|
||||
}
|
||||
|
||||
static void adv_la(conference_obj_t *conference, conference_member_t *member, switch_bool_t join)
|
||||
{
|
||||
if (conference && conference->la && member->session) {
|
||||
cJSON *msg, *data;
|
||||
const char *uuid = switch_core_session_get_uuid(member->session);
|
||||
const char *cookie = switch_channel_get_variable(member->channel, "event_channel_cookie");
|
||||
|
||||
msg = cJSON_CreateObject();
|
||||
data = json_add_child_obj(msg, "pvtData", NULL);
|
||||
|
||||
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(uuid));
|
||||
cJSON_AddItemToObject(msg, "eventType", cJSON_CreateString("channelPvtData"));
|
||||
|
||||
cJSON_AddItemToObject(data, "action", cJSON_CreateString(join ? "conference-liveArray-join" : "conference-liveArray-part"));
|
||||
cJSON_AddItemToObject(data, "laChannel", cJSON_CreateString(conference->la_event_channel));
|
||||
cJSON_AddItemToObject(data, "laName", cJSON_CreateString(conference->la_name));
|
||||
|
||||
if (cookie) {
|
||||
switch_event_channel_permission_modify(cookie, conference->la_event_channel, join);
|
||||
}
|
||||
|
||||
switch_event_channel_broadcast(uuid, &msg, modname, globals.event_channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gain exclusive access and add the member to the list */
|
||||
static switch_status_t conference_add_member(conference_obj_t *conference, conference_member_t *member)
|
||||
@@ -1585,7 +1913,29 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
switch_mutex_unlock(member->audio_in_mutex);
|
||||
|
||||
if (conference->la && member->channel) {
|
||||
member->json = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(member->json, cJSON_CreateStringPrintf("%0.4d", member->id));
|
||||
cJSON_AddItemToArray(member->json, cJSON_CreateString(switch_channel_get_variable(member->channel, "caller_id_number")));
|
||||
cJSON_AddItemToArray(member->json, cJSON_CreateString(switch_channel_get_variable(member->channel, "caller_id_name")));
|
||||
|
||||
cJSON_AddItemToArray(member->json, cJSON_CreateStringPrintf("%s@%s",
|
||||
switch_channel_get_variable(member->channel, "original_read_codec"),
|
||||
switch_channel_get_variable(member->channel, "original_read_rate")
|
||||
));
|
||||
|
||||
member->status_field = cJSON_CreateString("");
|
||||
cJSON_AddItemToArray(member->json, member->status_field);
|
||||
member_update_status_field(member);
|
||||
//switch_live_array_add_alias(conference->la, switch_core_session_get_uuid(member->session), "conference");
|
||||
adv_la(conference, member, SWITCH_TRUE);
|
||||
switch_live_array_add(conference->la, switch_core_session_get_uuid(member->session), -1, &member->json, SWITCH_FALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
send_rfc_event(conference);
|
||||
send_json_event(conference);
|
||||
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
@@ -1637,12 +1987,14 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf
|
||||
//switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
|
||||
switch_core_session_refresh_video(member->session);
|
||||
conference->video_floor_holder = member;
|
||||
member_update_status_field(member);
|
||||
} else {
|
||||
conference->video_floor_holder = NULL;
|
||||
}
|
||||
|
||||
if (old_member) {
|
||||
old_id = old_member->id;
|
||||
member_update_status_field(old_member);
|
||||
//switch_channel_clear_flag(old_member->channel, CF_VIDEO_PASSIVE);
|
||||
}
|
||||
|
||||
@@ -1714,6 +2066,7 @@ static void conference_set_floor_holder(conference_obj_t *conference, conference
|
||||
switch_channel_get_name(member->channel));
|
||||
|
||||
conference->floor_holder = member;
|
||||
member_update_status_field(member);
|
||||
} else {
|
||||
conference->floor_holder = NULL;
|
||||
}
|
||||
@@ -1721,6 +2074,7 @@ static void conference_set_floor_holder(conference_obj_t *conference, conference
|
||||
|
||||
if (old_member) {
|
||||
old_id = old_member->id;
|
||||
member_update_status_field(old_member);
|
||||
}
|
||||
|
||||
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
|
||||
@@ -1881,8 +2235,14 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
||||
switch_mutex_unlock(member->audio_in_mutex);
|
||||
|
||||
|
||||
if (conference->la && member->session) {
|
||||
switch_live_array_del(conference->la, switch_core_session_get_uuid(member->session));
|
||||
//switch_live_array_clear_alias(conference->la, switch_core_session_get_uuid(member->session), "conference");
|
||||
adv_la(conference, member, SWITCH_FALSE);
|
||||
}
|
||||
|
||||
send_rfc_event(conference);
|
||||
|
||||
send_json_event(conference);
|
||||
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
@@ -2062,6 +2422,11 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void conference_command_handler(switch_live_array_t *la, const char *cmd, const char *sessid, cJSON *jla, void *user_data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Main monitor thread (1 per distinct conference room) */
|
||||
static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
@@ -2079,6 +2444,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
int32_t z = 0;
|
||||
int member_score_sum = 0;
|
||||
int divisor = 0;
|
||||
conference_cdr_node_t *np;
|
||||
|
||||
if (!(divisor = conference->rate / 8000)) {
|
||||
divisor = 1;
|
||||
@@ -2108,6 +2474,26 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "conference-create");
|
||||
switch_event_fire(&event);
|
||||
|
||||
if (switch_test_flag(conference, CFLAG_LIVEARRAY_SYNC)) {
|
||||
char *p;
|
||||
|
||||
if (strchr(conference->name, '@')) {
|
||||
conference->la_event_channel = switch_core_sprintf(conference->pool, "conference-liveArray.%s", conference->name);
|
||||
} else {
|
||||
conference->la_event_channel = switch_core_sprintf(conference->pool, "conference-liveArray.%s@%s", conference->name, conference->domain);
|
||||
}
|
||||
|
||||
conference->la_name = switch_core_strdup(conference->pool, conference->name);
|
||||
if ((p = strchr(conference->la_name, '@'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
switch_live_array_create(conference->la_event_channel, conference->la_name, globals.event_channel_id, &conference->la);
|
||||
switch_live_array_set_user_data(conference->la, conference);
|
||||
switch_live_array_set_command_handler(conference->la, conference_command_handler);
|
||||
}
|
||||
|
||||
|
||||
while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
switch_size_t file_sample_len = samples;
|
||||
switch_size_t file_data_len = samples * 2;
|
||||
@@ -2505,6 +2891,14 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
switch_mutex_lock(conference->mutex);
|
||||
conference_stop_file(conference, FILE_STOP_ASYNC);
|
||||
conference_stop_file(conference, FILE_STOP_ALL);
|
||||
|
||||
for (np = conference->cdr_nodes; np; np = np->next) {
|
||||
if (np->var_event) {
|
||||
switch_event_destroy(&np->var_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Close Unused Handles */
|
||||
if (conference->fnode) {
|
||||
conference_file_node_t *fnode, *cur;
|
||||
@@ -2596,6 +2990,10 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
switch_thread_rwlock_unlock(conference->rwlock);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
|
||||
|
||||
if (conference->la) {
|
||||
switch_live_array_destroy(&conference->la);
|
||||
}
|
||||
|
||||
if (conference->sh) {
|
||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||
switch_core_speech_close(&conference->lsh, &flags);
|
||||
@@ -3241,7 +3639,6 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* if we have caller digits, feed them to the parser to find an action */
|
||||
if (switch_channel_has_dtmf(channel)) {
|
||||
char dtmf[128] = "";
|
||||
@@ -3251,7 +3648,12 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
if (switch_test_flag(member, MFLAG_DIST_DTMF)) {
|
||||
conference_send_all_dtmf(member, member->conference, dtmf);
|
||||
} else if (member->dmachine) {
|
||||
switch_ivr_dmachine_feed(member->dmachine, dtmf, NULL);
|
||||
char *p;
|
||||
char str[2] = "";
|
||||
for (p = dtmf; p && *p; p++) {
|
||||
str[0] = *p;
|
||||
switch_ivr_dmachine_feed(member->dmachine, str, NULL);
|
||||
}
|
||||
}
|
||||
} else if (member->dmachine) {
|
||||
switch_ivr_dmachine_ping(member->dmachine, NULL);
|
||||
@@ -3280,6 +3682,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
if (++hangover_hits >= hangover) {
|
||||
hangover_hits = hangunder_hits = 0;
|
||||
switch_clear_flag_locked(member, MFLAG_TALKING);
|
||||
member_update_status_field(member);
|
||||
check_agc_levels(member);
|
||||
clear_avg(member);
|
||||
member->score_iir = 0;
|
||||
@@ -3398,7 +3801,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
|
||||
if (!switch_test_flag(member, MFLAG_TALKING)) {
|
||||
switch_set_flag_locked(member, MFLAG_TALKING);
|
||||
|
||||
member_update_status_field(member);
|
||||
if (test_eflag(member->conference, EFLAG_START_TALKING) && switch_test_flag(member, MFLAG_CAN_SPEAK) &&
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
|
||||
conference_add_event_member_data(member, event);
|
||||
@@ -3435,6 +3838,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
if (++hangover_hits >= hangover) {
|
||||
hangover_hits = hangunder_hits = 0;
|
||||
switch_clear_flag_locked(member, MFLAG_TALKING);
|
||||
member_update_status_field(member);
|
||||
check_agc_levels(member);
|
||||
clear_avg(member);
|
||||
|
||||
@@ -3680,6 +4084,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
const char *ann = switch_channel_get_variable(channel, "conference_auto_outcall_announce");
|
||||
const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix");
|
||||
const char *maxwait = switch_channel_get_variable(channel, "conference_auto_outcall_maxwait");
|
||||
const char *delimiter_val = switch_channel_get_variable(channel, "conference_auto_outcall_delimiter");
|
||||
int to = 60;
|
||||
int wait_sec = 2;
|
||||
int loops = 0;
|
||||
@@ -3706,7 +4111,12 @@ static void conference_loop_output(conference_member_t *member)
|
||||
int x = 0;
|
||||
|
||||
switch_assert(cpstr);
|
||||
argc = switch_separate_string(cpstr, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
if (!zstr(delimiter_val) && strlen(delimiter_val) == 1) {
|
||||
char delimiter = *delimiter_val;
|
||||
argc = switch_separate_string(cpstr, delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
} else {
|
||||
argc = switch_separate_string(cpstr, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
}
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]);
|
||||
switch_assert(dial_str);
|
||||
@@ -3763,6 +4173,15 @@ static void conference_loop_output(conference_member_t *member)
|
||||
|
||||
switch_mutex_lock(member->write_mutex);
|
||||
|
||||
|
||||
if (switch_channel_test_flag(member->channel, CF_CONFERENCE_ADV)) {
|
||||
if (member->conference->la) {
|
||||
adv_la(member->conference, member, SWITCH_TRUE);
|
||||
}
|
||||
switch_channel_clear_flag(member->channel, CF_CONFERENCE_ADV);
|
||||
}
|
||||
|
||||
|
||||
if (switch_core_session_dequeue_event(member->session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
|
||||
if (event->event_id == SWITCH_EVENT_MESSAGE) {
|
||||
char *from = switch_event_get_header(event, "from");
|
||||
@@ -4864,6 +5283,8 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
member_update_status_field(member);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -4948,6 +5369,8 @@ static switch_status_t conf_api_sub_unmute(conference_member_t *member, switch_s
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
member_update_status_field(member);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -7260,6 +7683,10 @@ static void set_cflags(const char *flags, uint32_t *f)
|
||||
*f |= CFLAG_VIDEO_BRIDGE;
|
||||
} else if (!strcasecmp(argv[i], "audio-always")) {
|
||||
*f |= CFLAG_AUDIO_ALWAYS;
|
||||
} else if (!strcasecmp(argv[i], "json-events")) {
|
||||
*f |= CFLAG_JSON_EVENTS;
|
||||
} else if (!strcasecmp(argv[i], "livearray-sync")) {
|
||||
*f |= CFLAG_LIVEARRAY_SYNC;
|
||||
} else if (!strcasecmp(argv[i], "rfc-4579")) {
|
||||
*f |= CFLAG_RFC4579;
|
||||
}
|
||||
@@ -9308,6 +9735,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load)
|
||||
switch_console_add_complete_func("::conference::list_conferences", list_conferences);
|
||||
|
||||
|
||||
switch_event_channel_bind("conference", conference_event_channel_handler, &globals.event_channel_id);
|
||||
switch_event_channel_bind("conference-liveArray", conference_la_event_channel_handler, &globals.event_channel_id);
|
||||
|
||||
/* build api interface help ".syntax" field string */
|
||||
p = strdup("");
|
||||
for (i = 0; i < CONFFUNCAPISIZE; i++) {
|
||||
@@ -9389,6 +9819,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown)
|
||||
/* signal all threads to shutdown */
|
||||
globals.running = 0;
|
||||
|
||||
switch_event_channel_unbind(NULL, conference_event_channel_handler);
|
||||
switch_event_channel_unbind(NULL, conference_la_event_channel_handler);
|
||||
|
||||
switch_console_del_complete_func("::conference::list_conferences");
|
||||
|
||||
/* wait for all threads */
|
||||
|
||||
@@ -3622,6 +3622,9 @@ static switch_call_cause_t pickup_outgoing_channel(switch_core_session_t *sessio
|
||||
switch_core_session_set_private(nsession, tech_pvt);
|
||||
|
||||
nchannel = switch_core_session_get_channel(nsession);
|
||||
switch_channel_set_cap(nchannel, CC_PROXY_MEDIA);
|
||||
switch_channel_set_cap(nchannel, CC_BYPASS_MEDIA);
|
||||
|
||||
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
|
||||
switch_channel_set_caller_profile(nchannel, caller_profile);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
*
|
||||
*/
|
||||
#include <switch.h>
|
||||
#include <g711.h>
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_esf_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_esf, mod_esf_load, NULL, NULL);
|
||||
@@ -168,7 +169,7 @@ SWITCH_STANDARD_APP(bcast_function)
|
||||
if (ready == SEND_TYPE_RTP) {
|
||||
if (read_impl.ianacode != 0) {
|
||||
if (switch_core_codec_init(&codec,
|
||||
"PCMU",
|
||||
"L16",
|
||||
NULL,
|
||||
8000,
|
||||
20,
|
||||
@@ -200,8 +201,8 @@ SWITCH_STANDARD_APP(bcast_function)
|
||||
mcast_ip,
|
||||
mcast_port,
|
||||
0,
|
||||
8000,
|
||||
20, flags, "soft", &err, switch_core_session_get_pool(session));
|
||||
160,
|
||||
20000, flags, "soft", &err, switch_core_session_get_pool(session));
|
||||
|
||||
if (!switch_rtp_ready(rtp_session)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "RTP Error\n");
|
||||
@@ -237,7 +238,22 @@ SWITCH_STANDARD_APP(bcast_function)
|
||||
continue;
|
||||
}
|
||||
if (ready == SEND_TYPE_RTP) {
|
||||
short *dbuf;
|
||||
unsigned char *ebuf;
|
||||
uint32_t i;
|
||||
unsigned char encoded_data[4192];
|
||||
|
||||
dbuf = read_frame->data;
|
||||
ebuf = encoded_data;
|
||||
|
||||
for (i = 0; i < read_frame->datalen / sizeof(short); i++) {
|
||||
ebuf[i] = linear_to_ulaw(dbuf[i]);
|
||||
}
|
||||
read_frame->data = encoded_data;
|
||||
read_frame->datalen = read_frame->datalen / 2;
|
||||
switch_rtp_write_frame(rtp_session, read_frame);
|
||||
read_frame->data = dbuf;
|
||||
read_frame->datalen = read_frame->datalen * 2;
|
||||
} else {
|
||||
bytes = read_frame->packetlen;
|
||||
switch_socket_sendto(socket, audio_addr, 0, read_frame->packet, &bytes);
|
||||
|
||||
@@ -1067,7 +1067,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses
|
||||
switch_channel_event_set_data(consumer_channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "bridge-consumer-stop");
|
||||
if (use_count) {
|
||||
if (outbound_id) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", use_count);
|
||||
}
|
||||
@@ -2218,7 +2218,7 @@ SWITCH_STANDARD_API(fifo_add_outbound_function)
|
||||
|
||||
}
|
||||
|
||||
static void dec_use_count(switch_core_session_t *session, switch_bool_t send_event)
|
||||
static void dec_use_count(switch_core_session_t *session, const char *type)
|
||||
{
|
||||
char *sql;
|
||||
const char *outbound_id = NULL;
|
||||
@@ -2226,8 +2226,6 @@ static void dec_use_count(switch_core_session_t *session, switch_bool_t send_eve
|
||||
long now = (long) switch_epoch_time_now(NULL);
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
do_unbridge(session, NULL);
|
||||
|
||||
if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s untracking call on uuid %s!\n", switch_channel_get_name(channel), outbound_id);
|
||||
|
||||
@@ -2242,11 +2240,14 @@ static void dec_use_count(switch_core_session_t *session, switch_bool_t send_eve
|
||||
fifo_dec_use_count(outbound_id);
|
||||
}
|
||||
|
||||
if (send_event) {
|
||||
do_unbridge(session, NULL);
|
||||
|
||||
if (type) {
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", type);
|
||||
if (outbound_id) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
|
||||
@@ -2262,7 +2263,7 @@ static switch_status_t hanguphook(switch_core_session_t *session)
|
||||
switch_channel_state_t state = switch_channel_get_state(channel);
|
||||
|
||||
if (state >= CS_HANGUP && !switch_channel_test_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK)) {
|
||||
dec_use_count(session, SWITCH_TRUE);
|
||||
dec_use_count(session, "manual");
|
||||
switch_core_event_hook_remove_state_change(session, hanguphook);
|
||||
switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK);
|
||||
}
|
||||
@@ -2325,6 +2326,9 @@ SWITCH_STANDARD_APP(fifo_track_call_function)
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", MANUAL_QUEUE_NAME);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", data);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(data));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "manual");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
|
||||
switch_event_fire(&event);
|
||||
@@ -2729,16 +2733,33 @@ SWITCH_STANDARD_APP(fifo_function)
|
||||
const char *url = NULL;
|
||||
const char *caller_uuid = NULL;
|
||||
const char *outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid");
|
||||
switch_event_t *event;
|
||||
const char *cid_name = NULL, *cid_number = NULL;
|
||||
|
||||
//const char *track_use_count = switch_channel_get_variable(channel, "fifo_track_use_count");
|
||||
//int do_track = switch_true(track_use_count);
|
||||
|
||||
if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) {
|
||||
dec_use_count(session, SWITCH_FALSE);
|
||||
dec_use_count(session, NULL);
|
||||
switch_core_event_hook_remove_state_change(session, hanguphook);
|
||||
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING);
|
||||
}
|
||||
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
cid_name = switch_channel_get_variable(channel, "callee_id_name");
|
||||
cid_number = switch_channel_get_variable(channel, "callee_id_number");
|
||||
|
||||
if (!cid_name) {
|
||||
cid_name = switch_channel_get_variable(channel, "destination_number");
|
||||
}
|
||||
if (!cid_number) {
|
||||
cid_number = cid_name;
|
||||
}
|
||||
} else {
|
||||
cid_name = switch_channel_get_variable(channel, "caller_id_name");
|
||||
cid_number = switch_channel_get_variable(channel, "caller_id_number");
|
||||
}
|
||||
|
||||
if (!zstr(strat_str)) {
|
||||
if (!strcasecmp(strat_str, "more_ppl")) {
|
||||
strat = STRAT_MORE_PPL;
|
||||
@@ -3148,6 +3169,22 @@ SWITCH_STANDARD_APP(fifo_function)
|
||||
|
||||
}
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-start");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Name", cid_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
|
||||
if (outbound_id) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
|
||||
}
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
|
||||
@@ -3221,6 +3258,19 @@ SWITCH_STANDARD_APP(fifo_function)
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", arg_fifo_name);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Action", "channel-consumer-stop");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Type", "onhook");
|
||||
if (outbound_id) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id));
|
||||
}
|
||||
switch_event_fire(&event);
|
||||
}
|
||||
|
||||
del_bridge_call(switch_core_session_get_uuid(session));
|
||||
del_bridge_call(switch_core_session_get_uuid(other_session));
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
|
||||
|
||||
static switch_status_t channel_on_destroy(switch_core_session_t *session)
|
||||
{
|
||||
crtp_private_t *tech_pvt = switch_core_session_get_private(session);
|
||||
crtp_private_t *tech_pvt = NULL;
|
||||
|
||||
if ((tech_pvt = switch_core_session_get_private(session))) {
|
||||
|
||||
|
||||
@@ -5960,7 +5960,40 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
}
|
||||
|
||||
if (r_sdp) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) && r_sdp) {
|
||||
char ibuf[35] = "", pbuf[35] = "";
|
||||
const char *ptr;
|
||||
|
||||
if ((ptr = switch_stristr("c=IN IP4", r_sdp))) {
|
||||
int i = 0;
|
||||
|
||||
ptr += 8;
|
||||
|
||||
while(*ptr == ' ') {
|
||||
ptr++;
|
||||
}
|
||||
while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
|
||||
ibuf[i++] = *ptr++;
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, ibuf);
|
||||
}
|
||||
|
||||
if ((ptr = switch_stristr("m=audio", r_sdp))) {
|
||||
int i = 0;
|
||||
|
||||
ptr += 7;
|
||||
|
||||
while(*ptr == ' ') {
|
||||
ptr++;
|
||||
}
|
||||
while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
|
||||
pbuf[i++] = *ptr++;
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, pbuf);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
|
||||
}
|
||||
@@ -6893,6 +6926,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
|
||||
exten = (char *) refer_to->r_url->url_user;
|
||||
}
|
||||
|
||||
switch_core_session_queue_indication(session, SWITCH_MESSAGE_REFER_EVENT);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Process REFER to [%s@%s]\n", exten, (char *) refer_to->r_url->url_host);
|
||||
|
||||
switch_channel_set_variable(tech_pvt->channel, "transfer_disposition", "recv_replace");
|
||||
|
||||
@@ -311,16 +311,17 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
||||
if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) {
|
||||
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2);
|
||||
if (source->total) {
|
||||
|
||||
uint32_t bused = 0;
|
||||
switch_mutex_lock(source->mutex);
|
||||
for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
|
||||
if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
|
||||
continue;
|
||||
}
|
||||
switch_mutex_lock(cp->audio_mutex);
|
||||
if (switch_buffer_inuse(cp->audio_buffer) > source->samples * 768) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Leaking stream handle! [%s() %s:%d]\n", cp->func, cp->file,
|
||||
cp->line);
|
||||
bused = switch_buffer_inuse(cp->audio_buffer);
|
||||
if (bused > source->samples * 768) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n",
|
||||
cp->func, cp->file, cp->line, bused, (long)source->samples);
|
||||
switch_buffer_zero(cp->audio_buffer);
|
||||
} else {
|
||||
switch_buffer_write(cp->audio_buffer, dist_buf, used);
|
||||
|
||||
@@ -45,7 +45,6 @@ SWITCH_MODULE_DEFINITION_EX(mod_lua, mod_lua_load, mod_lua_shutdown, NULL, SMODF
|
||||
static struct {
|
||||
switch_memory_pool_t *pool;
|
||||
char *xml_handler;
|
||||
switch_event_node_t *node;
|
||||
} globals;
|
||||
|
||||
int luaopen_freeswitch(lua_State * L);
|
||||
@@ -339,18 +338,22 @@ static switch_status_t do_config(void)
|
||||
char *script = (char *) switch_xml_attr_soft(hook, "script");
|
||||
switch_event_types_t evtype;
|
||||
|
||||
if (!zstr(script)) {
|
||||
script = switch_core_strdup(globals.pool, script);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hook params: '%s' | '%s' | '%s'\n", event, subclass, script);
|
||||
|
||||
if (switch_name_event(event,&evtype) == SWITCH_STATUS_SUCCESS) {
|
||||
if (!zstr(script)) {
|
||||
if (switch_event_bind_removable(modname, evtype, !zstr(subclass) ? subclass : SWITCH_EVENT_SUBCLASS_ANY,
|
||||
lua_event_handler, script, &globals.node) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_event_bind(modname, evtype, !zstr(subclass) ? subclass : SWITCH_EVENT_SUBCLASS_ANY,
|
||||
lua_event_handler, script) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler for '%s' set to '%s'\n", switch_event_name(evtype), script);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: unsuccessful bind\n");
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: no script name\n", event);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: no script name for event type '%s'\n", event);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set event handler: unknown event type '%s'\n", event);
|
||||
@@ -691,7 +694,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lua_shutdown)
|
||||
{
|
||||
switch_event_unbind(&globals.node);
|
||||
switch_event_unbind_callback(lua_event_handler);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,23 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_radius_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_xml_radius, mod_xml_radius_load, mod_xml_radius_shutdown, NULL);
|
||||
|
||||
int GLOBAL_DEBUG = 0;
|
||||
/*
|
||||
* Time format 0:
|
||||
* 20:16:33.479 UTC Thu May 02 2013
|
||||
*
|
||||
* Time format 1:
|
||||
* 2013-05-03T00:53:26.139798+0400
|
||||
*
|
||||
*/
|
||||
int GLOBAL_TIME_FORMAT = 0;
|
||||
char *GLOBAL_TIME_ZONE = "UTC";
|
||||
static char radattrdays[7][4] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static char radattrmonths[12][4] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
switch_status_t mod_xml_radius_new_handle(rc_handle **new_handle, switch_xml_t xml) {
|
||||
switch_xml_t server, param;
|
||||
@@ -186,7 +203,26 @@ switch_status_t do_config()
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Could not find 'auth_invite' section in config file.\n");
|
||||
}
|
||||
|
||||
|
||||
if ((tmp = switch_xml_child(cfg, "global")) != NULL ) {
|
||||
for (param = switch_xml_child(tmp, "param"); param; param = param->next) {
|
||||
char *name = (char *) switch_xml_attr_soft(param, "name");
|
||||
char *value = (char *) switch_xml_attr_soft(param, "value");
|
||||
if ( strncmp(name, "time_format", 11) == 0 && value != NULL ) {
|
||||
GLOBAL_TIME_FORMAT = atoi(value);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Time format changed to %d\n", GLOBAL_TIME_FORMAT);
|
||||
}
|
||||
if ( strncmp(name, "time_zone", 9) == 0 && value != NULL ) {
|
||||
GLOBAL_TIME_ZONE = value;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Time zone changed to %s\n", GLOBAL_TIME_ZONE);
|
||||
}
|
||||
if ( strncmp(name, "debug", 5) == 0 && value != NULL ) {
|
||||
GLOBAL_DEBUG = atoi(value);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Debug changed to %d\n", GLOBAL_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serv = timeout = deadtime = retries = dict = seq = 0;
|
||||
if ((tmp = switch_xml_dup(switch_xml_child(cfg, "auth_app"))) != NULL ) {
|
||||
if ( (server = switch_xml_child(tmp, "connection")) != NULL) {
|
||||
@@ -375,11 +411,19 @@ switch_status_t mod_xml_radius_add_params(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
switch_time_exp_lt(&tm, time);
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
|
||||
if ( GLOBAL_TIME_FORMAT == 1 ) {
|
||||
av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
|
||||
GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
|
||||
tm.tm_mday, tm.tm_year + 1900);
|
||||
} else {
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
}
|
||||
|
||||
if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
|
||||
goto err;
|
||||
@@ -397,12 +441,19 @@ switch_status_t mod_xml_radius_add_params(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
switch_time_exp_lt(&tm, time);
|
||||
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
|
||||
|
||||
if ( GLOBAL_TIME_FORMAT == 1 ) {
|
||||
av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
|
||||
GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
|
||||
tm.tm_mday, tm.tm_year + 1900);
|
||||
} else {
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
}
|
||||
|
||||
if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
|
||||
goto err;
|
||||
@@ -424,12 +475,19 @@ switch_status_t mod_xml_radius_add_params(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
switch_time_exp_lt(&tm, time);
|
||||
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
|
||||
|
||||
if ( GLOBAL_TIME_FORMAT == 1 ) {
|
||||
av_value = switch_mprintf("%02u:%02u:%02u.%03u MSD %s %s %02u %04u",
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
|
||||
GLOBAL_TIME_FORMAT, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
|
||||
tm.tm_mday, tm.tm_year + 1900);
|
||||
} else {
|
||||
av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
|
||||
tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
|
||||
}
|
||||
|
||||
if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
|
||||
goto err;
|
||||
|
||||
+146
-13
@@ -139,6 +139,7 @@ typedef enum {
|
||||
struct switch_channel {
|
||||
char *name;
|
||||
switch_call_direction_t direction;
|
||||
switch_call_direction_t logical_direction;
|
||||
switch_queue_t *dtmf_queue;
|
||||
switch_queue_t *dtmf_log_queue;
|
||||
switch_mutex_t*dtmf_mutex;
|
||||
@@ -240,6 +241,7 @@ static struct switch_callstate_table CALLSTATE_CHART[] = {
|
||||
{"EARLY", CCS_EARLY},
|
||||
{"ACTIVE", CCS_ACTIVE},
|
||||
{"HELD", CCS_HELD},
|
||||
{"RING_WAIT", CCS_RING_WAIT},
|
||||
{"HANGUP", CCS_HANGUP},
|
||||
{"UNHOLD", CCS_UNHOLD},
|
||||
{NULL, 0}
|
||||
@@ -277,7 +279,11 @@ SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *chan
|
||||
switch_channel_callstate2str(o_callstate), switch_channel_callstate2str(callstate));
|
||||
|
||||
switch_channel_check_device_state(channel, channel->callstate);
|
||||
|
||||
|
||||
if (callstate == CCS_HANGUP) {
|
||||
process_device_hup(channel);
|
||||
}
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(o_callstate));
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Call-State-Number", "%d", callstate);
|
||||
@@ -388,7 +394,7 @@ SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch
|
||||
SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction)
|
||||
{
|
||||
if (!switch_core_session_in_thread(channel->session)) {
|
||||
channel->direction = direction;
|
||||
channel->direction = channel->logical_direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +403,11 @@ SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_
|
||||
return channel->direction;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_call_direction_t) switch_channel_logical_direction(switch_channel_t *channel)
|
||||
{
|
||||
return channel->logical_direction;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)
|
||||
{
|
||||
switch_assert(pool != NULL);
|
||||
@@ -418,7 +429,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel,
|
||||
switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
|
||||
(*channel)->hangup_cause = SWITCH_CAUSE_NONE;
|
||||
(*channel)->name = "";
|
||||
(*channel)->direction = direction;
|
||||
(*channel)->direction = (*channel)->logical_direction = direction;
|
||||
switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -1753,6 +1764,24 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw
|
||||
channel->flags[flag] = value;
|
||||
switch_mutex_unlock(channel->flag_mutex);
|
||||
|
||||
if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) {
|
||||
switch_channel_set_callstate(channel, CCS_RING_WAIT);
|
||||
}
|
||||
|
||||
if (flag == CF_DIALPLAN) {
|
||||
if (channel->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
|
||||
if (channel->device_node) {
|
||||
channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
|
||||
}
|
||||
} else {
|
||||
channel->logical_direction = SWITCH_CALL_DIRECTION_INBOUND;
|
||||
if (channel->device_node) {
|
||||
channel->device_node->direction = SWITCH_CALL_DIRECTION_OUTBOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HELD) {
|
||||
switch_hold_record_t *hr;
|
||||
const char *brto = switch_channel_get_partner_uuid(channel);
|
||||
@@ -1921,6 +1950,15 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch
|
||||
channel->flags[flag] = 0;
|
||||
switch_mutex_unlock(channel->flag_mutex);
|
||||
|
||||
if (flag == CF_DIALPLAN) {
|
||||
if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
|
||||
if (channel->device_node) {
|
||||
channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ACTIVE) {
|
||||
switch_channel_set_callstate(channel, CCS_UNHOLD);
|
||||
switch_mutex_lock(channel->profile_mutex);
|
||||
@@ -1935,6 +1973,10 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch
|
||||
switch_mutex_unlock(channel->profile_mutex);
|
||||
}
|
||||
|
||||
if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)) {
|
||||
switch_channel_set_callstate(channel, CCS_ACTIVE);
|
||||
}
|
||||
|
||||
if (flag == CF_OUTBOUND) {
|
||||
switch_channel_set_variable(channel, "is_outbound", NULL);
|
||||
}
|
||||
@@ -2602,6 +2644,7 @@ SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel
|
||||
switch_assert(caller_profile != NULL);
|
||||
|
||||
caller_profile->direction = channel->direction;
|
||||
caller_profile->logical_direction = channel->logical_direction;
|
||||
uuid = switch_core_session_get_uuid(channel->session);
|
||||
|
||||
if (!caller_profile->uuid || strcasecmp(caller_profile->uuid, uuid)) {
|
||||
@@ -2684,6 +2727,7 @@ SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *ch
|
||||
channel->caller_profile->hunt_caller_profile = NULL;
|
||||
if (channel->caller_profile && caller_profile) {
|
||||
caller_profile->direction = channel->direction;
|
||||
caller_profile->logical_direction = channel->logical_direction;
|
||||
channel->caller_profile->hunt_caller_profile = caller_profile;
|
||||
}
|
||||
switch_mutex_unlock(channel->profile_mutex);
|
||||
@@ -3137,8 +3181,6 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
|
||||
channel->state = CS_HANGUP;
|
||||
switch_mutex_unlock(channel->state_mutex);
|
||||
|
||||
process_device_hup(channel);
|
||||
|
||||
channel->hangup_cause = hangup_cause;
|
||||
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
|
||||
channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
|
||||
@@ -4664,28 +4706,73 @@ static void fetch_device_stats(switch_device_record_t *drec)
|
||||
{
|
||||
switch_device_node_t *np;
|
||||
|
||||
|
||||
memset(&drec->stats, 0, sizeof(switch_device_stats_t));
|
||||
|
||||
switch_mutex_lock(drec->mutex);
|
||||
for(np = drec->uuid_list; np; np = np->next) {
|
||||
drec->stats.total++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.total_in++;
|
||||
} else {
|
||||
drec->stats.total_out++;
|
||||
}
|
||||
|
||||
if (!np->hup_profile) {
|
||||
drec->stats.offhook++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.offhook_in++;
|
||||
} else {
|
||||
drec->stats.offhook_out++;
|
||||
}
|
||||
|
||||
if (np->callstate == CCS_HELD) {
|
||||
drec->stats.held++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.held_in++;
|
||||
} else {
|
||||
drec->stats.held_out++;
|
||||
}
|
||||
} else {
|
||||
if (np->callstate == CCS_EARLY) {
|
||||
drec->stats.early++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.early_in++;
|
||||
} else {
|
||||
drec->stats.early_out++;
|
||||
}
|
||||
} else if (np->callstate == CCS_RINGING) {
|
||||
drec->stats.ringing++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.ringing_in++;
|
||||
} else {
|
||||
drec->stats.ringing_out++;
|
||||
}
|
||||
} else if (np->callstate == CCS_RING_WAIT) {
|
||||
drec->stats.ring_wait++;
|
||||
} else if (np->callstate == CCS_HANGUP) {
|
||||
drec->stats.hup++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.hup_in++;
|
||||
} else {
|
||||
drec->stats.hup_out++;
|
||||
}
|
||||
} else if (np->callstate != CCS_DOWN) {
|
||||
drec->stats.active++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.active_in++;
|
||||
} else {
|
||||
drec->stats.active_out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
drec->stats.hup++;
|
||||
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
drec->stats.hup_in++;
|
||||
} else {
|
||||
drec->stats.hup_out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(drec->mutex);
|
||||
@@ -4826,7 +4913,7 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
|
||||
drec->state = SDS_HANGUP;
|
||||
} else {
|
||||
if (drec->stats.active == 0) {
|
||||
if ((drec->stats.ringing + drec->stats.early) > 0) {
|
||||
if ((drec->stats.ringing_out + drec->stats.early_out) > 0 || drec->stats.ring_wait > 0) {
|
||||
drec->state = SDS_RINGING;
|
||||
} else {
|
||||
if (drec->stats.held > 0) {
|
||||
@@ -4848,22 +4935,47 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
|
||||
return;
|
||||
}
|
||||
|
||||
if (!drec->call_start) {
|
||||
drec->call_start = switch_micro_time_now();
|
||||
}
|
||||
|
||||
switch(drec->state) {
|
||||
case SDS_RINGING:
|
||||
if (!drec->ring_start) {
|
||||
drec->ring_start = switch_micro_time_now();
|
||||
drec->ring_stop = 0;
|
||||
}
|
||||
break;
|
||||
case SDS_ACTIVE:
|
||||
case SDS_ACTIVE_MULTI:
|
||||
if (drec->last_state != SDS_HELD && drec->active_start) {
|
||||
drec->active_stop = switch_micro_time_now();
|
||||
} else if (!drec->active_start) {
|
||||
if (!drec->active_start) {
|
||||
drec->active_start = switch_micro_time_now();
|
||||
drec->active_stop = 0;
|
||||
}
|
||||
break;
|
||||
case SDS_HELD:
|
||||
if (!drec->hold_start) {
|
||||
drec->hold_start = switch_micro_time_now();
|
||||
drec->hold_stop = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (drec->last_state != SDS_HELD) {
|
||||
drec->active_stop = switch_micro_time_now();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (drec->active_start && drec->state != SDS_ACTIVE && drec->state != SDS_ACTIVE_MULTI) {
|
||||
drec->active_stop = switch_micro_time_now();
|
||||
}
|
||||
|
||||
if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) {
|
||||
drec->ring_stop = switch_micro_time_now();
|
||||
}
|
||||
|
||||
if (drec->hold_start && !drec->hold_stop && drec->state != SDS_HELD) {
|
||||
drec->hold_stop = switch_micro_time_now();
|
||||
}
|
||||
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_DEVICE_STATE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", drec->device_id);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state));
|
||||
@@ -4884,7 +4996,8 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1,
|
||||
"%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u Ringing:%u Early:%u Active:%u Held:%u Hungup:%u Dur: %u %s\n",
|
||||
"%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u "
|
||||
"Ringing:%u Early:%u Active:%u Held:%u Hungup:%u Dur: %u Ringtime: %u Holdtime: %u %s\n",
|
||||
switch_channel_get_name(channel),
|
||||
drec->device_id,
|
||||
switch_channel_callstate2str(callstate),
|
||||
@@ -4898,12 +5011,16 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
|
||||
drec->stats.held,
|
||||
drec->stats.hup,
|
||||
drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0,
|
||||
drec->ring_stop ? (uint32_t)(drec->ring_stop - drec->ring_start) / 1000 : 0,
|
||||
drec->hold_stop ? (uint32_t)(drec->hold_stop - drec->hold_start) / 1000 : 0,
|
||||
switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : "");
|
||||
|
||||
for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
|
||||
ptr->function(channel->session, callstate, drec);
|
||||
}
|
||||
|
||||
drec->last_stats = drec->stats;
|
||||
|
||||
if (drec->active_stop) {
|
||||
drec->active_start = drec->active_stop = 0;
|
||||
if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) {
|
||||
@@ -4911,6 +5028,20 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
|
||||
}
|
||||
}
|
||||
|
||||
if (drec->hold_stop) {
|
||||
drec->hold_start = drec->hold_stop = 0;
|
||||
if (drec->state == SDS_HELD) {
|
||||
drec->hold_start = switch_micro_time_now();
|
||||
}
|
||||
}
|
||||
|
||||
if (drec->ring_stop) {
|
||||
drec->ring_start = drec->ring_stop = 0;
|
||||
if (drec->state == SDS_RINGING) {
|
||||
drec->ring_start = switch_micro_time_now();
|
||||
}
|
||||
}
|
||||
|
||||
drec->last_call_time = switch_micro_time_now();
|
||||
|
||||
drec->last_state = drec->state;
|
||||
@@ -4938,6 +5069,8 @@ static void add_uuid(switch_device_record_t *drec, switch_channel_t *channel)
|
||||
node->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session));
|
||||
node->parent = drec;
|
||||
node->callstate = channel->callstate;
|
||||
node->direction = channel->logical_direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
|
||||
|
||||
channel->device_node = node;
|
||||
|
||||
if (!drec->uuid_list) {
|
||||
|
||||
@@ -295,6 +295,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -357,6 +359,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
if (session->bugs && switch_test_flag((*frame), SFF_CNG)) {
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -651,6 +655,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -700,6 +706,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -866,6 +874,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||
int prune = 0;
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -936,6 +946,8 @@ static switch_status_t perform_write(switch_core_session_t *session, switch_fram
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
ok = SWITCH_TRUE;
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1237,6 +1249,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||
for (bp = session->bugs; bp; bp = bp->next) {
|
||||
switch_bool_t ok = SWITCH_TRUE;
|
||||
|
||||
if (!bp->ready) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+73
-26
@@ -73,6 +73,7 @@ typedef struct codec_params_s {
|
||||
char *iananame;
|
||||
switch_payload_t pt;
|
||||
unsigned long rm_rate;
|
||||
unsigned long adv_rm_rate;
|
||||
uint32_t codec_ms;
|
||||
uint32_t bitrate;
|
||||
|
||||
@@ -192,13 +193,13 @@ struct switch_media_handle_s {
|
||||
|
||||
};
|
||||
|
||||
static int get_channels(const switch_codec_implementation_t *imp)
|
||||
static int get_channels(const char *name, int dft)
|
||||
{
|
||||
if (!strcasecmp(imp->iananame, "opus")) {
|
||||
if (!strcasecmp(name, "opus")) {
|
||||
return 2; /* IKR???*/
|
||||
}
|
||||
|
||||
return imp->number_of_channels;
|
||||
return dft ? dft : 1;
|
||||
}
|
||||
|
||||
static void _switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session, switch_media_type_t type)
|
||||
@@ -1436,6 +1437,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
|
||||
engine->codec_params.rm_encoding = switch_core_session_strdup(smh->session, imp->iananame);
|
||||
engine->codec_params.rm_fmtp = NULL;
|
||||
engine->codec_params.rm_rate = imp->samples_per_second;
|
||||
engine->codec_params.adv_rm_rate = imp->samples_per_second;
|
||||
if (strcasecmp(imp->iananame, "g722")) {
|
||||
engine->codec_params.rm_rate = imp->actual_samples_per_second;
|
||||
}
|
||||
engine->codec_params.codec_ms = imp->microseconds_per_packet / 1000;
|
||||
engine->codec_params.bitrate = imp->bits_per_second;
|
||||
engine->codec_params.channels = 1;
|
||||
@@ -2799,9 +2804,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
|
||||
if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
|
||||
got_crypto = 1;
|
||||
if (sdp_type == SDP_TYPE_REQUEST) {
|
||||
switch_channel_set_variable(session->channel, "answer_delay", "2500");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2983,6 +2985,8 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
const switch_codec_implementation_t *imp = codec_array[i];
|
||||
uint32_t bit_rate = imp->bits_per_second;
|
||||
uint32_t codec_rate = imp->samples_per_second;
|
||||
char *samp = NULL;
|
||||
|
||||
if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
|
||||
continue;
|
||||
}
|
||||
@@ -3009,24 +3013,41 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
match = 0;
|
||||
}
|
||||
|
||||
if (!zstr(map->rm_fmtp)) {
|
||||
samp = strstr(map->rm_fmtp, "samplerate=");
|
||||
}
|
||||
if (!strcasecmp(map->rm_encoding, "opus") && !strcasecmp(rm_encoding, imp->iananame) && samp) {
|
||||
char *rate_str = samp + 11;
|
||||
|
||||
if (rate_str && *rate_str) {
|
||||
near_rate = atoi(rate_str);
|
||||
near_match = imp;
|
||||
near_map = mmap = map;
|
||||
match = 0;
|
||||
goto near_match;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
if (scrooge) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||
"Bah HUMBUG! Sticking with %s@%uh@%ui\n",
|
||||
imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
|
||||
} else if (!near_match) {
|
||||
if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
|
||||
} else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
|
||||
/* ptime does not match */
|
||||
match = 0;
|
||||
|
||||
/* save first near_match */
|
||||
if (!near_match) {
|
||||
near_rate = map->rm_rate;
|
||||
near_match = imp;
|
||||
near_map = mmap = map;
|
||||
match = 0;
|
||||
|
||||
if (switch_true(switch_channel_get_variable_dup(channel, "rtp_negotiate_near_match", SWITCH_FALSE, -1))) {
|
||||
goto near_match;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
mimp = imp;
|
||||
mmap = map;
|
||||
@@ -3061,10 +3082,8 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
|
||||
if (num) {
|
||||
mimp = search[0];
|
||||
mmap = map;
|
||||
} else {
|
||||
mimp = near_match;
|
||||
mmap = map;
|
||||
}
|
||||
|
||||
if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) {
|
||||
@@ -3087,6 +3106,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
a_engine->codec_params.iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
|
||||
a_engine->codec_params.pt = (switch_payload_t) mmap->rm_pt;
|
||||
a_engine->codec_params.rm_rate = mimp->samples_per_second;
|
||||
a_engine->codec_params.adv_rm_rate = mimp->samples_per_second;
|
||||
if (strcasecmp(mimp->iananame, "g722")) {
|
||||
a_engine->codec_params.rm_rate = mimp->actual_samples_per_second;
|
||||
}
|
||||
a_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000;
|
||||
a_engine->codec_params.bitrate = mimp->bits_per_second;
|
||||
a_engine->codec_params.channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
|
||||
@@ -3346,7 +3369,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session, int sendonly)
|
||||
{
|
||||
int changed = 0;
|
||||
switch_rtp_engine_t *a_engine;//, *v_engine;
|
||||
switch_rtp_engine_t *a_engine, *v_engine;
|
||||
switch_media_handle_t *smh;
|
||||
switch_core_session_t *b_session = NULL;
|
||||
switch_channel_t *b_channel = NULL;
|
||||
@@ -3358,7 +3381,7 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session
|
||||
}
|
||||
|
||||
a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
|
||||
//v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
|
||||
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
|
||||
|
||||
|
||||
if (switch_core_session_get_partner(session, &b_session) == SWITCH_STATUS_SUCCESS) {
|
||||
@@ -3386,6 +3409,11 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session
|
||||
msg = "hold-private";
|
||||
}
|
||||
}
|
||||
|
||||
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
if (v_engine->rtp_session) {
|
||||
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
}
|
||||
|
||||
switch_channel_set_flag(session->channel, CF_PROTO_HOLD);
|
||||
switch_channel_mark_hold(session->channel, SWITCH_TRUE);
|
||||
@@ -3418,6 +3446,12 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session
|
||||
if (switch_channel_test_flag(session->channel, CF_HOLD_LOCK)) {
|
||||
switch_channel_set_flag(session->channel, CF_PROTO_HOLD);
|
||||
switch_channel_mark_hold(session->channel, SWITCH_TRUE);
|
||||
|
||||
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
if (v_engine->rtp_session) {
|
||||
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
}
|
||||
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
@@ -3445,6 +3479,12 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session
|
||||
switch_channel_clear_flag(session->channel, CF_PROTO_HOLD);
|
||||
switch_channel_mark_hold(session->channel, SWITCH_FALSE);
|
||||
switch_channel_presence(session->channel, "unknown", "unhold", NULL);
|
||||
|
||||
switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
if (v_engine->rtp_session) {
|
||||
switch_rtp_clear_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_PAUSE);
|
||||
}
|
||||
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@@ -5164,7 +5204,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
|
||||
}
|
||||
|
||||
if (smh->ianacodes[i] > 95 || switch_channel_test_flag(session->channel, CF_VERBOSE_SDP)) {
|
||||
int channels = get_channels(imp);
|
||||
int channels = get_channels(imp->iananame, imp->number_of_channels);
|
||||
|
||||
if (channels > 1) {
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", smh->ianacodes[i], imp->iananame, rate, channels);
|
||||
@@ -5644,11 +5684,11 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
|
||||
|
||||
|
||||
rate = a_engine->codec_params.rm_rate;
|
||||
rate = a_engine->codec_params.adv_rm_rate;
|
||||
|
||||
//if (!strcasecmp(a_engine->codec_params.rm_encoding, "opus")) {
|
||||
// a_engine->codec_params.adv_channels = 2;
|
||||
//}
|
||||
if (!a_engine->codec_params.adv_channels) {
|
||||
a_engine->codec_params.adv_channels = get_channels(a_engine->codec_params.rm_encoding, 1);
|
||||
}
|
||||
|
||||
if (a_engine->codec_params.adv_channels > 1) {
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n",
|
||||
@@ -6023,7 +6063,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
rate = imp->samples_per_second;
|
||||
}
|
||||
|
||||
channels = get_channels(imp);
|
||||
channels = get_channels(imp->iananame, imp->number_of_channels);
|
||||
|
||||
if (!strcasecmp(imp->iananame, "VP8")) {
|
||||
vp8 = ianacode;
|
||||
@@ -6439,6 +6479,7 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
|
||||
}
|
||||
a_engine->codec_params.iananame = switch_core_session_strdup(session, "PROXY");
|
||||
a_engine->codec_params.rm_rate = 8000;
|
||||
a_engine->codec_params.adv_rm_rate = 8000;
|
||||
a_engine->codec_params.codec_ms = 20;
|
||||
}
|
||||
|
||||
@@ -6467,11 +6508,11 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
|
||||
strncpy(q, p, 7);
|
||||
p += 7;
|
||||
q += 7;
|
||||
strncpy(q, strchr(a_engine->codec_params.local_sdp_ip, ':') ? "6 " : "4 ", 2);
|
||||
strncpy(q, strchr(a_engine->codec_params.adv_sdp_ip, ':') ? "6 " : "4 ", 2);
|
||||
p +=2;
|
||||
q +=2;
|
||||
strncpy(q, a_engine->codec_params.local_sdp_ip, strlen(a_engine->codec_params.local_sdp_ip));
|
||||
q += strlen(a_engine->codec_params.local_sdp_ip);
|
||||
strncpy(q, a_engine->codec_params.adv_sdp_ip, strlen(a_engine->codec_params.adv_sdp_ip));
|
||||
q += strlen(a_engine->codec_params.adv_sdp_ip);
|
||||
|
||||
while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
|
||||
if (p >= pe) {
|
||||
@@ -6584,6 +6625,7 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
|
||||
switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
|
||||
v_engine->codec_params.rm_encoding = "PROXY-VID";
|
||||
v_engine->codec_params.rm_rate = 90000;
|
||||
v_engine->codec_params.adv_rm_rate = 90000;
|
||||
v_engine->codec_params.codec_ms = 0;
|
||||
switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->codec_params.adv_sdp_port);
|
||||
if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(v_engine->rtp_session)) {
|
||||
@@ -6937,7 +6979,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
|
||||
|
||||
if (ok) {
|
||||
switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
//switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
switch_channel_set_flag(session->channel, CF_NOTIMER_DURING_BRIDGE);
|
||||
}
|
||||
|
||||
@@ -6985,7 +7027,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
|
||||
if (!switch_rtp_test_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_UDPTL) &&
|
||||
!switch_rtp_test_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) {
|
||||
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
//switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
}
|
||||
switch_channel_clear_flag(session->channel, CF_NOTIMER_DURING_BRIDGE);
|
||||
}
|
||||
@@ -7686,6 +7728,7 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
|
||||
|
||||
a_engine->codec_params.iananame = switch_core_session_strdup(session, "PROXY");
|
||||
a_engine->codec_params.rm_rate = 8000;
|
||||
a_engine->codec_params.adv_rm_rate = 8000;
|
||||
|
||||
a_engine->codec_params.codec_ms = 20;
|
||||
|
||||
@@ -7693,6 +7736,7 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
|
||||
switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
|
||||
v_engine->codec_params.rm_encoding = "PROXY-VID";
|
||||
v_engine->codec_params.rm_rate = 90000;
|
||||
v_engine->codec_params.adv_rm_rate = 90000;
|
||||
v_engine->codec_params.codec_ms = 0;
|
||||
switch_channel_set_flag(session->channel, CF_VIDEO);
|
||||
switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
|
||||
@@ -7764,6 +7808,7 @@ SWITCH_DECLARE(void) switch_core_media_proxy_codec(switch_core_session_t *sessio
|
||||
for (map = m->m_rtpmaps; map; map = map->rm_next) {
|
||||
a_engine->codec_params.iananame = switch_core_session_strdup(session, map->rm_encoding);
|
||||
a_engine->codec_params.rm_rate = map->rm_rate;
|
||||
a_engine->codec_params.adv_rm_rate = map->rm_rate;
|
||||
a_engine->codec_params.codec_ms = ptime;
|
||||
switch_core_media_set_codec(session, 0, smh->mparams->codec_flags);
|
||||
break;
|
||||
@@ -7841,6 +7886,7 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
|
||||
|
||||
if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_rate"))) {
|
||||
a_engine->codec_params.rm_rate = atoi(tmp);
|
||||
a_engine->codec_params.adv_rm_rate = a_engine->codec_params.rm_rate;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_ptime"))) {
|
||||
@@ -7895,6 +7941,7 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
|
||||
|
||||
if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_rate"))) {
|
||||
v_engine->codec_params.rm_rate = atoi(tmp);
|
||||
v_engine->codec_params.adv_rm_rate = v_engine->codec_params.rm_rate;
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_ptime"))) {
|
||||
|
||||
@@ -264,12 +264,14 @@ SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall_ma
|
||||
switch_memory_pool_t *pool;
|
||||
struct str_node *head = NULL, *np;
|
||||
switch_console_callback_match_t *my_matches = NULL;
|
||||
const char *like = NULL;
|
||||
|
||||
if (var_val && *var_val == '~') {
|
||||
like = var_val + 1;
|
||||
}
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
|
||||
if (!var_val)
|
||||
return NULL;
|
||||
|
||||
switch_mutex_lock(runtime.session_hash_mutex);
|
||||
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
||||
switch_hash_this(hi, NULL, NULL, &val);
|
||||
@@ -290,7 +292,8 @@ SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall_ma
|
||||
if ((session = switch_core_session_locate(np->str))) {
|
||||
const char *this_val;
|
||||
if (switch_channel_up_nosig(session->channel) &&
|
||||
(this_val = switch_channel_get_variable_dup(session->channel, var_name, SWITCH_FALSE, -1)) && (!strcmp(this_val, var_val))) {
|
||||
(this_val = switch_channel_get_variable_dup(session->channel, var_name, SWITCH_FALSE, -1)) &&
|
||||
(!var_val || (like && switch_stristr(like, var_val)) || !strcmp(this_val, var_val))) {
|
||||
switch_console_push_match(&my_matches, (const char *) np->str);
|
||||
}
|
||||
switch_core_session_rwunlock(session);
|
||||
|
||||
+25
-7
@@ -3055,6 +3055,7 @@ struct switch_live_array_s {
|
||||
switch_live_array_command_handler_t command_handler;
|
||||
void *user_data;
|
||||
alias_node_t *aliases;
|
||||
int refs;
|
||||
};
|
||||
|
||||
static switch_status_t la_broadcast(switch_live_array_t *la, cJSON **json)
|
||||
@@ -3215,9 +3216,21 @@ SWITCH_DECLARE(switch_status_t) switch_live_array_destroy(switch_live_array_t **
|
||||
switch_live_array_t *la = *live_arrayP;
|
||||
switch_memory_pool_t *pool;
|
||||
alias_node_t *np;
|
||||
int done = 0;
|
||||
|
||||
*live_arrayP = NULL;
|
||||
|
||||
switch_mutex_lock(la->mutex);
|
||||
if (la->refs) {
|
||||
la->refs--;
|
||||
}
|
||||
if (la->refs) done = 1;
|
||||
switch_mutex_unlock(la->mutex);
|
||||
|
||||
if (done) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
pool = la->pool;
|
||||
|
||||
switch_live_array_clear(la);
|
||||
@@ -3311,7 +3324,6 @@ SWITCH_DECLARE(switch_bool_t) switch_live_array_add_alias(switch_live_array_t *l
|
||||
return !exist;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_live_array_create(const char *event_channel, const char *name,
|
||||
switch_event_channel_id_t channel_id, switch_live_array_t **live_arrayP)
|
||||
{
|
||||
@@ -3346,6 +3358,10 @@ SWITCH_DECLARE(switch_status_t) switch_live_array_create(const char *event_chann
|
||||
switch_mutex_unlock(event_channel_manager.lamutex);
|
||||
}
|
||||
|
||||
switch_mutex_lock(la->mutex);
|
||||
la->refs++;
|
||||
switch_mutex_unlock(la->mutex);
|
||||
|
||||
*live_arrayP = la;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -3559,14 +3575,16 @@ SWITCH_DECLARE(void) switch_live_array_parse_json(cJSON *json, switch_event_chan
|
||||
const char *sessid = cJSON_GetObjectCstr(json, "sessid");
|
||||
|
||||
if (command) {
|
||||
switch_live_array_create(context, name, channel_id, &la);
|
||||
if (switch_live_array_create(context, name, channel_id, &la) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
if (!strcasecmp(command, "bootstrap")) {
|
||||
switch_live_array_bootstrap(la, sessid, channel_id);
|
||||
} else {
|
||||
if (la->command_handler) {
|
||||
la->command_handler(la, command, sessid, jla, la->user_data);
|
||||
if (!strcasecmp(command, "bootstrap")) {
|
||||
switch_live_array_bootstrap(la, sessid, channel_id);
|
||||
} else {
|
||||
if (la->command_handler) {
|
||||
la->command_handler(la, command, sessid, jla, la->user_data);
|
||||
}
|
||||
}
|
||||
switch_live_array_destroy(&la);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1695,6 +1695,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) {
|
||||
switch_channel_clear_flag(originatee_channel, CF_DIALPLAN);
|
||||
}
|
||||
|
||||
cleanup_proxy_mode_a(originator_session);
|
||||
cleanup_proxy_mode_a(originatee_session);
|
||||
|
||||
|
||||
+90
-31
@@ -1890,21 +1890,22 @@ static switch_status_t enable_remote_rtcp_socket(switch_rtp_t *rtp_session, cons
|
||||
"Setting RTCP remote addr to %s:%d\n", host, rtp_session->remote_rtcp_port);
|
||||
}
|
||||
|
||||
if (!(rtp_session->rtcp_sock_input && rtp_session->rtcp_sock_output)) {
|
||||
if (rtp_session->rtcp_sock_input && switch_sockaddr_get_family(rtp_session->rtcp_remote_addr) ==
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_local_addr)) {
|
||||
rtp_session->rtcp_sock_output = rtp_session->rtcp_sock_input;
|
||||
} else {
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
|
||||
switch_socket_close(rtp_session->rtcp_sock_output);
|
||||
}
|
||||
if ((status = switch_socket_create(&rtp_session->rtcp_sock_output,
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_remote_addr),
|
||||
SOCK_DGRAM, 0, rtp_session->pool)) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Socket Error!";
|
||||
}
|
||||
if (rtp_session->rtcp_sock_input && switch_sockaddr_get_family(rtp_session->rtcp_remote_addr) ==
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_local_addr)) {
|
||||
rtp_session->rtcp_sock_output = rtp_session->rtcp_sock_input;
|
||||
} else {
|
||||
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
|
||||
switch_socket_close(rtp_session->rtcp_sock_output);
|
||||
}
|
||||
|
||||
if ((status = switch_socket_create(&rtp_session->rtcp_sock_output,
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_remote_addr),
|
||||
SOCK_DGRAM, 0, rtp_session->pool)) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Socket Error!";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
*err = "RTCP NOT ACTIVE!";
|
||||
}
|
||||
@@ -2510,12 +2511,42 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, d
|
||||
if (rtp_session->dtls) {
|
||||
free_dtls(&rtp_session->dtls);
|
||||
}
|
||||
|
||||
if (rtp_session->jb) {
|
||||
stfu_n_reset(rtp_session->jb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((type & DTLS_TYPE_RTCP) && rtp_session->rtcp_dtls) {
|
||||
free_dtls(&rtp_session->rtcp_dtls);
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_SRTP
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
|
||||
int x;
|
||||
for(x = 0; x < 2; x++) {
|
||||
if (rtp_session->send_ctx[x]) {
|
||||
srtp_dealloc(rtp_session->send_ctx[x]);
|
||||
rtp_session->send_ctx[x] = NULL;
|
||||
}
|
||||
}
|
||||
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND] = 0;
|
||||
}
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV]) {
|
||||
int x;
|
||||
for (x = 0; x < 2; x++) {
|
||||
if (rtp_session->recv_ctx[x]) {
|
||||
srtp_dealloc(rtp_session->recv_ctx[x]);
|
||||
rtp_session->recv_ctx[x] = NULL;
|
||||
}
|
||||
}
|
||||
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2560,7 +2591,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
|
||||
|
||||
dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
|
||||
dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
|
||||
//dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR);
|
||||
dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR);
|
||||
|
||||
dtls->ssl_ctx = SSL_CTX_new(DTLSv1_method());
|
||||
switch_assert(dtls->ssl_ctx);
|
||||
@@ -2603,7 +2634,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (!zstr(dtls->ca) && (ret=SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
|
||||
if (!zstr(dtls->ca) && switch_file_exists(dtls->ca, rtp_session->pool) == SWITCH_STATUS_SUCCESS
|
||||
&& (ret = SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check chain cert failed [%d]\n",
|
||||
rtp_type(rtp_session) ,
|
||||
SSL_get_error(dtls->ssl, ret));
|
||||
@@ -2964,7 +2996,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
"Starting timer [%s] %d bytes per %dms\n", timer_name, samples_per_interval, ms_per_packet / 1000);
|
||||
} else {
|
||||
memset(&rtp_session->timer, 0, sizeof(rtp_session->timer));
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error starting timer [%s], async RTP disabled\n", timer_name);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR,
|
||||
"Error Starting timer [%s] %d bytes per %dms, async RTP disabled\n", timer_name, samples_per_interval, ms_per_packet / 1000);
|
||||
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
}
|
||||
} else {
|
||||
@@ -3360,7 +3393,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
|
||||
ice->ice_params = ice_params;
|
||||
ice->pass = "";
|
||||
ice->rpass = "";
|
||||
|
||||
ice->ready = 0;
|
||||
ice->rready = 0;
|
||||
ice->next_run = switch_micro_time_now();
|
||||
|
||||
if (password) {
|
||||
@@ -4014,6 +4048,21 @@ static void do_flush(switch_rtp_t *rtp_session, int force)
|
||||
READ_DEC(rtp_session);
|
||||
}
|
||||
|
||||
static int jb_valid(switch_rtp_t *rtp_session)
|
||||
{
|
||||
if (rtp_session->ice.ice_user) {
|
||||
if (!rtp_session->ice.ready && rtp_session->ice.rready) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtp_session->dtls && rtp_session->dtls->state != DS_READY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define return_cng_frame() do_cng = 1; goto timer_check
|
||||
|
||||
static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags, switch_bool_t return_jb_packet)
|
||||
@@ -4157,14 +4206,13 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] &&
|
||||
rtp_session->recv_msg.header.version == 2 && rtp_session->recv_msg.header.x) { /* header extensions */
|
||||
uint16_t length;
|
||||
|
||||
rtp_session->recv_msg.ext = (switch_rtp_hdr_ext_t *) rtp_session->recv_msg.body;
|
||||
length = ntohs((uint16_t)rtp_session->recv_msg.ext->length);
|
||||
|
||||
rtp_session->recv_msg.ext->length = ntohs((uint16_t)rtp_session->recv_msg.ext->length);
|
||||
rtp_session->recv_msg.ext->profile = ntohs((uint16_t)rtp_session->recv_msg.ext->profile);
|
||||
|
||||
if (rtp_session->recv_msg.ext->length < SWITCH_RTP_MAX_BUF_LEN_WORDS) {
|
||||
rtp_session->recv_msg.ebody = rtp_session->recv_msg.body + (rtp_session->recv_msg.ext->length * 4) + 4;
|
||||
if (length < SWITCH_RTP_MAX_BUF_LEN_WORDS) {
|
||||
rtp_session->recv_msg.ebody = rtp_session->recv_msg.body + (length * 4) + 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4222,7 +4270,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] &&
|
||||
*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
|
||||
ts && !rtp_session->jb && !rtp_session->pause_jb && ts == rtp_session->last_cng_ts) {
|
||||
ts && !rtp_session->jb && !rtp_session->pause_jb && jb_valid(rtp_session) && ts == rtp_session->last_cng_ts) {
|
||||
/* we already sent this frame..... */
|
||||
*bytes = 0;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -4340,7 +4388,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->jb && !rtp_session->pause_jb && rtp_session->recv_msg.header.version == 2 && *bytes) {
|
||||
if (rtp_session->jb && !rtp_session->pause_jb && jb_valid(rtp_session) && rtp_session->recv_msg.header.version == 2 && *bytes) {
|
||||
if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
|
||||
!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
|
||||
stfu_n_reset(rtp_session->jb);
|
||||
@@ -4365,7 +4413,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
*bytes = 0;
|
||||
}
|
||||
|
||||
if (rtp_session->jb && !rtp_session->pause_jb) {
|
||||
if (rtp_session->jb && !rtp_session->pause_jb && jb_valid(rtp_session)) {
|
||||
if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) {
|
||||
memcpy(RTP_BODY(rtp_session), jb_frame->data, jb_frame->dlen);
|
||||
|
||||
@@ -4545,7 +4593,14 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
return status;
|
||||
}
|
||||
|
||||
static int using_ice(switch_rtp_t *rtp_session)
|
||||
{
|
||||
if (rtp_session->ice.ice_user || rtp_session->rtcp_ice.ice_user) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_type, switch_frame_flag_t *flags, switch_io_flag_t io_flags)
|
||||
{
|
||||
@@ -4693,7 +4748,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
pt = 100000;
|
||||
}
|
||||
|
||||
|
||||
if (using_ice(rtp_session)) {
|
||||
pt = 20000;
|
||||
}
|
||||
|
||||
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
|
||||
|
||||
|
||||
@@ -4780,20 +4838,19 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
}
|
||||
}
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
if (using_ice(rtp_session)) {
|
||||
if (check_rtcp_and_ice(rtp_session) == -1) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
goto recvfrom;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
|
||||
(rtp_session->dtmf_data.out_digit_dur == 0)) {
|
||||
return_cng_frame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rtcp:
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
|
||||
@@ -5749,7 +5806,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
send = 0;
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_PAUSE]) {
|
||||
send = 0;
|
||||
}
|
||||
|
||||
if (send) {
|
||||
send_msg->header.seq = htons(++rtp_session->seq);
|
||||
|
||||
Reference in New Issue
Block a user