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/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 59370e742a..05eb175f22 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -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;
}
}
@@ -790,12 +790,12 @@ 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);
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), 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_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;
}
@@ -817,7 +817,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);
}
}
@@ -826,7 +826,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);
normal_failure:
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
return SWITCH_STATUS_GENERR;
@@ -850,7 +850,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;
}
@@ -858,7 +858,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;
}
@@ -867,7 +867,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;
}
@@ -885,15 +885,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;
}
@@ -904,7 +904,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;
@@ -1245,7 +1245,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);
@@ -1273,7 +1273,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;
}
diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h
index f0dc1c76fe..1fd5ecbd29 100644
--- a/src/include/switch_caller.h
+++ b/src/include/switch_caller.h
@@ -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;
diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h
index 2e53ef6107..dd3870f8ae 100644
--- a/src/include/switch_channel.h
+++ b/src/include/switch_channel.h
@@ -633,6 +633,8 @@ 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);
SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel);
SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel);
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index db3e67c5a8..8e41a882a6 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -109,6 +109,7 @@ typedef struct switch_device_stats_s {
uint32_t early;
uint32_t early_in;
uint32_t early_out;
+ uint32_t ring_wait;
} switch_device_stats_t;
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 758fe54c5b..e43db7be08 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -27,6 +27,7 @@
* Bret McDanel
* Joseph Sullivan
* Raymond Chandler
+ * Emmanuel Schmidbauer
*
* switch_types.h -- Data Types
*
@@ -945,6 +946,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,
@@ -1114,6 +1116,7 @@ typedef enum {
CCS_EARLY,
CCS_ACTIVE,
CCS_HELD,
+ CCS_RING_WAIT,
CCS_HANGUP,
CCS_UNHOLD
} switch_channel_callstate_t;
diff --git a/src/include/switch_version.h.template b/src/include/switch_version.h.template
index 2e253dc69f..06169d603f 100644
--- a/src/include/switch_version.h.template
+++ b/src/include/switch_version.h.template
@@ -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
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index 265effdb2e..bc04e21d65 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -32,6 +32,8 @@
* David Weekly
* Joao Mesquita
* Raymond Chandler
+ * Seven Du
+ * Emmanuel Schmidbauer
*
* mod_conference.c -- Software Conference Bridge
*
@@ -3605,6 +3607,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;
@@ -3631,7 +3634,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);
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 8d7b5c6f37..b5b7718231 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -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);
diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c
index d3c7a87aa7..9f99b2df7b 100644
--- a/src/mod/applications/mod_fifo/mod_fifo.c
+++ b/src/mod/applications/mod_fifo/mod_fifo.c
@@ -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));
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 b283cb2c01..f3d5585fdf 100644
--- a/src/mod/codecs/mod_opus/mod_opus.c
+++ b/src/mod/codecs/mod_opus/mod_opus.c
@@ -36,36 +36,231 @@
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,
- codec->implementation->number_of_channels, OPUS_APPLICATION_VOIP, &err);
+ context->encoder_object = opus_encoder_create(samplerate,
+ codec->implementation->number_of_channels,
+ OPUS_APPLICATION_VOIP, &err);
if (err != OPUS_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
@@ -73,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) {
@@ -143,7 +350,7 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec,
if (len > 1275) len = 1275;
bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len);
-
+
if (bytes > 0) {
*encoded_data_len = (uint32_t) bytes;
return SWITCH_STATUS_SUCCESS;
@@ -186,26 +393,40 @@ 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 */
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 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 */
@@ -218,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/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c
index f943933248..cb34325f07 100644
--- a/src/mod/endpoints/mod_sofia/rtp.c
+++ b/src/mod/endpoints/mod_sofia/rtp.c
@@ -304,7 +304,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))) {
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 9230944a43..ee03d68876 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -179,7 +179,7 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
if (sip->sip_route) {
if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_route))) {
const char *v = switch_channel_get_variable(channel, "sip_full_route");
- if (!v) {
+ if (!v) {
switch_channel_set_variable(channel, "sip_full_route", full);
}
su_free(nh->nh_home, full);
@@ -5755,9 +5755,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (r_sdp) {
sdp_parser_t *parser;
sdp_session_t *sdp;
-
+ tech_pvt->remote_sdp_str = NULL;
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
-
+ printf("WTF %d\n---\n%s\n---\n%s", (profile->ndlb & PFLAG_NDLB_ALLOW_NONDUP_SDP), tech_pvt->remote_sdp_str, r_sdp);
if (!(profile->ndlb & PFLAG_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->remote_sdp_str) && !strcmp(tech_pvt->remote_sdp_str, r_sdp))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp);
is_dup_sdp = 1;
@@ -5855,6 +5855,39 @@ 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)) {
+ 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");
}
@@ -6785,6 +6818,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");
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 9839688ca0..92e018acce 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -39,13 +39,13 @@
switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line);
#define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__)
-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;
}
void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist)
@@ -317,7 +317,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
}
if (tech_pvt->ianacodes[i] > 95 || 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", tech_pvt->ianacodes[i], imp->iananame, rate, channels);
@@ -547,6 +547,10 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
rate = tech_pvt->adv_rm_rate;
+ if (!tech_pvt->adv_channels) {
+ tech_pvt->adv_channels = get_channels(tech_pvt->rm_encoding, 1);
+ }
+
if (tech_pvt->adv_channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n",
tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate, tech_pvt->adv_channels);
@@ -776,7 +780,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
rate = imp->samples_per_second;
}
- channels = get_channels(imp);
+ channels = get_channels(imp->iananame, imp->number_of_channels);
if (channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame,
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..f852d2c5f8 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,35 @@ 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 if faxing is not in progress
+ * @param call the call to flag
+ * @param faxing true if faxing is in progress
+ * @return true if set, false if can't set because faxing is already in progress. Reset always succeeds.
+ */
+int rayo_call_set_faxing(struct rayo_call *call, int faxing)
+{
+ if (!faxing || (faxing && !call->faxing)) {
+ call->faxing = faxing;
+ return 1;
+ }
+ return 0;
}
#define RAYO_MIXER_LOCATE(mixer_name) rayo_mixer_locate(mixer_name, __FILE__, __LINE__)
@@ -1104,13 +1131,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 +1318,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 +1980,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 +2383,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 +3121,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;
}
diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.h b/src/mod/event_handlers/mod_rayo/mod_rayo.h
index dd0adb3192..c65236b64a 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 int 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
+
/**
*