[Freeswitch-svn] [commit] r2843 - in freeswitch/trunk: conf src src/mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Tue Sep 26 23:44:14 EDT 2006


Author: anthm
Date: Tue Sep 26 23:44:14 2006
New Revision: 2843

Modified:
   freeswitch/trunk/conf/freeswitch.xml
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/switch_xml.c

Log:
peliminary sofia inbound reg support rm all traces of sofia and rebuild or face certian doom

Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml	(original)
+++ freeswitch/trunk/conf/freeswitch.xml	Tue Sep 26 23:44:14 2006
@@ -476,6 +476,12 @@
   </section>
 
   <section name="directory" description="User Directory">
+    <domain name="mydomain.com">
+      <user id="1000">
+	<param name="password" value="mypass"/>
+	<param name="mypref" value="myval"/>
+	</user>
+    </domain>
   </section>
 
 </document>

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	Tue Sep 26 23:44:14 2006
@@ -53,8 +53,19 @@
 #include <sofia-sip/sip_status.h>
 #include <sofia-sip/sdp.h>
 #include <sofia-sip/sip_protos.h>
-#define DBFILE "sofia"
 
+static char reg_sql[] =
+"CREATE TABLE sip_registrations (\n"
+"   user            VARCHAR(255),\n"
+"   host            VARCHAR(255),\n"
+"   contact         VARCHAR(255),\n"
+"   expires         INTEGER(8)"
+");\n";
+
+
+
+
+
 static const char modname[] = "mod_sofia";
 #define STRLEN 15
 
@@ -97,11 +108,14 @@
 	switch_hash_t *profile_hash;
 	switch_mutex_t *hash_mutex;
 	uint32_t callid;
+	int32_t running;
+	switch_mutex_t *mutex;
 } globals;
 
 struct sofia_profile {
 	int debug;
 	char *name;
+	char *dbname;
 	char *dialplan;
 	char *context;
 	char *extrtpip;
@@ -127,6 +141,8 @@
 	sip_alias_node_t *aliases;
 	switch_payload_t te;
 	uint32_t codec_flags;
+	switch_mutex_t *reg_mutex;
+	switch_core_db_t *db;
 };
 
 
@@ -234,6 +250,13 @@
                          sip_t const *sip,
                          tagi_t tags[]);
 
+static void sip_i_register(nua_t *nua,
+						   sofia_profile_t *profile,
+						   nua_handle_t *nh,
+						   switch_core_session_t *session,
+						   sip_t const *sip,
+						   tagi_t tags[]);
+
 static void event_callback(nua_event_t   event,
                            int           status,
                            char const   *phrase,
@@ -254,6 +277,83 @@
 
 /* BODY OF THE MODULE */
 /*************************************************************************************************************************************************************/
+struct callback_t {
+	char *val;
+	switch_size_t len;
+	int matches;
+};
+
+static int find_callback(void *pArg, int argc, char **argv, char **columnNames){
+	struct callback_t *cbt = (struct callback_t *) pArg;
+
+	switch_copy_string(cbt->val, argv[0], cbt->len);
+	cbt->matches++;
+	return 0;
+}
+
+static int del_callback(void *pArg, int argc, char **argv, char **columnNames){
+	switch_event_t *s_event;
+
+	if (argc >=3 ) {
+		if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_EXPIRE) == SWITCH_STATUS_SUCCESS) {
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "user", "%s", argv[0]);
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "host", "%s", argv[1]);
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact", "%s", argv[2]);
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%d", argv[3]);
+			switch_event_fire(&s_event);
+		}
+	}
+	return 0;
+}
+
+static void check_expire(sofia_profile_t *profile, time_t now)
+{
+	char sql[1024];
+	char *errmsg;
+
+	switch_mutex_lock(profile->reg_mutex);
+	snprintf(sql, sizeof(sql), "select * from sip_registrations where expires > 0 and expires < %ld", (long) now);	
+	switch_core_db_exec(profile->db, sql, del_callback, NULL, &errmsg);
+
+	if (errmsg) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", sql, errmsg);
+		switch_core_db_free(errmsg);
+		errmsg = NULL;
+	}
+	
+	snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires < %ld", (long) now);
+	switch_core_db_persistant_execute(profile->db, sql, 1);
+	switch_mutex_unlock(profile->reg_mutex);
+}
+
+static char *find_reg_url(sofia_profile_t *profile, char *user, char *host, char *val, switch_size_t len)
+{
+	char *errmsg;
+	struct callback_t cbt = {0};
+
+
+	cbt.val = val;
+	cbt.len = len;
+	switch_mutex_lock(profile->reg_mutex);
+	if (host) {
+		snprintf(val, len, "select contact from sip_registrations where user='%s' and host='%s'", user, host);	
+	} else {
+		snprintf(val, len, "select contact from sip_registrations where user='%s'", user);	
+	}
+
+	switch_core_db_exec(profile->db, val, find_callback, &cbt, &errmsg);
+
+	if (errmsg) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", val, errmsg);
+		switch_core_db_free(errmsg);
+		errmsg = NULL;
+	}
+
+	switch_mutex_unlock(profile->reg_mutex);
+	return cbt.matches ? val : NULL;
+}
+
+
 static void set_local_sdp(private_object_t *tech_pvt)
 {
 	char buf[1024];
@@ -1151,6 +1251,7 @@
 	switch_caller_profile_t *caller_profile = NULL;
 	private_object_t *tech_pvt = NULL;
 	switch_channel_t *channel;
+	char *host;
 
 	*new_session = NULL;
 
@@ -1181,10 +1282,18 @@
         terminate_session(&nsession, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, __LINE__);
         goto done;
 	}
