[Freeswitch-svn] [commit] r3115 - in freeswitch/trunk: conf libs/libdingaling/src src/mod/dialplans/mod_dialplan_xml src/mod/endpoints/mod_dingaling src/mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Fri Oct 20 02:17:01 EDT 2006


Author: anthm
Date: Fri Oct 20 02:17:00 2006
New Revision: 3115

Modified:
   freeswitch/trunk/conf/freeswitch.xml
   freeswitch/trunk/libs/libdingaling/src/libdingaling.c
   freeswitch/trunk/libs/libdingaling/src/libdingaling.h
   freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c

Log:
Presence and Chat Gateway Code

This is some brand new stuff to gateway chat/presence/audio from one protocol to another
So far it only works between google/jingle and SIP

All I had to test the SIP end was X-Lite and Eyebeam and GoogleTalk on the jingle end.

With this setup registered X-Lite's can chat with each other and call each other 
as well as X-Lite to GoogleTalk and GoogleTalk to X-Lite audio calls.

Chat May also be done between X-Lite and jabber 

You'll also need a jabber server configured for component login so you can interface.
We have only tested with jabberd2 so far.

Configure DNS so srv records for jabber for your subdomain (fs.mydomain.com in the example)
so the jabber records are pointed at your jabber server.

RELEVANT CONFIGS

<!-- Brian has no jingle support so send calls to him over to his iax url -->
<extension name="bkw">
  <condition field="destination_number" expression="^jingle\+brian at agents.cylynx.com$">
    <action application="bridge" data="iax/guest at brianwest.homeunix.org/9184290404"/>
  </condition>
</extension>

<!-- Assumption is made here that both sip and jingle have the same profile/domain name as documented below -->

<extension name="jingle2sip">
  <condition field="source" expression="mod_dingaling"/>
  <condition field="destination_number" expression="^sip\+([^\@]+)\@(.*)$">
    <action application="bridge" data="sofia/$2/$1%$2"/>
  </condition>
</extension>

<extension name="sip2jingle">
  <condition field="source" expression="mod_sofia"/>
  <condition field="destination_number" expression="^jingle\+([^\@]+)\@(.*)$">
    <action application="bridge" data="dingaling/sip+${sip_fromuser}@${sip_fromhost}/$1@$2"/>
  </condition>
</extension>


<configuration name="sofia.conf" description="sofia Endpoint">
  <global_settings>
    <param name="log-level" value="0"/>
  </global_settings>

  <profiles>
    <profile name="fs.mydomain.com">
      <registrations/>
      <settings>
	<param name="debug" value="1"/>
	<param name="rfc2833-pt" value="101"/>
	<param name="sip-port" value="5060"/>
	<param name="dialplan" value="XML"/>
	<param name="dtmf-duration" value="100"/>
	<param name="codec-prefs" value="PCMU"/>
	<param name="codec-ms" value="20"/>
	<param name="accept-blind-reg" value="true"/>
	<param name="manage-presence" value="true"/>
	<!--<param name="full-id-in-dialplan" value="true"/>-->
	<!--<param name="auth-calls" value="true"/>-->
	<!--<param name="auth-all-packets" value="true"/>-->
	<param name="use-rtp-timer" value="true"/>
	<param name="rtp-timer-name" value="soft"/>
	<param name="rtp-ip" value="100.200.100.200"/>
	<param name="sip-ip" value="fs.mydomain.com"/>
      </settings>
    </profile>
  </profiles>

</configuration>


<configuration name="dingaling.conf" description="XMPP Jingle Endpoint">
  <settings>
    <param name="debug" value="0"/>
    <param name="codec-prefs" value="PCMU"/>
  </settings>

  <profile type="component">
    <param name="name" value="fs.mydomain.com"/>
    <param name="password" value="secret"/>
    <param name="dialplan" value="XML"/>
    <param name="rtp-ip" value="208.64.200.42"/>
    <param name="server" value="jabber.freeswitch.org:5347"/>
    <!-- disable to trade async for more calls -->
    <param name="use-rtp-timer" value="true"/>
    <param name="exten" value="_auto_"/>
    <!--<param name="vad" value="both"/>-->
  </profile>

</configuration>



Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml	(original)
+++ freeswitch/trunk/conf/freeswitch.xml	Fri Oct 20 02:17:00 2006
@@ -113,8 +113,8 @@
     </configuration>
 
     <configuration name="sofia.conf" description="sofia Endpoint">
-      <profiles>
-        <profile name="test">
+      <profile>
+        <profile name="mydomain1.com">
           <registrations>
             <!-- <registration name="asterlink">
               <param name="register-scheme" value="Digest"/>
@@ -138,7 +138,7 @@
             <param name="use-rtp-timer" value="true"/>
             <param name="rtp-timer-name" value="soft"/>
             <param name="rtp-ip" value="192.168.1.20"/>
-            <param name="sip-ip" value="192.168.1.20"/>
+            <param name="sip-ip" value="mydomain1.com"/>
 
             <!-- this lets anything register -->
             <!--  comment the next line and uncomment one or both of the other 2 lines for call authentication -->
@@ -268,10 +268,12 @@
         <param name="debug" value="0"/>
         <param name="codec-prefs" value="PCMU"/>
       </settings>
