Merge branch 'master' of git://git.freeswitch.org/freeswitch

This commit is contained in:
Moises Silva 2010-09-02 18:46:22 -04:00
commit ceddc5b84f
29 changed files with 595 additions and 143 deletions

View File

@ -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

View File

@ -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}

View File

@ -596,7 +596,7 @@
<extension name="ringback_183_uk_ring">
<condition field="destination_number" expression="^9181$">
<action application="set" data="ringback=$${uk-ring}"/>
<action application="bridge" data="loopback/wait"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
@ -604,7 +604,7 @@
<extension name="ringback_183_music_ring">
<condition field="destination_number" expression="^9182$">
<action application="set" data="ringback=$${hold_music}"/>
<action application="bridge" data="loopback/wait"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
@ -613,7 +613,7 @@
<condition field="destination_number" expression="^9183$">
<action application="set" data="transfer_ringback=$${uk-ring}"/>
<action application="answer"/>
<action application="bridge" data="loopback/wait"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
@ -622,7 +622,7 @@
<condition field="destination_number" expression="^9184$">
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="answer"/>
<action application="bridge" data="loopback/wait"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>

View File

@ -11,6 +11,7 @@
<param name="date-format" value="D/M/Y"/>
<param name="odbc-dsn" value=""/>
<param name="debug" value="4"/>
<param name="auto-restart" value="true"/>
</settings>
<device-types>
<device-type id="Cisco ATA 186">

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 = { \

View File

@ -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");

1
src/mod/applications/mod_curl/mod_curl.c Executable file → Normal file
View File

@ -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);

View File

@ -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) {

View File

@ -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.

View File

@ -0,0 +1 @@
To compile this module use latest ptlib/h323plis combinations listed at http://www.gnugk.org/compiling-gnugk.html

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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();

View File

@ -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 );
};
}

View File

@ -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,
"<?xml version=\"1.0\"?>\n"
"<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
"version=\"%s\" state=\"%s\" entity=\"%s\">\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);

View File

@ -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);

View File

@ -24,7 +24,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\..\..\managed\debug\</OutputPath>
<OutputPath>..\..\..\..\..\Win32\Debug\mod\</OutputPath>
<DefineConstants>TRACE;DEBUG;CLR_VERSION40</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -32,11 +32,33 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\..\..\managed\release\</OutputPath>
<OutputPath>..\..\..\..\..\Win32\Release\mod\</OutputPath>
<DefineConstants>TRACE;CLR_VERSION40</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\mod\</OutputPath>
<DefineConstants>TRACE;DEBUG;CLR_VERSION40</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\mod\</OutputPath>
<DefineConstants>TRACE;CLR_VERSION40</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">

View File

@ -319,11 +319,9 @@
<ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="managed\FreeSWITCH.Managed.csproj">
<ProjectReference Include="managed\FreeSWITCH.Managed.2010.csproj">
<Project>{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -26,7 +26,7 @@
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* switch_caller.c -- Caller Identification
* switch_resample.c -- Resampler
*
*/

View File

@ -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';
}