Merge branch 'master' into v1.4.beta

This commit is contained in:
Ken Rice
2013-11-02 17:36:09 -05:00
28 changed files with 1462 additions and 159 deletions
+21 -19
View File
@@ -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
View File
@@ -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;
+5 -3
View File
@@ -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"
+4 -4
View File
@@ -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;
+1
View File
@@ -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;
+1
View File
@@ -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);
+23
View File
@@ -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);
+4
View File
@@ -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;
+8 -2
View File
@@ -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);
+19 -3
View File
@@ -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);
+57 -7
View File
@@ -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));
+1 -1
View File
@@ -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))) {
+35 -1
View File
@@ -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);
+8 -5
View File
@@ -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;
}
+75 -17
View File
@@ -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
View File
@@ -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) {
+13
View File
@@ -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
View File
@@ -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"))) {
+7 -4
View File
@@ -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
View File
@@ -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);
}
}
}
+4
View File
@@ -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
View File
@@ -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);