diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln
index 7e0733ce70..c865b6861a 100644
--- a/Freeswitch.2010.sln
+++ b/Freeswitch.2010.sln
@@ -1771,12 +1771,12 @@ Global
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x64.ActiveCfg = Release|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.ActiveCfg = Debug|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.Build.0 = Debug|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.ActiveCfg = Debug|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|Any CPU
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.ActiveCfg = Debug|x64
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|x64
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.ActiveCfg = Release|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.Build.0 = Release|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.ActiveCfg = Release|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|Any CPU
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.ActiveCfg = Release|x64
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|x64
{E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.ActiveCfg = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.Build.0 = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|x64.ActiveCfg = Release|Win32
diff --git a/bootstrap.sh b/bootstrap.sh
index 59a568769e..0ea5cd43d4 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -341,7 +341,7 @@ rm -rf autom4te*.cache
echo "Entering directory ${LIBDIR}/apr-util"
cd ${LIBDIR}/apr-util
-if [ "${BGJOB}" == "false" ] ; then
+if [ "${BGJOB}" = "false" ] ; then
./buildconf
else
./buildconf &
@@ -350,14 +350,14 @@ fi
for i in ${SUBDIRS}
do
- if [ "${BGJOB}" == "false" ] ; then
+ if [ "${BGJOB}" = "false" ] ; then
libbootstrap ${i}
else
libbootstrap ${i} &
fi
done
-if [ "${BGJOB}" == "true" ] ; then
+if [ "${BGJOB}" = "true" ] ; then
wait
fi
cd ${BASEDIR}
diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml
index f7a82ea966..9862eed711 100644
--- a/conf/dialplan/default.xml
+++ b/conf/dialplan/default.xml
@@ -596,7 +596,7 @@
-
+
@@ -604,7 +604,7 @@
-
+
@@ -613,7 +613,7 @@
-
+
@@ -622,7 +622,7 @@
-
+
diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml
index eaa493c047..e48557b234 100644
--- a/conf/skinny_profiles/internal.xml
+++ b/conf/skinny_profiles/internal.xml
@@ -11,6 +11,7 @@
+
diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c
index 353dd139ab..ef6e7447a1 100644
--- a/libs/libdingaling/src/libdingaling.c
+++ b/libs/libdingaling/src/libdingaling.c
@@ -163,6 +163,7 @@ struct ldl_session {
apr_hash_t *variables;
apr_time_t created;
void *private_data;
+ ldl_user_flag_t flags;
};
static int on_disco_default(void *user_data, ikspak *pak);
@@ -346,6 +347,7 @@ ldl_status ldl_session_create(ldl_session_t **session_p, ldl_handle_t *handle, c
session->created = apr_time_now();
session->state = LDL_STATE_NEW;
session->variables = apr_hash_make(session->pool);
+ session->flags = flags;
*session_p = session;
@@ -387,7 +389,24 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if (type) {
- if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
+ if (!strcasecmp(type, "redirect")) {
+ apr_hash_t *hash = session->handle->sessions;
+ char *p = to;
+ if ((p = strchr(to, ':'))) {
+ p++;
+ } else {
+ p = to;
+ }
+
+
+ apr_hash_set(hash, session->them, APR_HASH_KEY_STRING, NULL);
+ apr_hash_set(hash, session->id, APR_HASH_KEY_STRING, NULL);
+ session->them = apr_pstrdup(session->pool, p);
+ apr_hash_set(handle->sessions, session->them, APR_HASH_KEY_STRING, session);
+ apr_hash_set(handle->sessions, session->id, APR_HASH_KEY_STRING, session);
+
+ dl_signal = LDL_SIGNAL_REDIRECT;
+ } else if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
dl_signal = LDL_SIGNAL_INITIATE;
@@ -499,6 +518,12 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if ((key = iks_find_attrib(tag, "port"))) {
session->candidates[index].port = (uint16_t)atoi(key);
}
+
+ if (!session->candidates[index].type) {
+ session->candidates[index].type = apr_pstrdup(session->pool, "stun");
+ }
+
+
if (globals.debug) {
globals.logger(DL_LOG_DEBUG,
"New Candidate %d\n"
@@ -947,6 +972,18 @@ static void cancel_retry(ldl_handle_t *handle, char *id)
apr_thread_mutex_unlock(handle->lock);
}
+static iks* working_find(iks *tag, const char *name)
+{
+ while(tag) {
+ if (!strcasecmp(iks_name(tag), name)) {
+ return tag;
+ }
+ tag = iks_next_tag(tag);
+ }
+
+ return NULL;
+}
+
static int on_commands(void *user_data, ikspak *pak)
{
ldl_handle_t *handle = user_data;
@@ -956,8 +993,22 @@ static int on_commands(void *user_data, ikspak *pak)
char *type = iks_find_attrib(pak->x, "type");
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
uint8_t is_error = strcasecmp(type, "error") ? 0 : 1;
+ iks *xml, *xsession, *xerror = NULL, *xredir = NULL;
+
+ xml = iks_child (pak->x);
+
+ if (is_error) {
+ if ((xerror = working_find(xml, "error"))) {
+ char *code = iks_find_attrib(xerror, "code");
+ if (code && !strcmp(code, "302") &&
+ ((xredir = iks_find(xerror, "ses:redirect")) || (xredir = iks_find(xerror, "redirect")))) {
+ is_result = 0;
+ is_error = 0;
+ cancel_retry(handle, iqid);
+ }
+ }
+ }
- iks *xml;
if (is_result) {
iks *tag = iks_child (pak->x);
@@ -989,9 +1040,12 @@ static int on_commands(void *user_data, ikspak *pak)
}
}
+
+
if ((is_result || is_error) && iqid && from) {
cancel_retry(handle, iqid);
+
if (is_result) {
if (handle->response_callback) {
handle->response_callback(handle, iqid);
@@ -999,30 +1053,37 @@ static int on_commands(void *user_data, ikspak *pak)
return IKS_FILTER_EAT;
} else if (is_error) {
return IKS_FILTER_EAT;
+
}
}
- xml = iks_child (pak->x);
- while (xml) {
- char *name = iks_name_nons(xml);
- if (!strcasecmp(name, "session")) {
- char *id = iks_find_attrib(xml, "id");
- //printf("SESSION type=%s name=%s id=%s\n", type, name, id);
- if (parse_session_code(handle, id, from, to, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
- iks *reply;
- if ((reply = iks_make_iq(IKS_TYPE_RESULT, NULL))) {
- iks_insert_attrib(reply, "to", from);
- iks_insert_attrib(reply, "from", to);
- iks_insert_attrib(reply, "id", iqid);
- apr_queue_push(handle->queue, reply);
- reply = NULL;
- }
+
+ if ((xsession = working_find(xml, "ses:session")) || (xsession = working_find(xml, "session"))) {
+ char *id;
+
+ id = iks_find_attrib(xsession, "id");
+
+ if (xredir) {
+ to = iks_cdata(iks_child(xredir));
+ type = "redirect";
+ }
+
+ if (strcasecmp(type, "error") && strcasecmp(type, "redirect")) {
+ type = NULL;
+ }
+
+ if (parse_session_code(handle, id, from, to, xsession, type) == LDL_STATUS_SUCCESS) {
+ iks *reply;
+ if ((reply = iks_make_iq(IKS_TYPE_RESULT, NULL))) {
+ iks_insert_attrib(reply, "to", from);
+ iks_insert_attrib(reply, "from", to);
+ iks_insert_attrib(reply, "id", iqid);
+ apr_queue_push(handle->queue, reply);
+ reply = NULL;
}
}
- xml = iks_next_tag(xml);
}
-
return IKS_FILTER_EAT;
}
@@ -1922,6 +1983,69 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
}
+
+unsigned int ldl_session_transport(ldl_session_t *session,
+ ldl_candidate_t *candidates,
+ unsigned int clen)
+
+{
+ iks *iq, *sess, *tag;
+ unsigned int x, id = 0;
+
+
+ for (x = 0; x < clen; x++) {
+ char buf[512];
+ iq = NULL;
+ sess = NULL;
+ id = 0;
+
+ new_session_iq(session, &iq, &sess, &id, "transport-info");
+ //tag = iks_insert(sess, "transport");
+ //iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
+ tag = sess;
+
+ if (0) add_elements(session, tag);
+ tag = iks_insert(tag, "transport");
+ iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
+
+ tag = iks_insert(tag, "candidate");
+
+ if (candidates[x].name) {
+ iks_insert_attrib(tag, "name", candidates[x].name);
+ }
+ if (candidates[x].address) {
+ iks_insert_attrib(tag, "address", candidates[x].address);
+ }
+ if (candidates[x].port) {
+ snprintf(buf, sizeof(buf), "%u", candidates[x].port);
+ iks_insert_attrib(tag, "port", buf);
+ }
+ if (candidates[x].username) {
+ iks_insert_attrib(tag, "username", candidates[x].username);
+ }
+ if (candidates[x].password) {
+ iks_insert_attrib(tag, "password", candidates[x].password);
+ }
+ if (candidates[x].pref) {
+ snprintf(buf, sizeof(buf), "%0.1f", candidates[x].pref);
+ iks_insert_attrib(tag, "preference", buf);
+ }
+ if (candidates[x].protocol) {
+ iks_insert_attrib(tag, "protocol", candidates[x].protocol);
+ }
+ if (candidates[x].type) {
+ iks_insert_attrib(tag, "type", candidates[x].type);
+ }
+
+ iks_insert_attrib(tag, "network", "0");
+ iks_insert_attrib(tag, "generation", "0");
+ schedule_packet(session->handle, id, iq, LDL_RETRY);
+ }
+
+
+ return id;
+}
+
unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates,
unsigned int clen)
@@ -1981,6 +2105,8 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
return id;
}
+
+
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
{
iks *pres, *msg;
@@ -2344,6 +2470,12 @@ int ldl_handle_running(ldl_handle_t *handle)
return ldl_test_flag(handle, LDL_FLAG_RUNNING) ? 1 : 0;
}
+
+int ldl_session_gateway(ldl_session_t *session)
+{
+ return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0;
+}
+
int ldl_handle_connected(ldl_handle_t *handle)
{
return ldl_test_flag(handle, LDL_FLAG_CONNECTED) ? 1 : 0;
diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h
index 07a71b3987..d78643810c 100644
--- a/libs/libdingaling/src/libdingaling.h
+++ b/libs/libdingaling/src/libdingaling.h
@@ -131,7 +131,8 @@ typedef enum {
LDL_FLAG_SASL_PLAIN = (1 << 11),
LDL_FLAG_SASL_MD5 = (1 << 12),
LDL_FLAG_COMPONENT = (1 << 13),
- LDL_FLAG_OUTBOUND = (1 << 14)
+ LDL_FLAG_OUTBOUND = (1 << 14),
+ LDL_FLAG_GATEWAY = (1 << 15)
} ldl_user_flag_t;
typedef enum {
@@ -152,7 +153,8 @@ typedef enum {
LDL_SIGNAL_LOGIN_FAILURE,
LDL_SIGNAL_CONNECTED,
LDL_SIGNAL_TRANSPORT_ACCEPT,
- LDL_SIGNAL_REJECT
+ LDL_SIGNAL_REJECT,
+ LDL_SIGNAL_REDIRECT
} ldl_signal_t;
typedef enum {
@@ -494,6 +496,10 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates,
unsigned int clen);
+unsigned int ldl_session_transport(ldl_session_t *session,
+ ldl_candidate_t *candidates,
+ unsigned int clen);
+
/*!
\brief Initiate or Accept a new session and provide transport options
\param session the session to initiate or accept
@@ -586,6 +592,8 @@ ldl_status ldl_handle_init(ldl_handle_t **handle,
*/
void ldl_handle_run(ldl_handle_t *handle);
+int ldl_session_gateway(ldl_session_t *handle);
+
/*!
\brief Stop a libDingaLing handle
\param handle the Dingaling handle to stop
diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h
index 158de6ce63..68719062b7 100644
--- a/src/include/switch_loadable_module.h
+++ b/src/include/switch_loadable_module.h
@@ -120,6 +120,25 @@ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_inte
*/
SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(const char *name);
+/*!
+ \brief Enumerates a list of all modules discovered in a directory
+ \param the directory to look for modules in
+ \param memory pool
+ \param callback function to call for each module found
+ \param user data argument to pass to the callback function
+ \return the resulting status
+ */
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data);
+
+
+/*!
+ \brief Enumerates a list of all currently loaded modules
+ \param callback function to call for each module found
+ \param user data argument to pass to the callback function
+ \return the resulting status
+ */
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data);
+
/*!
\brief build a dynamic module object and register it (for use in double embeded modules)
\param filename the name of the modules source file
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index dacf2dddda..5a88cd5751 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -1731,6 +1731,8 @@ typedef struct switch_loadable_module_function_table {
switch_module_flag_t flags;
} switch_loadable_module_function_table_t;
+typedef int (*switch_modulename_callback_func_t) (void *user_data, const char *module_name);
+
#define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \
static const char modname[] = #name ; \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index cc864a266b..e1eb2a6b6a 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -4651,9 +4651,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add fsctl flush_db_handles");
switch_console_set_complete("add fsctl min_idle_cpu");
switch_console_set_complete("add fsctl send_sighup");
+ switch_console_set_complete("add load ::console::list_available_modules");
switch_console_set_complete("add nat_map reinit");
switch_console_set_complete("add nat_map republish");
switch_console_set_complete("add nat_map status");
+ switch_console_set_complete("add reload ::console::list_loaded_modules");
switch_console_set_complete("add reloadacl reloadxml");
switch_console_set_complete("add show aliases");
switch_console_set_complete("add show api");
@@ -4678,6 +4680,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add show timer");
switch_console_set_complete("add shutdown");
switch_console_set_complete("add sql_escape");
+ switch_console_set_complete("add unload ::console::list_loaded_modules");
switch_console_set_complete("add uuid_audio ::console::list_uuid start read mute");
switch_console_set_complete("add uuid_audio ::console::list_uuid start read level");
switch_console_set_complete("add uuid_audio ::console::list_uuid start write mute");
diff --git a/src/mod/applications/mod_curl/mod_curl.c b/src/mod/applications/mod_curl/mod_curl.c
old mode 100755
new mode 100644
index 9081ca6094..4f6aefd313
--- a/src/mod/applications/mod_curl/mod_curl.c
+++ b/src/mod/applications/mod_curl/mod_curl.c
@@ -272,6 +272,7 @@ SWITCH_STANDARD_APP(curl_app_function)
} else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) {
method = switch_core_strdup(pool, argv[i]);
} else if (!strcasecmp("post", argv[i])) {
+ method = "post";
if (++i < argc) {
postdata = switch_core_strdup(pool, argv[i]);
switch_url_decode(postdata);
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index bb88ac5b1a..69ce125d0f 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -1001,7 +1001,13 @@ static int do_candidates(struct private_object *tech_pvt, int force)
cand[0].protocol = "udp";
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port,
cand[0].username);
- tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
+
+ if (ldl_session_gateway(tech_pvt->dlsession)) {
+ tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1);
+ } else {
+ tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
+ }
+
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT);
switch_set_flag_locked(tech_pvt, TFLAG_RTP_READY);
}
@@ -1112,6 +1118,7 @@ static switch_status_t negotiate_media(switch_core_session_t *session)
now = switch_micro_time_now();
elapsed = (unsigned int) ((now - started) / 1000);
+
if (switch_channel_down(channel) || switch_test_flag(tech_pvt, TFLAG_BYE)) {
goto out;
}
@@ -1643,6 +1650,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char workspace[1024] = "";
char *p, *u, ubuf[512] = "", *user = NULL, *f_cid_msg = NULL;
const char *cid_msg = NULL;
+ ldl_user_flag_t flags = LDL_FLAG_OUTBOUND;
+
switch_copy_string(workspace, outbound_profile->destination_number, sizeof(workspace));
profile_name = workspace;
@@ -1711,7 +1720,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
- if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, user, idbuf, sizeof(idbuf)))) {
+ if (switch_stristr("voice.google.com", callto)) {
+ full_id = callto;
+ flags |= LDL_FLAG_GATEWAY;
+ } else if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, user, idbuf, sizeof(idbuf)))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, "Unknown Recipient!\n");
terminate_session(new_session, __LINE__, SWITCH_CAUSE_NO_USER_RESPONSE);
return SWITCH_CAUSE_NO_USER_RESPONSE;
@@ -1768,7 +1780,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_stun_random_string(sess_id, 10, "0123456789");
tech_pvt->us = switch_core_session_strdup(*new_session, user);
tech_pvt->them = switch_core_session_strdup(*new_session, full_id);
- ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, user, LDL_FLAG_OUTBOUND);
+ ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, user, flags);
if (session) {
switch_channel_t *calling_channel = switch_core_session_get_channel(session);
@@ -1780,6 +1792,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
cid_msg = f_cid_msg;
}
+ if ((flags & LDL_FLAG_GATEWAY)) {
+ cid_msg = NULL;
+ }
+
if (cid_msg) {
char *them;
them = strdup(tech_pvt->them);
@@ -3128,6 +3144,11 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
break;
case LDL_SIGNAL_TRANSPORT_ACCEPT:
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT_ACCEPT);
+
+ if (ldl_session_gateway(dlsession)) {
+ do_candidates(tech_pvt, 1);
+ }
+
break;
case LDL_SIGNAL_INITIATE:
if (dl_signal) {
@@ -3243,7 +3264,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
choice = x;
ok = 1;
}
-
+
if (ok) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]);
@@ -3348,6 +3369,10 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
goto done;
}
break;
+ case LDL_SIGNAL_REDIRECT:
+ do_describe(tech_pvt, 1);
+ break;
+
case LDL_SIGNAL_ERROR:
case LDL_SIGNAL_TERMINATE:
if (channel) {
diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt
index 9dfda1e829..ff47780118 100644
--- a/src/mod/endpoints/mod_h323/changes.txt
+++ b/src/mod/endpoints/mod_h323/changes.txt
@@ -1,4 +1,3 @@
-set network_addr of caller profile to signaling ip address. (requested by Steven Ayre)
move PTrace level set to FSH323EndPoint::Initialise
partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive.
apply changes from mod_h323-patch.diff by Peter Olsson.
diff --git a/src/mod/endpoints/mod_h323/compiling.txt b/src/mod/endpoints/mod_h323/compiling.txt
new file mode 100644
index 0000000000..91d547f13f
--- /dev/null
+++ b/src/mod/endpoints/mod_h323/compiling.txt
@@ -0,0 +1 @@
+To compile this module use latest ptlib/h323plis combinations listed at http://www.gnugk.org/compiling-gnugk.html
diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp
index 45a9043d3f..aeee422ca5 100644
--- a/src/mod/endpoints/mod_h323/mod_h323.cpp
+++ b/src/mod/endpoints/mod_h323/mod_h323.cpp
@@ -614,7 +614,7 @@ H323Connection *FSH323EndPoint::CreateConnection(
}
switch_core_session_t *fsSession = switch_core_session_request(GetSwitchInterface(),
- (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
+ (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
if (fsSession == NULL)
return NULL;
diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp
index e38e113196..8935bbb06d 100644
--- a/src/mod/endpoints/mod_opal/mod_opal.cpp
+++ b/src/mod/endpoints/mod_opal/mod_opal.cpp
@@ -513,7 +513,7 @@ OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userDat
{
FSManager & mgr = (FSManager &) GetManager();
switch_core_session_t *fsSession = switch_core_session_request(mgr.GetSwitchInterface(),
- (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
+ (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
if (fsSession == NULL)
return NULL;
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c
index 9ee9e1e45d..5da1367a35 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.c
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.c
@@ -121,6 +121,7 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
stream->write_function(stream, "Date-Format \t%s\n", profile->date_format);
stream->write_function(stream, "DBName \t%s\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn));
stream->write_function(stream, "Debug \t%d\n", profile->debug);
+ stream->write_function(stream, "Auto-Restart \t%d\n", profile->auto_restart);
/* stats */
stream->write_function(stream, "CALLS-IN \t%d\n", profile->ib_calls);
stream->write_function(stream, "FAILED-CALLS-IN \t%d\n", profile->ib_failed_calls);
@@ -1187,7 +1188,8 @@ uint8_t listener_is_ready(listener_t *listener)
&& listener
&& listener->sock
&& switch_test_flag(listener, LFLAG_RUNNING)
- && listener->profile->listener_ready;
+ && switch_test_flag(listener->profile, PFLAG_LISTENER_READY)
+ && !switch_test_flag(listener->profile, PFLAG_RESPAWN);
}
static void add_listener(listener_t *listener)
@@ -1248,7 +1250,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_mutex_unlock(globals.mutex);
}
-static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch_bool_t flush_events)
+static void flush_listener(listener_t *listener)
{
if(!zstr(listener->device_name)) {
@@ -1410,7 +1412,17 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
status = skinny_read_packet(listener, &request);
if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket Error!\n");
+ switch(status) {
+ case SWITCH_STATUS_BREAK:
+ break;
+ case SWITCH_STATUS_TIMEOUT:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Communication Time Out with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
+ break;
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Communication Error with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
+ }
switch_clear_flag_locked(listener, LFLAG_RUNNING);
break;
}
@@ -1432,11 +1444,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
remove_listener(listener);
if (listener->profile->debug > 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Complete with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
}
switch_thread_rwlock_wrlock(listener->rwlock);
- flush_listener(listener, SWITCH_TRUE, SWITCH_TRUE);
+ flush_listener(listener);
if (listener->sock) {
close_socket(&listener->sock, profile);
@@ -1445,19 +1458,10 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
switch_thread_rwlock_unlock(listener->rwlock);
if (listener->profile->debug > 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Closed with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
}
- /* TODO
- for(int line = 0 ; line < SKINNY_MAX_BUTTON_COUNT ; line++) {
- if(listener->session[line]) {
- switch_channel_clear_flag(switch_core_session_get_channel(listener->session[line]), CF_CONTROLLED);
- //TODO switch_clear_flag_locked(listener, LFLAG_SESSION);
- switch_core_session_rwunlock(listener->session[line]);
- destroy_pool = 0;
- }
- }
- */
if(destroy_pool == 0) {
goto no_destroy_pool;
}
@@ -1502,6 +1506,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
return NULL;
}
+new_socket:
while(globals.running) {
rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool);
if (rv)
@@ -1526,7 +1531,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
switch_yield(100000);
}
- profile->listener_ready = 1;
+ switch_set_flag_locked(profile, PFLAG_LISTENER_READY);
while(globals.running) {
@@ -1539,6 +1544,10 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
if (!globals.running) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
goto end;
+ } else if (switch_test_flag(profile, PFLAG_RESPAWN)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n");
+ switch_clear_flag_locked(profile, PFLAG_RESPAWN);
+ goto new_socket;
} else {
/* I wish we could use strerror_r here but its not defined everywhere =/ */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));
@@ -1590,6 +1599,17 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
return NULL;
}
+
+void launch_skinny_profile_thread(skinny_profile_t *profile) {
+ switch_thread_t *thread;
+ switch_threadattr_t *thd_attr = NULL;
+
+ switch_threadattr_create(&thd_attr, profile->pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+ switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool);
+}
+
/*****************************************************************************/
/* MODULE FUNCTIONS */
/*****************************************************************************/
@@ -1603,9 +1623,9 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!var)
return SWITCH_STATUS_FALSE;
- if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port") || !strcasecmp(var, "odbc-dsn"))) {
+ if (profile->sock && !strcasecmp(var, "odbc-dsn")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Skinny profile settings 'ip', 'port' and 'odbc-dsn' can't be changed while running\n");
+ "Skinny profile setting 'odbc-dsn' can't be changed while running\n");
return SWITCH_STATUS_FALSE;
}
@@ -1643,9 +1663,17 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
}
} else if (!strcasecmp(var, "debug")) {
profile->debug = atoi(val);
+ } else if (!strcasecmp(var, "auto-restart")) {
+ profile->auto_restart = switch_true(val);
} else {
return SWITCH_STATUS_FALSE;
}
+ if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port"))) {
+ switch_set_flag_locked(profile, PFLAG_RESPAWN);
+ switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
+ close_socket(&profile->sock, profile);
+ }
+
return SWITCH_STATUS_SUCCESS;
}
@@ -1684,9 +1712,11 @@ static switch_status_t load_skinny_config(void)
profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool;
profile->name = switch_core_strdup(profile->pool, profile_name);
- switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ profile->auto_restart = SWITCH_TRUE;
switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
for (param = switch_xml_child(xsettings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
@@ -1950,6 +1980,41 @@ static void skinny_message_waiting_event_handler(switch_event_t *event)
}
+static void skinny_trap_event_handler(switch_event_t *event)
+{
+ const char *cond = switch_event_get_header(event, "condition");
+
+
+ if (cond && !strcmp(cond, "network-address-change") && globals.auto_restart) {
+ const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4");
+ const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4");
+ const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6");
+ const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6");
+ switch_hash_index_t *hi;
+ const void *var;
+ void *val;
+ skinny_profile_t *profile;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
+
+ switch_mutex_lock(globals.mutex);
+ if (globals.profile_hash) {
+ for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &var, NULL, &val);
+ if ((profile = (skinny_profile_t *) val) && profile->auto_restart) {
+ if (!strcmp(profile->ip, old_ip4)) {
+ skinny_profile_set(profile, "ip", new_ip4);
+ } else if (!strcmp(profile->ip, old_ip6)) {
+ skinny_profile_set(profile, "ip", new_ip6);
+ }
+ }
+ }
+ }
+ switch_mutex_unlock(globals.mutex);
+ }
+
+}
/*****************************************************************************/
SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
{
@@ -1964,6 +2029,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_core_hash_init(&globals.profile_hash, globals.pool);
globals.running = 1;
+ globals.auto_restart = SWITCH_TRUE;
load_skinny_config();
@@ -1980,6 +2046,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n");
/* Not such severe to prevent loading */
}
+ if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our trap handler!\n");
+ /* Not such severe to prevent loading */
+ }
/* reserve events */
if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
@@ -2017,16 +2087,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
void *val;
skinny_profile_t *profile;
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr = NULL;
switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val;
-
- switch_threadattr_create(&thd_attr, profile->pool);
- switch_threadattr_detach_set(thd_attr, 1);
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool);
+
+ launch_skinny_profile_thread(profile);
}
switch_mutex_unlock(globals.mutex);
@@ -2048,6 +2113,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)
switch_event_unbind(&globals.heartbeat_node);
switch_event_unbind(&globals.call_state_node);
switch_event_unbind(&globals.message_waiting_node);
+ switch_event_unbind(&globals.trap_node);
switch_event_free_subclass(SKINNY_EVENT_REGISTER);
switch_event_free_subclass(SKINNY_EVENT_UNREGISTER);
switch_event_free_subclass(SKINNY_EVENT_EXPIRE);
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h
index 41b9b72a6e..f52f171fdc 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.h
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.h
@@ -52,11 +52,18 @@ struct skinny_globals {
switch_event_node_t *heartbeat_node;
switch_event_node_t *call_state_node;
switch_event_node_t *message_waiting_node;
+ switch_event_node_t *trap_node;
+ int auto_restart;
};
typedef struct skinny_globals skinny_globals_t;
extern skinny_globals_t globals;
+typedef enum {
+ PFLAG_LISTENER_READY = (1 << 0),
+ PFLAG_RESPAWN = (1 << 1),
+} profile_flag_t;
+
struct skinny_profile {
/* prefs */
char *name;
@@ -70,6 +77,7 @@ struct skinny_profile {
uint32_t keep_alive;
char date_format[6];
int debug;
+ int auto_restart;
switch_hash_t *device_type_params_hash;
/* db */
char *dbname;
@@ -89,7 +97,8 @@ struct skinny_profile {
switch_socket_t *sock;
switch_mutex_t *sock_mutex;
struct listener *listeners;
- uint8_t listener_ready;
+ int flags;
+ switch_mutex_t *flag_mutex;
/* call id */
uint32_t next_call_id;
/* others */
@@ -114,7 +123,7 @@ typedef enum {
typedef enum {
LFLAG_RUNNING = (1 << 0),
-} event_flag_t;
+} listener_flag_t;
#define SKINNY_MAX_LINES 42
struct listener {
diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c
index 0ef0beb2d5..86eea74fc8 100644
--- a/src/mod/endpoints/mod_skinny/skinny_api.c
+++ b/src/mod/endpoints/mod_skinny/skinny_api.c
@@ -230,6 +230,7 @@ static switch_status_t skinny_api_list_settings(const char *line, const char *cu
switch_console_push_match(&my_matches, "date-format");
switch_console_push_match(&my_matches, "odbc-dsn");
switch_console_push_match(&my_matches, "debug");
+ switch_console_push_match(&my_matches, "auto-restart");
if (my_matches) {
*matches = my_matches;
diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c
index ba4cba70db..28699b9c03 100644
--- a/src/mod/endpoints/mod_skinny/skinny_protocol.c
+++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c
@@ -119,7 +119,7 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
}
if (!listener_is_ready(listener)) {
- return SWITCH_STATUS_FALSE;
+ return SWITCH_STATUS_BREAK;
}
ptr = mbuf;
@@ -136,7 +136,10 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
status = switch_socket_recv(listener->sock, ptr, &mlen);
- if (!listener_is_ready(listener) || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
+ if (!listener_is_ready(listener)) {
+ return SWITCH_STATUS_BREAK;
+ }
+ if (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break.\n");
return SWITCH_STATUS_FALSE;
}
@@ -167,20 +170,13 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
}
if(bytes >= request->length + 2*SKINNY_MESSAGE_FIELD_SIZE) {
/* Message body */
-#ifdef SKINNY_MEGA_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "Got complete request: length=%d,reserved=%x,type=%x,data=%d\n",
- request->length,request->reserved,request->type,request->data.as_char);
-#endif
*req = request;
return SWITCH_STATUS_SUCCESS;
}
}
}
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Listener timed out.\n");
- switch_clear_flag_locked(listener, LFLAG_RUNNING);
- return SWITCH_STATUS_FALSE;
+ return SWITCH_STATUS_TIMEOUT;
}
if (do_sleep) {
switch_cond_next();
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 16b928bb47..14d05fd977 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -436,18 +436,24 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
mwi_status = switch_stristr("Messages-Waiting: ", sip->sip_payload->pl_data);
if ( mwi_status ) {
+ char *mwi_stat;
mwi_status += strlen( "Messages-Waiting: " );
- mwi_status = switch_strip_whitespace( mwi_status );
+ mwi_stat = switch_strip_whitespace( mwi_status );
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Forwarding unsolicited MWI ( %s : %s@%s )\n", mwi_status, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Forwarding unsolicited MWI ( %s : %s@%s )\n",
+ mwi_stat, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
if (switch_event_create(&s_event, SWITCH_EVENT_MESSAGE_WAITING) == SWITCH_STATUS_SUCCESS) {
- switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", mwi_status );
- switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", mwi_stat );
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM,
+ "MWI-Message-Account", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
switch_event_fire(&s_event);
}
+ switch_safe_free(mwi_stat);
}
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Dropping unsolicited MWI ( %s@%s ) because of ACL\n", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Dropping unsolicited MWI ( %s@%s ) because of ACL\n",
+ sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
};
}
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index 39b495d392..73d930314b 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -565,34 +565,32 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
probe_euser = (p + 1);
}
-
-
-
if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) {
sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", probe_euser, probe_host);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
switch_safe_free(sql);
- sql = switch_mprintf("select sip_registrations.sip_user, '%q', sip_registrations.status, "
+ sql = switch_mprintf("select sip_registrations.sip_user, sip_registrations.orig_server_host, sip_registrations.status, "
"sip_registrations.rpid,'', sip_dialogs.uuid, sip_dialogs.state, sip_dialogs.direction, "
"sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, sip_presence.status,sip_presence.rpid,sip_presence.open_closed,"
"'%q','%q' "
"from sip_registrations left join sip_dialogs on "
"(sip_dialogs.sip_from_user = sip_registrations.sip_user "
- "and sip_dialogs.sip_from_host = sip_registrations.sip_host) "
+ "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or "
+ "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) "
"left join sip_presence on "
- "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.sip_host=sip_presence.sip_host and "
+ "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and "
"sip_registrations.profile_name=sip_presence.profile_name) "
"where sip_registrations.sip_user='%q' and "
- "(sip_registrations.sip_host='%q' or sip_registrations.presence_hosts like '%%%q%%')",
- probe_host, dh.status, dh.rpid, probe_euser, probe_host, probe_host);
+ "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' "
+ "or sip_registrations.presence_hosts like '%%%q%%')",
+ dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_host);
switch_assert(sql);
-
if (mod_sofia_globals.debug_presence > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name);
}
@@ -622,6 +620,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
sofia_glue_release_profile(profile);
switch_safe_free(sql);
}
+
switch_safe_free(probe_user);
}
@@ -961,7 +960,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char
switch_event_header_t *hp;
if (argc > 5) {
- uuid = switch_str_nil(argv[5]);
+ uuid = argv[5];
state = switch_str_nil(argv[6]);
direction = switch_str_nil(argv[7]);
if (argc > 8) {
@@ -998,12 +997,13 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char
}
if (zstr(state)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", SOFIA_CHAT_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "resubscribe");
+ //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "resubscribe");
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", uuid);
+ if (uuid) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", uuid);
+ }
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", state);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", state);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", direction);
@@ -1317,15 +1317,21 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
}
if (is_dialog) {
+ char *version = switch_event_get_header(helper->event, "event_count");
+ if (!version) {
+ version = "0";
+ }
+
stream.write_function(&stream,
"\n"
"\n",
- switch_str_nil(switch_event_get_header(helper->event, "event_count")),
- !strcasecmp(answer_state, "resubscribe") ? "partial" : "full", clean_id);
+ version,
+ zstr(uuid) ? "partial" : "full", clean_id);
}
- if (strcasecmp(event_status, "Registered")) {
+ //if (strcasecmp(event_status, "Registered")) {
+ if (!zstr(uuid)) {
if (!zstr(answer_state)) {
astate = answer_state;
}
@@ -2232,8 +2238,11 @@ void sofia_presence_handle_sip_i_subscribe(int status,
if (switch_event_create(&pevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "login", profile->url);
- switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host);
+ //switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host);
+ switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
+ switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
+ switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 18df1c4398..6b90b775fc 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -787,6 +787,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *from_user = NULL;
const char *from_host = NULL;
const char *reg_host = profile->reg_db_domain;
+ const char *sub_host = profile->sub_domain;
char contact_str[1024] = "";
int nat_hack = 0;
uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
@@ -851,6 +852,9 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (!reg_host) {
reg_host = to_host;
}
+ if (!sub_host) {
+ sub_host = to_host;
+ }
if (contact->m_url) {
const char *port = contact->m_url->url_port;
@@ -1146,11 +1150,14 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
if (multi_reg) {
+
+#ifdef DEL_SUBS
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
- to_user, reg_host, contact_str);
+ to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
+#endif
if (multi_reg_contact) {
@@ -1160,14 +1167,35 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
} else {
- sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, reg_host);
+#ifdef DEL_SUBS
+ sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+#endif
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
+
+ if (profile->reg_db_domain) {
+ sofia_profile_t *xprofile;
+
+ if ((xprofile = sofia_glue_find_profile(to_host))) {
+ sofia_glue_release_profile(xprofile);
+ } else {
+
+ if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n",
+ to_host, profile->name);
+ }
+
+
+ }
+ }
+
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
@@ -1220,7 +1248,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
@@ -1234,8 +1262,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
@@ -1253,7 +1281,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
@@ -1262,7 +1290,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "unavailable");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
@@ -1280,15 +1308,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if ((p = strchr(icontact + 4, ':'))) {
*p = '\0';
}
-
+#ifdef DEL_SUBS
if (multi_reg_contact) {
sql =
- switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
+ switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+#endif
if (multi_reg_contact) {
sql =
@@ -1301,10 +1330,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact);
} else {
- if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
+#ifdef DEL_SUBS
+ if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
-
+#endif
if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
@@ -1333,15 +1363,26 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
+#if 0
+ if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
+ switch_event_fire(&s_event);
+ }
+#else
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
- switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_fire(&s_event);
- }
-
+ }
+#endif
} else {
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
diff --git a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
index 740ae04cff..4c1382b9a6 100644
--- a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
+++ b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
@@ -24,7 +24,7 @@
true
full
false
- ..\..\..\..\..\managed\debug\
+ ..\..\..\..\..\Win32\Debug\mod\
TRACE;DEBUG;CLR_VERSION40
prompt
4
@@ -32,11 +32,33 @@
pdbonly
true
- ..\..\..\..\..\managed\release\
+ ..\..\..\..\..\Win32\Release\mod\
TRACE;CLR_VERSION40
prompt
4
+
+ true
+ ..\..\..\..\..\x64\Debug\mod\
+ TRACE;DEBUG;CLR_VERSION40
+ full
+ x64
+ prompt
+ true
+ true
+ true
+
+
+ ..\..\..\..\..\x64\Release\mod\
+ TRACE;CLR_VERSION40
+ true
+ pdbonly
+ x64
+ prompt
+ true
+ true
+ true
+
diff --git a/src/mod/languages/mod_managed/mod_managed.2010.vcxproj b/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
index 76ce260a91..ee1f7d7e96 100644
--- a/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
+++ b/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
@@ -319,11 +319,9 @@
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
- false
-
+
{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}
- false
diff --git a/src/switch_console.c b/src/switch_console.c
index e82290bce7..30d1d97fed 100644
--- a/src/switch_console.c
+++ b/src/switch_console.c
@@ -553,6 +553,46 @@ struct match_helper {
switch_console_callback_match_t *my_matches;
};
+static int modulename_callback(void *pArg, const char *module_name)
+{
+ struct match_helper *h = (struct match_helper *) pArg;
+
+ switch_console_push_match(&h->my_matches, module_name);
+ return 0;
+}
+
+SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_available_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ struct match_helper h = { 0 };
+
+ if (switch_loadable_module_enumerate_available(SWITCH_GLOBAL_dirs.mod_dir, modulename_callback, &h) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (h.my_matches) {
+ *matches = h.my_matches;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_loaded_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ struct match_helper h = { 0 };
+
+ if (switch_loadable_module_enumerate_loaded(modulename_callback, &h) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (h.my_matches) {
+ *matches = h.my_matches;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct match_helper *h = (struct match_helper *) pArg;
@@ -1542,6 +1582,8 @@ SWITCH_DECLARE(switch_status_t) switch_console_init(switch_memory_pool_t *pool)
{
switch_mutex_init(&globals.func_mutex, SWITCH_MUTEX_NESTED, pool);
switch_core_hash_init(&globals.func_hash, pool);
+ switch_console_add_complete_func("::console::list_available_modules", (switch_console_complete_callback_t) switch_console_list_available_modules);
+ switch_console_add_complete_func("::console::list_loaded_modules", (switch_console_complete_callback_t) switch_console_list_loaded_modules);
switch_console_add_complete_func("::console::list_uuid", (switch_console_complete_callback_t) switch_console_list_uuid);
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/switch_event.c b/src/switch_event.c
index 1301d92477..cfd6a7a139 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -79,6 +79,7 @@ static switch_memory_pool_t *THRUNTIME_POOL = NULL;
static switch_thread_t *EVENT_QUEUE_THREADS[NUMBER_OF_QUEUES] = { 0 };
static switch_queue_t *EVENT_QUEUE[NUMBER_OF_QUEUES] = { 0 };
static switch_thread_t *EVENT_DISPATCH_QUEUE_THREADS[MAX_DISPATCH_VAL] = { 0 };
+static uint8_t EVENT_DISPATCH_QUEUE_RUNNING[MAX_DISPATCH_VAL] = { 0 };
static switch_queue_t *EVENT_DISPATCH_QUEUE[MAX_DISPATCH_VAL] = { 0 };
static int POOL_COUNT_MAX = SWITCH_CORE_QUEUE_LEN;
static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL;
@@ -238,9 +239,9 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
{
switch_queue_t *queue = (switch_queue_t *) obj;
int my_id = 0;
+
switch_mutex_lock(EVENT_QUEUE_MUTEX);
THREAD_COUNT++;
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
for (my_id = 0; my_id < NUMBER_OF_QUEUES; my_id++) {
if (EVENT_DISPATCH_QUEUE[my_id] == queue) {
@@ -248,6 +249,9 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
}
}
+ EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
+ switch_mutex_unlock(EVENT_QUEUE_MUTEX);
+
for (;;) {
void *pop = NULL;
switch_event_t *event = NULL;
@@ -270,6 +274,7 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
switch_mutex_lock(EVENT_QUEUE_MUTEX);
+ EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
THREAD_COUNT--;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
@@ -298,6 +303,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
for (;;) {
void *pop = NULL;
switch_event_t *event = NULL;
+ int loops = 0;
if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
break;
@@ -314,13 +320,13 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
event = (switch_event_t *) pop;
while (event) {
- int max;
- switch_mutex_lock(EVENT_QUEUE_MUTEX);
- max = SOFT_MAX_DISPATCH;
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
+ if (++loops > 2) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event system overloading\n");
+ switch_yield(1000000);
+ }
- for (index = 0; (int)index < max; index++) {
+ for (index = 0; index < SOFT_MAX_DISPATCH; index++) {
if (switch_queue_trypush(EVENT_DISPATCH_QUEUE[index], event) == SWITCH_STATUS_SUCCESS) {
event = NULL;
break;
@@ -328,19 +334,15 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
}
if (event) {
- switch_mutex_lock(EVENT_QUEUE_MUTEX);
if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Adding a new event thread #%d\n", SOFT_MAX_DISPATCH + 1);
+ switch_mutex_lock(EVENT_QUEUE_MUTEX);
launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL);
+ switch_mutex_unlock(EVENT_QUEUE_MUTEX);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event threads maxed out at %d.\n", SOFT_MAX_DISPATCH);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n");
switch_yield(1000000);
}
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
}
-
-
- switch_cond_next();
}
}
@@ -566,6 +568,8 @@ static void launch_dispatch_threads(uint32_t max, int len, switch_memory_pool_t
{
switch_threadattr_t *thd_attr;
uint32_t index = 0;
+ int launched = 0;
+ uint32_t sanity = 200;
if (max > MAX_DISPATCH) {
return;
@@ -584,8 +588,10 @@ static void launch_dispatch_threads(uint32_t max, int len, switch_memory_pool_t
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_threadattr_priority_increase(thd_attr);
switch_thread_create(&EVENT_DISPATCH_QUEUE_THREADS[index], thd_attr, switch_event_dispatch_thread, EVENT_DISPATCH_QUEUE[index], pool);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Create event dispatch thread %d\n", index);
- switch_yield(100000);
+ while(--sanity && !EVENT_DISPATCH_QUEUE_RUNNING[index]) switch_yield(10000);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Create event dispatch thread %d\n", index);
+ launched++;
+ break;
}
SOFT_MAX_DISPATCH = index;
diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c
index 97cb5e8d70..0ef3624326 100644
--- a/src/switch_loadable_module.c
+++ b/src/switch_loadable_module.c
@@ -1068,6 +1068,62 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir,
}
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data)
+{
+ switch_dir_t *dir = NULL;
+ switch_status_t status;
+ char buffer[256];
+ const char *fname;
+ const char *fname_ext;
+ char *fname_base;
+
+#ifdef WIN32
+ const char *ext = ".dll";
+#else
+ const char *ext = ".so";
+#endif
+
+ if ((status = switch_dir_open(&dir, dir_path, loadable_modules.pool)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+
+ while((fname = switch_dir_next_file(dir, buffer, sizeof(buffer)))) {
+ if ((fname_ext = strrchr(fname, '.'))) {
+ if (!strcmp(fname_ext, ext)) {
+ if (!(fname_base = switch_mprintf("%.*s", (int)(fname_ext-fname), fname))) {
+ status = SWITCH_STATUS_GENERR;
+ goto end;
+ }
+ callback(user_data, fname_base);
+ switch_safe_free(fname_base)
+ }
+ }
+ }
+
+
+ end:
+ switch_dir_close(dir);
+ return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data)
+{
+ switch_hash_index_t *hi;
+ void *val;
+ switch_loadable_module_t *module;
+
+ switch_mutex_lock(loadable_modules.mutex);
+ for (hi = switch_hash_first(NULL, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ module = (switch_loadable_module_t *) val;
+
+ callback(user_data, module->module_interface->module_name);
+ }
+ switch_mutex_unlock(loadable_modules.mutex);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
switch_module_load_t switch_module_load,
switch_module_runtime_t switch_module_runtime,
@@ -1627,27 +1683,34 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
{
switch_api_interface_t *api;
switch_status_t status;
+ char *arg_no_spaces;
+ char *cmd_no_spaces;
switch_assert(stream != NULL);
switch_assert(stream->data != NULL);
switch_assert(stream->write_function != NULL);
+
+ cmd_no_spaces = switch_strip_whitespace(cmd);
+ arg_no_spaces = switch_strip_whitespace(arg);
+
+
if (!stream->param_event) {
switch_event_create(&stream->param_event, SWITCH_EVENT_API);
}
if (stream->param_event) {
- if (cmd) {
- switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd);
+ if (cmd_no_spaces) {
+ switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_no_spaces);
}
- if (arg) {
- switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg);
+ if (arg_no_spaces) {
+ switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_no_spaces);
}
}
- if (cmd && (api = switch_loadable_module_get_api_interface(cmd)) != 0) {
- if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) {
+ if (cmd_no_spaces && (api = switch_loadable_module_get_api_interface(cmd_no_spaces)) != 0) {
+ if ((status = api->function(arg_no_spaces, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
}
UNPROTECT_INTERFACE(api);
@@ -1660,6 +1723,8 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
switch_event_fire(&stream->param_event);
}
+ switch_safe_free(cmd_no_spaces);
+ switch_safe_free(arg_no_spaces);
return status;
}
diff --git a/src/switch_resample.c b/src/switch_resample.c
index 3264b9ed99..65ebe3c32f 100644
--- a/src/switch_resample.c
+++ b/src/switch_resample.c
@@ -26,7 +26,7 @@
* Anthony Minessale II
*
*
- * switch_caller.c -- Caller Identification
+ * switch_resample.c -- Resampler
*
*/
diff --git a/src/switch_utils.c b/src/switch_utils.c
index d7c5d6b6d4..91b78f7bbb 100644
--- a/src/switch_utils.c
+++ b/src/switch_utils.c
@@ -724,7 +724,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
if (!sp)
return NULL;
- while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 20) || (*sp == 11) ) {
+ while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
sp++;
}
@@ -735,7 +735,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
p = s + (strlen(s) - 1);
- while ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 20) || (*p == 11) ) {
+ while ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11) ) {
*p-- = '\0';
}