[Freeswitch-svn] [commit] r3035 - in freeswitch/trunk: libs/libdingaling/src src src/include src/mod/endpoints/mod_dingaling src/mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Wed Oct 11 20:59:10 EDT 2006


Author: anthm
Date: Wed Oct 11 20:59:09 2006
New Revision: 3035

Modified:
   freeswitch/trunk/libs/libdingaling/src/libdingaling.c
   freeswitch/trunk/libs/libdingaling/src/libdingaling.h
   freeswitch/trunk/src/include/switch_core.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/switch_core.c
   freeswitch/trunk/src/switch_event.c
   freeswitch/trunk/src/switch_ivr.c

Log:
refactoring and general improvement (do a make sure)

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.c
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.c	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.c	Wed Oct 11 20:59:09 2006
@@ -445,11 +445,29 @@
 {
 	ldl_handle_t *handle = user_data;
 	char *from = iks_find_attrib(pak->x, "from");
+	char *type = iks_find_attrib(pak->x, "type");
+	char *show = iks_find_cdata(pak->x, "show");
+	char *status = iks_find_cdata(pak->x, "status");
 	char id[1024];
 	char *resource;
 	struct ldl_buffer *buffer;
 	size_t x;
+	ldl_signal_t signal;
+
+	if (type && !strcasecmp(type, "unavailable")) {
+		signal = LDL_SIGNAL_PRESENCE_OUT;
+	} else {
+		signal = LDL_SIGNAL_PRESENCE_IN;
+	}
+
+	if (!status) {
+		status = type;
+	}
 	
+	if (handle->session_callback) {
+        handle->session_callback(handle, NULL, signal, from, status ? status : "n/a", show ? show : "n/a");
+    }
+
 	if (!apr_hash_get(handle->sub_hash, from, APR_HASH_KEY_STRING)) {
 		iks *msg;
 		apr_hash_set(handle->sub_hash, 	apr_pstrdup(handle->pool, from), APR_HASH_KEY_STRING, &marker);

Modified: freeswitch/trunk/libs/libdingaling/src/libdingaling.h
==============================================================================
--- freeswitch/trunk/libs/libdingaling/src/libdingaling.h	(original)
+++ freeswitch/trunk/libs/libdingaling/src/libdingaling.h	Wed Oct 11 20:59:09 2006
@@ -119,6 +119,8 @@
 	LDL_SIGNAL_INITIATE,
 	LDL_SIGNAL_CANDIDATES,
 	LDL_SIGNAL_MSG,
+	LDL_SIGNAL_PRESENCE_IN,
+	LDL_SIGNAL_PRESENCE_OUT,
 	LDL_SIGNAL_TERMINATE,
 	LDL_SIGNAL_ERROR,
 	LDL_SIGNAL_LOGIN_SUCCESS,

Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h	(original)
+++ freeswitch/trunk/src/include/switch_core.h	Wed Oct 11 20:59:09 2006
@@ -83,6 +83,8 @@
 	void *pointer_reply;
 	/*! optional arbitrary pointer reply's size */
 	switch_size_t pointer_reply_size;
+	/*! message flags */
+	switch_core_session_message_flag_t flags;
 };
 
 /*! \brief A generic object to pass as a thread's session object to allow mutiple arguements and a pool */
@@ -420,6 +422,22 @@
   \return the status returned by the message handler
 */
 SWITCH_DECLARE (switch_status_t) switch_core_session_message_send(char *uuid_str, switch_core_session_message_t *message);
+
+/*! 
+  \brief Queue a message on a session
+  \param session the session to queue the message to
+  \param message the message to queue
+  \return SWITCH_STATUS_SUCCESS if the message was queued
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_session_queue_message(switch_core_session_t *session, switch_core_session_message_t *message);
+
+/*! 
+  \brief DE-Queue an message on a given session
+  \param session the session to de-queue the message on
+  \param message the de-queued message
+  \return the  SWITCH_STATUS_SUCCESS if the message was de-queued
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_session_t *session, switch_core_session_message_t **message);
 
 /*! 
   \brief Queue an event on another session using its uuid

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Oct 11 20:59:09 2006
@@ -247,7 +247,8 @@
 	SWITCH_MESSAGE_INDICATE_PROGRESS,
 	SWITCH_MESSAGE_INDICATE_BRIDGE,
 	SWITCH_MESSAGE_INDICATE_UNBRIDGE,
-	SWITCH_MESSAGE_INDICATE_TRANSFER
+	SWITCH_MESSAGE_INDICATE_TRANSFER,
+	SWITCH_MESSAGE_INDICATE_RINGING
 } switch_core_session_message_types_t;
 
 
@@ -348,6 +349,10 @@
 	SWITCH_CHANNEL_ID_EVENT
 } switch_text_channel_t;
 
+typedef enum {
+	SCSMF_DYNAMIC = (1 << 0)
+} switch_core_session_message_flag_t;
+
 #define SWITCH_UUID_FORMATTED_LENGTH APR_UUID_FORMATTED_LENGTH 	
 #define SWITCH_CHANNEL_LOG SWITCH_CHANNEL_ID_LOG, __FILE__, __FUNCTION__, __LINE__
 #define SWITCH_CHANNEL_LOG_CLEAN SWITCH_CHANNEL_ID_LOG_CLEAN, __FILE__, __FUNCTION__, __LINE__
@@ -610,6 +615,7 @@
 	SWITCH_EVENT_MODULE_LOAD		- Module was loaded
 	SWITCH_EVENT_DTMF				- DTMF was sent
 	SWITCH_EVENT_MESSAGE			- A Basic Message
+	SWITCH_EVENT_PRESENCE			- Presence Info
 	SWITCH_EVENT_CODEC				- Codec Change
 	SWITCH_EVENT_BACKGROUND_JOB		- Background Job
     SWITCH_EVENT_ALL				- All events at once
@@ -644,6 +650,8 @@
 	SWITCH_EVENT_MODULE_LOAD,
 	SWITCH_EVENT_DTMF,
 	SWITCH_EVENT_MESSAGE,
+	SWITCH_EVENT_PRESENCE_IN,
+	SWITCH_EVENT_PRESENCE_OUT,
 	SWITCH_EVENT_CODEC,
 	SWITCH_EVENT_BACKGROUND_JOB,
 	SWITCH_EVENT_ALL

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	Wed Oct 11 20:59:09 2006
@@ -38,7 +38,6 @@
 
 #define DL_EVENT_LOGIN_SUCCESS "dingaling::login_success"
 #define DL_EVENT_LOGIN_FAILURE "dingaling::login_failure"
-#define DL_EVENT_MESSAGE "dingaling::message"
 #define DL_EVENT_CONNECTED "dingaling::connected"
 
 static const char modname[] = "mod_dingaling";
@@ -1191,11 +1190,6 @@
 		return SWITCH_STATUS_GENERR;
 	}
 
-	if (switch_event_reserve_subclass(DL_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", DL_EVENT_MESSAGE);
-		return SWITCH_STATUS_GENERR;
-	}
-
 	if (switch_event_reserve_subclass(DL_EVENT_CONNECTED) != SWITCH_STATUS_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", DL_EVENT_CONNECTED);
 		return SWITCH_STATUS_GENERR;
@@ -1533,12 +1527,30 @@
 
 	if (!dlsession) {
 		switch(signal) {
+		case LDL_SIGNAL_PRESENCE_IN:
+			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", profile->login);
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", from);
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", subject);
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", msg);
+				switch_event_fire(&event);
+			}
+			break;
+		case LDL_SIGNAL_PRESENCE_OUT:
+			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", profile->login);
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", from);
+				switch_event_fire(&event);
+			}
+			break;
 		case LDL_SIGNAL_MSG:
-			if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, DL_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+			if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", profile->login);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", from);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "subject", subject);
-				switch_event_add_body(event, msg);
+				if (msg) {
+					switch_event_add_body(event, msg);
+				}
 				switch_event_fire(&event);
 			}
 			break;
@@ -1639,12 +1651,13 @@
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SESSION MSG [%s]\n", msg);
 		}
 
-		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, DL_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+		if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", profile->login);
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", from);
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "subject", subject);
-			switch_event_add_body(event, msg);
-
+			if (msg) {
+				switch_event_add_body(event, msg);
+			}
 			if (switch_core_session_queue_event(tech_pvt->session, &event) != SWITCH_STATUS_SUCCESS) {
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
 				switch_event_fire(&event);

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	Wed Oct 11 20:59:09 2006
@@ -42,6 +42,9 @@
 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
@@ -49,6 +52,7 @@
 struct sofia_private {
 	switch_core_session_t *session;
 	outbound_reg_t *oreg;
+	sip_presence_t *presence;
 };
 
 typedef struct sofia_private sofia_private_t;
@@ -113,7 +117,8 @@
 	PFLAG_AUTH_CALLS = (1 << 0),
 	PFLAG_BLIND_REG = (1 << 1),
 	PFLAG_AUTH_ALL = (1 << 2),
-	PFLAG_FULL_ID = (1 << 3)
+	PFLAG_FULL_ID = (1 << 3),
+	PFLAG_PRESENCE = (1 << 4)
 } PFLAGS;
 
 typedef enum {
@@ -183,6 +188,14 @@
 	struct outbound_reg *next;
 };
 
+
+struct sip_presence {
+	sofia_private_t sofia_private;
+	nua_handle_t *nh;
+	sofia_profile_t *profile;
+};
+
+
 struct sofia_profile {
 	int debug;
 	char *name;
@@ -216,6 +229,8 @@
 	switch_mutex_t *ireg_mutex;
 	switch_mutex_t *oreg_mutex;
 	outbound_reg_t *registrations;
+	sip_presence_t *presence;
+	su_home_t *home;
 };
 
 
@@ -1311,6 +1326,7 @@
 						SOATAG_AUDIO_AUX("cn telephone-event"),
 						NUTAG_INCLUDE_EXTRA_SDP(1),
 						TAG_END());
+			
 		}
 	}
 
@@ -1605,6 +1621,9 @@
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-activate timed RTP!\n");
 		}
 		break;
+	case SWITCH_MESSAGE_INDICATE_RINGING:
+		nua_respond(tech_pvt->nh, SIP_180_RINGING, TAG_END());
+		break;
 	case SWITCH_MESSAGE_INDICATE_PROGRESS: {
 		struct private_object *tech_pvt;
 	    switch_channel_t *channel = NULL;
@@ -1809,11 +1828,11 @@
 
 			for (map = m->m_rtpmaps; map; map = map->rm_next) {
 				int32_t i;
-								
+				
 				if (!strcasecmp(map->rm_encoding, "telephone-event")) {
 					tech_pvt->te = (switch_payload_t)map->rm_pt;
 				}
-
+				
 				for (i = 0; i < tech_pvt->num_codecs; i++) {
 					const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec Compare [%s:%d]/[%s:%d]\n", 
@@ -1823,7 +1842,7 @@
 					} else {
 						match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
 					}
-								
+					
 					if (match && (map->rm_rate == imp->samples_per_second)) {
 						tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *)map->rm_encoding);
 						tech_pvt->pt = (switch_payload_t)map->rm_pt;
@@ -1902,6 +1921,76 @@
 	}
 }
 
+static void sip_i_message(int status,
+						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 (sip) {
+		sip_from_t const *from = sip->sip_from;
+		char *from_user = NULL;
+		char *from_host = NULL;
+		sip_to_t const *to = sip->sip_to;
+		char *to_user = NULL;
+		char *to_host = NULL;
+		sip_subject_t const *sip_subject = sip->sip_subject;
+		sip_payload_t *payload = sip->sip_payload;
+		const char *subject = "n/a";
+		char *msg = "";
+
+
+		if (from) {
+			from_user = (char *) from->a_url->url_user;
+			from_host = (char *) from->a_url->url_host;
+		}
+
+		if (to) {
+			to_user = (char *) to->a_url->url_user;
+			to_host = (char *) to->a_url->url_host;
+		}
+
+		if (payload) {
+			msg = payload->pl_data;
+		}
+
+		if (sip_subject) {
+			subject = sip_subject->g_value;
+		}
+
+		if (nh) {			
+			char *message = "hello world";
+			char buf[256] = "";
+
+			if (find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
+				nua_handle_t *msg_nh;
+
+
+				msg_nh = nua_handle(profile->nua, NULL,
+									SIPTAG_FROM(sip->sip_to),
+									SIPTAG_TO_STR(buf),
+									SIPTAG_CONTACT_STR(profile->url),
+									TAG_END());
+
+
+				nua_message(msg_nh,
+							SIPTAG_CONTENT_TYPE_STR("text/plain"),
+							TAG_IF(message,
+								   SIPTAG_PAYLOAD_STR(message)),
+							TAG_END());
+
+				nua_handle_destroy(msg_nh);
+			}
+			
+		} 
+		//printf("==================================\nFrom: %s@%s\nSubject: %s\n\n%s\n\n",from_user,from_host,subject,msg);
+	}
+	
+}
+
 static void sip_i_state(int status,
 						char const *phrase, 
 						nua_t *nua,
@@ -1964,6 +2053,27 @@
 		break;
 	case nua_callstate_proceeding:
 		if (channel) {
+			if (status == 180) {
+				if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
+					if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
+						switch_core_session_message_t msg;
+						msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
+						msg.from = __FILE__;
+						switch_core_session_receive_message(other_session, &msg);
+						switch_core_session_rwunlock(other_session);
+					}
+					
+				} else {
+					switch_core_session_message_t *msg;
+					if ((msg = malloc(sizeof(*msg)))) {
+						memset(msg, 0, sizeof(*msg));
+						msg->message_id = SWITCH_MESSAGE_INDICATE_RINGING;
+						msg->from = __FILE__;
+						switch_core_session_queue_message(session, msg);
+						switch_set_flag(msg, SCSMF_DYNAMIC);
+					}
+				}
+			}
 			if (r_sdp) {
 				if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
 					switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
@@ -2462,7 +2572,32 @@
 }
 
 
+static void sip_i_subscribe(int status,
+						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[])
+{
+	nua_respond(nh, SIP_200_OK, 
+				TAG_END());
+}
 
+static void sip_r_subscribe(int status,
+						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[])
+{
+
+}
+
+
 /*---------------------------------------*/
 static void sip_i_refer(nua_t *nua,
 						sofia_profile_t *profile,
@@ -2850,7 +2985,23 @@
 }
 
 
+static void sip_i_options(int status,
+						  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[])
+{
+	nua_respond(nh, SIP_200_OK, 
+				//SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+				//SOATAG_AUDIO_AUX("cn telephone-event"),
+				//NUTAG_INCLUDE_EXTRA_SDP(1),
+				TAG_END());
+}
 
+
 static void sip_r_register(int status,
 						   char const *phrase,
 						   nua_t *nua,
@@ -3000,6 +3151,10 @@
 		//sip_r_options(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
 
+	case nua_i_options:
+		sip_i_options(status, phrase, nua, profile, nh, sofia_private, sip, tags);
+		break;
+
 	case nua_i_fork:
 		//sip_i_fork(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
@@ -3033,7 +3188,7 @@
 		break;
 
 	case nua_i_message:
-		//sip_i_message(nua, profile, nh, sofia_private, sip, tags);
+		sip_i_message(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
 
 	case nua_r_info:
@@ -3053,9 +3208,13 @@
 		break;
      
 	case nua_r_subscribe:
-		//sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
+		sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
 
+	case nua_i_subscribe:
+		sip_i_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
+		break;
+
 	case nua_r_unsubscribe:
 		//sip_r_unsubscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
@@ -3063,7 +3222,9 @@
 	case nua_r_publish:
 		//sip_r_publish(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
-    
+    case nua_r_notifier:
+		nua_respond(nh, SIP_200_OK, TAG_END());
+		break;
 	case nua_r_notify:
 		//sip_r_notify(status, phrase, nua, profile, nh, sofia_private, sip, tags);
 		break;
@@ -3180,6 +3341,8 @@
 				   NUTAG_AUTOALERT(0),
 				   NUTAG_ALLOW("REGISTER"),
 				   NUTAG_ALLOW("REFER"),
+				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW("PUBLISH")),
+				   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ENABLEMESSAGE(1)),
 				   SIPTAG_SUPPORTED_STR("100rel, precondition"),
 				   SIPTAG_USER_AGENT_STR(SOFIA_USER_AGENT),
 				   TAG_END());