-      <!-- *NOTE* your resource (after the /) MUST contain the string "talk" (upper or lower case is ok) -->
-      <!-- *NOTE* as of May 2 2006 you must set"auto-login" to"true" if you want to be able to auto-login on startup"/> -->
-      <interface>
-        <param name="name" value="jingle"/>
+
+      <!-- *NOTE* change <x-profile></x-profile> to <profile></profile> to enable -->
+
+      <!-- Client Profile (Original mode) -->
+      <x-profile type="client">
+        <param name="name" value="mydomain.com"/>
         <param name="login" value="myjid at myserver.com/talk"/>
         <param name="password" value="mypass"/>
         <param name="dialplan" value="XML"/>
@@ -296,7 +298,23 @@
         <!-- <param name="vad" value="in"/> -->
         <!-- <param name="vad" value="out"/> -->
         <param name="vad" value="both"/>
-      </interface>
+      </x-profile>
+
+      <!-- Component (Server to Server Login) -->
+      <x-profile type="component">
+	<!-- All traffic for *@sub.mydomain.com will come to you -->
+	<param name="name" value="sub.mydomain.com"/>
+        <param name="password" value="secret"/>
+	<param name="dialplan" value="XML"/>
+	<param name="rtp-ip" value="208.64.200.42"/>
+	<param name="server" value="jabber.server.org:5347"/>
+        <!-- disable to trade async for more calls -->
+        <param name="use-rtp-timer" value="true"/>
+	<!-- "_auto_" means the extension will be automaticly set to the called jid -->
+        <param name="exten" value="_auto_"/>
+        <!--<param name="vad" value="both"/>-->
+      </x-profile>
+
     </configuration>
 
     <configuration name="xml_rpc.conf" description="XML RPC">

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.c
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.c	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.c	Fri Oct 20 02:17:00 2006
@@ -712,7 +712,7 @@
 	if (!type || (type && strcasecmp(type, "probe"))) {
 
 		if (handle->session_callback) {
-			handle->session_callback(handle, NULL, signal, to, from, status ? status : "n/a", show ? show : "n/a");
+			handle->session_callback(handle, NULL, signal, to, id, status ? status : "n/a", show ? show : "n/a");
 		}
 	}
 
@@ -720,7 +720,7 @@
 	return IKS_FILTER_EAT;
 }
 
-static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message) 
+static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message) 
 {
 	iks *pres;
 	char buf[512];
@@ -743,21 +743,28 @@
 			iks_insert_attrib(pres, "type", type);
 		}
 
+		if (rpid) {
+			if ((tag = iks_insert (pres, "show"))) {
+				iks_insert_cdata(tag, rpid, 0);
+			}
+		}
 
-
-		if (message) {			
+		if (message) {
 			if ((tag = iks_insert (pres, "status"))) {
-				iks_insert_cdata(tag, message ? message : "", 0);
-				if ((tag = iks_insert(pres, "c"))) {
-					iks_insert_attrib(tag, "node", "http://www.freeswitch.org/xmpp/client/caps");
-					iks_insert_attrib(tag, "ver", "1.0.0.1");
-					iks_insert_attrib(tag, "ext", "sidebar voice-v1");
-					iks_insert_attrib(tag, "client", "libdingaling2");
-					iks_insert_attrib(tag, "xmlns", "http://jabber.org/protocol/caps");
-				}
+				iks_insert_cdata(tag, message, 0);
 			}
 		}
-	
+
+		if (message || rpid) {
+			if ((tag = iks_insert(pres, "c"))) {
+				iks_insert_attrib(tag, "node", "http://www.freeswitch.org/xmpp/client/caps");
+				iks_insert_attrib(tag, "ver", "1.0.0.1");
+				iks_insert_attrib(tag, "ext", "sidebar voice-v1");
+				iks_insert_attrib(tag, "client", "libdingaling");
+				iks_insert_attrib(tag, "xmlns", "http://jabber.org/protocol/caps");
+			}
+		}
+
 		apr_queue_push(handle->queue, pres);
 	}
 }
@@ -1559,9 +1566,9 @@
 	return handle->private_info;
 }
 
-void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message)
+void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message)
 {
-	do_presence(handle, from, to, type, message);
+	do_presence(handle, from, to, type, rpid, message);
 }
 
 void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body)

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.h
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.h	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.h	Fri Oct 20 02:17:00 2006
@@ -369,9 +369,10 @@
   \param from the from address
   \param to the to address
   \param type the type of presence
+  \param rpid data for the icon
   \param message a status message
 */
