[Freeswitch-trunk] [commit] r6802 - in freeswitch/trunk: conf/directory libs/sofia-sip/libsofia-sip-ua/nua src src/mod/endpoints/mod_sofia

Freeswitch SVN brian at freeswitch.org
Fri Dec 14 19:39:53 EST 2007


Author: brian
Date: Fri Dec 14 19:39:53 2007
New Revision: 6802

Modified:
   freeswitch/trunk/conf/directory/default.xml
   freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   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/switch_channel.c

Log:
wip

Modified: freeswitch/trunk/conf/directory/default.xml
==============================================================================
--- freeswitch/trunk/conf/directory/default.xml	(original)
+++ freeswitch/trunk/conf/directory/default.xml	Fri Dec 14 19:39:53 2007
@@ -2,7 +2,7 @@
   <!--the domain or ip (the right hand side of the @ in the addr-->
   <domain name="$${domain}">
     <params>
-      <param name="dial-string" value="sofia/${dialed_domain}/${dialed_user}"/>
+      <param name="dial-string" value="{presence_id=${dialed_user}@${dialed_domain}}sofia/${dialed_domain}/${dialed_user}"/>
     </params>
 
     <X-PRE-PROCESS cmd="include" data="default/*.xml"/>

Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c	(original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c	Fri Dec 14 19:39:53 2007
@@ -2125,7 +2125,7 @@
   }
 
   if (du->du_cr && cr != du->du_cr) {
-    assert(!nua_client_is_queued(du->du_cr));
+
     if (nua_client_is_queued(du->du_cr))
       return -1;
     if (nua_client_is_reporting(du->du_cr)) {

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 Dec 14 19:39:53 2007
@@ -998,9 +998,13 @@
 							   "Call-ID \t%s\n"
 							   "User    \t%s@%s\n"
 							   "Contact \t%s\n"
+							   "Agent   \t%s\n"
 							   "Status  \t%s(%s) EXP(%s)\n\n", 
 							   switch_str_nil(argv[0]), switch_str_nil(argv[1]), switch_str_nil(argv[2]), switch_str_nil(argv[3]), 
-							   switch_str_nil(argv[4]), switch_str_nil(argv[5]), exp_buf);
+							   switch_str_nil(argv[7]), 
+							   switch_str_nil(argv[4]), 
+							   switch_str_nil(argv[5]), 
+							   exp_buf);
 	return 0;
 }
 

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	Fri Dec 14 19:39:53 2007
@@ -58,6 +58,17 @@
 							   char const *phrase,
 							   nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[])
 {
+	if (status == 481 && sip) {
+		const char *call_id = sip->sip_call_id->i_id;
+		char *sql;
+		switch_core_hash_delete(profile->sub_hash, call_id);
+		
+		sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
+		switch_assert(sql != NULL);
+		sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex);
+		free(sql);
+		nua_handle_destroy(nh);
+	}
 }
 
 void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
@@ -318,7 +329,7 @@
 		sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL);
 		switch_safe_free(sql);
 		
-		sql = switch_mprintf("insert into sip_registrations values ('%q', '%q','%q','%q','Regestered', '%q', %ld, '%q')",
+		sql = switch_mprintf("insert into sip_registrations values ('%q', '%q','%q','%q','Registered', '%q', %ld, '%q')",
 							 call_id, from_user, from_host, contact_str, rpid, expires, user_agent);
 
 		if (sql) {
@@ -398,6 +409,7 @@
 				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ENABLEMESSAGE(1)),
 				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("presence")),
 				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("dialog")),
+				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("call-info")),
 				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("presence.winfo")),
 				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("message-summary")),
 				   SIPTAG_SUPPORTED_STR("100rel, precondition, timer"), SIPTAG_USER_AGENT_STR(profile->user_agent), TAG_END());

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	Fri Dec 14 19:39:53 2007
@@ -1233,6 +1233,7 @@
 		if (!switch_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
 			const char *stream;
 			switch_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+			switch_channel_presence(tech_pvt->channel, "unknown", "hold");
 			if (tech_pvt->max_missed_packets) {
 				switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets * 10);
 			}