-	
-	tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
-	snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
-	
+
+	if ((host = strchr(dest, '%'))) {
+		char buf[128];
+		*host++ = '\0';
+		find_reg_url(profile, dest, host, buf, sizeof(buf));
+		tech_pvt->dest = switch_core_session_strdup(nsession, buf);
+		dest = tech_pvt->dest + 4;
+	} else {
+		tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
+		snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
+	}
+
 	channel = switch_core_session_get_channel(nsession);
 	attach_private(nsession, profile, tech_pvt, dest);	
 	caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
@@ -1553,6 +1662,106 @@
 	}
 }
 
+
+static void sip_i_register(nua_t *nua,
+						   sofia_profile_t *profile,
+						   nua_handle_t *nh,
+						   switch_core_session_t *session,
+						   sip_t const *sip,
+						   tagi_t tags[])
+{
+	sip_from_t const *from = sip->sip_from;
+	sip_expires_t const *expires = sip->sip_expires;
+	//sip_to_t const *to = sip->sip_to;
+	sip_contact_t const *contact = sip->sip_contact;
+	// SIP_407_PROXY_AUTH_REQUIRED
+	switch_xml_t domain, xml, user, param;
+	char params[1024] = "";
+	char *sql;
+	switch_event_t *s_event;
+	char *from_user = (char *) from->a_url->url_user;
+	char *from_host = (char *) from->a_url->url_host;
+	char *contact_user = (char *) contact->m_url->url_user;
+	char *contact_host = (char *) contact->m_url->url_host;
+	char buf[512];
+	
+	snprintf(params, sizeof(params), "from_user=%s&from_host=%s&contact_user=%s&contact_host=%s",
+			 from_user,
+			 from_host,
+			 contact_user,
+			 contact_host 
+			 );
+
+
+	if (switch_xml_locate("directory", "domain", "name", (char *)from->a_url->url_host, &xml, &domain, params) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of directory failed\n");
+		nua_respond(nh, SIP_401_UNAUTHORIZED, SIPTAG_CONTACT(contact), TAG_END());
+		return;
+	}
+
+	if (!(user = switch_xml_find_child(domain, "user", "id", from_user))) {
+		nua_respond(nh, SIP_401_UNAUTHORIZED, SIPTAG_CONTACT(contact), TAG_END());
+		switch_xml_free(xml);
+		return;
+	}
+	
+
+	for (param = switch_xml_child(user, "param"); param; param = param->next) {
+		char *var = (char *) switch_xml_attr_soft(param, "name");
+		char *val = (char *) switch_xml_attr_soft(param, "value");
+
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param [%s]=[%s]\n", var, val);
+	}
+
+
+	if (!find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
+		sql = switch_core_db_mprintf("insert into sip_registrations values ('%q','%q','sip:%q@%q',%ld)", 
+									 from_user,
+									 from_host,
+									 contact_user,
+									 contact_host,
+									 (long) time(NULL) + (long)expires->ex_delta);
+	} else {
+		sql = switch_core_db_mprintf("update sip_registrations set contact='sip:%q@%q', expires=%ld where user='%q' and host='%q'",
+									 contact_user,
+                                     contact_host,
+									 (long) time(NULL) + (long)expires->ex_delta,
+									 from_user,
+									 from_host);
+		
+	}
+	
+	if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from_user", "%s", from_user);
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from_host", "%s", from_host);
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact_user", "%s", contact_user);
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact_host", "%s", contact_host);
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long)expires->ex_delta);
+		switch_event_fire(&s_event);
+	}
+	if (sql) {
+		switch_mutex_lock(profile->reg_mutex);
+		switch_core_db_persistant_execute(profile->db, sql, 25);
+					switch_core_db_free(sql);
+					sql = NULL;
+					switch_mutex_unlock(profile->reg_mutex);
+	}
+	
+	switch_xml_free(xml);
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a Register from [%s@%s] contact [%s@%s] expires %ld\n", 
+					  from_user, 
+					  from_host,
+					  contact_user,
+					  contact_host,
+					  (long)expires->ex_delta
+					  );
+
+	
+	nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact), TAG_END());
+	//nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED, TAG_END());
+}
+
 static void event_callback(nua_event_t   event,
 						   int           status,
 						   char const   *phrase,
@@ -1605,6 +1814,10 @@
 		sip_i_invite(nua, profile, nh, session, sip, tags);
 		break;
 
+    case nua_i_register:
+ 		sip_i_register (nua, profile, nh, session, sip, tags);
+        break;
+
 	case nua_i_prack:
 		//sip_i_prack(nua, profile, nh, session, sip, tags);
 		break;
@@ -1695,12 +1908,15 @@
 	}
 }
 