@@ -3198,6 +3361,8 @@
 					   NUTAG_AUTOALERT(0),
 					   NUTAG_ALLOW("REGISTER"),
 					   NUTAG_ALLOW("REFER"),
+					   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW("PUBLISH")),
+					   TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ENABLEMESSAGE(1)),
 					   SIPTAG_SUPPORTED_STR("100rel, precondition"),
 					   SIPTAG_USER_AGENT_STR(SOFIA_USER_AGENT),
 					   TAG_END());
@@ -3217,10 +3382,6 @@
 	switch_mutex_init(&profile->ireg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
 	switch_mutex_init(&profile->oreg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
 
-	switch_mutex_lock(globals.mutex);
-	globals.running = 1;
-	switch_mutex_unlock(globals.mutex);
-
 	ireg_loops = IREG_SECONDS;
 	oreg_loops = OREG_SECONDS;
 
@@ -3230,6 +3391,45 @@
 		switch_event_fire(&s_event);
 	}
 
+	if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._tcp");
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
+		switch_event_fire(&s_event);
+	}
+
+	if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._sctp");
+		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
+		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,
+										   TAG_END());
+		profile->presence->sofia_private.presence = profile->presence;
+		nua_handle_bind(profile->presence->nh, &profile->presence->sofia_private);
+
+		nua_notifier(profile->presence->nh,
+					 NUTAG_URL(profile->url),
+					 SIPTAG_EXPIRES_STR("3600"),
+					 SIPTAG_FROM_STR(profile->url),
+					 //SIPTAG_EVENT_STR("presence"),
+					 SIPTAG_EVENT_STR("message-summary"),
+					 //SIPTAG_ALLOW_EVENTS_STR("message-summary"),
+					 SIPTAG_CONTENT_TYPE_STR("text/urllist"),
+					 //SIPTAG_CONTENT_TYPE_STR("application/pidf-partial+xml"),
+					 //SIPTAG_CONTENT_TYPE_STR("text/plain"),
+					 NUTAG_SUBSTATE(nua_substate_pending),
+					 TAG_END());
+
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating notifier for %s\n", profile->url);
+	}
+
 	while(globals.running == 1) {
 		if (++ireg_loops >= IREG_SECONDS) {
 			check_expire(profile, time(NULL));
@@ -3243,6 +3443,13 @@
 
 		su_root_step(profile->s_root, 1000);
 	}
+
+	/*
+	if (profile->presence && profile->presence->nh) {
+		nua_handle_destroy(profile->presence->nh);
+		profile->presence->nh = NULL;
+	}
+	*/
 	
 	if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) {
 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp");
@@ -3251,7 +3458,6 @@
 	}
 
 	su_root_destroy(profile->s_root);
