either break everything or make it cooler ... ?

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5036 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-04-29 01:16:49 +00:00
parent 6a392d2577
commit ffb254ad49
7 changed files with 361 additions and 67 deletions

View File

@ -244,6 +244,10 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
switch_mutex_lock(tech_pvt->profile->flag_mutex);
tech_pvt->profile->inuse--;
switch_mutex_unlock(tech_pvt->profile->flag_mutex);
if (tech_pvt->sofia_private) {
*tech_pvt->sofia_private->uuid = '\0';
}
@ -275,7 +279,6 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
assert(channel != NULL);
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if (!switch_test_flag(tech_pvt, TFLAG_ANS) && !switch_channel_test_flag(channel, CF_OUTBOUND)) {
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
@ -314,9 +317,11 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
}
}
}
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
}
return SWITCH_STATUS_SUCCESS;
@ -336,7 +341,7 @@ static switch_status_t sofia_read_video_frame(switch_core_session_t *session, sw
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@ -408,7 +413,7 @@ static switch_status_t sofia_write_video_frame(switch_core_session_t *session, s
}
}
if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@ -440,7 +445,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@ -535,7 +540,7 @@ static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_
}
}
if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@ -880,6 +885,126 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc
return SWITCH_STATUS_SUCCESS;
}
typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
{
sofia_profile_t *profile = NULL;
switch_hash_index_t *hi;
void *val;
int c = 0;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (hi = switch_hash_first(switch_hash_pool_get(mod_sofia_globals.profile_hash), mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
profile = (sofia_profile_t *) val;
if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
stream->write_function(stream, "Profile %s\n", profile->name);
c++;
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
stream->write_function(stream, "%d profiles\n", c);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t *stream)
{
sofia_profile_t *profile = NULL;
char *profile_name = argv[0];
if (argc < 2) {
stream->write_function(stream, "Invalid Args!\n");
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[1], "start")) {
if (config_sofia(1, argv[0]) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "%s started successfully\n", argv[0]);
} else {
stream->write_function(stream, "Failure starting %s\n", argv[0]);
}
return SWITCH_STATUS_SUCCESS;
}
if (switch_strlen_zero(profile_name) || !(profile = sofia_glue_find_profile(profile_name))) {
stream->write_function(stream, "Invalid Profile [%s]", switch_str_nil(profile_name));
return SWITCH_STATUS_SUCCESS;
}
if (!strcasecmp(argv[1], "stop")) {
sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
stream->write_function(stream, "stopping: %s", profile->name);
}
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
{
char *argv[1024] = { 0 };
int argc = 0;
char *mycmd = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
sofia_command_t func = NULL;
int lead = 1;
const char *usage_string = "USAGE:\n"
"--------------------------------------------------------------------------------\n"
"sofia help\n"
"sofia profile <options>\n"
"sofia status\n"
"--------------------------------------------------------------------------------\n";
if (isession) {
return SWITCH_STATUS_FALSE;
}
if (switch_strlen_zero(cmd)) {
stream->write_function(stream, "%s", usage_string);
goto done;
}
if (!(mycmd = strdup(cmd))) {
status = SWITCH_STATUS_MEMERR;
goto done;
}
if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
stream->write_function(stream, "%s", usage_string);
goto done;
}
if (!strcasecmp(argv[0], "profile")) {
func = cmd_profile;
} else if (!strcasecmp(argv[0], "status")) {
func = cmd_status;
} else if (!strcasecmp(argv[0], "help")) {
stream->write_function(stream, "%s", usage_string);
goto done;
}
if (func) {
status = func(&argv[lead], argc - lead, stream);
} else {
stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
}
done:
switch_safe_free(mycmd);
return status;
}
static const switch_io_routines_t sofia_io_routines = {
/*.outgoing_channel */ sofia_outgoing_channel,
/*.read_frame */ sofia_read_frame,
@ -928,6 +1053,14 @@ static const switch_management_interface_t sofia_management_interface = {
/*.management_function */ sofia_manage
};
static switch_api_interface_t sofia_api_interface = {
/*.interface_name */ "sofia",
/*.desc */ "Sofia Controls",
/*.function */ sofia_function,
/*.syntax */ "<cmd> <args>",
/*.next */ NULL
};
static const switch_loadable_module_interface_t sofia_module_interface = {
/*.module_name */ modname,
/*.endpoint_interface */ &sofia_endpoint_interface,
@ -935,7 +1068,7 @@ static const switch_loadable_module_interface_t sofia_module_interface = {
/*.dialplan_interface */ NULL,
/*.codec_interface */ NULL,
/*.application_interface */ NULL,
/*.api_interface */ NULL,
/*.api_interface */ &sofia_api_interface,
/*.file_interface */ NULL,
/*.speech_interface */ NULL,
/*.directory_interface */ NULL,
@ -954,7 +1087,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_core_session_t *nsession;
char *data, *profile_name, *dest;
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
switch_caller_profile_t *caller_profile = NULL;
private_object_t *tech_pvt = NULL;
switch_channel_t *nchannel;
@ -979,7 +1112,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (!strncasecmp(profile_name, "gateway", 7)) {
char *gw;
outbound_reg_t *gateway_ptr;
sofia_gateway_t *gateway_ptr = NULL;
if (!(gw = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n");
@ -1016,6 +1149,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s", dest);
}
tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact);
sofia_reg_release_gateway(gateway_ptr);
} else {
if (!(dest = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n");
@ -1102,6 +1236,10 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
done:
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
return cause;
}
@ -1133,7 +1271,7 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
switch_core_hash_init(&mod_sofia_globals.gateway_hash, module_pool);
switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED, module_pool);
if (config_sofia(0) != SWITCH_STATUS_SUCCESS) {
if (config_sofia(0, NULL) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}

View File

@ -47,8 +47,8 @@
static const char modname[] = "mod_sofia";
static const switch_state_handler_table_t noop_state_handler = { 0 };
struct outbound_reg;
typedef struct outbound_reg outbound_reg_t;
struct sofia_gateway;
typedef struct sofia_gateway sofia_gateway_t;
struct sofia_profile;
typedef struct sofia_profile sofia_profile_t;
@ -82,7 +82,7 @@ typedef struct private_object private_object_t;
struct sofia_private {
char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
outbound_reg_t *gateway;
sofia_gateway_t *gateway;
su_home_t *home;
};
@ -109,7 +109,8 @@ typedef enum {
PFLAG_PRESENCE = (1 << 4),
PFLAG_PASS_RFC2833 = (1 << 5),
PFLAG_DISABLE_TRANSCODING = (1 << 6),
PFLAG_REWRITE_TIMESTAMPS = (1 << 7)
PFLAG_REWRITE_TIMESTAMPS = (1 << 7),
PFLAG_RUNNING = (1 << 8)
} PFLAGS;
typedef enum {
@ -170,7 +171,7 @@ typedef enum {
REG_STATE_NOREG
} reg_state_t;
struct outbound_reg {
struct sofia_gateway {
sofia_private_t *sofia_private;
nua_handle_t *nh;
sofia_profile_t *profile;
@ -191,7 +192,7 @@ struct outbound_reg {
uint32_t flags;
reg_state_t state;
switch_memory_pool_t *pool;
struct outbound_reg *next;
struct sofia_gateway *next;
};
@ -229,11 +230,14 @@ struct sofia_profile {
uint32_t codec_flags;
switch_mutex_t *ireg_mutex;
switch_mutex_t *gateway_mutex;
outbound_reg_t *gateways;
sofia_gateway_t *gateways;
su_home_t *home;
switch_hash_t *profile_hash;
switch_hash_t *chat_hash;
switch_core_db_t *master_db;
switch_thread_rwlock_t *rwlock;
switch_mutex_t *flag_mutex;
uint32_t inuse;
#ifdef SWITCH_HAVE_ODBC
char *odbc_dsn;
char *odbc_user;
@ -350,6 +354,17 @@ typedef enum {
AUTH_STALE,
} auth_res_t;
#define sofia_test_pflag(obj, flag) ((obj)->pflags & flag)
#define sofia_set_pflag(obj, flag) (obj)->pflags |= (flag)
#define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\
switch_mutex_lock(obj->flag_mutex);\
(obj)->pflags |= (flag);\
switch_mutex_unlock(obj->flag_mutex);
#define sofia_clear_pflag_locked(obj, flag) switch_mutex_lock(obj->flag_mutex); (obj)->pflags &= ~(flag); switch_mutex_unlock(obj->flag_mutex);
#define sofia_clear_pflag(obj, flag) (obj)->pflags &= ~(flag)
#define sofia_copy_pflags(dest, src, flags) (dest)->pflags &= ~(flags); (dest)->pflags |= ((src)->pflags & (flags))
/* Function Prototypes */
/*************************************************************************************************************************************************************/
@ -398,7 +413,7 @@ void event_handler(switch_event_t *event);
void sofia_presence_event_handler(switch_event_t *event);
void sofia_presence_mwi_event_handler(switch_event_t *event);
void sofia_presence_cancel(void);
switch_status_t config_sofia(int reload);
switch_status_t config_sofia(int reload, char *profile_name);
auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, const char *regstr, char *np, size_t nplen, char *ip);
void sofia_reg_handle_sip_r_challenge(int status,
char const *phrase,
@ -427,8 +442,8 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now);
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
void sofia_reg_unregister(sofia_profile_t *profile);
switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
outbound_reg_t *sofia_reg_find_gateway(char *key);
void sofia_reg_add_gateway(char *key, outbound_reg_t *gateway);
sofia_gateway_t *sofia_reg_find_gateway(char *key);
void sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway);
void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp);
int sofia_glue_get_user_host(char *in, char **user, char **host);
switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status);
@ -449,3 +464,4 @@ switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile,
void *pdata);
char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len);
void sofia_glue_check_video_codecs(private_object_t *tech_pvt);
void sofia_reg_release_gateway(sofia_gateway_t *gateway);

View File

@ -70,7 +70,7 @@ void sofia_event_callback(nua_event_t event,
}
}
if (status != 100 && status != 200) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event [%s] status [%d][%s] session: %s\n",
nua_event_name(event), status, phrase, session ? switch_channel_get_name(channel) : "n/a");
@ -110,6 +110,10 @@ void sofia_event_callback(nua_event_t event,
switch (event) {
case nua_r_shutdown:
if (status >= 200) {
su_root_break(profile->s_root);
}
break;
case nua_r_get_params:
case nua_r_invite:
case nua_r_unregister:
@ -201,7 +205,7 @@ void event_handler(switch_event_t *event)
char *rpid = switch_event_get_header(event, "orig-rpid");
long expires = (long) time(NULL) + atol(exp_str);
char *profile_name = switch_event_get_header(event, "orig-profile-name");
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
char buf[512];
if (!rpid) {
@ -233,6 +237,9 @@ void event_handler(switch_event_t *event)
}
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
}
}
@ -340,7 +347,9 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting thread for %s\n", profile->name);
while (mod_sofia_globals.running == 1) {
sofia_set_pflag_locked(profile, PFLAG_RUNNING);
while (mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (++ireg_loops >= IREG_SECONDS) {
sofia_reg_check_expire(profile, time(NULL));
ireg_loops = 0;
@ -353,23 +362,40 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
su_root_step(profile->s_root, 1000);
}
sofia_glue_sql_close(profile);
//sofia_reg_check_expire(profile, 0);
//sofia_reg_check_gateway(profile, 0);
switch_thread_rwlock_wrlock(profile->rwlock);
sofia_reg_unregister(profile);
su_home_unref(profile->home);
nua_shutdown(profile->nua);
su_root_run(profile->s_root);
nua_destroy(profile->nua);
while(0 && profile->inuse) {
switch_yield(1000000);
}
if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp");
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
switch_event_fire(&s_event);
}
sofia_glue_sql_close(profile);
su_home_unref(profile->home);
su_root_destroy(profile->s_root);
pool = profile->pool;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
switch_core_hash_delete(mod_sofia_globals.profile_hash, profile->name);
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
switch_thread_rwlock_unlock(profile->rwlock);
switch_core_destroy_memory_pool(&pool);
end:
switch_mutex_lock(mod_sofia_globals.mutex);
@ -417,14 +443,15 @@ static void logger(void *logarg, char const *fmt, va_list ap)
}
switch_status_t config_sofia(int reload)
switch_status_t config_sofia(int reload, char *profile_name)
{
char *cf = "sofia.conf";
switch_xml_t cfg, xml = NULL, xprofile, param, settings, profiles, gateway_tag, gateways_tag;
switch_status_t status = SWITCH_STATUS_SUCCESS;
sofia_profile_t *profile = NULL;
char url[512] = "";
sofia_gateway_t *gp;
int profile_found = 0;
if (!reload) {
su_init();
@ -432,6 +459,14 @@ switch_status_t config_sofia(int reload)
su_log_redirect(tport_log, logger, NULL);
}
if (!switch_strlen_zero(profile_name) && (profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile [%s] Already exists.\n", switch_str_nil(profile_name));
status = SWITCH_STATUS_FALSE;
switch_thread_rwlock_unlock(profile->rwlock);
return status;
}
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
status = SWITCH_STATUS_FALSE;
@ -458,7 +493,18 @@ switch_status_t config_sofia(int reload)
char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name");
switch_memory_pool_t *pool = NULL;
if (!xprofilename) {
xprofilename = "unnamed";
}
if (profile_name) {
if (strcasecmp(profile_name, xprofilename)) {
continue;
} else {
profile_found = 1;
}
}
/* Setup the pool */
if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
@ -470,9 +516,7 @@ switch_status_t config_sofia(int reload)
goto done;
}
if (!xprofilename) {
xprofilename = "unnamed";
}
profile->pool = pool;
@ -481,7 +525,8 @@ switch_status_t config_sofia(int reload)
profile->dbname = switch_core_strdup(profile->pool, url);
switch_core_hash_init(&profile->chat_hash, profile->pool);
switch_thread_rwlock_create(&profile->rwlock, profile->pool);
switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
profile->dtmf_duration = 100;
profile->codec_ms = 20;
@ -503,7 +548,6 @@ switch_status_t config_sofia(int reload)
if ((profile->odbc_pass = strchr(profile->odbc_user, ':'))) {
*profile->odbc_pass++ = '\0';
}
#else
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
@ -682,7 +726,7 @@ switch_status_t config_sofia(int reload)
if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
outbound_reg_t *gateway;
sofia_gateway_t *gateway;
if (switch_strlen_zero(name)) {
name = "anonymous";
@ -790,12 +834,15 @@ switch_status_t config_sofia(int reload)
gateway->next = profile->gateways;
profile->gateways = gateway;
if (sofia_reg_find_gateway(gateway->name)) {
if ((gp = sofia_reg_find_gateway(gateway->name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate gateway '%s'\n", gateway->name);
} else if (sofia_reg_find_gateway(gateway->register_from)) {
sofia_reg_release_gateway(gp);
} else if ((gp=sofia_reg_find_gateway(gateway->register_from))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate uri '%s'\n", gateway->register_from);
} else if (sofia_reg_find_gateway(gateway->register_contact)) {
sofia_reg_release_gateway(gp);
} else if ((gp=sofia_reg_find_gateway(gateway->register_contact))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate contact '%s'\n", gateway->register_from);
sofia_reg_release_gateway(gp);
} else {
sofia_reg_add_gateway(gateway->name, gateway);
sofia_reg_add_gateway(gateway->register_from, gateway);
@ -816,6 +863,9 @@ switch_status_t config_sofia(int reload)
}
profile = NULL;
}
if (profile_found) {
break;
}
}
}
done:
@ -823,6 +873,11 @@ switch_status_t config_sofia(int reload)
switch_xml_free(xml);
}
if (profile_name && !profile_found) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Such Profile '%s'\n", profile_name);
status = SWITCH_STATUS_FALSE;
}
return status;
}
@ -1169,6 +1224,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
tech_pvt->nh = NULL;
switch_mutex_lock(profile->flag_mutex);
profile->inuse--;
switch_mutex_unlock(profile->flag_mutex);
} else if (sofia_private) {
if (sofia_private->home) {
su_home_unref(sofia_private->home);
@ -1706,7 +1765,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_request->rq_url) {
outbound_reg_t *gateway;
sofia_gateway_t *gateway;
char *from_key = switch_core_session_sprintf(session, "sip:%s@%s",
(char *) sip->sip_request->rq_url->url_user,
(char *) sip->sip_request->rq_url->url_host);
@ -1714,6 +1773,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if ((gateway = sofia_reg_find_gateway(from_key))) {
context = gateway->register_context;
switch_channel_set_variable(channel, "sip_gateway", gateway->name);
sofia_reg_release_gateway(gateway);
}
}

View File

@ -315,9 +315,13 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
switch_mutex_lock(tech_pvt->flag_mutex);
switch_mutex_lock(profile->flag_mutex);
tech_pvt->flags = profile->flags;
switch_mutex_unlock(tech_pvt->flag_mutex);
tech_pvt->profile = profile;
profile->inuse++;
switch_mutex_unlock(profile->flag_mutex);
switch_mutex_unlock(tech_pvt->flag_mutex);
if (tech_pvt->bte) {
tech_pvt->te = tech_pvt->bte;
} else if (!tech_pvt->te) {
@ -1420,7 +1424,14 @@ sofia_profile_t *sofia_glue_find_profile(char *key)
sofia_profile_t *profile;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
profile = (sofia_profile_t *) switch_core_hash_find(mod_sofia_globals.profile_hash, key);
if ((profile = (sofia_profile_t *) switch_core_hash_find(mod_sofia_globals.profile_hash, key))) {
if (!sofia_test_pflag(profile, PFLAG_RUNNING)) {
profile = NULL;
} else if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
profile = NULL;
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
return profile;
@ -1508,6 +1519,7 @@ void sofia_glue_sql_close(sofia_profile_t *profile)
} else {
#endif
switch_core_db_close(profile->master_db);
profile->master_db = NULL;
#ifdef SWITCH_HAVE_ODBC
}
#endif

View File

@ -43,7 +43,7 @@ switch_status_t sofia_presence_chat_send(char *proto, char *from, char *to, char
{
char buf[256];
char *user, *host;
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
char *ffrom = NULL;
nua_handle_t *msg_nh;
char *contact;
@ -98,6 +98,10 @@ switch_status_t sofia_presence_chat_send(char *proto, char *from, char *to, char
switch_safe_free(ffrom);
free(user);
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
}
return SWITCH_STATUS_SUCCESS;
@ -178,7 +182,7 @@ void sofia_presence_mwi_event_handler(switch_event_t *event)
{
char *account, *dup_account, *yn, *host, *user;
char *sql;
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
switch_stream_handle_t stream = { 0 };
switch_event_header_t *hp;
@ -230,11 +234,16 @@ void sofia_presence_mwi_event_handler(switch_event_t *event)
switch_safe_free(sql);
switch_safe_free(dup_account);
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
}
void sofia_presence_event_handler(switch_event_t *event)
{
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
switch_hash_index_t *hi;
void *val;
char *from = switch_event_get_header(event, "from");
@ -364,6 +373,9 @@ void sofia_presence_event_handler(switch_event_t *event)
sofia_presence_resub_callback,
profile);
switch_thread_rwlock_unlock(profile->rwlock);
switch_safe_free(sql);
}
switch_safe_free(user);
@ -569,7 +581,7 @@ static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char *
char *expires = argv[10];
char *body = argv[11];
char *exp;
sofia_profile_t *profile;
sofia_profile_t *profile = NULL;
char *tmp, *id = NULL;
nua_handle_t *nh;
int expire_sec = atoi(expires);
@ -606,6 +618,11 @@ static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char *
switch_safe_free(id);
switch_safe_free(exp);
if (profile) {
switch_thread_rwlock_unlock(profile->rwlock);
}
return 0;
}

View File

@ -39,7 +39,7 @@
void sofia_reg_unregister(sofia_profile_t *profile)
{
outbound_reg_t *gateway_ptr;
sofia_gateway_t *gateway_ptr;
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (gateway_ptr->sofia_private) {
free(gateway_ptr->sofia_private);
@ -52,11 +52,16 @@ void sofia_reg_unregister(sofia_profile_t *profile)
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
{
outbound_reg_t *gateway_ptr;
sofia_gateway_t *gateway_ptr;
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
int ss_state = nua_callstate_authenticating;
reg_state_t ostate = gateway_ptr->state;
if (!now) {
gateway_ptr->state = ostate = REG_STATE_UNREGED;
gateway_ptr->expires_str = "0";
}
switch (ostate) {
case REG_STATE_NOREG:
break;
@ -80,14 +85,26 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
nua_register(gateway_ptr->nh,
SIPTAG_FROM_STR(gateway_ptr->register_from),
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
NUTAG_REGISTRAR(gateway_ptr->register_proxy),
NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
gateway_ptr->retry = now + 10;
if (now) {
nua_register(gateway_ptr->nh,
SIPTAG_FROM_STR(gateway_ptr->register_from),
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
NUTAG_REGISTRAR(gateway_ptr->register_proxy),
NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
gateway_ptr->retry = now + 10;
} else {
nua_unregister(gateway_ptr->nh,
SIPTAG_FROM_STR(gateway_ptr->register_from),
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
NUTAG_REGISTRAR(gateway_ptr->register_proxy),
NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
}
gateway_ptr->retry = now + time(NULL);
gateway_ptr->state = REG_STATE_TRYING;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error registering %s\n", gateway_ptr->name);
gateway_ptr->state = REG_STATE_FAILED;
@ -107,7 +124,6 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
break;
}
}
}
@ -157,7 +173,11 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now)
}
#endif
snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
if (now) {
snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
} else {
snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0", profile->name);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_callback(profile,
@ -166,12 +186,23 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now)
sql,
sofia_reg_del_callback,
NULL);
snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld", (long) now);
if (now) {
snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld", (long) now);
} else {
snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0");
}
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld", (long) now);
if (now) {
snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld", (long) now);
} else {
snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0");
}
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld", (long) now);
if (now) {
snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld", (long) now);
} else {
snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0");
}
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
switch_mutex_unlock(profile->ireg_mutex);
@ -479,7 +510,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
char const *phrase,
nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
{
outbound_reg_t *gateway = NULL;
sofia_gateway_t *gateway = NULL;
sip_www_authenticate_t const *authenticate = NULL;
char const *realm = NULL;
char *p = NULL, *duprealm = NULL, *qrealm = NULL;
@ -522,7 +553,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
}
if (profile) {
outbound_reg_t *gateway_ptr;
sofia_gateway_t *gateway_ptr;
if ((duprealm = strdup(realm))) {
qrealm = duprealm;
@ -548,13 +579,21 @@ void sofia_reg_handle_sip_r_challenge(int status,
}
if (!gateway) {
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (scheme && qrealm && !strcasecmp(gateway_ptr->register_scheme, scheme)
&& !strcasecmp(gateway_ptr->register_realm, qrealm)) {
gateway = gateway_ptr;
if (!switch_test_flag(gateway->profile, PFLAG_RUNNING)) {
gateway = NULL;
} else if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
gateway = NULL;
}
break;
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
if (!gateway) {
@ -578,7 +617,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), SIPTAG_WWW_AUTHENTICATE_REF(authenticate), TAG_END());
nua_authenticate(nh, SIPTAG_EXPIRES_STR(gateway->expires_str), NUTAG_AUTH(authentication), TAG_END());
sofia_reg_release_gateway(gateway);
return;
cancel:
@ -761,18 +800,29 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co
}
outbound_reg_t *sofia_reg_find_gateway(char *key)
sofia_gateway_t *sofia_reg_find_gateway(char *key)
{
outbound_reg_t *gateway;
sofia_gateway_t *gateway = NULL;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
gateway = (outbound_reg_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key);
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
if ((gateway = (sofia_gateway_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING)) {
gateway = NULL;
} else if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
gateway = NULL;
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
return gateway;
}
void sofia_reg_add_gateway(char *key, outbound_reg_t * gateway)
void sofia_reg_release_gateway(sofia_gateway_t *gateway)
{
switch_thread_rwlock_unlock(gateway->profile->rwlock);
}
void sofia_reg_add_gateway(char *key, sofia_gateway_t * gateway)
{
switch_mutex_lock(mod_sofia_globals.hash_mutex);
switch_core_hash_insert(mod_sofia_globals.gateway_hash, key, gateway);

View File

@ -372,6 +372,7 @@ SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
switch_safe_free(handle->password);
free(handle);
}
*handlep = NULL;
}
SWITCH_DECLARE(switch_odbc_state_t) switch_odbc_handle_get_state(switch_odbc_handle_t *handle)