+#define REG_SECONDS 30
 static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void *obj)
 {
 	sofia_profile_t *profile = (sofia_profile_t *) obj;
 	switch_memory_pool_t *pool;
 	sip_alias_node_t *node;
+	uint32_t loops = 0;
 
+
 	profile->s_root = su_root_create(NULL);
 	profile->nua = nua_create(profile->s_root, /* Event loop */
 							  event_callback, /* Callback for processing events */
@@ -1712,8 +1928,7 @@
 				   NUTAG_EARLY_MEDIA(1),				   
 				   NUTAG_AUTOANSWER(0),
 				   NUTAG_AUTOALERT(0),
-				   //NUTAG_ALLOW("REGISTER"),
-				   //SIPTAG_ALLOW_STR("REGISTER"),
+				   NUTAG_ALLOW("REGISTER"),
 				   SIPTAG_SUPPORTED_STR("100rel, precondition"),
 				   TAG_END());
 				   
@@ -1728,17 +1943,46 @@
 		nua_set_params(node->nua,
 					   NUTAG_EARLY_MEDIA(1),
 					   NUTAG_AUTOANSWER(0),
+					   NUTAG_ALLOW("REGISTER"),
 					   SIPTAG_SUPPORTED_STR("100rel, precondition"),
 					   NUTAG_AUTOALERT(0),
 					   TAG_END());
 		
 	}
 
-	su_root_run(profile->s_root);
+
+	if ((profile->db = switch_core_db_open_file(profile->dbname))) {
+		switch_core_db_test_reactive(profile->db, "select * from sip_registrations", reg_sql);
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n");
+		return NULL;
+	}
+
+	switch_mutex_init(&profile->reg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+
+	switch_mutex_lock(globals.mutex);
+	globals.running = 1;
+	switch_mutex_unlock(globals.mutex);
+
+	loops = REG_SECONDS;
+
+	while(globals.running == 1) {
+		if (++loops >= REG_SECONDS) {
+			check_expire(profile, time(NULL));
+			loops = 0;
+		}
+
+		su_root_step(profile->s_root, 1000);
+		//su_root_run(profile->s_root);
+	}
+
 	su_root_destroy(profile->s_root);
 
 	pool = profile->pool;
 	switch_core_destroy_memory_pool(&pool);
+	switch_mutex_lock(globals.mutex);
+	globals.running = 0;
+	switch_mutex_unlock(globals.mutex);
 	
 	return NULL;
 }
@@ -1764,7 +2008,7 @@
 	char *cf = "sofia.conf";
 	switch_xml_t cfg, xml = NULL, xprofile, param;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
-	
+
 	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;
@@ -1791,10 +2035,15 @@
 		if (!xprofilename) {
 			xprofilename = "unnamed";
 		}
+		
 
+		
+
 		profile->pool = pool;
 
 		profile->name = switch_core_strdup(profile->pool, xprofilename);
+		snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename);
+		profile->dbname = switch_core_strdup(profile->pool, url);
 
 		profile->dtmf_duration = 100;		
 		profile->codec_ms = 20;
@@ -1910,7 +2159,6 @@
 
 }
 
-
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
 {
 
@@ -1920,6 +2168,8 @@
 	}
 
 	memset(&globals, 0, sizeof(globals));
+	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
+	
 	su_init();
 
 
@@ -1939,10 +2189,17 @@
 
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
 {
-	/*  Adding Note so we can destroy these properly. Will remind tony.
-	 *  nua_destroy (nua);
-	 *  su_root_destroy (root);
-	 */
+
+	switch_mutex_lock(globals.mutex);
+	if (globals.running == 1) {
+		globals.running = -1;
+	}
+	switch_mutex_unlock(globals.mutex);
+
+	while(globals.running) {
+		switch_yield(1000);
+	}
+
 	su_deinit();
 
 	return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/trunk/src/switch_xml.c
==============================================================================
--- freeswitch/trunk/src/switch_xml.c	(original)
+++ freeswitch/trunk/src/switch_xml.c	Tue Sep 26 23:44:14 2006
@@ -168,8 +168,7 @@
 
 	for (p = switch_xml_child(node, childname); p; p = p->next) {
 		const char *aname = switch_xml_attr(p, attrname);
-
-		if (!strcasecmp(aname, value)) {
+		if (aname && value && !strcasecmp(aname, value)) {
 			break;
 		}
 	}



More information about the Freeswitch-svn mailing list