-
 	pool = profile->pool;
 	switch_core_destroy_memory_pool(&pool);
 	switch_mutex_lock(globals.mutex);
@@ -3285,6 +3491,10 @@
 	sofia_profile_t *profile = NULL;
 	char url[512] = "";
 
+	switch_mutex_lock(globals.mutex);
+	globals.running = 1;
+	switch_mutex_unlock(globals.mutex);
+
 	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;
@@ -3367,6 +3577,10 @@
 						profile->sipdomain = switch_core_strdup(profile->pool, val);
 					} else if (!strcasecmp(var, "rtp-timer-name")) {
 						profile->timer_name = switch_core_strdup(profile->pool, val);
+					} else if (!strcasecmp(var, "manage-presence")) {
+						if (switch_true(val)) {
+							profile->pflags |= PFLAG_PRESENCE;
+						}
 					} else if (!strcasecmp(var, "auth-calls")) {
 						if (switch_true(val)) {
 							profile->pflags |= PFLAG_AUTH_CALLS;
@@ -3588,7 +3802,59 @@
 	}
 }
 
+static void msg_event_handler(switch_event_t *event)
+{
+	switch_hash_index_t *hi;
+	void *val;
+	sofia_profile_t *profile;
+	int open = 0;
+	char *from = switch_event_get_header(event, "from");
+	//char *status = switch_event_get_header(event, "status");
+	
+	switch(event->event_id) {
+	case SWITCH_EVENT_PRESENCE_IN:
+		open = 1;
+		break;
+	case SWITCH_EVENT_PRESENCE_OUT:
+		open = 0;
+		break;
+	default:
+		break;
+	}
 
+	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;
+		if (profile && profile->presence) {
+			char *url;
+			char *myfrom = strdup(from);
+			char *p;
+			for(p = myfrom; *p ; p++) {
+				if (*p == '@') {
+					*p = '!';
+				}
+			}
+			
+			url = switch_core_db_mprintf("sip:%s", myfrom);
+
+			nua_publish(profile->presence->nh,
+						SIPTAG_EVENT_STR("presence"),
+						SIPTAG_CONTENT_TYPE_STR("text/urllist"),
+						SIPTAG_PAYLOAD_STR(url),
+						TAG_NULL());
+
+			switch_safe_free(url);
+			switch_safe_free(myfrom);
+			
+		}
+		
+	}
+
+	
+
+}
+
+
 SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
 {
 
@@ -3614,7 +3880,20 @@
 
 	config_sofia(0);
 
+	if (switch_event_bind((char *) modname, SWITCH_EVENT_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY, msg_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
+		return SWITCH_STATUS_GENERR;
+	}
 
+	if (switch_event_bind((char *) modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, msg_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
+		return SWITCH_STATUS_GENERR;
+	}
+
+	if (switch_event_bind((char *) modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, msg_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
+		return SWITCH_STATUS_GENERR;
+	}
 
 	/* connect my internal structure to the blank pointer passed to me */
 	*module_interface = &sofia_module_interface;

Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c	(original)
+++ freeswitch/trunk/src/switch_core.c	Wed Oct 11 20:59:09 2006
@@ -50,6 +50,7 @@
 #endif
 
 #define SWITCH_EVENT_QUEUE_LEN 256
+#define SWITCH_MESSAGE_QUEUE_LEN 256
 #define SWITCH_SQL_QUEUE_LEN 2000
 
 #define SWITCH_BUFFER_BLOCK_FRAMES 25
@@ -105,6 +106,7 @@
 	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
 	void *private_info;
 	switch_queue_t *event_queue;
+	switch_queue_t *message_queue;
 	switch_queue_t *private_event_queue;
 	switch_thread_rwlock_t *bug_rwlock;
 	switch_media_bug_t *bugs;
@@ -1413,8 +1415,7 @@
 	return status;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session,
-																  switch_core_session_message_t *message)
+SWITCH_DECLARE(switch_status_t) switch_core_session_receive_message(switch_core_session_t *session, switch_core_session_message_t *message)
 {
 	switch_io_event_hook_receive_message_t *ptr;
 	switch_status_t status = SWITCH_STATUS_FALSE;
@@ -1429,11 +1430,44 @@
 				}
 			}
 		}
-	} 
+	}
+	return status;
+}
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_queue_message(switch_core_session_t *session, switch_core_session_message_t *message)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	assert(session != NULL);
+
+	if (!session->message_queue) {
+		switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
+	}
+
+	if (session->message_queue) {
+		if (switch_queue_trypush(session->message_queue, message) == SWITCH_STATUS_SUCCESS) {
+			status = SWITCH_STATUS_SUCCESS;
+		}
+	}
+
 	return status;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_session_t *session, switch_core_session_message_t **message)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	void *pop;