@@ -1251,6 +1252,7 @@
 			}
 			switch_channel_set_flag_partner(tech_pvt->channel, CF_BREAK);
 			switch_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+			switch_channel_presence(tech_pvt->channel, "unknown", "unhold");
 		}
 	}
 

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	Fri Dec 14 19:39:53 2007
@@ -40,6 +40,11 @@
 static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char **columnNames);
 static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames);
 
+struct presence_helper {
+	sofia_profile_t *profile;
+	switch_event_t *event;
+};
+
 switch_status_t sofia_presence_chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint)
 {
 	char buf[256];
@@ -117,7 +122,8 @@
 	sofia_profile_t *profile;
 	switch_hash_index_t *hi;
 	void *val;
-
+	struct presence_helper helper;
+	
 	if ((sql = switch_mprintf("select *,-1,'unavailable','unavailable' from sip_subscriptions where event='presence'"))) {
 		switch_mutex_lock(mod_sofia_globals.hash_mutex);
 		for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
@@ -126,8 +132,9 @@
 			if (!(profile->pflags & PFLAG_PRESENCE)) {
 				continue;
 			}
-
-			if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_callback, profile) != SWITCH_TRUE) {
+			helper.profile = profile;
+			helper.event = NULL;
+			if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper) != SWITCH_TRUE) {
 				continue;
 			}
 		}
@@ -275,6 +282,7 @@
 	char *rpid = switch_event_get_header(event, "rpid");
 	char *status = switch_event_get_header(event, "status");
 	char *event_type = switch_event_get_header(event, "event_type");
+	char *alt_event_type = switch_event_get_header(event, "alt_event_type");
 	char *sql = NULL;
 	char *euser = NULL, *user = NULL, *host = NULL;
 
@@ -309,7 +317,8 @@
 	}
 
 	if (event->event_id == SWITCH_EVENT_ROSTER) {
-
+		struct presence_helper helper;
+		
 		if (from) {
 			sql = switch_mprintf("select *,1,'%q','%q' from sip_subscriptions where event='presence' and full_from like '%%%q%%'", status, rpid, from);
 		} else {
@@ -324,13 +333,14 @@
 			if (!(profile->pflags & PFLAG_PRESENCE)) {
 				continue;
 			}
-
+			helper.profile = profile;
+            helper.event = NULL;
 			sofia_glue_execute_sql_callback(profile,
 											SWITCH_FALSE,
 											profile->ireg_mutex,
 											sql,
 											sofia_presence_sub_callback,
-											profile);
+											&helper);
 		}
 		switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 		free(sql);
@@ -341,6 +351,10 @@
 		event_type = "presence";
 	}
 
+	if (switch_strlen_zero(alt_event_type)) {
+		alt_event_type = "presence";
+	}
+	
 	if ((user = strdup(from))) {
 		if ((host = strchr(user, '@'))) {
 			char *p;
@@ -399,14 +413,14 @@
 	case SWITCH_EVENT_PRESENCE_IN:
 		sql =
 			switch_mprintf
-			("select *,1,'%q','%q' from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q'",
-			 status, rpid, proto, event_type, euser, host);
+			("select *,1,'%q','%q' from sip_subscriptions where proto='%q' and (event='%q' or event='%q') and sub_to_user='%q' and sub_to_host='%q'",
+			 status, rpid, proto, event_type, alt_event_type, euser, host);
 		break;
 	case SWITCH_EVENT_PRESENCE_OUT:
 		sql =
 			switch_mprintf
-			("select *,0,'%q','%q' from sip_subscriptions where proto='%q' and event='%q' and sub_to_user='%q' and sub_to_host='%q'",
-			 status, rpid, proto, event_type, euser, host);
+			("select *,0,'%q','%q' from sip_subscriptions where proto='%q' and (event='%q' or event='%q') and sub_to_user='%q' and sub_to_host='%q'",
+			 status, rpid, proto, event_type, alt_event_type, euser, host);
 		break;
 	default:
 		break;
@@ -421,12 +435,15 @@
 		}
 
 		if (sql) {
+			struct presence_helper helper;
+			helper.profile = profile;
+            helper.event = event;
 			sofia_glue_execute_sql_callback(profile,
 											SWITCH_FALSE,
 											profile->ireg_mutex,
 											sql,
 											sofia_presence_sub_callback,
-											profile);
+											&helper);
 		}
 	}
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
@@ -455,13 +472,14 @@
 	if (switch_strlen_zero(status)) {
 		status = "Available";
 	}
