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