+
+	assert(session != NULL);
+	
+	if (session->message_queue) {
+		if ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
+			*message = (switch_core_session_message_t *) pop;
+		}
+	}
+
+	return status;
+}
 
 SWITCH_DECLARE(switch_status_t) switch_core_session_receive_event(switch_core_session_t *session, switch_event_t **event)
 	 

Modified: freeswitch/trunk/src/switch_event.c
==============================================================================
--- freeswitch/trunk/src/switch_event.c	(original)
+++ freeswitch/trunk/src/switch_event.c	Wed Oct 11 20:59:09 2006
@@ -123,6 +123,8 @@
 	"MODULE_LOAD",
 	"DTMF",
 	"MESSAGE",
+	"PRESENCE_IN",
+	"PRESENCE_OUT",
 	"CODEC",
 	"BACKGROUND_JOB",
 	"ALL"

Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c	(original)
+++ freeswitch/trunk/src/switch_ivr.c	Wed Oct 11 20:59:09 2006
@@ -1244,7 +1244,7 @@
 	int *stream_id_p;
 	int stream_id = 0, pre_b = 0, ans_a = 0, ans_b = 0, originator = 0;
 	switch_input_callback_function_t input_callback;
-	switch_core_session_message_t msg = {0};
+	switch_core_session_message_t *message, msg = {0};
 	void *user_data;
 
 	switch_channel_t *chan_a, *chan_b;