-	if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
+	if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->url);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", user, host);
 		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_add_header(event, SWITCH_STACK_BOTTOM, "proto-specific-event-name", "%s", event_name);
 		switch_event_fire(&event);
 	}
 
@@ -529,7 +547,8 @@
 
 static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
-	sofia_profile_t *profile = (sofia_profile_t *) pArg;
+	struct presence_helper *helper = (struct presence_helper *) pArg;
+	sofia_profile_t *profile = helper->profile;
 	char *pl;
 	char *id, *note;
 	uint32_t in = atoi(argv[13]);
@@ -584,34 +603,68 @@
 	}
 
 	to = switch_mprintf("sip:%s@%s", user, host);
-	pl = switch_mprintf("<?xml version='1.0' encoding='UTF-8'?>\r\n"
-						"<presence xmlns='urn:ietf:params:xml:ns:pidf'\r\n"
-						"xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model'\r\n"
-						"xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid'\r\n"
-						"xmlns:c='urn:ietf:params:xml:ns:pidf:cipid'\r\n"
-						"entity='pres:%s'>\r\n"
-						"<presentity uri=\"%s;method=SUBSCRIBE\"/>\r\n"
-						"<atom id=\"1002\">\r\n"
-						"<address uri=\"%s\" priority=\"0.800000\">\r\n"
-						"<status status=\"%s\">\r\n"
-						"<note>%s</note>\r\n"
-						"</status>\r\n"
-						"<msnsubstatus substatus=\"%s\"/>\r\n"
-						"</address>\r\n"
-						"</atom>\r\n"
-						"<tuple id='t6a5ed77e'>\r\n"
-						"<status>\r\n"
-						"<basic>%s</basic>\r\n"
-						"</status>\r\n"
-						"</tuple>\r\n"
-						"<dm:person id='p06360c4a'>\r\n"
-						"<rpid:activities>\r\n" "<rpid:%s/>\r\n" 
-						"</rpid:activities>%s</dm:person>\r\n" 
-						"</presence>", id, 
-						id, profile->url, open, status, prpid,
-						open, rpid, note);
+	
+	if (!strcmp(event, "dialog") && helper->event) {
+		switch_stream_handle_t stream = { 0 };
+		//const char *direction = switch_str_nil(switch_event_get_header(helper->event, "call-direction"));
+		const char *uuid = switch_str_nil(switch_event_get_header(helper->event, "unique-id"));
+		const char *state = switch_str_nil(switch_event_get_header(helper->event, "channel-state"));
+		const char *status = switch_str_nil(switch_event_get_header(helper->event, "status"));
+		
+		SWITCH_STANDARD_STREAM(stream);
+
+							  
+		stream.write_function(&stream, 
+							  "<?xml version=\"1.0\"?>\n"
+							  "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
+							  "version=\"%s\" state=\"full\" entity=\"%s\">\n", 
+							  switch_str_nil(switch_event_get_header(helper->event, "event_count")), to);
+		
+		if (!strcasecmp(state, "RING")) {
+			stream.write_function(&stream, "<dialog id=\"%s\" direction=\"recipient\">\n", uuid);
+		} else {
+			stream.write_function(&stream, "<dialog id=\"%s\">\n", uuid);
+		}
+		
+		stream.write_function(&stream, "<state>%s</state>\n", switch_str_nil(switch_event_get_header(helper->event, "answer-state")));
+		if (!strcasecmp(status, "hold")) {
+			stream.write_function(&stream, "<local>\n<target uri=\"%s\">\n"
+						   "<param pname=\"+sip.rendering\" pvalue=\"no\">\n"
+								  "</target>\n</local>\n", to);
+		}
+		stream.write_function(&stream, "</dialog>\n</dialog-info>\n");
+		pl = stream.data;
+	} else {
+		pl = switch_mprintf("<?xml version='1.0' encoding='UTF-8'?>\r\n"
+							"<presence xmlns='urn:ietf:params:xml:ns:pidf'\r\n"
+							"xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model'\r\n"
+							"xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid'\r\n"
+							"xmlns:c='urn:ietf:params:xml:ns:pidf:cipid'\r\n"
+							"entity='pres:%s'>\r\n"
+							"<presentity uri=\"%s;method=SUBSCRIBE\"/>\r\n"
+							"<atom id=\"1002\">\r\n"
+							"<address uri=\"%s\" priority=\"0.800000\">\r\n"
+							"<status status=\"%s\">\r\n"
+							"<note>%s</note>\r\n"
+							"</status>\r\n"
+							"<msnsubstatus substatus=\"%s\"/>\r\n"
+							"</address>\r\n"
+							"</atom>\r\n"
+							"<tuple id='t6a5ed77e'>\r\n"
+							"<status>\r\n"
+							"<basic>%s</basic>\r\n"
+							"</status>\r\n"
+							"</tuple>\r\n"
+							"<dm:person id='p06360c4a'>\r\n"
+							"<rpid:activities>\r\n" "<rpid:%s/>\r\n" 
+							"</rpid:activities>%s</dm:person>\r\n" 
+							"</presence>", id, 
+							id, profile->url, open, status, prpid,
+							open, rpid, note);
+	}
 
 	nua_notify(nh,
+			   NUTAG_NEWSUB(1),
 			   SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=3600"),
 			   SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
 
@@ -666,6 +719,7 @@
 	exp = switch_mprintf("active;expires=%ld", expire_sec);
 
 	nua_notify(nh,
+			   NUTAG_NEWSUB(1),
 			   SIPTAG_SUBSCRIPTION_STATE_STR(exp),
 			   SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END());
 	
@@ -745,10 +799,13 @@
 		const char *display = "\"user\"";
 		switch_event_t *sevent;
 		int sub_state;
+		int sent_reply = 0;
 
 		tl_gets(tags,
 				NUTAG_SUBSTATE_REF(sub_state), TAG_END());
 
+		event = sip_header_as_string(profile->home, (void *) sip->sip_event);
+
 		if (contact) {
 			char *port = (char *) contact->m_url->url_port;
 
@@ -818,7 +875,7 @@
 				switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "login", "%s", profile->name);
 				switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
 				switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host);