-void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message);
+void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *rpid, char *message);
 
 /*!
   \brief Send a message

Modified: freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
==============================================================================
--- freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	(original)
+++ freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c	Fri Oct 20 02:17:00 2006
@@ -94,6 +94,11 @@
 	for (x = 0; x < (len-1) && x < strlen(data);) {
 		if (data[x] == '$') {
 			x++;
+			
+			if (!(data[x] > 47 && data[x] < 58)) {
+				substituted[y++] = data[x-1];
+				continue;
+			}
 
 			while (data[x] > 47 && data[x] < 58) {
 				index[z++] = data[x];

Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c	Fri Oct 20 02:17:00 2006
@@ -47,7 +47,9 @@
 static char sub_sql[] =
 "CREATE TABLE subscriptions (\n"
 "   sub_from            VARCHAR(255),\n"
-"   sub_to          VARCHAR(255)\n"
+"   sub_to          VARCHAR(255),\n"
+"   show          VARCHAR(255),\n"
+"   status          VARCHAR(255)\n"
 ");\n";
 
 
@@ -186,7 +188,39 @@
 static ldl_status handle_response(ldl_handle_t *handle, char *id);
 static switch_status_t load_config(void);
 
+static char *translate_rpid(char *in, char *ext)
+{
+	char *r = NULL;
 
+	if (in && (strstr(in, "null") || strstr(in, "NULL"))) {
+		in = NULL;
+	}
+
+	if (!in) {
+		in = ext;
+	}
+
+	if (!in) {
+		return NULL;
+	}
+	
+	if (!strcasecmp(in, "busy")) {
+		r = "dnd";
+	}
+
+	if (!strcasecmp(in, "unavailable")) {
+		r = "dnd";
+	}
+
+	if (ext && !strcasecmp(ext, "idle")) {
+		r = "away";
+	} else if (ext && !strcasecmp(ext, "away")) {
+		r = "away";
+	}
+	
+	return r;
+}
+
 static int sub_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
 	struct mdl_profile *profile = (struct mdl_profile *) pArg;
@@ -194,17 +228,18 @@
 	char *sub_from = argv[0];
 	char *sub_to = argv[1];
 	char *type = argv[2];
-	char *show = argv[3];
+	char *rpid = argv[3];
+	char *status = argv[4];
 
 	if (switch_strlen_zero(type)) {
 		type = NULL;
 	} else if (!strcasecmp(type, "unavailable")) {
-		show = NULL;
+		status = NULL;
 	}
+	rpid = translate_rpid(rpid, status);
+	
+	ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, rpid, status);
 
-
-	ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, show);
-
 	return 0;
 }
 
@@ -215,9 +250,17 @@
 	char *sub_from = argv[0];
 	char *sub_to = argv[1];
 	char *show = argv[2];
+	char *status = argv[3];
 
+	if (!strcasecmp(status, "n/a")) {
+		if (!strcasecmp(show, "dnd")) {
+			status = "Busy";
+		} else if (!strcasecmp(show, "away")) {
+			status = "Idle";
+		}
+	}
 
-	ldl_handle_send_presence(profile->handle, sub_to, sub_from, NULL, show);
+	ldl_handle_send_presence(profile->handle, sub_to, sub_from, NULL, show, status);
 
 	return 0;
 }
@@ -229,22 +272,17 @@
     void *val;
 	char *from = switch_event_get_header(event, "from");
 	char *status= switch_event_get_header(event, "status");
-	char *show= switch_event_get_header(event, "show");
-	char *type = NULL;
+	char *rpid = switch_event_get_header(event, "rpid");
+	char *type = switch_event_get_header(event, "event_subtype");
 	char *sql;
 	switch_core_db_t *db;
 	char *p;
 
 
 	if (status && !strcasecmp(status, "n/a")) {
-		status = show;
-		if (status && !strcasecmp(status, "n/a")) {
-			status = NULL;
-		}
+		status = NULL;
 	}
 
-
-
 	switch(event->event_id) {
 	case SWITCH_EVENT_PRESENCE_IN:
 		if (!status) {
@@ -259,12 +297,12 @@
 	}
 	
 
-
 	if ((p = strchr(from, '/'))) {
 		*p = '\0';
 	}
 	
-	sql = switch_mprintf("select *,'%q','%q' from subscriptions where sub_to='%q'", type ? type : "", status ? status : "unavailable", from);
+	sql = switch_mprintf("select sub_from, sub_to,'%q','%q','%q' from subscriptions where sub_to='%q'", 
+						 type ? type : "", rpid, status ? status : "unavailable", from);
 	for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) {
 		char *errmsg;
         switch_hash_this(hi, NULL, NULL, &val);
@@ -326,7 +364,7 @@
 static void roster_event_handler(switch_event_t *event)
 {
 	char *status= switch_event_get_header(event, "status");
-	char *show= switch_event_get_header(event, "show");
+	char *from= switch_event_get_header(event, "from");
 	char *event_type = switch_event_get_header(event, "event_type");
 	struct mdl_profile *profile = NULL;
 	switch_hash_index_t *hi;
@@ -334,19 +372,19 @@
 	char *sql;
 	switch_core_db_t *db;
 
-
 	if (status && !strcasecmp(status, "n/a")) {
-		status = show;
-		if (status && !strcasecmp(status, "n/a")) {
-			status = NULL;
-		}
+		status = NULL;
 	}
 
 	if (switch_strlen_zero(event_type)) {
 		event_type="presence";
 	}
 
-	sql = switch_mprintf("select *,'%q' from subscriptions", show ? show : "unavilable");
+	if (from) {
+		sql = switch_mprintf("select *,'%q' from subscriptions where sub_from='%q'", status ? status : "", from);
+	} else {
+		sql = switch_mprintf("select *,'%q' from subscriptions", status ? status : "");
+	}
 
 	for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) {
 		char *errmsg;
@@ -457,7 +495,13 @@
 {
 	ldl_handle_t *handle = obj;
 	struct mdl_profile *profile = NULL;
+	switch_event_t *event;
 
+	if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME);
+		switch_event_fire(&event);
+	}
+
 	profile = ldl_handle_get_private(handle);
 	globals.handles++;
 	switch_set_flag(profile, TFLAG_IO);
@@ -1307,7 +1351,7 @@
 			snprintf(ubuf, sizeof(ubuf), "%s@%s/talk", u, profile_name);
 			user = ubuf;
 		} else {
-			user = mdl_profile->login;
+			user = (char *) modname;
 		}
 
 		if ((mdl_profile = switch_core_hash_find(globals.profile_hash, profile_name))) {
@@ -1554,25 +1598,6 @@
 		if (switch_true(val)) {
 			profile->user_flags |= LDL_FLAG_TLS;
 		}
-	} else if (!strcasecmp(var, "component")) {
-		if (switch_true(val)) {
-			char dbname[256];
-			switch_core_db_t *db;
-
-			profile->user_flags |= LDL_FLAG_COMPONENT;
-			switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED, module_pool);
-			snprintf(dbname, sizeof(dbname), "dingaling_%s", profile->name);
-			profile->dbname = switch_core_strdup(module_pool, dbname);
-
-			if ((db = switch_core_db_open_file(profile->dbname))) {
-				switch_core_db_test_reactive(db, "select * from subscriptions", sub_sql);
-			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n");
-				return;
-			}
-			switch_core_db_close(db);
-			
-		}
 	} else if (!strcasecmp(var, "sasl")) {
 		if (!strcasecmp(val, "plain")) {
 			profile->user_flags |= LDL_FLAG_SASL_PLAIN;
@@ -1669,6 +1694,7 @@
 		}
 	}
 	
+
 	if (profile && init_profile(profile, 1) == SWITCH_STATUS_SUCCESS) {
 		stream->write_function(stream, "OK\n");
 	} else {
@@ -1715,7 +1741,14 @@
 		}
 	}
 	
-	for (xmlint = switch_xml_child(cfg, "interface"); xmlint; xmlint = xmlint->next) {
+	if (!(xmlint = switch_xml_child(cfg, "profile"))) {
+		if ((xmlint = switch_xml_child(cfg, "interface"))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "!!!!!!! DEPRICATION WARNING 'interface' is now 'profile' !!!!!!!\n");
+		}
+	}
+
+	for (; xmlint; xmlint = xmlint->next) {
+		char *type = (char *) switch_xml_attr_soft(xmlint, "type");
 		for (param = switch_xml_child(xmlint, "param"); param; param = param->next) {
 			char *var = (char *) switch_xml_attr_soft(param, "name");
 			char *val = (char *) switch_xml_attr_soft(param, "value");
@@ -1732,6 +1765,31 @@
 			set_profile_val(profile, var, val);
 		}
 
+
+		if (type && !strcasecmp(type, "component")) {
+			char dbname[256];
+			switch_core_db_t *db;
+
+			if (!profile->login && profile->name) {
+				profile->login = switch_core_strdup(module_pool, profile->name);
+			}
+
+			switch_set_flag(profile, TFLAG_AUTO);
+			profile->message = "";
+			profile->user_flags |= LDL_FLAG_COMPONENT;
+			switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED, module_pool);
+			snprintf(dbname, sizeof(dbname), "dingaling_%s", profile->name);
+			profile->dbname = switch_core_strdup(module_pool, dbname);
+
+			if ((db = switch_core_db_open_file(profile->dbname))) {
+				switch_core_db_test_reactive(db, "select * from subscriptions", sub_sql);
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n");
+				continue;
+			}
+			switch_core_db_close(db);
+		}
+
 		if (profile) {
 			init_profile(profile, switch_test_flag(profile, TFLAG_AUTO) ? 1 : 0);
 			profile = NULL;
@@ -1815,7 +1873,7 @@
 		case LDL_SIGNAL_SUBSCRIBE:
 			if ((profile->user_flags & LDL_FLAG_COMPONENT)) {
 
-				if ((sql = switch_mprintf("insert into subscriptions values('%q','%q')", from, to))) {
+				if ((sql = switch_mprintf("insert into subscriptions values('%q','%q','%q','%q')", from, to, msg, subject))) {
 					execute_sql(profile->dbname, sql, profile->mutex);
 					switch_core_db_free(sql);
 				}
@@ -1829,17 +1887,30 @@
 			}
 			break;
 		case LDL_SIGNAL_PRESENCE_IN:
+
+			if ((sql = switch_mprintf("update subscriptions set show='%q', status='%q' where sub_from='%q'", msg, subject, from))) {
+				execute_sql(profile->dbname, sql, profile->mutex);
+				switch_core_db_free(sql);
+			}
+
 			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s",  from);
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", msg);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", subject);
-				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "%s", msg);
 				switch_event_fire(&event);
 			}
 
 			break;
+
 		case LDL_SIGNAL_PRESENCE_OUT:
+
+			if ((sql = switch_mprintf("update subscriptions set show='%q', status='%q' where sub_from='%q'", msg, subject, from))) {
+				execute_sql(profile->dbname, sql, profile->mutex);
+				switch_core_db_free(sql);
+			}
+
 			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_NAME);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login);

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	Fri Oct 20 02:17:00 2006
@@ -43,9 +43,6 @@
 struct outbound_reg;
 typedef struct outbound_reg outbound_reg_t;
 
-struct sip_presence;
-typedef struct sip_presence sip_presence_t;
-
 struct sofia_profile;
 typedef struct sofia_profile sofia_profile_t;
 #define NUA_MAGIC_T sofia_profile_t
@@ -53,7 +50,6 @@
 struct sofia_private {
 	switch_core_session_t *session;
 	outbound_reg_t *oreg;
-	sip_presence_t *presence;
 };
 
 typedef struct sofia_private sofia_private_t;
@@ -86,6 +82,7 @@
 "   host            VARCHAR(255),\n"
 "   contact         VARCHAR(1024),\n"
 "   status          VARCHAR(255),\n"
+"   rpid            VARCHAR(255),\n"
 "   expires         INTEGER(8)"
 ");\n";
 
@@ -211,13 +208,6 @@
 };
 
 
-struct sip_presence {
-	sofia_private_t sofia_private;
-	nua_handle_t *nh;
-	sofia_profile_t *profile;
-};
-
-
 struct sofia_profile {
 	int debug;
 	char *name;
@@ -251,7 +241,6 @@
 	switch_mutex_t *ireg_mutex;
 	switch_mutex_t *oreg_mutex;
 	outbound_reg_t *registrations;
-	sip_presence_t *presence;
 	su_home_t *home;
 	switch_hash_t *profile_hash;
 	switch_hash_t *chat_hash;
@@ -2673,17 +2662,15 @@
 	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_str[1025] = "";
+	char contact_str[1024] = "";
 	char buf[512];
 	char *passwd = NULL;
 	uint8_t stale = 0, ret = 0, forbidden = 0;
 	auth_res_t auth_res;
 	long exptime = 60;
 	switch_event_t *event;
+	char *rpid = "unknown";
 
-
-	
-
 	if (sip->sip_contact) {
 		char *port = (char *) contact->m_url->url_port;
 		if (!port) {
@@ -2824,76 +2811,84 @@
 	}
  reg:
 
-	if (!find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
-		sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Registered', %ld)", 
-									 from_user,
-									 from_host,
-									 contact_str,
-									 (long) time(NULL) + (long)exptime);
+	if (exptime) {
+		if (!find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
+			sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Registered', '%q', %ld)", 
+								 from_user,
+								 from_host,
+								 contact_str,
+								 rpid,
+								 (long) time(NULL) + (long)exptime);
 
-	} else {
-		sql = switch_mprintf("update sip_registrations set contact='%q', expires=%ld where user='%q' and host='%q'",
-                                     contact_str,
-									 (long) time(NULL) + (long)exptime,
-									 from_user,
-									 from_host);
+		} else {
+			sql = switch_mprintf("update sip_registrations set contact='%q', expires=%ld, rpid='%q' where user='%q' and host='%q'",
+								 contact_str,
+								 (long) time(NULL) + (long)exptime,
+								 rpid,
+								 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, "profile-name", "%s", profile->name);
-		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", "%s", contact_str);
-		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long)exptime);
-		switch_event_fire(&s_event);
-	}
+		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, "profile-name", "%s", profile->name);
+			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", "%s", contact_str);
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid);
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long)exptime);
+			switch_event_fire(&s_event);
+		}
 
-	if (sql) {
-		execute_sql(profile->dbname, sql, profile->ireg_mutex);
-		switch_safe_free(sql);
-		sql = NULL;
-	}
+		if (sql) {
+			execute_sql(profile->dbname, sql, profile->ireg_mutex);
+			switch_safe_free(sql);
+			sql = NULL;
+		}
 	
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Register from [%s@%s] contact [%s] expires %ld\n", 
-					  from_user, 
-					  from_host,
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Register:\nFrom:    [%s@%s]\nContact: [%s]\nExpires: [%ld]\n", 
+						  from_user, 
+						  from_host,
 					  contact_str,
 					  (long)exptime
 					  );
 
 
-
-	if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) {
-		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
-		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
-		switch_event_fire(&event);
-	}
-
-	if (exptime) {
 		if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
+			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid);
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host);
 			
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "Registered");
-			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "Registered");
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
 			switch_event_fire(&event);
 		}
 	} else {
+		if ((sql = switch_mprintf("delete from sip_subscriptions where user='%q' and host='%q'", from_user, from_host))) {
+			execute_sql(profile->dbname, sql, profile->ireg_mutex);
+			switch_safe_free(sql);
+			sql = NULL;
+		}
 		if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host);
 		
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "unavailable");
-			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "unavailable");
+			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
 			switch_event_fire(&event);
 		}
 	}
 
+
+	if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
+		switch_event_fire(&event);
+	}
+
 	if (regtype == REG_REGISTER) {
 		nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact),
 					NUTAG_WITH_THIS(nua),
@@ -2920,9 +2915,9 @@
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from);
-		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", status);
-		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", status);
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
 		switch_event_fire(&event);
 	}
 
@@ -2935,30 +2930,31 @@
 	char *pl;
 	char *id, *note;
 	uint32_t in = atoi(argv[0]);
-	char *msg = argv[1];
-	char *proto = argv[2];
-	char *user = argv[3];
-	char *host = argv[4];
-	char *sub_to_user = argv[5];
-	char *sub_to_host = argv[6];
-	char *event = argv[7];
-	char *contact = argv[8];
-	char *callid = argv[9];
-	char *full_from = argv[10];
-	char *full_via = argv[11];
+	char *status = argv[1];
+	char *rpid = argv[2];
+	char *proto = argv[3];
+	char *user = argv[4];
+	char *host = argv[5];
+	char *sub_to_user = argv[6];
+	char *sub_to_host = argv[7];
+	char *event = argv[8];
+	char *contact = argv[9];
+	char *callid = argv[10];
+	char *full_from = argv[11];
+	char *full_via = argv[12];
 	nua_handle_t *nh;
-	char *doing;
 	char *to;
 	char *open;
 	
+	if (!rpid) {
+		rpid = "unknown";
+	}
 
 	if (in) {
-		note = switch_mprintf("<dm:note>%s</dm:note>", msg);
-		doing="available";
+		note = switch_mprintf("<dm:note>%s</dm:note>", status);
 		open = "open";
 	} else {
 		note = NULL;
-		doing="unavailable";
 		open = "closed";
 	}
 
@@ -2984,9 +2980,8 @@
 								"<dm:person id='p06360c4a'>\r\n"
 								"<rpid:activities>\r\n"
 								"<rpid:%s/>\r\n"
-								"<rpid:unknown/>\r\n"
 								"</rpid:activities>%s</dm:person>\r\n"
-								"</presence>", id, open, doing, note);
+								"</presence>", id, open, rpid, note);
 
 	nh = nua_handle(profile->nua, NULL,	TAG_END());
 					
@@ -3022,7 +3017,7 @@
 						tagi_t tags[])
 {
 		if (sip) {
-			long exp;
+			long exp, exp_raw;
 			sip_to_t const *to = sip->sip_to;
 			sip_from_t const *from = sip->sip_from;
 			sip_contact_t const *contact = sip->sip_contact;
@@ -3040,8 +3035,8 @@
 			char *full_via = NULL;
 			switch_core_db_t *db;
 			char *errmsg;
+			char *sstr;
 
-
 			if (from) {
 				from_user = (char *) from->a_url->url_user;
 				from_host = (char *) from->a_url->url_host;
@@ -3094,10 +3089,10 @@
 			full_from = sip_header_as_string(profile->home, (void *)sip->sip_from);
 			full_via = sip_header_as_string(profile->home, (void *)sip->sip_via);
 
+			exp_raw = (sip->sip_expires ? sip->sip_expires->ex_delta : 3600);
+			exp = (long) time(NULL) + exp_raw;
+			
 
-			exp = (long) time(NULL) + (sip->sip_expires ? sip->sip_expires->ex_delta : 60);
-
-
 			if ((sql = switch_mprintf("delete from sip_subscriptions where "
 											  "proto='%q' and user='%q' and host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q';\n"
 											  "insert into sip_subscriptions values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
@@ -3123,27 +3118,29 @@
 				switch_safe_free(sql);
 			}
 
-			
+			sstr = switch_mprintf("active;expires=%ld", exp_raw);
+
 			nua_respond(nh, SIP_202_ACCEPTED,
-						SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=3600"),
+						SIPTAG_SUBSCRIPTION_STATE_STR(sstr),
 						SIPTAG_FROM(sip->sip_to),
 						SIPTAG_TO(sip->sip_from),
 						SIPTAG_CONTACT_STR(to_str),
 						TAG_END());
 
-
+			switch_safe_free(sstr);
+			
 			if (!(db = switch_core_db_open_file(profile->dbname))) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
 				goto end;
 			}
-			if ((sql = switch_mprintf("select 'sip+%q@%q',status from sip_registrations where user='%q' and host='%q'", to_user, to_host, to_user, to_host))) {
+			if ((sql = switch_mprintf("select 'sip+%q@%q',status,rpid from sip_registrations where user='%q' and host='%q'", 
+									  to_user, to_host, to_user, to_host))) {
 				switch_mutex_lock(profile->ireg_mutex);
 				switch_core_db_exec(db, sql, sub_reg_callback, profile, &errmsg);
 				switch_mutex_unlock(profile->ireg_mutex);
-				switch_core_db_close(db);
 				switch_safe_free(sql);
 			}
-
+			switch_core_db_close(db);
 		end:
 			
 			if (event) {
@@ -3449,6 +3446,7 @@
 		sip_from_t const *from = sip->sip_from;
 		char *from_user = NULL;
 		char *from_host = NULL;
+		char *rpid = "unknown";
 		sip_payload_t *payload = sip->sip_payload;
 		char *event_type;
 
@@ -3458,7 +3456,7 @@
 		}
 
 		if (payload) {
-			switch_xml_t xml, note, person, tuple, status, basic;
+			switch_xml_t xml, note, person, tuple, status, basic, act;
 			switch_event_t *event;
 			uint8_t in = 0;
 			char *sql;
@@ -3474,6 +3472,14 @@
 					note_txt = note->txt;
 				}
 
+				if (person && (act = switch_xml_child(person, "rpid:activities"))) {
+					if ((rpid = strchr(act->child->name, ':'))) {
+						rpid++;
+					} else {
+						rpid = act->child->name;
+					}
+				}
+
 				if (!strcasecmp(status_txt, "open")) {
 					if (switch_strlen_zero(note_txt)) {
 						note_txt = "Available";
@@ -3485,7 +3491,8 @@
 					}
 				}
 				
-				if ((sql = switch_mprintf("update sip_registrations set status='%q' where user='%q' and host='%q'", note_txt, from_user, from_host))) {
+				if ((sql = switch_mprintf("update sip_registrations set status='%q',rpid='%q' where user='%q' and host='%q'", 
+										  note_txt, rpid, from_user, from_host))) {
 					execute_sql(profile->dbname, sql, profile->ireg_mutex);
 					switch_safe_free(sql);
 				}
@@ -3495,17 +3502,18 @@
 				if (in) {
 					if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host);
 						
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", note_txt);
-						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "%s", status_txt);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "%s", event_type);
 						switch_event_fire(&event);
 					}
 				} else {
 					if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "sip");
+						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "rpid", "%s", rpid);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_NAME, from_user, from_host);
 
@@ -3630,7 +3638,8 @@
 			switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
 			set_chat_hash(tech_pvt, sip);
 			
-			
+			switch_channel_set_variable(channel, "sip_fromuser", (char *) from->a_url->url_user);
+			switch_channel_set_variable(channel, "sip_fromhost", (char *) from->a_url->url_host);
 			if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
 																	  (char *) from->a_url->url_user,
 																	  profile->dialplan,
@@ -3840,10 +3849,12 @@
 		tech_pvt = switch_core_session_get_private(session);
 	}
 
-	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(switch_core_session_get_channel(session)) : "n/a"
-					  );
+	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(switch_core_session_get_channel(session)) : "n/a"
+						  );
+	}
 
 	if ((profile->pflags & PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
 		sip_authorization_t const *authorization = NULL;
@@ -3982,6 +3993,7 @@
 	case nua_i_active:
 	case nua_i_ack:
 	case nua_i_terminated:
+	case nua_r_set_params:
 		break;
 
 	default:
@@ -4144,24 +4156,17 @@
 		switch_event_fire(&s_event);
 	}
 
-	if (profile->pflags & PFLAG_PRESENCE) {
-		if (!(profile->presence = switch_core_alloc(profile->pool, sizeof(*profile->presence)))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
-			return NULL;
-		}
 
-		profile->presence->nh = nua_handle(profile->nua, NULL, SIPTAG_CONTACT_STR(profile->url), TAG_END());
-										   
-		profile->presence->sofia_private.presence = profile->presence;
-		nua_handle_bind(profile->presence->nh, &profile->presence->sofia_private);
-
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating presence for %s\n", profile->url);
-	}
-
 	switch_mutex_lock(globals.hash_mutex);
 	switch_core_hash_insert(globals.profile_hash, profile->name, profile);
 	switch_mutex_unlock(globals.hash_mutex);
 
+	if (profile->pflags & PFLAG_PRESENCE) {
+		if (switch_event_create(&s_event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) {
+			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_NAME);
+			switch_event_fire(&s_event);
+		}
+	}
 
 	while(globals.running == 1) {
 		if (++ireg_loops >= IREG_SECONDS) {
@@ -4491,11 +4496,16 @@
 		char *from_host = switch_event_get_header(event, "orig-from-host");
 		char *contact_str = switch_event_get_header(event, "orig-contact");
 		char *exp_str = switch_event_get_header(event, "orig-expires");
+		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;
 		char buf[512];
 
+		if (!rpid) {
+			rpid = "unknown";
+		}
+
 		if (!profile_name || !(profile = (sofia_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name))) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n");
 			return;
@@ -4503,17 +4513,19 @@
 
 
 		if (!find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
-			sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Regestered', %ld)", 
-										 from_user,
-										 from_host,
-										 contact_str,
-										 expires);
+			sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','Regestered', '%q', %ld)", 
+								 from_user,
+								 from_host,
+								 contact_str,
+								 rpid,
+								 expires);
 		} else {
-			sql = switch_mprintf("update sip_registrations set contact='%q', expires=%ld where user='%q' and host='%q'",
-										 contact_str,
-										 expires,
-										 from_user,
-										 from_host);
+			sql = switch_mprintf("update sip_registrations set contact='%q', rpid='%q', expires=%ld where user='%q' and host='%q'",
+								 contact_str,
+								 rpid,
+								 expires,
+								 from_user,
+								 from_host);
 			
 		}
 	
@@ -4603,7 +4615,7 @@
 	switch_hash_index_t *hi;
     void *val;
 
-	if ((sql = switch_mprintf("select 0,'%q',* from sip_subscriptions where event='presence'"))) {
+	if ((sql = switch_mprintf("select 0,'unavailable','unavailable',* from sip_subscriptions where event='presence'"))) {
 		for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) {
 			switch_hash_this(hi, NULL, NULL, &val);
 			profile = (sofia_profile_t *) val;
@@ -4625,25 +4637,83 @@
 
 }
 
+
+static char *translate_rpid(char *in, char *ext)
+{
+	char *r = NULL;
+
+	if (in && (strstr(in, "null") || strstr(in, "NULL"))) {
+		in = NULL;
+	}
+
+	if (!in) {
+		in = ext;
+	}
+
+	if (!in) {
+		return NULL;
+	}
+	
+	if (!strcasecmp(in, "dnd")) {
+		r = "busy";
+	}
+
+	if (ext && !strcasecmp(ext, "away")) {
+		r = "idle";
+	}
+	
+	return r;
+}
+
 static void pres_event_handler(switch_event_t *event)
 {
 	sofia_profile_t *profile;
 	switch_hash_index_t *hi;
     void *val;
 	char *from = switch_event_get_header(event, "from");
+	char *rpid = switch_event_get_header(event, "rpid");
 	char *status= switch_event_get_header(event, "status");
-	char *show= switch_event_get_header(event, "show");
 	char *event_type = switch_event_get_header(event, "event_type");
-	char *sql = NULL;
-	char *user = NULL, *host = NULL;
+	char *sql = NULL, *sql2 = NULL;
+	char *euser = NULL, *user = NULL, *host = NULL;
 	char *errmsg;
 	char *resource;
 	switch_core_db_t *db;
 
+	if (rpid && !strcasecmp(rpid, "n/a")) {
+		rpid = NULL;
+	}
 
+	if (status && !strcasecmp(status, "n/a")) {
+		status = NULL;
+	}
+
+	if (rpid) {
+		rpid = translate_rpid(rpid, status);
+	}
+
+	if (!status) {
+		status = "Available";
+
+		if (rpid) {
+			if (!strcasecmp(rpid, "busy")) {
+				status = "Busy";
+			} else if (!strcasecmp(rpid, "unavailable")) {
+				status = "Idle";
+			} else if (!strcasecmp(rpid, "away")) {
+				status = "Idle";
+			}
+		}
+	}
+
 	if (event->event_id == SWITCH_EVENT_ROSTER) {
-		sql = switch_mprintf("select 1,'%q',* from sip_subscriptions where event='presence'", status ? status : "Available");
 
+		if (from) {
+			sql = switch_mprintf("select 1,'%q',%q',* from sip_subscriptions where event='presence' and full_from like '%%%q%%'", status, rpid, from);
+		} else {
+			sql = switch_mprintf("select 1,'%q',%q',* from sip_subscriptions where event='presence'", status, rpid);
+		}
+
 		for (hi = switch_hash_first(apr_hash_pool_get(globals.profile_hash), globals.profile_hash); hi; hi = switch_hash_next(hi)) {
 			switch_hash_this(hi, NULL, NULL, &val);
 			profile = (sofia_profile_t *) val;
@@ -4667,13 +4737,6 @@
 		return;
 	}
 
-	if (status && !strcasecmp(status, "n/a")) {
-		status = show;
-		if (status && !strcasecmp(status, "n/a")) {
-			status = NULL;
-		}
-	}
-
 	if (switch_strlen_zero(event_type)) {
 		event_type="presence";
 	}
@@ -4685,6 +4748,11 @@
 		if ((resource = strchr(host, '/'))) {
 			*resource++ = '\0';
 		}
+		if ((euser = strchr(user, '+'))) {
+			euser++;
+		} else {
+			euser = user;
+		}
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
 		return;
@@ -4701,19 +4769,12 @@
 
 	switch(event->event_id) {
 	case SWITCH_EVENT_PRESENCE_IN:
-		if (!status) {
-			status = "Available";
-		}
-
-		sql = switch_mprintf("select 1,'%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", 
-									 status , event_type, user, host);
+		sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", 
+							 status , rpid, event_type, euser, host);
 		break;
 	case SWITCH_EVENT_PRESENCE_OUT:
-		if (!status) {
-			status = "Unavailable";
-		}
-		sql = switch_mprintf("select 0,'%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", 
-									 status, event_type, user, host);
+		sql = switch_mprintf("select 0,'%q','%q',* from sip_subscriptions where event='%q' and sub_to_user='%q' and sub_to_host='%q'", 
+							 status, rpid, event_type, euser, host);
 		break;
 	default:
 		break;
@@ -4734,18 +4795,19 @@
 			switch_mutex_lock(profile->ireg_mutex);
 			switch_core_db_exec(db, sql, sub_callback, profile, &errmsg);
 			switch_mutex_unlock(profile->ireg_mutex);
-			switch_safe_free(sql);
-		
-			if ((sql = switch_mprintf("select 'sip+%q@%q',status from sip_registrations where user='%q' and host='%q'", user, host, user, host))) {
+			
+			
+			if ((sql2 = switch_mprintf("select 'sip+%q@%q',status,rpid from sip_registrations where user='%q' and host='%q'", euser, host, user, host))) {
 				switch_mutex_lock(profile->ireg_mutex);
-				switch_core_db_exec(db, sql, sub_reg_callback, profile, &errmsg);
+				switch_core_db_exec(db, sql2, sub_reg_callback, profile, &errmsg);
 				switch_mutex_unlock(profile->ireg_mutex);
-				switch_core_db_close(db);
-				switch_safe_free(sql);
+				switch_safe_free(sql2);
 			}
+			switch_core_db_close(db);
 		}
 	}
 
+	switch_safe_free(sql);
 	switch_safe_free(user);
 }
 



More information about the Freeswitch-svn mailing list