@@ -1297,62 +1297,65 @@
 			break;
 		}
 
-		if (!switch_channel_test_flag(chan_a, CF_HOLD)) {
-			
-			if (!ans_a && originator) {
-				if (!ans_b && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
-					switch_channel_answer(chan_a);
-					ans_a++;
-				} else if (!pre_b && switch_channel_test_flag(chan_b, CF_EARLY_MEDIA)) {
-					switch_channel_pre_answer(chan_a);
-					pre_b++;
+		if (switch_core_session_dequeue_private_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {
+			switch_channel_set_flag(chan_b, CF_HOLD);
+			switch_ivr_parse_event(session_a, event);
+			switch_channel_clear_flag(chan_b, CF_HOLD);
+			switch_event_destroy(&event);
+		}
+
+		/* if 1 channel has DTMF pass it to the other */
+		if (switch_channel_has_dtmf(chan_a)) {
+			char dtmf[128];
+			switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
+			switch_core_session_send_dtmf(session_b, dtmf);
+
+			if (input_callback) {
+				if (input_callback(session_a, dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
+					switch_mutex_lock(data->mutex);
+					data->running = -1;
+					switch_mutex_unlock(data->mutex);
+					break;
 				}
-				switch_yield(10000);
-				continue;
 			}
+		}
 
-			if (switch_core_session_dequeue_private_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {
-				switch_channel_set_flag(chan_b, CF_HOLD);
-				switch_ivr_parse_event(session_a, event);
-				switch_channel_clear_flag(chan_b, CF_HOLD);
-				switch_event_destroy(&event);
+		if (switch_core_session_dequeue_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {
+			if (input_callback) {
+				status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
 			}
 
-			/* if 1 channel has DTMF pass it to the other */
-			if (switch_channel_has_dtmf(chan_a)) {
-				char dtmf[128];
-				switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf));
-				switch_core_session_send_dtmf(session_b, dtmf);
-
-				if (input_callback) {
-					if (input_callback(session_a, dtmf, SWITCH_INPUT_TYPE_DTMF, user_data, 0) != SWITCH_STATUS_SUCCESS) {
-						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s ended call via DTMF\n", switch_channel_get_name(chan_a));
-						switch_mutex_lock(data->mutex);
-						data->running = -1;
-						switch_mutex_unlock(data->mutex);
-						break;
-					}
-				}
+			if (switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
+				switch_event_destroy(&event);
 			}
 
-			if (switch_core_session_dequeue_event(session_a, &event) == SWITCH_STATUS_SUCCESS) {
-				if (input_callback) {
-					status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
-				}
+		}
 
-				if (switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
-					switch_event_destroy(&event);
-				}
-
+		if (switch_core_session_dequeue_message(session_b, &message) == SWITCH_STATUS_SUCCESS) {
+			switch_core_session_receive_message(session_a, message);
+			if (switch_test_flag(message, SCSMF_DYNAMIC)) {
+				switch_safe_free(message);
 			}
+		}
  
+		if (!ans_a && originator) {
+			if (!ans_b && switch_channel_test_flag(chan_b, CF_ANSWERED)) {
+				switch_channel_answer(chan_a);
+				ans_a++;
+			} else if (!pre_b && switch_channel_test_flag(chan_b, CF_EARLY_MEDIA)) {
+				switch_channel_pre_answer(chan_a);
+				pre_b++;
+			}
+			switch_yield(10000);
+			continue;
 		}
 
 		/* read audio from 1 channel and write it to the other */
 		status = switch_core_session_read_frame(session_a, &read_frame, -1, stream_id);
 
 		if (SWITCH_READ_ACCEPTABLE(status)) {
-			if (status != SWITCH_STATUS_BREAK) {
+			if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD)) {
 				if (switch_core_session_write_frame(session_b, read_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write: %s Bad Frame....[%u] Bubye!\n",
 									  switch_channel_get_name(chan_b), read_frame->datalen);
@@ -1367,10 +1370,7 @@
 			data->running = -1;
 			switch_mutex_unlock(data->mutex);
 		}
-
-		//switch_yield(1000);
 	}
-
 	
 	msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE;
 	msg.from = __FILE__;
@@ -1968,6 +1968,15 @@
 		while ((!caller_channel || switch_channel_ready(caller_channel)) && 
 			   check_channel_status(peer_channels, peer_sessions, and_argc, &idx, file, key) && ((time(NULL) - start) < (time_t)timelimit_sec)) {
 
+			if (or_argc == 1 && and_argc == 1) { /* when there is only 1 channel to call and bridge */
+				switch_core_session_message_t *message = NULL;
+				if (switch_core_session_dequeue_message(peer_sessions[0], &message) == SWITCH_STATUS_SUCCESS) {
+					switch_core_session_receive_message(session, message);
+					if (switch_test_flag(message, SCSMF_DYNAMIC)) {
+						switch_safe_free(message);
+					}
+				}
+			}
 
 			/* read from the channel while we wait if the audio is up on it */
 			if (session && !switch_channel_test_flag(caller_channel, CF_NOMEDIA) && 



More information about the Freeswitch-svn mailing list