-				
+				switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", "%s", event);
 				switch_event_fire(&sevent);
 			}
 		}
@@ -843,7 +900,6 @@
 		}
 
 		call_id = sip->sip_call_id->i_id;
-		event = sip_header_as_string(profile->home, (void *) sip->sip_event);
 		full_from = sip_header_as_string(profile->home, (void *) sip->sip_from);
 		full_via = sip_header_as_string(profile->home, (void *) sip->sip_via);
 
@@ -881,20 +937,31 @@
 
 			switch_mutex_unlock(profile->ireg_mutex);
 			sstr = switch_mprintf("active;expires=%ld", exp_raw);
-			switch_core_hash_insert(profile->sub_hash, call_id, nh);
+			if (status < 200) {
+				switch_core_hash_insert(profile->sub_hash, call_id, nh);
+			}
 		}
+	
+		if (status < 200) {
+			nua_respond(nh, SIP_202_ACCEPTED,
+						NUTAG_WITH_THIS(nua),
+						SIPTAG_SUBSCRIPTION_STATE_STR(sstr), 
+						SIPTAG_FROM(sip->sip_to),
+						SIPTAG_TO(sip->sip_from),
+						SIPTAG_CONTACT_STR(contact_str),
+						TAG_END());
+		}
+		
+		sent_reply++;
 
