diff --git a/Makefile.am b/Makefile.am
index 21b83bad2f..a3e942a036 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,9 +3,17 @@ SUBDIRS = . src
AUTOMAKE_OPTIONS = foreign
NAME = freeswitch
+AM_LIBAPR_CFLAGS := $(shell ./libs/apr/apr-1-config --cflags)
+AM_LIBAPR_CPPFLAGS := $(shell ./libs/apr/apr-1-config --cppflags --includes)
+AM_LIBAPR_LDFLAGS := $(shell ./libs/apr/apr-1-config --ldflags)
+AM_LIBAPR_LIBS := $(subst $(CURDIR)/,,$(shell ./libs/apr/apr-1-config \--link-libtool \--libs))
+AM_LIBAPU_CPPFLAGS := $(shell ./libs/apr-util/apu-1-config --includes)
+AM_LIBAPU_LDFLAGS := $(shell ./libs/apr-util/apu-1-config --ldflags)
+AM_LIBAPU_LIBS := $(subst $(CURDIR)/,,$(shell ./libs/apr-util/apu-1-config \--link-libtool \--libs))
+
AM_CFLAGS = $(SWITCH_AM_CFLAGS) $(SWITCH_ANSI_CFLAGS)
AM_CPPFLAGS = $(SWITCH_AM_CXXFLAGS) -Ilibs/sofia-sip/libsofia-sip-ua/sdp -Ilibs/sofia-sip/libsofia-sip-ua/su
-AM_LDFLAGS = $(SWITCH_AM_LDFLAGS)
+AM_LDFLAGS = $(SWITCH_AM_LDFLAGS) $(AM_LIBAPR_LDFLAGS) $(AM_LIBAPU_LDFLAGS)
DEFAULT_SOUNDS=en-us-callie-8000
@@ -101,8 +109,8 @@ $(RECURSIVE_TARGETS): freeswitch
exit 1; \
fi ;
-CORE_CFLAGS = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes`
-CORE_CFLAGS += `$(switch_builddir)/libs/apr-util/apu-1-config --includes`
+CORE_CFLAGS = $(AM_LIBAPR_CFLAGS) $(AM_LIBAPR_CPPFLAGS)
+CORE_CFLAGS += $(AM_LIBAPU_CPPFLAGS)
CORE_CFLAGS += -I$(switch_srcdir)/libs/libtpl-1.5/src
CORE_CFLAGS += -I$(switch_srcdir)/libs/stfu
CORE_CFLAGS += -I$(switch_builddir)/libs/sqlite
@@ -112,7 +120,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/crypto/include -Ilibs/srtp/crypto/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff-4.0.2/libtiff
-CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la
+CORE_LIBS = $(AM_LIBAPU_LIBS) $(AM_LIBAPR_LIBS)
CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la
if ENABLE_SRTP
diff --git a/acinclude.m4 b/acinclude.m4
index 58b5500a80..aeba17b5c3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -6,7 +6,6 @@ m4_include([build/config/ac_gcc_archflag.m4])
m4_include([build/config/ac_gcc_x86_cpuid.m4])
m4_include([build/config/ax_lib_mysql.m4])
m4_include([build/config/ax_check_java.m4])
-m4_include([build/config/uuid.m4])
m4_include([build/config/erlang.m4])
m4_include([build/config/odbc.m4])
m4_include([build/config/sched_setaffinity.m4])
diff --git a/build/config/uuid.m4 b/build/config/uuid.m4
deleted file mode 100644
index 7f37c23c66..0000000000
--- a/build/config/uuid.m4
+++ /dev/null
@@ -1,17 +0,0 @@
-AC_DEFUN([CHECK_LIBUUID],
- [
- PKG_CHECK_MODULES([LIBUUID], [uuid >= 1.41.2],
- [LIBUUID_FOUND=yes], [LIBUUID_FOUND=no])
- if test "$LIBUUID_FOUND" = "no" ; then
- PKG_CHECK_MODULES([LIBUUID], [uuid],
- [LIBUUID_FOUND=yes], [LIBUUID_FOUND=no])
- if test "$LIBUUID_FOUND" = "no" ; then
- AC_MSG_WARN([libuuid development package highly recommended!])
- else
- LIBUUID_INCLUDEDIR=$(pkg-config --variable=includedir uuid)
- LIBUUID_CFLAGS+=" -I$LIBUUID_INCLUDEDIR/uuid "
- fi
- fi
- AC_SUBST([LIBUUID_CFLAGS])
- AC_SUBST([LIBUUID_LIBS])
- ])
diff --git a/conf/rayo/autoload_configs/rayo.conf.xml b/conf/rayo/autoload_configs/rayo.conf.xml
index 35419319bc..c8171569af 100644
--- a/conf/rayo/autoload_configs/rayo.conf.xml
+++ b/conf/rayo/autoload_configs/rayo.conf.xml
@@ -16,6 +16,12 @@
+
+
+
+
+
+
@@ -65,6 +71,7 @@
]]>
]]>
]]>
+ ]]>
]]>
]]>
]]>
diff --git a/configure.in b/configure.in
index d186eebc94..9307c958c9 100644
--- a/configure.in
+++ b/configure.in
@@ -412,10 +412,6 @@ if test "x$enable_core_odbc_support" != "xno"; then
AC_CHECK_LIB([odbc], [SQLDisconnect],, AC_MSG_ERROR([no usable libodbc; please install unixodbc devel package or equivalent]))
fi
-CHECK_LIBUUID
-SWITCH_AM_LDFLAGS="$LIBUUID_LIBS $SWITCH_AM_LDFLAGS"
-SWITCH_AM_CFLAGS="$LIBUUID_CFLAGS $SWITCH_AM_CFLAGS"
-
AC_ARG_ENABLE(core-pgsql-support,
[AS_HELP_STRING([--enable-core-pgsql-support], [Compile with PGSQL Support])],,[enable_core_pgsql_support="no"])
AC_ARG_ENABLE(core-pgsql-pkgconfig,
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 3ac9bd0a36..227d5a698f 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -789,11 +789,16 @@ 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) {
+ if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to read from dead channel %s device %d:%d\n", name, span_id, chan_id);
+ goto normal_failure;
+ }
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_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 {
tech_pvt->read_error = 0;
}
@@ -822,6 +827,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
fail:
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);
+normal_failure:
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
return SWITCH_STATUS_GENERR;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
index 8cf43bbdfd..fdeb67f4b9 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
@@ -291,13 +291,23 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
return FTDM_FAIL;
case FTDM_SIG_STATE_SUSPENDED:
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
+ int cas_bits = 0xFF;
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits);
+ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL);
+ }
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)) {
+ int cas_bits = 0x00;
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_CAS_BITS, &cas_bits);
+ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
+ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
+ }
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
}
@@ -643,7 +653,7 @@ 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) {
+ if (ftdmchan->state == FTDM_CHANNEL_STATE_UP) {
cas_bits = 0;
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CAS_BITS, &cas_bits);
if (!(state_counter % 5000)) {
diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
index bb7e477092..e7122740aa 100644
--- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
+++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
@@ -951,6 +951,21 @@ static FIO_GET_ALARMS_FUNCTION(zt_get_alarms)
return FTDM_SUCCESS;
}
+#define ftdm_zt_set_event_pending(fchan) \
+ do { \
+ ftdm_set_io_flag(fchan, FTDM_CHANNEL_IO_EVENT); \
+ fchan->last_event_time = ftdm_current_time_in_ms(); \
+ } while (0);
+
+#define ftdm_zt_store_chan_event(fchan, revent) \
+ do { \
+ if (fchan->io_data) { \
+ ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Dropping event %d, not retrieved on time\n", revent); \
+ } \
+ fchan->io_data = (void *)zt_event_id; \
+ ftdm_zt_set_event_pending(fchan); \
+ } while (0);
+
/**
* \brief Waits for an event on a Zaptel/DAHDI channel
* \param ftdmchan Channel to open
@@ -1015,7 +1030,7 @@ pollagain:
*flags |= FTDM_WRITE;
}
- if (inflags & POLLPRI) {
+ if ((inflags & POLLPRI) || (ftdmchan->io_data && (*flags & FTDM_EVENTS))) {
*flags |= FTDM_EVENTS;
}
@@ -1044,19 +1059,28 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event)
j++;
}
- r = poll(pfds, j, ms);
+ r = poll(pfds, j, ms);
if (r == 0) {
return FTDM_TIMEOUT;
- } else if (r < 0 || (pfds[i-1].revents & POLLERR)) {
+ } else if (r < 0) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return FTDM_FAIL;
}
for(i = 1; i <= span->chan_count; i++) {
- if (pfds[i-1].revents & POLLPRI) {
- ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT);
- span->channels[i]->last_event_time = ftdm_current_time_in_ms();
+
+ ftdm_channel_lock(span->channels[i]);
+
+ if (pfds[i-1].revents & POLLERR) {
+ ftdm_log_chan(span->channels[i], FTDM_LOG_ERROR, "POLLERR, flags=%d\n", pfds[i-1].events);
+
+ ftdm_channel_unlock(span->channels[i]);
+
+ continue;
+ }
+ if ((pfds[i-1].revents & POLLPRI) || (span->channels[i]->io_data)) {
+ ftdm_zt_set_event_pending(span->channels[i]);
k++;
}
if (pfds[i-1].revents & POLLIN) {
@@ -1065,6 +1089,9 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event)
if (pfds[i-1].revents & POLLOUT) {
ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_WRITE);
}
+
+ ftdm_channel_unlock(span->channels[i]);
+
}
if (!k) {
@@ -1243,7 +1270,10 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event)
ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT);
}
- if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
+ if (ftdmchan->io_data) {
+ zt_event_id = (zt_event_t)ftdmchan->io_data;
+ ftdmchan->io_data = NULL;
+ } else if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event from channel: %s\n",
strerror(errno));
return FTDM_FAIL;
@@ -1274,30 +1304,48 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
uint32_t i, event_id = FTDM_OOB_INVALID;
zt_event_t zt_event_id = 0;
- for(i = 1; i <= span->chan_count; i++) {
+ for (i = 1; i <= span->chan_count; i++) {
ftdm_channel_t *fchan = span->channels[i];
- if (ftdm_test_io_flag(fchan, FTDM_CHANNEL_IO_EVENT)) {
- ftdm_clear_io_flag(fchan, FTDM_CHANNEL_IO_EVENT);
- if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
- snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
- return FTDM_FAIL;
- }
- ftdm_channel_lock(fchan);
- if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) {
- ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to process DAHDI event %d from channel\n", zt_event_id);
- ftdm_channel_unlock(fchan);
- return FTDM_FAIL;
- }
+ ftdm_channel_lock(fchan);
+
+ if (!ftdm_test_io_flag(fchan, FTDM_CHANNEL_IO_EVENT)) {
+
ftdm_channel_unlock(fchan);
- fchan->last_event_time = 0;
- span->event_header.e_type = FTDM_EVENT_OOB;
- span->event_header.enum_id = event_id;
- span->event_header.channel = fchan;
- *event = &span->event_header;
- return FTDM_SUCCESS;
+ continue;
}
+
+ ftdm_clear_io_flag(fchan, FTDM_CHANNEL_IO_EVENT);
+
+ if (fchan->io_data) {
+ zt_event_id = (zt_event_t)fchan->io_data;
+ fchan->io_data = NULL;
+ } else if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
+ ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to retrieve DAHDI event from channel: %s\n", strerror(errno));
+
+ ftdm_channel_unlock(fchan);
+
+ continue;
+ }
+
+ if ((zt_channel_process_event(fchan, &event_id, zt_event_id)) != FTDM_SUCCESS) {
+ ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to process DAHDI event %d from channel\n", zt_event_id);
+
+ ftdm_channel_unlock(fchan);
+
+ return FTDM_FAIL;
+ }
+
+ fchan->last_event_time = 0;
+ span->event_header.e_type = FTDM_EVENT_OOB;
+ span->event_header.enum_id = event_id;
+ span->event_header.channel = fchan;
+ *event = &span->event_header;
+
+ ftdm_channel_unlock(fchan);
+
+ return FTDM_SUCCESS;
}
return FTDM_FAIL;
@@ -1348,11 +1396,13 @@ static FIO_READ_FUNCTION(zt_read)
}
if (handle_dtmf_event(ftdmchan, zt_event_id)) {
- /* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
- ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Event %d is not dmtf related. Skipping one media read cycle\n", zt_event_id);
+ /* Enqueue this event for later */
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Deferring event %d to be able to read data\n", zt_event_id);
+ ftdm_zt_store_chan_event(ftdmchan, zt_event_id);
+ } else {
+ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Skipping one IO read cycle due to DTMF event processing\n");
}
- ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Skipping one IO read cycle due to events pending in the driver queue\n");
- break;
+ continue;
}
/* Read error, keep going unless to many errors force us to abort ...*/
@@ -1405,8 +1455,9 @@ tryagain:
}
if (handle_dtmf_event(ftdmchan, zt_event_id)) {
- /* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
- ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id);
+ /* Enqueue this event for later */
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Deferring event %d to be able to write data\n", zt_event_id);
+ ftdm_zt_store_chan_event(ftdmchan, zt_event_id);
}
goto tryagain;
diff --git a/libs/libedit/configure.ac b/libs/libedit/configure.ac
index 207bb0f118..7bd2ac6326 100644
--- a/libs/libedit/configure.ac
+++ b/libs/libedit/configure.ac
@@ -71,7 +71,7 @@ AC_PROG_GCC_TRADITIONAL
#AC_FUNC_REALLOC
AC_TYPE_SIGNAL
AC_FUNC_STAT
-AC_CHECK_FUNCS([endpwent isascii memchr memset re_comp regcomp strcasecmp strchr strcspn strdup strerror strrchr strstr strtol issetugid])
+AC_CHECK_FUNCS([endpwent isascii memchr memset re_comp regcomp strcasecmp strchr strlcat strlcpy strcspn strdup strerror strrchr strstr strtol issetugid])
EL_GETPW_R_POSIX
EL_GETPW_R_DRAFT
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index bff9b72a78..aa6adb67e9 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -178,6 +178,7 @@ struct switch_core_session {
switch_size_t recur_buffer_len;
switch_media_handle_t *media_handle;
+ uint32_t decoder_errors;
};
struct switch_media_bug {
diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h
index 9641718f07..5c083101a9 100644
--- a/src/include/switch_core_media.h
+++ b/src/include/switch_core_media.h
@@ -68,7 +68,6 @@ typedef enum {
SCMF_RUNNING,
SCMF_DISABLE_TRANSCODING,
SCMF_AUTOFIX_TIMING,
- SCMF_AUTOFIX_PT,
SCMF_CODEC_GREEDY,
SCMF_CODEC_SCROOGE,
SCMF_DISABLE_HOLD,
@@ -81,6 +80,8 @@ typedef enum {
SCMF_AUTOFLUSH,
SCMF_REWRITE_TIMESTAMPS,
SCMF_RTP_AUTOFLUSH_DURING_BRIDGE,
+ SCMF_MULTI_ANSWER_AUDIO,
+ SCMF_MULTI_ANSWER_VIDEO,
SCMF_MAX
} switch_core_media_flag_t;
@@ -156,6 +157,53 @@ typedef struct switch_core_media_params_s {
} switch_core_media_params_t;
+typedef struct xpayload_map_s {
+ uint32_t pt;
+ uint32_t send_pt;
+ uint32_t rate;
+ uint32_t ptime;
+ switch_media_type_t type;
+ uint8_t negotiated;
+ char *name;
+ switch_sdp_type_t sdp_type;
+ unsigned long hash;
+ struct xpayload_map_s *next;
+} xpayload_map_t;
+
+typedef struct payload_map_s {
+ switch_media_type_t type;
+ switch_sdp_type_t sdp_type;
+ uint32_t ptime;
+ uint32_t rate;
+ uint8_t allocated;
+ uint8_t negotiated;
+ unsigned long hash;
+
+ char *rm_encoding;
+ char *iananame;
+ switch_payload_t pt;
+ unsigned long rm_rate;
+ unsigned long adv_rm_rate;
+ uint32_t codec_ms;
+ uint32_t bitrate;
+
+ char *rm_fmtp;
+
+ switch_payload_t agreed_pt;
+ switch_payload_t recv_pt;
+
+ char *fmtp_out;
+
+ char *remote_sdp_ip;
+ switch_port_t remote_sdp_port;
+
+ int channels;
+ int adv_channels;
+
+ struct payload_map_s *next;
+
+} payload_map_t;
+
static inline const char *switch_media_type2str(switch_media_type_t type)
{
switch(type) {
@@ -216,7 +264,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
SWITCH_DECLARE(switch_status_t) switch_core_media_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip);
SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_core_session_t *session,
switch_core_session_t *other_session, switch_t38_options_t *t38_options);
-SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, const char *ip, switch_port_t port, const char *sr, int force);
+SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, switch_sdp_type_t sdp_type,
+ const char *ip, switch_port_t port, const char *sr, int force);
SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup);
SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t *session, switch_t38_options_t *t38_options, int insist);
@@ -232,7 +281,6 @@ SWITCH_DECLARE(void) switch_core_media_kill_socket(switch_core_session_t *sessio
SWITCH_DECLARE(switch_status_t) switch_core_media_queue_rfc2833(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf);
SWITCH_DECLARE(switch_status_t) switch_core_media_queue_rfc2833_in(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf);
SWITCH_DECLARE(uint8_t) switch_core_media_ready(switch_core_session_t *session, switch_media_type_t type);
-SWITCH_DECLARE(void) switch_core_media_set_recv_pt(switch_core_session_t *session, switch_media_type_t type, switch_payload_t pt);
SWITCH_DECLARE(void) switch_core_media_set_telephony_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te);
SWITCH_DECLARE(void) switch_core_media_set_telephony_recv_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te);
SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_stats(switch_core_session_t *session, switch_media_type_t type, switch_memory_pool_t *pool);
@@ -257,6 +305,14 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void);
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);
+SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_session_t *session,
+ switch_media_type_t type,
+ const char *name,
+ switch_sdp_type_t sdp_type,
+ uint32_t pt,
+ uint32_t rate,
+ uint32_t ptime,
+ uint8_t negotiated);
SWITCH_END_EXTERN_C
#endif
diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h
index 39ffb9ca6b..4e46b61d2f 100644
--- a/src/include/switch_frame.h
+++ b/src/include/switch_frame.h
@@ -37,6 +37,7 @@
#define SWITCH_FRAME_H
#include
+#include
SWITCH_BEGIN_EXTERN_C
/*! \brief An abstraction of a data frame */
@@ -71,6 +72,7 @@ SWITCH_BEGIN_EXTERN_C
/*! frame flags */
switch_frame_flag_t flags;
void *user_data;
+ payload_map_t *pmap;
};
SWITCH_END_EXTERN_C
diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h
index bd509cc29a..ca0b3f3b8d 100644
--- a/src/include/switch_rtp.h
+++ b/src/include/switch_rtp.h
@@ -485,7 +485,6 @@ SWITCH_DECLARE(void) switch_rtp_set_private(switch_rtp_t *rtp_session, void *pri
*/
SWITCH_DECLARE(void) switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, switch_payload_t te);
SWITCH_DECLARE(void) switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_session, switch_payload_t te);
-SWITCH_DECLARE(void) switch_rtp_set_recv_pt(switch_rtp_t *rtp_session, switch_payload_t pt);
/*!
\brief Set the payload type for comfort noise
@@ -500,7 +499,7 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
\return the pointer to the private data
*/
SWITCH_DECLARE(void *) switch_rtp_get_private(switch_rtp_t *rtp_session);
-
+SWITCH_DECLARE(switch_status_t) switch_rtp_set_payload_map(switch_rtp_t *rtp_session, payload_map_t **pmap);
SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs);
SWITCH_DECLARE(switch_rtp_stats_t *) switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool);
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 2e4259817a..4a3153de5a 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -1929,40 +1929,91 @@ SWITCH_STANDARD_API(cond_function)
}
a = argv[0];
+ while(*a == ' ' || *a == '\t') a++;
- if ((expr = strchr(a, '!'))) {
- *expr++ = '\0';
- if (*expr == '=') {
- o = O_NE;
- }
- } else if ((expr = strchr(a, '>'))) {
- if (*(expr + 1) == '=') {
+ if (*a == '\'') {
+ if ((expr = switch_find_end_paren(a, '\'', '\''))) {
+ a++;
*expr++ = '\0';
- o = O_GE;
} else {
- o = O_GT;
+ goto error;
}
- } else if ((expr = strchr(a, '<'))) {
- if (*(expr + 1) == '=') {
+ } else {
+ if ((expr = strchr(a, ' '))) {
*expr++ = '\0';
- o = O_LE;
} else {
- o = O_LT;
- }
- } else if ((expr = strchr(a, '='))) {
- *expr++ = '\0';
- if (*expr == '=') {
- o = O_EQ;
+ expr = a;
}
}
+ while(expr && *expr) {
+ switch(*expr) {
+ case '!':
+ case '<':
+ case '>':
+ case '=':
+ goto done;
+ default:
+ expr++;
+ break;
+ }
+ }
+
+ done:
+
+ switch(*expr) {
+ case '!':
+ *expr++ = '\0';
+ if (*expr == '=') {
+ o = O_NE;
+ *expr++ = '\0';
+ }
+ break;
+
+ case '>':
+ *expr++ = '\0';
+ if (*expr == '=') {
+ o = O_GE;
+ *expr++ = '\0';
+ } else {
+ o = O_GT;
+ }
+ break;
+
+ case '<':
+ *expr++ = '\0';
+ if (*expr == '=') {
+ o = O_LE;
+ *expr++ = '\0';
+ } else {
+ o = O_LT;
+ }
+ break;
+
+ case '=':
+ *expr++ = '\0';
+ if (*expr == '=') {
+ o = O_EQ;
+ *expr++ = '\0';
+ }
+ break;
+
+ default:
+ goto error;
+ }
+
+
if (o) {
char *s_a = NULL, *s_b = NULL;
int a_is_num, b_is_num;
- *expr++ = '\0';
+
+ expr++;
b = expr;
+
s_a = switch_strip_spaces(a, SWITCH_TRUE);
s_b = switch_strip_spaces(b, SWITCH_TRUE);
+
+
a_is_num = switch_is_number(s_a);
b_is_num = switch_is_number(s_b);
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 8f3f1a81b8..55e681aa09 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -184,7 +184,8 @@ typedef enum {
MFLAG_NOMOH = (1 << 19),
MFLAG_VIDEO_BRIDGE = (1 << 20),
MFLAG_INDICATE_MUTE_DETECT = (1 << 21),
- MFLAG_PAUSE_RECORDING = (1 << 22)
+ MFLAG_PAUSE_RECORDING = (1 << 22),
+ MFLAG_ACK_VIDEO = (1 << 23)
} member_flag_t;
typedef enum {
@@ -1796,6 +1797,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
channel = switch_core_session_get_channel(member->session);
+ if (switch_channel_test_flag(channel, CF_VIDEO)) {
+ switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
+ }
+
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
@@ -2595,6 +2600,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
char *rfile = switch_channel_expand_variables(channel, conference->auto_record);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile);
launch_conference_record_thread(conference, rfile, SWITCH_TRUE);
+
if (rfile != conference->auto_record) {
conference->record_filename = switch_core_strdup(conference->pool, rfile);
switch_safe_free(rfile);
@@ -3639,6 +3645,12 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
break;
}
+ if (switch_channel_test_flag(channel, CF_VIDEO) && !switch_test_flag(member, MFLAG_ACK_VIDEO)) {
+ switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
+ switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
+ switch_core_session_refresh_video(member->session);
+ }
+
/* if we have caller digits, feed them to the parser to find an action */
if (switch_channel_has_dtmf(channel)) {
char dtmf[128] = "";
diff --git a/src/mod/applications/mod_mongo/Makefile b/src/mod/applications/mod_mongo/Makefile
index 9ce16b1171..7a6e1058ab 100644
--- a/src/mod/applications/mod_mongo/Makefile
+++ b/src/mod/applications/mod_mongo/Makefile
@@ -1,6 +1,6 @@
BASE=../../../..
-MONGO_CXX_DRIVER_VERSION=v1.8
+MONGO_CXX_DRIVER_VERSION=v2.4
MONGO_CXX_DRIVER_URL=http://downloads.mongodb.org/cxx-driver
MONGO_CXX_DRIVER_TARBALL=mongodb-linux-x86_64-$(MONGO_CXX_DRIVER_VERSION)-latest.tgz
MONGO_CXX_DRIVER_SRC=$(BASE)/libs/mongo-cxx-driver-$(MONGO_CXX_DRIVER_VERSION)
@@ -9,7 +9,7 @@ LIBMONGOCLIENT_A =$(MONGO_CXX_DRIVER_SRC)/libmongoclient.a
LOCAL_SOURCES=mongo_conn.cpp
LOCAL_OBJS=mongo_conn.o
-LOCAL_CFLAGS=-I$(MONGO_CXX_DRIVER_SRC)/mongo
+LOCAL_CFLAGS=-I$(MONGO_CXX_DRIVER_SRC)/src
LOCAL_LIBADD=$(LIBMONGOCLIENT_A)
LOCAL_LDFLAGS=-lboost_thread -lboost_filesystem-mt -lboost_system-mt
MODDIR=$(shell pwd)
diff --git a/src/mod/applications/mod_mongo/fpic_hack.diff b/src/mod/applications/mod_mongo/fpic_hack.diff
index 882f3c899a..1f85f85c97 100644
--- a/src/mod/applications/mod_mongo/fpic_hack.diff
+++ b/src/mod/applications/mod_mongo/fpic_hack.diff
@@ -1,11 +1,11 @@
---- SConstruct.orig 2011-04-28 19:00:36.000000000 +0200
-+++ SConstruct 2011-04-28 19:01:19.000000000 +0200
-@@ -45,7 +45,7 @@
- linux = True
+--- SConstruct 2013-10-30 17:18:51.160645496 -0400
++++ new 2013-10-30 17:22:18.790072856 -0400
+@@ -78,7 +78,7 @@
+ env['DIST_ARCHIVE_SUFFIX'] = '.tgz'
if nix:
-- env.Append( CPPFLAGS=" -O3" )
-+ env.Append( CPPFLAGS=" -I../pcre -fPIC -O3" )
- env.Append( LIBS=["pthread"] )
+- env.Append(CCFLAGS=["-O3", "-pthread"])
++ env.Append(CCFLAGS=["-I../pcre", "-fPIC", "-O3", "-pthread"])
if linux:
- env.Append( LINKFLAGS=" -Wl,--as-needed -Wl,-zdefs " )
+ env.Append(LINKFLAGS=["-pthread"])
+
diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp
index 83b31c7546..8c3536def2 100644
--- a/src/mod/applications/mod_mongo/mod_mongo.cpp
+++ b/src/mod/applications/mod_mongo/mod_mongo.cpp
@@ -1,6 +1,6 @@
-/*
+/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2012, Anthony Minessale II
+ * Copyright (C) 2005-2013, Anthony Minessale II
*
* Version: MPL 1.1
*
@@ -22,7 +22,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- *
+ *
* Tamas Cseke
*
* mod_mongo.cpp -- API for MongoDB
@@ -53,7 +53,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
switch_assert(ns != NULL);
if ((json_query = strchr(ns, DELIMITER))) {
- *json_query++ = '\0';
+ *json_query++ = '\0';
}
if (!zstr(ns) && !zstr(json_query)) {
@@ -62,7 +62,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
BSONObj out;
BSONObjBuilder cmd;
- cmd.append("mapreduce", conn->nsGetCollection(ns));
+ cmd.append("mapreduce", nsGetCollection(ns));
if (!zstr(globals.map)) {
cmd.appendCode("map", globals.map);
}
@@ -79,10 +79,10 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
conn = mongo_connection_pool_get(globals.conn_pool);
if (conn) {
- conn->runCommand(conn->nsGetDB(ns), cmd.done(), out);
+ conn->runCommand(nsGetDB(ns), cmd.done(), out);
mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE);
- stream->write_function(stream, "-OK\n%s\n", out.toString().c_str());
+ stream->write_function(stream, "-OK\n%s\n", out.jsonString().c_str());
} else {
stream->write_function(stream, "-ERR\nNo connection\n");
}
@@ -93,7 +93,7 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
}
} else {
- stream->write_function(stream, "-ERR\n%s\n", MAPREDUCE_SYNTAX);
+ stream->write_function(stream, "-ERR\n%s\n", MAPREDUCE_SYNTAX);
}
switch_safe_free(ns);
@@ -104,50 +104,50 @@ SWITCH_STANDARD_API(mongo_mapreduce_function)
SWITCH_STANDARD_API(mongo_find_one_function)
{
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- char *ns = NULL, *json_query = NULL, *json_fields = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *ns = NULL, *json_query = NULL, *json_fields = NULL;
- ns = strdup(cmd);
- switch_assert(ns != NULL);
+ ns = strdup(cmd);
+ switch_assert(ns != NULL);
- if ((json_query = strchr(ns, DELIMITER))) {
- *json_query++ = '\0';
- if ((json_fields = strchr(json_query, DELIMITER))) {
- *json_fields++ = '\0';
- }
- }
+ if ((json_query = strchr(ns, DELIMITER))) {
+ *json_query++ = '\0';
+ if ((json_fields = strchr(json_query, DELIMITER))) {
+ *json_fields++ = '\0';
+ }
+ }
- if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) {
+ if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) {
- DBClientBase *conn = NULL;
+ DBClientBase *conn = NULL;
- try {
- BSONObj query = fromjson(json_query);
- BSONObj fields = fromjson(json_fields);
+ try {
+ BSONObj query = fromjson(json_query);
+ BSONObj fields = fromjson(json_fields);
- conn = mongo_connection_pool_get(globals.conn_pool);
- if (conn) {
- BSONObj res = conn->findOne(ns, Query(query), &fields);
- mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE);
+ conn = mongo_connection_pool_get(globals.conn_pool);
+ if (conn) {
+ BSONObj res = conn->findOne(ns, Query(query), &fields);
+ mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_FALSE);
- stream->write_function(stream, "-OK\n%s\n", res.toString().c_str());
- } else {
- stream->write_function(stream, "-ERR\nNo connection\n");
- }
- } catch (DBException &e) {
- if (conn) {
- mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE);
- }
- stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
- }
+ stream->write_function(stream, "-OK\n%s\n", res.jsonString().c_str());
+ } else {
+ stream->write_function(stream, "-ERR\nNo connection\n");
+ }
+ } catch (DBException &e) {
+ if (conn) {
+ mongo_connection_pool_put(globals.conn_pool, conn, SWITCH_TRUE);
+ }
+ stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str());
+ }
- } else {
+ } else {
stream->write_function(stream, "-ERR\n%s\n", FIND_ONE_SYNTAX);
- }
+ }
- switch_safe_free(ns);
+ switch_safe_free(ns);
- return status;
+ return status;
}
static switch_status_t config(void)
@@ -214,21 +214,21 @@ SWITCH_MODULE_DEFINITION(mod_mongo, mod_mongo_load, mod_mongo_shutdown, NULL);
SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load)
{
- switch_api_interface_t *api_interface;
- switch_application_interface_t *app_interface;
+ switch_api_interface_t *api_interface;
+ switch_application_interface_t *app_interface;
- *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
- memset(&globals, 0, sizeof(globals));
+ memset(&globals, 0, sizeof(globals));
- if (config() != SWITCH_STATUS_SUCCESS) {
- return SWITCH_STATUS_TERM;
- }
-
- SWITCH_ADD_API(api_interface, "mongo_find_one", "findOne", mongo_find_one_function, FIND_ONE_SYNTAX);
- SWITCH_ADD_API(api_interface, "mongo_mapreduce", "Map/Reduce", mongo_mapreduce_function, MAPREDUCE_SYNTAX);
+ if (config() != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_TERM;
+ }
- return SWITCH_STATUS_SUCCESS;
+ SWITCH_ADD_API(api_interface, "mongo_find_one", "findOne", mongo_find_one_function, FIND_ONE_SYNTAX);
+ SWITCH_ADD_API(api_interface, "mongo_mapreduce", "Map/Reduce", mongo_mapreduce_function, MAPREDUCE_SYNTAX);
+
+ return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown)
diff --git a/src/mod/applications/mod_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h
index 00e927f3a1..822dacaf63 100644
--- a/src/mod/applications/mod_mongo/mod_mongo.h
+++ b/src/mod/applications/mod_mongo/mod_mongo.h
@@ -1,6 +1,6 @@
-/*
+/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2012, Anthony Minessale II
+ * Copyright (C) 2005-2013, Anthony Minessale II
*
* Version: MPL 1.1
*
@@ -32,22 +32,19 @@
#ifndef MOD_MONGO_H
#define MOD_MONGO_H
-#include
-#include
-#include
-#include
+#include
using namespace mongo;
typedef struct {
- char *conn_str;
+ char *conn_str;
- switch_size_t min_connections;
- switch_size_t max_connections;
- switch_size_t size;
- switch_queue_t *connections;
- switch_mutex_t *mutex;
- switch_memory_pool_t *pool;
+ switch_size_t min_connections;
+ switch_size_t max_connections;
+ switch_size_t size;
+ switch_queue_t *connections;
+ switch_mutex_t *mutex;
+ switch_memory_pool_t *pool;
} mongo_connection_pool_t;
@@ -56,7 +53,7 @@ switch_status_t mongo_connection_create(DBClientBase **connection, const char *c
void mongo_connection_destroy(DBClientBase **conn);
switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections,
- const char *conn_str);
+ const char *conn_str);
void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool);
diff --git a/src/mod/applications/mod_mongo/mongo_conn.cpp b/src/mod/applications/mod_mongo/mongo_conn.cpp
index 8c7687b860..fd095fe54a 100644
--- a/src/mod/applications/mod_mongo/mongo_conn.cpp
+++ b/src/mod/applications/mod_mongo/mongo_conn.cpp
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2012, Anthony Minessale II
+ * Copyright (C) 2005-2013, Anthony Minessale II
*
* Version: MPL 1.1
*
@@ -42,162 +42,161 @@
switch_status_t mongo_connection_create(DBClientBase **connection, const char *conn_str)
{
- DBClientBase *conn = NULL;
- string conn_string(conn_str), err_msg;
- ConnectionString cs = ConnectionString::parse(conn_string, err_msg);
- switch_status_t status = SWITCH_STATUS_FALSE;
-
- if (!cs.isValid()) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str());
- return status;
- }
+ DBClientBase *conn = NULL;
+ string conn_string(conn_str), err_msg;
+ ConnectionString cs = ConnectionString::parse(conn_string, err_msg);
+ switch_status_t status = SWITCH_STATUS_FALSE;
- try {
- conn = cs.connect(err_msg);
- } catch (DBException &e) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str());
- return status;
- }
+ if (!cs.isValid()) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str());
+ return status;
+ }
- if (conn) {
- *connection = conn;
- status = SWITCH_STATUS_SUCCESS;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str);
- }
+ try {
+ conn = cs.connect(err_msg);
+ } catch (DBException &e) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str());
+ return status;
+ }
- return status;
+ if (conn) {
+ *connection = conn;
+ status = SWITCH_STATUS_SUCCESS;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str);
+ }
+
+ return status;
}
void mongo_connection_destroy(DBClientBase **conn)
{
- switch_assert(*conn != NULL);
- delete *conn;
+ switch_assert(*conn != NULL);
+ delete *conn;
- *conn = NULL;
+ *conn = NULL;
}
switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections,
- const char *conn_str)
+ const char *conn_str)
{
- switch_memory_pool_t *pool = NULL;
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- mongo_connection_pool_t *cpool = NULL;
- DBClientBase *conn = NULL;
+ switch_memory_pool_t *pool = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ mongo_connection_pool_t *cpool = NULL;
+ DBClientBase *conn = NULL;
- if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
- return status;
- }
+ if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
- if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) {
- switch_goto_status(SWITCH_STATUS_MEMERR, done);
- }
+ if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) {
+ switch_goto_status(SWITCH_STATUS_MEMERR, done);
+ }
- if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) {
- goto done;
- }
+ if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) {
+ goto done;
+ }
- if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) {
- goto done;
- }
+ if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) {
+ goto done;
+ }
- cpool->min_connections = min_connections;
- cpool->max_connections = max_connections;
- cpool->conn_str = switch_core_strdup(pool, conn_str);
-
- cpool->pool = pool;
+ cpool->min_connections = min_connections;
+ cpool->max_connections = max_connections;
+ cpool->conn_str = switch_core_strdup(pool, conn_str);
+ cpool->pool = pool;
- for (cpool->size = 0; cpool->size < min_connections; cpool->size++) {
+ for (cpool->size = 0; cpool->size < min_connections; cpool->size++) {
- if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) {
- mongo_connection_pool_put(cpool, conn, SWITCH_FALSE);
- } else {
- break;
- }
- }
+ if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) {
+ mongo_connection_pool_put(cpool, conn, SWITCH_FALSE);
+ } else {
+ break;
+ }
+ }
done:
- if (status == SWITCH_STATUS_SUCCESS) {
- *conn_pool = cpool;
- } else {
- switch_core_destroy_memory_pool(&pool);
- }
+ if (status == SWITCH_STATUS_SUCCESS) {
+ *conn_pool = cpool;
+ } else {
+ switch_core_destroy_memory_pool(&pool);
+ }
- return status;
+ return status;
}
void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool)
{
- mongo_connection_pool_t *cpool = *conn_pool;
- void *data = NULL;
+ mongo_connection_pool_t *cpool = *conn_pool;
+ void *data = NULL;
- switch_assert(cpool != NULL);
+ switch_assert(cpool != NULL);
- while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) {
- mongo_connection_destroy((DBClientBase **)&data);
- }
+ while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) {
+ mongo_connection_destroy((DBClientBase **)&data);
+ }
- switch_mutex_destroy(cpool->mutex);
- switch_core_destroy_memory_pool(&cpool->pool);
+ switch_mutex_destroy(cpool->mutex);
+ switch_core_destroy_memory_pool(&cpool->pool);
- *conn_pool = NULL;
+ *conn_pool = NULL;
}
DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool)
{
- DBClientBase *conn = NULL;
- void *data = NULL;
+ DBClientBase *conn = NULL;
+ void *data = NULL;
- switch_assert(conn_pool != NULL);
+ switch_assert(conn_pool != NULL);
- switch_mutex_lock(conn_pool->mutex);
+ switch_mutex_lock(conn_pool->mutex);
- if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) {
- conn = (DBClientBase *) data;
- } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) {
- if (++conn_pool->size > conn_pool->max_connections) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n");
- }
- }
+ if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) {
+ conn = (DBClientBase *) data;
+ } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) {
+ if (++conn_pool->size > conn_pool->max_connections) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n");
+ }
+ }
- switch_mutex_unlock(conn_pool->mutex);
+ switch_mutex_unlock(conn_pool->mutex);
#ifdef MONGO_POOL_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif
- return conn;
+ return conn;
}
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy)
{
- switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_assert(conn_pool != NULL);
- switch_assert(conn != NULL);
+ switch_assert(conn_pool != NULL);
+ switch_assert(conn != NULL);
- switch_mutex_lock(conn_pool->mutex);
- if (destroy || conn_pool->size > conn_pool->max_connections) {
+ switch_mutex_lock(conn_pool->mutex);
+ if (destroy || conn_pool->size > conn_pool->max_connections) {
#ifdef MONGO_POOL_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn);
#endif
- mongo_connection_destroy(&conn);
- conn_pool->size--;
- } else {
+ mongo_connection_destroy(&conn);
+ conn_pool->size--;
+ } else {
#ifdef MONGO_POOL_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn);
#endif
- status = switch_queue_push(conn_pool->connections, conn);
- }
+ status = switch_queue_push(conn_pool->connections, conn);
+ }
- switch_mutex_unlock(conn_pool->mutex);
+ switch_mutex_unlock(conn_pool->mutex);
#ifdef MONGO_POOL_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif
- return status;
+ return status;
}
/* For Emacs:
diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c
index b1681ea5fa..f3d5585fdf 100644
--- a/src/mod/codecs/mod_opus/mod_opus.c
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -36,35 +36,229 @@
SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load);
SWITCH_MODULE_DEFINITION(mod_opus, mod_opus_load, NULL, NULL);
+/*! \brief Various codec settings */
+struct opus_codec_settings {
+ int useinbandfec;
+ int usedtx;
+ int maxaveragebitrate;
+ int stereo;
+ int cbr;
+ int sprop_maxcapturerate;
+ int sprop_stereo;
+ int maxptime;
+ int minptime;
+ int ptime;
+ int samplerate;
+};
+typedef struct opus_codec_settings opus_codec_settings_t;
+
+static opus_codec_settings_t default_codec_settings = {
+ /*.useinbandfec */ 1,
+ /*.usedtx */ 1,
+ /*.maxaveragebitrate */ 30000,
+ /*.stereo*/ 0,
+ /*.cbr*/ 0,
+ /*.sprop_maxcapturerate*/ 0,
+ /*.sprop_stereo*/ 0,
+ /*.maxptime*/ 0,
+ /*.minptime*/ 0,
+ /*.ptime*/ 0,
+ /*.samplerate*/ 0
+};
+
struct opus_context {
OpusEncoder *encoder_object;
OpusDecoder *decoder_object;
int frame_size;
};
+static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
+{
+ if (codec_fmtp) {
+ opus_codec_settings_t local_settings = { 0 };
+ opus_codec_settings_t *codec_settings = &local_settings;
+
+ if (codec_fmtp->private_info) {
+ codec_settings = codec_fmtp->private_info;
+ if (zstr(fmtp)) {
+ memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
+ }
+ }
+
+ if (fmtp) {
+ int x, argc;
+ char *argv[10];
+ char *fmtp_dup = strdup(fmtp);
+
+ switch_assert(fmtp_dup);
+
+ argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+ for (x = 0; x < argc; x++) {
+ char *data = argv[x];
+ char *arg;
+ switch_assert(data);
+ while (*data == ' ') {
+ data++;
+ }
+
+
+ if ((arg = strchr(data, '='))) {
+ *arg++ = '\0';
+
+ if (codec_settings) {
+ if (!strcasecmp(data, "useinbandfec")) {
+ codec_settings->useinbandfec = switch_true(arg);
+ }
+
+ if (!strcasecmp(data, "usedtx")) {
+ codec_settings->usedtx = switch_true(arg);
+ }
+
+ if (!strcasecmp(data, "sprop-maxcapturerate")) {
+ codec_settings->sprop_maxcapturerate = atoi(arg);
+ }
+
+ if (!strcasecmp(data, "maxptime")) {
+ codec_settings->maxptime = atoi(arg);
+ }
+
+ if (!strcasecmp(data, "minptime")) {
+ codec_settings->minptime = atoi(arg);
+ }
+
+ if (!strcasecmp(data, "ptime")) {
+ codec_settings->ptime = atoi(arg);
+ codec_fmtp->microseconds_per_packet = codec_settings->ptime * 1000;
+ }
+
+ if (!strcasecmp(data, "samplerate")) {
+ codec_settings->samplerate = atoi(arg);
+ codec_fmtp->actual_samples_per_second = codec_settings->samplerate;
+ }
+
+ if (!strcasecmp(data, "maxaveragebitrate")) {
+ codec_settings->maxaveragebitrate = atoi(arg);
+ switch(codec_fmtp->actual_samples_per_second) {
+ case 8000:
+ {
+ if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) {
+ codec_settings->maxaveragebitrate = 20000;
+ }
+ break;
+ }
+ case 12000:
+ {
+ if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) {
+ codec_settings->maxaveragebitrate = 25000;
+ }
+ break;
+ }
+ case 16000:
+ {
+ if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) {
+ codec_settings->maxaveragebitrate = 30000;
+ }
+ break;
+ }
+ case 24000:
+ {
+ if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) {
+ codec_settings->maxaveragebitrate = 40000;
+ }
+ break;
+ }
+
+ default:
+ /* this should never happen but 20000 is common among all rates */
+ codec_settings->maxaveragebitrate = 20000;
+ break;
+ }
+
+
+ codec_fmtp->bits_per_second = codec_settings->maxaveragebitrate;
+ }
+
+ }
+ }
+ }
+ free(fmtp_dup);
+ }
+ //codec_fmtp->bits_per_second = bit_rate;
+ return SWITCH_STATUS_SUCCESS;
+ }
+ return SWITCH_STATUS_FALSE;
+}
+
+static char *gen_fmtp(opus_codec_settings_t *settings, switch_memory_pool_t *pool)
+{
+ char buf[256] = "";
+
+ if (settings->useinbandfec) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1;");
+ }
+
+ if (settings->usedtx) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1;");
+ }
+
+ if (settings->maxaveragebitrate) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d;", settings->maxaveragebitrate);
+
+ }
+
+ if (settings->ptime) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d;", settings->ptime);
+ }
+
+ if (settings->minptime) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d;", settings->minptime);
+ }
+
+ if (settings->maxptime) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d;", settings->maxptime);
+ }
+
+ if (settings->samplerate) {
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d;", settings->samplerate);
+ }
+
+ if (end_of(buf) == ';') {
+ end_of(buf) = '\0';
+ }
+
+ return switch_core_strdup(pool, buf);
+
+}
+
static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
struct opus_context *context = NULL;
int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
int decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
+ switch_codec_fmtp_t codec_fmtp;
+ opus_codec_settings_t opus_codec_settings = { 0 };
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
return SWITCH_STATUS_FALSE;
}
context->frame_size = codec->implementation->samples_per_packet;
-
+
+ memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+ codec_fmtp.private_info = &opus_codec_settings;
+ switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp);
+
+ codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool);
+
if (encoding) {
/* come up with a way to specify these */
- int bitrate_bps = codec->implementation->bits_per_second;
+ int bitrate_bps = OPUS_AUTO;
int use_vbr = 1;
int complexity = 10;
- int use_inbandfec = 1;
- int use_dtx = 1;
- int bandwidth = OPUS_BANDWIDTH_FULLBAND;
int err;
+ int samplerate = opus_codec_settings.samplerate ? opus_codec_settings.samplerate : codec->implementation->actual_samples_per_second;
- context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second,
+ context->encoder_object = opus_encoder_create(samplerate,
codec->implementation->number_of_channels,
OPUS_APPLICATION_VOIP, &err);
@@ -74,12 +268,24 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
}
opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
- opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth));
+
+ if (codec->implementation->actual_samples_per_second == 8000) {
+ opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
+ opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
+ } else {
+ opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
+ }
+
opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr));
opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity));
- opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(use_inbandfec));
- opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(use_dtx));
+ if (opus_codec_settings.useinbandfec) {
+ opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(opus_codec_settings.useinbandfec));
+ }
+
+ if (opus_codec_settings.usedtx) {
+ opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(opus_codec_settings.usedtx));
+ }
}
if (decoding) {
@@ -187,19 +393,33 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
int mss = 10000;
int x = 0;
int rate = 48000;
- int bits = 32000;
+ int bits = 0;
+ char *dft_fmtp = NULL;
+ opus_codec_settings_t settings = { 0 };
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "OPUS (STANDARD)");
+ codec_interface->parse_fmtp = switch_opus_fmtp_parse;
+
+ settings = default_codec_settings;
+
+
for (x = 0; x < 3; x++) {
+
+ settings.ptime = mss / 1000;
+ settings.maxptime = settings.ptime;
+ settings.minptime = settings.ptime;
+ settings.samplerate = rate;
+ dft_fmtp = gen_fmtp(&settings, pool);
+
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
116, /* the IANA code number */
"opus",/* the IANA code name */
- NULL, /* default fmtp to send (can be overridden by the init function) */
- rate, /* samples transferred per second */
+ dft_fmtp, /* default fmtp to send (can be overridden by the init function) */
+ 48000, /* samples transferred per second */
rate, /* actual samples transferred per second */
bits, /* bits transferred per second */
mss, /* number of microseconds per frame */
@@ -219,6 +439,44 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
}
+
+ samples = 80;
+ bytes = 160;
+ mss = 10000;
+ rate = 8000;
+
+ for (x = 0; x < 3; x++) {
+
+ settings.ptime = mss / 1000;
+ settings.maxptime = settings.ptime;
+ settings.minptime = settings.ptime;
+ settings.samplerate = rate;
+ dft_fmtp = gen_fmtp(&settings, pool);
+
+ switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
+ 116, /* the IANA code number */
+ "opus",/* the IANA code name */
+ dft_fmtp, /* default fmtp to send (can be overridden by the init function) */
+ 48000, /* samples transferred per second */
+ rate, /* actual samples transferred per second */
+ bits, /* bits transferred per second */
+ mss, /* number of microseconds per frame */
+ samples, /* number of samples per frame */
+ bytes, /* number of bytes per frame decompressed */
+ 0, /* number of bytes per frame compressed */
+ 1,/* number of channels represented */
+ 1, /* number of frames per network packet */
+ switch_opus_init, /* function to initialize a codec handle using this implementation */
+ switch_opus_encode, /* function to encode raw data into encoded data */
+ switch_opus_decode, /* function to decode encoded data into raw data */
+ switch_opus_destroy); /* deinitalize a codec handle using this implementation */
+
+ bytes += 160;
+ samples += 80;
+ mss += 10000;
+
+ }
+
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/codecs/mod_vp8/mod_vp8.c b/src/mod/codecs/mod_vp8/mod_vp8.c
index 121b9ab0c9..2a0a5540ba 100644
--- a/src/mod/codecs/mod_vp8/mod_vp8.c
+++ b/src/mod/codecs/mod_vp8/mod_vp8.c
@@ -83,9 +83,21 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vp8_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "VP8 Video (passthru)");
+
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_VIDEO, 99, "VP8", NULL, 90000, 90000, 0,
0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
+ SWITCH_ADD_CODEC(codec_interface, "red Video (passthru)");
+ switch_core_codec_add_implementation(pool, codec_interface,
+ SWITCH_CODEC_TYPE_VIDEO, 103, "red", NULL, 90000, 90000, 0,
+ 0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
+ SWITCH_ADD_CODEC(codec_interface, "ulpfec Video (passthru)");
+ switch_core_codec_add_implementation(pool, codec_interface,
+ SWITCH_CODEC_TYPE_VIDEO, 104, "ulpfec", NULL, 90000, 90000, 0,
+ 0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 7286c5de16..dc6351799d 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -626,13 +626,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY nomedia - sending ack\n");
nua_ack(tech_pvt->nh,
- TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
- SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
- SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
- SOATAG_REUSE_REJECTED(1),
- SOATAG_RTP_SELECT(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
- TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
- TAG_END());
+ TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
+ SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+ SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
+ SOATAG_REUSE_REJECTED(1),
+ SOATAG_RTP_SELECT(1),
+ SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
+ TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
+ TAG_END());
sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE); // all done
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
@@ -667,7 +668,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
tech_pvt->mparams.local_sdp_str = NULL;
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
} else {
switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
@@ -683,12 +684,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
if (sofia_use_soa(tech_pvt)) {
+
nua_respond(tech_pvt->nh, SIP_200_OK,
TAG_IF(is_proxy, NUTAG_AUTOANSWER(0)),
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
- SOATAG_REUSE_REJECTED(1), TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)),
+ SOATAG_REUSE_REJECTED(1),
+ SOATAG_RTP_SELECT(1),
SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
@@ -762,7 +765,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
return status;
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
@@ -834,7 +837,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
- TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)),
+ SOATAG_RTP_SELECT(1),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
@@ -1221,7 +1224,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
}
- if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+ if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
}
}
@@ -1264,7 +1267,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
if (ip && port) {
- switch_core_media_gen_local_sdp(session, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
@@ -1397,7 +1400,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
goto end_lock;
}
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
if (send_invite) {
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
@@ -2081,7 +2084,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
goto end_lock;
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
diff --git a/src/mod/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c
index a34b8cfd74..a1467f9647 100644
--- a/src/mod/endpoints/mod_sofia/rtp.c
+++ b/src/mod/endpoints/mod_sofia/rtp.c
@@ -513,7 +513,7 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi
}
switch_rtp_set_default_payload(tech_pvt->rtp_session, pt);
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt);
+ //switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt);
}
if (compare_var(event, channel, kRFC2833PT)) {
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index f2194487d4..527de9b8fb 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -1492,8 +1492,8 @@ static void our_sofia_event_callback(nua_event_t event,
sofia_reg_check_socket(profile, sofia_private->call_id, sofia_private->network_ip, sofia_private->network_port);
+ nua_handle_destroy(nh);
}
- nua_handle_destroy(nh);
}
break;
case nua_r_authenticate:
@@ -3743,7 +3743,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
profile->auto_restart = 1;
sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
- sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
+ sofia_set_media_flag(profile, SCMF_RENEG_ON_REINVITE);
sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
@@ -4381,12 +4381,6 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING);
}
- } else if (!strcasecmp(var, "rtp-autofix-pt")) {
- if (switch_true(val)) {
- sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
- } else {
- sofia_clear_media_flag(profile, SCMF_AUTOFIX_PT);
- }
} else if (!strcasecmp(var, "contact-user")) {
profile->contact_user = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "nat-options-ping")) {
@@ -5250,7 +5244,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
sofia_update_callee_id(session, profile, sip, SWITCH_FALSE);
- if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+ if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
}
@@ -6204,7 +6198,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
} else {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
switch_channel_set_state(channel, CS_HIBERNATE);
if (sofia_use_soa(tech_pvt)) {
@@ -6321,7 +6315,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
goto done;
}
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 1);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
@@ -6427,7 +6421,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
goto done;
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n");
@@ -6446,7 +6440,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (is_ok) {
if (switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
@@ -6486,7 +6480,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
goto done;
}
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 833a725d44..d5bbe14c55 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -752,7 +752,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->mparams.local_sdp_str)) {
- switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+ switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
}
sofia_set_flag_locked(tech_pvt, TFLAG_READY);
diff --git a/src/mod/event_handlers/mod_rayo/Makefile b/src/mod/event_handlers/mod_rayo/Makefile
index 6fccfdf318..a3bfc45d47 100644
--- a/src/mod/event_handlers/mod_rayo/Makefile
+++ b/src/mod/event_handlers/mod_rayo/Makefile
@@ -11,6 +11,7 @@ LOCAL_OBJS= $(IKS_LA) \
nlsml.o \
rayo_components.o \
rayo_elements.o \
+ rayo_fax_components.o \
rayo_input_component.o \
rayo_output_component.o \
rayo_prompt_component.o \
@@ -23,6 +24,7 @@ LOCAL_SOURCES= \
nlsml.c \
rayo_components.c \
rayo_elements.c \
+ rayo_fax_components.c \
rayo_input_component.c \
rayo_output_component.c \
rayo_prompt_component.c \
diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
index 35419319bc..3fdc772daf 100644
--- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
+++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
@@ -16,6 +16,12 @@
+
+
+
+
+
+
@@ -65,6 +71,7 @@
]]>
]]>
]]>
+ ]]>
]]>
]]>
]]>
diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c
index 6dd58d29c6..88eb44b417 100644
--- a/src/mod/event_handlers/mod_rayo/mod_rayo.c
+++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c
@@ -126,6 +126,8 @@ struct rayo_call {
switch_hash_t *pcps;
/** current idle start time */
switch_time_t idle_start_time;
+ /** true if fax is in progress */
+ int faxing;
/** 1 if joined to call, 2 if joined to mixer */
int joined;
/** pending join */
@@ -950,6 +952,7 @@ static void rayo_call_cleanup(struct rayo_actor *actor)
iks_delete(revent);
switch_event_destroy(&event);
+ switch_core_hash_destroy(&call->pcps);
}
/**
@@ -963,11 +966,30 @@ const char *rayo_call_get_dcp_jid(struct rayo_call *call)
/**
* @param call the Rayo call
- * @return true if joined
+ * @return true if joined (or a join is in progress)
*/
-static int rayo_call_is_joined(struct rayo_call *call)
+int rayo_call_is_joined(struct rayo_call *call)
{
- return call->joined;
+ return call->joined || call->pending_join_request;
+}
+
+/**
+ * @param call to check if faxing
+ * @return true if faxing is in progress
+ */
+int rayo_call_is_faxing(struct rayo_call *call)
+{
+ return call->faxing;
+}
+
+/**
+ * Set faxing flag
+ * @param call the call to flag
+ * @param faxing true if faxing is in progress
+ */
+void rayo_call_set_faxing(struct rayo_call *call, int faxing)
+{
+ call->faxing = faxing;
}
#define RAYO_MIXER_LOCATE(mixer_name) rayo_mixer_locate(mixer_name, __FILE__, __LINE__)
@@ -1104,13 +1126,23 @@ static struct rayo_call *_rayo_call_create(const char *uuid, const char *file, i
return rayo_call_init(call, pool, uuid, file, line);
}
+/**
+ * Mixer destructor
+ */
+static void rayo_mixer_cleanup(struct rayo_actor *actor)
+{
+ struct rayo_mixer *mixer = RAYO_MIXER(actor);
+ switch_core_hash_destroy(&mixer->members);
+ switch_core_hash_destroy(&mixer->subscribers);
+}
+
/**
* Initialize mixer
*/
static struct rayo_mixer *rayo_mixer_init(struct rayo_mixer *mixer, switch_memory_pool_t *pool, const char *name, const char *file, int line)
{
char *mixer_jid = switch_mprintf("%s@%s", name, RAYO_JID(globals.server));
- rayo_actor_init(RAYO_ACTOR(mixer), pool, RAT_MIXER, "", name, mixer_jid, NULL, rayo_mixer_send, file, line);
+ rayo_actor_init(RAYO_ACTOR(mixer), pool, RAT_MIXER, "", name, mixer_jid, rayo_mixer_cleanup, rayo_mixer_send, file, line);
switch_core_hash_init(&mixer->members, pool);
switch_core_hash_init(&mixer->subscribers, pool);
switch_safe_free(mixer_jid);
@@ -1281,6 +1313,7 @@ static void rayo_peer_server_cleanup(struct rayo_actor *actor)
RAYO_UNLOCK(client);
RAYO_DESTROY(client);
}
+ switch_core_hash_destroy(&rserver->clients);
switch_mutex_unlock(globals.clients_mutex);
}
@@ -1942,6 +1975,12 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
goto done;
}
+ if (rayo_call_is_faxing(RAYO_CALL(call))) {
+ /* can't join a call while it's faxing */
+ response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "fax is in progress");
+ goto done;
+ }
+
if (RAYO_CALL(call)->pending_join_request) {
/* don't allow concurrent join requests */
response = iks_new_error_detailed(msg->payload, STANZA_ERROR_UNEXPECTED_REQUEST, "(un)join request is pending");
@@ -2339,11 +2378,14 @@ static iks *on_iq_get_xmpp_disco(struct rayo_actor *server, struct rayo_message
iks *node = msg->payload;
iks *response = NULL;
iks *x;
+ iks *feature;
response = iks_new_iq_result(node);
x = iks_insert(response, "query");
iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_DISCO);
- x = iks_insert(x, "feature");
- iks_insert_attrib(x, "var", RAYO_NS);
+ feature = iks_insert(x, "feature");
+ iks_insert_attrib(feature, "var", RAYO_NS);
+ feature = iks_insert(x, "feature");
+ iks_insert_attrib(feature, "var", RAYO_FAX_NS);
/* TODO The response MUST also include features for the application formats and transport methods supported by
* the responding entity, as described in the relevant specifications.
@@ -3074,12 +3116,22 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s
switch_time_t idle_start = call->idle_start_time;
int idle_duration_ms = (now - idle_start) / 1000;
/* detect idle session (rayo-client has stopped controlling call) and terminate call */
- if (rayo_call_is_joined(call)) {
+ if (rayo_call_is_joined(call) || rayo_call_is_faxing(call)) {
call->idle_start_time = now;
} else if (idle_duration_ms > globals.max_idle_ms) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ending abandoned call. idle_duration_ms = %i ms\n", idle_duration_ms);
switch_channel_hangup(channel, RAYO_CAUSE_HANGUP);
}
+
+ /* check for break request */
+ {
+ const char *break_jid = switch_channel_get_variable(channel, "rayo_read_frame_interrupt");
+ struct rayo_actor *actor;
+ if (break_jid && (actor = RAYO_LOCATE(break_jid))) {
+ RAYO_UNLOCK(actor);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
}
return SWITCH_STATUS_SUCCESS;
}
@@ -3117,18 +3169,17 @@ SWITCH_STANDARD_APP(rayo_app)
}
}
if (!call) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Missing rayo call!!\n");
- goto done;
+ /* this scenario can only happen if a call was originated through a mechanism other than
+ and then the rayo APP was executed to offer control */
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Outbound call that wasn't created with , will try to offer control\n");
}
ok = 1;
- } else {
- /* inbound call - offer control */
+ }
+
+ if (!call) {
+ /* offer control */
switch_hash_index_t *hi = NULL;
iks *offer = NULL;
- if (call) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Call is already under Rayo 3PCC!\n");
- goto done;
- }
call = rayo_call_create(switch_core_session_get_uuid(session));
switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_call_jid", RAYO_JID(call));
@@ -3161,6 +3212,7 @@ SWITCH_STANDARD_APP(rayo_app)
/* nobody to offer to */
if (!ok) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Rejecting rayo call - there are no online rayo clients to offer call to\n");
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE);
}
}
diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.h b/src/mod/event_handlers/mod_rayo/mod_rayo.h
index dd0adb3192..b862802f31 100644
--- a/src/mod/event_handlers/mod_rayo/mod_rayo.h
+++ b/src/mod/event_handlers/mod_rayo/mod_rayo.h
@@ -153,6 +153,9 @@ extern void rayo_actor_destroy(struct rayo_actor *actor, const char *file, int l
#define RAYO_DESTROY(x) rayo_actor_destroy(RAYO_ACTOR(x), __FILE__, __LINE__)
#define RAYO_SEQ_NEXT(x) rayo_actor_seq_next(RAYO_ACTOR(x))
+extern int rayo_call_is_joined(struct rayo_call *call);
+extern int rayo_call_is_faxing(struct rayo_call *call);
+extern void rayo_call_set_faxing(struct rayo_call *call, int faxing);
extern const char *rayo_call_get_dcp_jid(struct rayo_call *call);
#define rayo_mixer_get_name(mixer) RAYO_ID(mixer)
diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.c b/src/mod/event_handlers/mod_rayo/rayo_components.c
index b5137d9459..7ad96d2a7d 100644
--- a/src/mod/event_handlers/mod_rayo/rayo_components.c
+++ b/src/mod/event_handlers/mod_rayo/rayo_components.c
@@ -226,7 +226,8 @@ switch_status_t rayo_components_load(switch_loadable_module_interface_t **module
if (rayo_input_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_output_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_prompt_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
- rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) {
+ rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
+ rayo_fax_components_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_TERM;
}
return SWITCH_STATUS_SUCCESS;
@@ -241,6 +242,7 @@ switch_status_t rayo_components_shutdown(void)
rayo_output_component_shutdown();
rayo_prompt_component_shutdown();
rayo_record_component_shutdown();
+ rayo_fax_components_shutdown();
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/event_handlers/mod_rayo/rayo_components.h b/src/mod/event_handlers/mod_rayo/rayo_components.h
index 6e93dfbc43..5d1367d645 100644
--- a/src/mod/event_handlers/mod_rayo/rayo_components.h
+++ b/src/mod/event_handlers/mod_rayo/rayo_components.h
@@ -49,6 +49,9 @@
#define RAYO_PROMPT_NS RAYO_BASE "prompt:" RAYO_VERSION
#define RAYO_PROMPT_COMPLETE_NS RAYO_BASE "prompt:complete:" RAYO_VERSION
+#define RAYO_FAX_NS RAYO_BASE "fax:" RAYO_VERSION
+#define RAYO_FAX_COMPLETE_NS RAYO_BASE "fax:complete:" RAYO_VERSION
+
#define COMPONENT_COMPLETE_STOP "stop", RAYO_EXT_COMPLETE_NS
#define COMPONENT_COMPLETE_ERROR "error", RAYO_EXT_COMPLETE_NS
#define COMPONENT_COMPLETE_HANGUP "hangup", RAYO_EXT_COMPLETE_NS
@@ -58,12 +61,14 @@ extern switch_status_t rayo_input_component_load(switch_loadable_module_interfac
extern switch_status_t rayo_output_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file);
extern switch_status_t rayo_prompt_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file);
extern switch_status_t rayo_record_component_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file);
+extern switch_status_t rayo_fax_components_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file);
extern switch_status_t rayo_components_shutdown(void);
extern switch_status_t rayo_input_component_shutdown(void);
extern switch_status_t rayo_output_component_shutdown(void);
extern switch_status_t rayo_prompt_component_shutdown(void);
extern switch_status_t rayo_record_component_shutdown(void);
+extern switch_status_t rayo_fax_components_shutdown(void);
extern void rayo_component_send_start(struct rayo_component *component, iks *iq);
extern void rayo_component_send_iq_error(struct rayo_component *component, iks *iq, const char *error_name, const char *error_type);
diff --git a/src/mod/event_handlers/mod_rayo/rayo_elements.c b/src/mod/event_handlers/mod_rayo/rayo_elements.c
index 34577a9492..78209c3bd6 100644
--- a/src/mod/event_handlers/mod_rayo/rayo_elements.c
+++ b/src/mod/event_handlers/mod_rayo/rayo_elements.c
@@ -32,6 +32,7 @@
* component validation
*/
ELEMENT(RAYO_INPUT)
+ ATTRIB(xmlns,, any)
STRING_ATTRIB(mode, any, "any,dtmf,voice")
OPTIONAL_ATTRIB(terminator,, dtmf_digit)
ATTRIB(recognizer,, any)
@@ -48,10 +49,22 @@ ELEMENT(RAYO_INPUT)
ATTRIB(start-timers, true, bool)
ELEMENT_END
+/**
+ * command validation
+ */
+ELEMENT(RAYO_JOIN)
+ ATTRIB(xmlns,, any)
+ STRING_ATTRIB(direction, duplex, "send,recv,duplex")
+ STRING_ATTRIB(media, bridge, "bridge,direct")
+ ATTRIB(call-uri,, any)
+ ATTRIB(mixer-name,, any)
+ELEMENT_END
+
/**
*