[Freeswitch-svn] [commit] r5036 - in freeswitch/trunk/src: . mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Sat Apr 28 21:16:49 EDT 2007


Author: anthm
Date: Sat Apr 28 21:16:49 2007
New Revision: 5036

Modified:
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
   freeswitch/trunk/src/switch_odbc.c

Log:
either break everything or make it cooler ... ?

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Sat Apr 28 21:16:49 2007
@@ -244,6 +244,10 @@
 
 	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 @@
 	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 @@
 				}
 			}
 		}
+
 		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 @@
 	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 @@
 		}
 	}
 
-	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 @@
 	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 @@
 		}
 	}
 
-	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 @@
 	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 @@
 	/*.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 @@
 	/*.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 @@
 	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 @@
 
 	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 @@
 			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 @@
 	}
 
   done:
+	if (profile) {
+		switch_thread_rwlock_unlock(profile->rwlock);
+	}
+
 	return cause;
 }
 
@@ -1133,7 +1271,7 @@
 	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;
 	}
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	Sat Apr 28 21:16:49 2007
@@ -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 @@
 
 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 @@
 	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 @@
 	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 @@
 	uint32_t flags;
 	reg_state_t state;
 	switch_memory_pool_t *pool;
-	struct outbound_reg *next;
+	struct sofia_gateway *next;
 };
 
 
@@ -229,11 +230,14 @@
 	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 @@
 	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 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_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 @@
 											  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);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Sat Apr 28 21:16:49 2007
@@ -70,7 +70,7 @@
 		}
 	}
 
-
+	
 	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 @@
 
 	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 @@
 		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 @@
 
 		}
 
+		if (profile) {
+			switch_thread_rwlock_unlock(profile->rwlock);
+		}
 	}
 }
 
@@ -340,7 +347,9 @@
 
 	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 @@
 
 		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 @@
 }
 
 
-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 @@
 		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 @@
 				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 @@
 					goto done;
 				}
 
-				if (!xprofilename) {
-					xprofilename = "unnamed";
-				}
+				
 
 				profile->pool = pool;
 
@@ -481,7 +525,8 @@
 				
 				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 @@
 						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 @@
 				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 @@
 							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 @@
 				}
 				profile = NULL;
 			}
+			if (profile_found) {
+				break;
+			}
 		}
 	}
   done:
@@ -823,6 +873,11 @@
 		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 @@
 
 			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 @@
 
 
 	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 @@
 		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);
 		}
 	}
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Sat Apr 28 21:16:49 2007
@@ -315,9 +315,13 @@
 
 
 	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 *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 @@
 	} else {
 #endif
 		switch_core_db_close(profile->master_db);
+		profile->master_db = NULL;
 #ifdef SWITCH_HAVE_ODBC
 	}
 #endif

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	Sat Apr 28 21:16:49 2007
@@ -43,7 +43,7 @@
 {
 	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_safe_free(ffrom);
 		free(user);
+
+		if (profile) {
+			switch_thread_rwlock_unlock(profile->rwlock);
+		}
 	}
 
 	return SWITCH_STATUS_SUCCESS;
@@ -178,7 +182,7 @@
 {
 	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 @@
 
 	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 @@
 												sofia_presence_resub_callback,
 												profile);
 
+				
+				switch_thread_rwlock_unlock(profile->rwlock);
+					
 				switch_safe_free(sql);
 			}
 			switch_safe_free(user);
@@ -569,7 +581,7 @@
 	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 @@
 
 	switch_safe_free(id);
 	switch_safe_free(exp);
+
+	if (profile) {
+		switch_thread_rwlock_unlock(profile->rwlock);
+	}
+
 	return 0;
 }
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	Sat Apr 28 21:16:49 2007
@@ -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_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 @@
 				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 @@
 			break;
 		}
 	}
-
 }
 
 
@@ -157,7 +173,11 @@
     }
 #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 @@
 									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 @@
 							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 @@
 	}
 
 	if (profile) {
-		outbound_reg_t *gateway_ptr;
+		sofia_gateway_t *gateway_ptr;
 
 		if ((duprealm = strdup(realm))) {
 			qrealm = duprealm;
@@ -548,13 +579,21 @@
 			}
 
 			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 @@
 	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 @@
 }
 
 
-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);

Modified: freeswitch/trunk/src/switch_odbc.c
==============================================================================
--- freeswitch/trunk/src/switch_odbc.c	(original)
+++ freeswitch/trunk/src/switch_odbc.c	Sat Apr 28 21:16:49 2007
@@ -372,6 +372,7 @@
 		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)



More information about the Freeswitch-svn mailing list