-		nua_respond(nh, SIP_202_ACCEPTED,
-					NUTAG_WITH_THIS(nua),
-					SIPTAG_SUBSCRIPTION_STATE_STR(sstr), 
-					SIPTAG_FROM(sip->sip_to),
-					SIPTAG_TO(sip->sip_from),
-					SIPTAG_CONTACT_STR(contact_str),
-					TAG_END());
-
-		nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/octet-stream"),
-				   SIPTAG_PAYLOAD_STR("Come to ClueCon http://www.cluecon.com\n\n"),
+#if 0
+		nua_notify(nh, 
+				   NUTAG_NEWSUB(1),
+				   SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event), 
+				   SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
+				   SIPTAG_PAYLOAD_STR("Note: Come to ClueCon http://www.cluecon.com\n\n"),
 				   TAG_END());
+#endif
 
 		switch_safe_free(sstr);
 
@@ -930,7 +997,12 @@
 		switch_safe_free(d_user);
 		switch_safe_free(to_str);
 		switch_safe_free(contact_str);
+
+		if (!sent_reply) {
+			nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END());
+		}
 	}
+
 }
 
 void sofia_presence_handle_sip_r_subscribe(int status,

Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c	(original)
+++ freeswitch/trunk/src/switch_channel.c	Fri Dec 14 19:39:53 2007
@@ -120,6 +120,7 @@
 	switch_hash_t *private_hash;
 	switch_call_cause_t hangup_cause;
 	int vi;
+	int event_count;
 };
 
 
@@ -305,6 +306,7 @@
 	}
 
 	if (switch_event_create(&event, type) == SWITCH_STATUS_SUCCESS) {
+		switch_channel_event_set_data(channel, event);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "%s", __FILE__);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", __FILE__);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", id);
@@ -316,6 +318,8 @@
 			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, "alt_event_type", "dialog");
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", channel->event_count++);
 		switch_event_fire(&event);
 	}
 
@@ -587,8 +591,11 @@
 	switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG, "%s Running State Change %s\n",
 					  channel->name, state_names[channel->state]);
 	channel->running_state = channel->state;
-	
 
+	if (channel->state >= CS_RING) {
+		switch_channel_presence(channel, "unknown", (char *) state_names[channel->state]);
+	}
+	
 	if (channel->state < CS_HANGUP) {
 		switch_event_t *event;
 		if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
@@ -601,6 +608,14 @@
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%s", (char *) state_num);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Name", "%s", channel->name);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", switch_core_session_get_uuid(channel->session));
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Call-Direction", "%s", switch_channel_test_flag(channel, CF_OUTBOUND) ? "outbound" : "inbound");
+				if (switch_channel_test_flag(channel, CF_ANSWERED)) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "confirmed");
+				} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
+				} else {
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
+				}
 			}
 			switch_event_fire(&event);
 		}
@@ -799,9 +814,6 @@
 
 
 	if (ok) {
-		if (state > CS_RING) {
-			switch_channel_presence(channel, "unknown", (char *) state_names[state]);
-		}
 		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG, "%s State Change %s -> %s\n",
 						  channel->name, state_names[last_state], state_names[state]);
 		switch_mutex_lock(channel->flag_mutex);
@@ -858,6 +870,15 @@
 	switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Name", "%s", switch_channel_get_name(channel));
 	switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", switch_core_session_get_uuid(channel->session));
 
+	switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Call-Direction", "%s", switch_channel_test_flag(channel, CF_OUTBOUND) ? "outbound" : "inbound");
+	if (switch_channel_test_flag(channel, CF_ANSWERED)) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
+	} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
+	} else {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
+	}
+
 	if ((codec = switch_core_session_get_read_codec(channel->session)) && codec->implementation) {
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", "%s", switch_str_nil(codec->implementation->iananame));
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", codec->implementation->actual_samples_per_second);



More information about the Freeswitch-trunk mailing list