Index: src/mod/endpoints/mod_sofia/mod_sofia.c
===================================================================
--- src/mod/endpoints/mod_sofia/mod_sofia.c	(revision 3059)
+++ src/mod/endpoints/mod_sofia/mod_sofia.c	(working copy)
@@ -24,6 +24,7 @@
  * Contributor(s):
  * 
  * Anthony Minessale II <anthmct@yahoo.com>
+ * Ken Rice, Asteria Solutions Group, Inc <ken@asteriasgi.com>
  *
  *
  * mod_sofia.c -- SOFIA SIP Endpoint
@@ -66,8 +67,8 @@
 #define MULTICAST_EVENT "multicast::event"
 #define SOFIA_REPLACES_HEADER "_sofia_replaces_"
 #define SOFIA_USER_AGENT "FreeSWITCH(mod_sofia)"
+#define SIP_KEY 2
 
-
 #include <sofia-sip/nua.h>
 #include <sofia-sip/sip_status.h>
 #include <sofia-sip/sdp.h>
@@ -251,6 +252,8 @@
 	outbound_reg_t *registrations;
 	sip_presence_t *presence;
 	su_home_t *home;
+	switch_hash_t *profile_hash;
+	switch_hash_t *chat_hash;
 };
 
 
@@ -296,6 +299,9 @@
 	char *xferto;
 	char *kick;
 	char *origin;
+	char *hash_key;
+	char *chat_from;
+	char *chat_to;
 	unsigned long rm_rate;
 	switch_payload_t pt;
 	switch_mutex_t *flag_mutex;
@@ -982,6 +988,7 @@
 
 	tech_pvt->read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
 
+
 	switch_channel_set_variable(channel, "endpoint_disposition", "INIT");
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SOFIA INIT\n");
 
@@ -1113,6 +1120,9 @@
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s hanging up, cause: %s\n", 
 			  switch_channel_get_name(channel), switch_channel_cause2str(cause), sip_cause);
 
+	if (tech_pvt->hash_key) {
+		switch_core_hash_delete(tech_pvt->profile->chat_hash, tech_pvt->hash_key);
+	}
 
 	if (tech_pvt->kick && (asession = switch_core_session_locate(tech_pvt->kick))) {
 		switch_channel_t *a_channel = switch_core_session_get_channel(asession);
@@ -1714,6 +1724,44 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t sofia_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+	switch_channel_t *channel;
+    struct private_object *tech_pvt;
+	char *body;
+	nua_handle_t *msg_nh;
+
+    channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+    tech_pvt = switch_core_session_get_private(session);
+    assert(tech_pvt != NULL);
+
+
+	if (!(body = switch_event_get_body(event))) {
+		body = "";
+	}
+
+
+	printf("WTF [%s][%s][%s]\n", tech_pvt->chat_from, tech_pvt->chat_to, body);
+	if (tech_pvt->hash_key) {
+		msg_nh = nua_handle(tech_pvt->profile->nua, NULL,
+							SIPTAG_FROM_STR(tech_pvt->chat_from),
+							NUTAG_URL(tech_pvt->chat_to),
+							SIPTAG_TO_STR(tech_pvt->chat_to),
+							SIPTAG_CONTACT_STR(tech_pvt->profile->url),
+							TAG_END());
+
+
+		nua_message(msg_nh,
+					SIPTAG_CONTENT_TYPE_STR("text/html"),
+					SIPTAG_PAYLOAD_STR(body),
+					TAG_END());
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 static const switch_io_routines_t sofia_io_routines = {
 	/*.outgoing_channel */ sofia_outgoing_channel,
 	/*.answer_channel */ sofia_answer_channel,
@@ -1723,7 +1771,8 @@
 	/*.waitfor_read */ sofia_waitfor_read,
 	/*.waitfor_read */ sofia_waitfor_write,
 	/*.send_dtmf*/ sofia_send_dtmf,
-	/*.receive_message*/ sofia_receive_message
+	/*.receive_message*/ sofia_receive_message,
+	/*.receive_event*/ sofia_receive_event
 };
 
 static const switch_state_handler_table_t sofia_event_handlers = {
@@ -1976,6 +2025,58 @@
 	}
 }
 
+
+static void set_hash_key(char *hash_key, int32_t len, sip_t const *sip, int flip)
+{
+	if (flip) {
+		snprintf(hash_key, len, "%s%s%s%s%s%s",
+				 (char *) sip->sip_from->a_url->url_user,
+				 (char *) sip->sip_from->a_url->url_host,
+				 (char *) sip->sip_from->a_url->url_params,
+
+				 (char *) sip->sip_to->a_url->url_user,
+				 (char *) sip->sip_to->a_url->url_host,
+				 (char *) sip->sip_to->a_url->url_params
+				 );	
+
+	} else {
+		snprintf(hash_key, len, "%s%s%s%s%s%s",
+				 (char *) sip->sip_to->a_url->url_user,
+				 (char *) sip->sip_to->a_url->url_host,
+				 (char *) sip->sip_to->a_url->url_params,
+				 
+				 (char *) sip->sip_from->a_url->url_user,
+				 (char *) sip->sip_from->a_url->url_host,
+				 (char *) sip->sip_from->a_url->url_params
+				 );	
+	}
+}
+
+static void set_chat_hash(private_object_t *tech_pvt, sip_t const *sip)
+{
+	char hash_key[256] = "";
+	char buf[512];
+
+	if (!sip || tech_pvt->hash_key) {
+		return;
+	}
+
+	if (find_reg_url(tech_pvt->profile, (char *) sip->sip_from->a_url->url_user, (char *) sip->sip_from->a_url->url_host, buf, sizeof(buf))) {
+		tech_pvt->chat_from = sip_header_as_string(tech_pvt->home, (void *)sip->sip_to);
+		tech_pvt->chat_to = switch_core_session_strdup(tech_pvt->session, buf);
+		set_hash_key(hash_key, sizeof(hash_key), sip, 0);
+	} else {
+		return;
+	}
+
+	
+
+	tech_pvt->hash_key = switch_core_session_strdup(tech_pvt->session, hash_key);
+	switch_core_hash_insert(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt);
+
+}
+
+
 static void sip_i_message(int status,
 						char const *phrase, 
 						nua_t *nua,
@@ -1995,7 +2096,7 @@
 		sip_subject_t const *sip_subject = sip->sip_subject;
 		sip_payload_t *payload = sip->sip_payload;
 		const char *subject = "n/a";
-		char *msg = "";
+		char *msg = NULL;
 
 		if (strstr((char*)sip->sip_content_type->c_subtype, "composing")) {
 			return;
@@ -2020,34 +2121,34 @@
 		}
 
 		if (nh) {			
-			char *message = "<b>hello world</b>";
-			char buf[256] = "";
+			char hash_key[512];
+			private_object_t *tech_pvt;
+			switch_channel_t *channel;
 
-			if (find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
-				nua_handle_t *msg_nh;
+			set_hash_key(hash_key, sizeof(hash_key), sip, 0);
+			if ((tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) {
+				switch_event_t *event;
 
-
-				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/html"),
-							TAG_IF(message,
-								   SIPTAG_PAYLOAD_STR(message)),
-							TAG_END());
-
+				channel = switch_core_session_get_channel(tech_pvt->session);
+				if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == 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", tech_pvt->hash_key);
+					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
+					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);
+					}
+				}
 			}
-			
 		} 
-		//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,
@@ -2089,6 +2190,8 @@
 		
 		tech_pvt->nh = nh;
 		
+		
+
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s entering state [%s]\n", 
 						  switch_channel_get_name(channel),
 						  nua_callstate_name(ss_state));
@@ -2097,6 +2200,7 @@
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp);			
 			tech_pvt->remote_sdp_str = switch_core_session_strdup(session, (char *)r_sdp);
 			switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, (char *) r_sdp);
+
 		}
 	}
 
@@ -2201,7 +2305,6 @@
 					if (match) {
 						nua_handle_t *bnh;
 						sip_replaces_t *replaces;
-					
 						switch_channel_set_variable(channel, "endpoint_disposition", "RECEIVED");
 						switch_channel_set_state(channel, CS_INIT);
 						switch_set_flag_locked(tech_pvt, TFLAG_READY);
@@ -2447,14 +2550,22 @@
 	uint8_t stale = 0, ret = 0, forbidden = 0;
 	auth_res_t auth_res;
 	long exptime = 60;
+	switch_event_t *event;
 
+
+	
+
 	if (sip->sip_contact) {
+		char *port = (char *) contact->m_url->url_port;
+		if (!port) {
+			port = "5060";
+		}
 		if (contact->m_url->url_params) {
 			snprintf(contact_str, sizeof(contact_str), "sip:%s@%s:%s;%s", 
-					 contact->m_url->url_user, contact->m_url->url_host, contact->m_url->url_port, contact->m_url->url_params);
+					 contact->m_url->url_user, contact->m_url->url_host, port, contact->m_url->url_params);
 		} else {
 			snprintf(contact_str, sizeof(contact_str), "sip:%s@%s:%s", 
-					 contact->m_url->url_user, contact->m_url->url_host, contact->m_url->url_port);
+					 contact->m_url->url_user, contact->m_url->url_host, port);
 		}
 	}
 	
@@ -2623,6 +2734,21 @@
 					  (long)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, "from", "%s@%s", 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);
+	}
+
+
 	if (regtype == REG_REGISTER) {
 		nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact),
 					NUTAG_WITH_THIS(nua),
@@ -2667,14 +2793,19 @@
 			}
 
 			if (contact) {
+				char *port = (char *) contact->m_url->url_port;
+				if (!port) {
+					port = "5060";
+				}
+
 				if (contact->m_url->url_params) {
 					contact_str = switch_core_db_mprintf("sip:%s@%s:%s;%s", 
 														 contact->m_url->url_user,
-														 contact->m_url->url_host, contact->m_url->url_port, contact->m_url->url_params);
+														 contact->m_url->url_host, port, contact->m_url->url_params);
 				} else {
 					contact_str = switch_core_db_mprintf("sip:%s@%s:%s", 
 														 contact->m_url->url_user,
-														 contact->m_url->url_host, contact->m_url->url_port);
+														 contact->m_url->url_host, port);
 				}
 			}
 			
@@ -3095,8 +3226,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@%s", from_user, from_host);
-						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", status_txt);
-						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "%s", note_txt);
+						
+						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);
 					}
@@ -3105,6 +3237,7 @@
 						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", from_user, from_host);
+
 						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_type", "%s", event_type);
 						switch_event_fire(&event);
 					}
@@ -3213,11 +3346,14 @@
 				return;
 			}
 
+
 			attach_private(session, profile, tech_pvt, username);
 
 			channel = switch_core_session_get_channel(session);
 			switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
+			set_chat_hash(tech_pvt, sip);
 			
+			
 			if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
 																	  (char *) from->a_url->url_user,
 																	  profile->dialplan,
@@ -3357,6 +3493,9 @@
 			
 			return;
 		}
+		if (tech_pvt) {
+			set_chat_hash(tech_pvt, sip);
+		}
 	}
 	
 	if (!oreg) {
@@ -3851,6 +3990,7 @@
 				profile->name = switch_core_strdup(profile->pool, xprofilename);
 				snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename);
 				profile->dbname = switch_core_strdup(profile->pool, url);
+				switch_core_hash_init(&profile->chat_hash, profile->pool);
 
 				profile->dtmf_duration = 100;		
 				profile->codec_ms = 20;
@@ -4044,6 +4184,7 @@
 							}
 							oreg->next = profile->registrations;
 							profile->registrations = oreg;
+
 						}
 					}
 				}
@@ -4207,6 +4348,36 @@
 	char *resource;
 	switch_core_db_t *db;
 
+	if (event->key == SIP_KEY) {
+		return;
+	}
+
+	if (event->event_id == SWITCH_EVENT_ROSTER) {
+		sql = switch_core_db_mprintf("select 1,'%q',* from sip_subscriptions where event='presence'", status ? status : "Available");
+
+		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->pflags & PFLAG_PRESENCE)) {
+				continue;
+			}
+
+			if (sql) {
+				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);
+					continue;
+				}
+				switch_mutex_lock(profile->ireg_mutex);
+				switch_core_db_exec(db, sql, sub_callback, profile, &errmsg);
+				switch_mutex_unlock(profile->ireg_mutex);
+				switch_core_db_close(db);
+			}
+
+		}
+
+		return;
+	}
+
 	if (status && !strcasecmp(status, "n/a")) {
 		status = show;
 		if (status && !strcasecmp(status, "n/a")) {
@@ -4323,6 +4494,11 @@
 		return SWITCH_STATUS_GENERR;
 	}
 
+	if (switch_event_bind((char *) modname, SWITCH_EVENT_ROSTER, 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;
 
Index: src/mod/endpoints/mod_dingaling/mod_dingaling.c
===================================================================
--- src/mod/endpoints/mod_dingaling/mod_dingaling.c	(revision 3059)
+++ src/mod/endpoints/mod_dingaling/mod_dingaling.c	(working copy)
@@ -34,8 +34,8 @@
 
 #define DL_CAND_WAIT 10000000
 #define DL_CAND_INITIAL_WAIT 2000000
+#define JINGLE_KEY 1
 
-
 #define DL_EVENT_LOGIN_SUCCESS "dingaling::login_success"
 #define DL_EVENT_LOGIN_FAILURE "dingaling::login_failure"
 #define DL_EVENT_CONNECTED "dingaling::connected"
@@ -44,6 +44,13 @@
 
 static switch_memory_pool_t *module_pool = NULL;
 
+static char sub_sql[] =
+"CREATE TABLE subscriptions (\n"
+"   sub_from            VARCHAR(255),\n"
+"   sub_to          VARCHAR(255)\n"
+");\n";
+
+
 typedef enum {
 	TFLAG_IO = (1 << 0),
 	TFLAG_INBOUND = (1 << 1),
@@ -104,6 +111,8 @@
     char *exten;
     char *context;
 	char *timer_name;
+	char *dbname;
+	switch_mutex_t *mutex;
     ldl_handle_t *handle;
     uint32_t flags;
     uint32_t user_flags;
@@ -173,11 +182,192 @@
 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout,
 										   switch_io_flag_t flags, int stream_id);
 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
-static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *from, char *subject, char *msg);
+static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *to, char *from, char *subject, char *msg);
 static ldl_status handle_response(ldl_handle_t *handle, char *id);
 static switch_status_t load_config(void);
 
 
+static int sub_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+	struct mdl_profile *profile = (struct mdl_profile *) pArg;
+
+	char *sub_from = argv[0];
+	char *sub_to = argv[1];
+	char *type = argv[2];
+	char *show = argv[3];
+
+	if (switch_strlen_zero(type)) {
+		type = NULL;
+	}
+
+	ldl_handle_send_presence(profile->handle, sub_to, sub_from, type, show);
+
+	return 0;
+}
+
+static int rost_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+	struct mdl_profile *profile = (struct mdl_profile *) pArg;
+
+	char *sub_from = argv[0];
+	char *sub_to = argv[1];
+	char *show = argv[2];
+
+	ldl_handle_send_presence(profile->handle, sub_to, sub_from, NULL, show);
+
+	return 0;
+}
+
+static void pres_event_handler(switch_event_t *event)
+{
+	struct mdl_profile *profile = NULL;
+	switch_hash_index_t *hi;
+    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 *sql;
+	switch_core_db_t *db;
+	char *p;
+
+	if (event->key == JINGLE_KEY) {
+		return;
+	}
+
+	if (status && !strcasecmp(status, "n/a")) {
+		status = show;
+		if (status && !strcasecmp(status, "n/a")) {
+			status = NULL;
+		}
+	}
+
+
+
+	switch(event->event_id) {
+	case SWITCH_EVENT_PRESENCE_IN:
+		if (!status) {
+			status = "Available";
+		}
+		break;
+	case SWITCH_EVENT_PRESENCE_OUT:
+		type = "unavailable";
+		break;
+	default:
+		break;
+	}
+	
+
+
+	if ((p = strchr(from, '/'))) {
+		*p = '\0';
+	}
+	
+	sql = switch_core_db_mprintf("select *,'%q','%q' from subscriptions where sub_to='%q'", type ? type : "", status, from);
+
+	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 = (struct mdl_profile *) val;
+		char *errmsg;
+
+        if (!(profile->user_flags & LDL_FLAG_COMPONENT)) {
+			continue;
+        }
+
+
+		if (sql) {
+			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);
+				continue;
+			}
+			switch_mutex_lock(profile->mutex);
+			switch_core_db_exec(db, sql, sub_callback, profile, &errmsg);
+			switch_mutex_unlock(profile->mutex);
+			switch_core_db_close(db);
+		}
+		
+
+	}
+
+	switch_safe_free(sql);
+}
+
+
+static void roster_event_handler(switch_event_t *event)
+{
+	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 *event_type = switch_event_get_header(event, "event_type");
+	char *user, *host, *resource;
+	struct mdl_profile *profile = NULL;
+	switch_hash_index_t *hi;
+    void *val;
+	char *sql;
+	switch_core_db_t *db;
+
+	if (event->key == JINGLE_KEY) {
+		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";
+	}
+
+	if ((user = strdup(from))) {
+		if ((host = strchr(user, '@'))) {
+			*host++ = '\0';
+		}
+		if ((resource = strchr(host, '/'))) {
+			*resource++ = '\0';
+		}
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
+		return;
+	}
+
+	if (!host) {
+		switch_safe_free(user);
+		return;
+	}
+	
+	sql = switch_core_db_mprintf("select *,'%q' from subscriptions", show);
+
+	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 = (struct mdl_profile *) val;
+		char *errmsg;
+
+        if (!(profile->user_flags & LDL_FLAG_COMPONENT)) {
+			continue;
+        }
+
+
+		if (sql) {
+			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);
+				continue;
+			}
+			switch_mutex_lock(profile->mutex);
+			switch_core_db_exec(db, sql, rost_callback, profile, &errmsg);
+			switch_mutex_unlock(profile->mutex);
+			switch_core_db_close(db);
+		}
+		
+	}
+
+	switch_safe_free(sql);
+	switch_safe_free(user);
+
+}
+
 static void terminate_session(switch_core_session_t **session, int line, switch_call_cause_t cause)
 {
 	if (*session) {
@@ -645,7 +835,7 @@
 
 	tech_pvt = switch_core_session_get_private(session);
 	assert(tech_pvt != NULL);
-
+	
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL RING\n", switch_channel_get_name(channel));
 
 	return SWITCH_STATUS_SUCCESS;
@@ -1079,6 +1269,7 @@
 		char sess_id[11] = "";
 		char *dnis = NULL;
 		char workspace[1024] = "";
+		char *p, *u, ubuf[512] = "", *user = NULL;;
 		
 		switch_copy_string(workspace, outbound_profile->destination_number, sizeof(workspace));
 		profile_name = workspace;
@@ -1094,13 +1285,23 @@
 			*dnis++ = '\0';
 		}
 
+		if ((p = strchr(profile_name, '@'))) {
+			*p++ = '\0';
+			u = profile_name;
+			profile_name = p;
+			snprintf(ubuf, sizeof(ubuf), "%s@%s/talk", u, profile_name);
+			user = ubuf;
+		} else {
+			user = mdl_profile->login;
+		}
+
 		if ((mdl_profile = switch_core_hash_find(globals.profile_hash, profile_name))) {
 			if (!ldl_handle_ready(mdl_profile->handle)) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doh! we are not logged in yet!\n");
 				terminate_session(new_session,  __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 				return SWITCH_STATUS_GENERR;
 			}
-			if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, idbuf, sizeof(idbuf)))) {
+			if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, user, idbuf, sizeof(idbuf)))) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unknown Recipient!\n");
 				terminate_session(new_session,  __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 				return SWITCH_STATUS_GENERR;
@@ -1151,7 +1352,7 @@
 		
 		switch_stun_random_string(sess_id, 10, "0123456789");
 
-		ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, mdl_profile->login);
+		ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, user);
 		tech_pvt->profile = mdl_profile;
 		ldl_session_set_private(dlsession, *new_session);
 		ldl_session_set_value(dlsession, "dnis", dnis);
@@ -1195,7 +1396,21 @@
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!", DL_EVENT_CONNECTED);
 		return SWITCH_STATUS_GENERR;
 	}
+	
+	if (switch_event_bind((char *) modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, pres_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, pres_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_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, roster_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 = &channel_module_interface;
 
@@ -1323,6 +1538,25 @@
 		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;
@@ -1510,8 +1744,29 @@
 }
 
 
+static void execute_sql(char *dbname, char *sql, switch_mutex_t *mutex)
+{
+	switch_core_db_t *db;
 
-static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *from, char *subject, char *msg)
+	if (mutex) {
+		switch_mutex_lock(mutex);
+	}
+
+	if (!(db = switch_core_db_open_file(dbname))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", dbname);
+		goto end;
+	}
+	
+	switch_core_db_persistant_execute(db, sql, 25);
+	switch_core_db_close(db);
+
+ end:
+	if (mutex) {
+		switch_mutex_unlock(mutex);
+	}
+}
+
+static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsession, ldl_signal_t signal, char *to, char *from, char *subject, char *msg)
 {
 	struct mdl_profile *profile = NULL;
 	switch_core_session_t *session = NULL;
@@ -1519,7 +1774,8 @@
     struct private_object *tech_pvt = NULL;
 	switch_event_t *event;
 	ldl_status status = LDL_STATUS_SUCCESS;
-	
+	char *sql;
+
 	assert(handle != NULL);
 
 	if (!(profile = ldl_handle_get_private(handle))) {
@@ -1530,6 +1786,22 @@
 
 	if (!dlsession) {
 		switch(signal) {
+		case LDL_SIGNAL_SUBSCRIBE:
+			if ((profile->user_flags & LDL_FLAG_COMPONENT)) {
+
+				if ((sql = switch_core_db_mprintf("insert into subscriptions values('%q','%q')", from, to))) {
+					execute_sql(profile->dbname, sql, profile->mutex);
+					switch_core_db_free(sql);
+				}
+			}
+			break;
+		case LDL_SIGNAL_ROSTER:
+			if (switch_event_create(&event, SWITCH_EVENT_ROSTER) == SWITCH_STATUS_SUCCESS) {
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "proto", "jingle");
+				event->key = JINGLE_KEY;
+				switch_event_fire(&event);
+			}
+			break;
 		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, "proto", "jingle");
@@ -1537,14 +1809,17 @@
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "status", "%s", subject);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "show", "%s", msg);
+				event->key = JINGLE_KEY;
 				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, "proto", "jingle");
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "login", "%s", profile->login);
 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s", from);
+				event->key = JINGLE_KEY;
 				switch_event_fire(&event);
 			}
 			break;
@@ -1554,12 +1829,13 @@
 				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, "subject", "%s", subject);
+				event->key = JINGLE_KEY;
 				if (msg) {
 					switch_event_add_body(event, msg);
 				}
 
 				if (profile->auto_reply) {
-					ldl_handle_send_msg(handle, from, "", profile->auto_reply);
+					ldl_handle_send_msg(handle, profile->login, from, "", profile->auto_reply);
 				}
 
 				switch_event_fire(&event);
@@ -1803,6 +2079,7 @@
 						char *context;
 						char *cid_name;
 						char *cid_num;
+						char *t, *them = NULL;
 
 						memset(payloads, 0, sizeof(payloads));
 
@@ -1814,6 +2091,18 @@
 
 						if (!(exten = ldl_session_get_value(dlsession, "dnis"))) {
 							exten = profile->exten;
+							if (!strcmp(exten, "_auto_")) {
+								if ((t = ldl_session_get_callee(dlsession))) {
+									if ((them = strdup(t))) {
+										char *p;
+										if ((p = strchr(them, '/'))) {
+											*p = '\0';
+										}
+										exten = them;
+									}
+								}
+								
+							}
 						}
 			
 						if (!(context = ldl_session_get_value(dlsession, "context"))) {
@@ -1851,6 +2140,8 @@
 							}
 						}
 
+						switch_safe_free(them);
+						
 						if (lanaddr) {
 							switch_set_flag_locked(tech_pvt, TFLAG_LANADDR);
 						}
Index: src/include/switch_event.h
===================================================================
--- src/include/switch_event.h	(revision 3059)
+++ src/include/switch_event.h	(working copy)
@@ -97,6 +97,8 @@
 	void *bind_user_data;
 	/*! user data from the event sender */
 	void *event_user_data;
+	/*! unique key */
+	unsigned long key;
 	struct switch_event *next;
 };
 
Index: src/include/switch_core.h
===================================================================
--- src/include/switch_core.h	(revision 3059)
+++ src/include/switch_core.h	(working copy)
@@ -841,6 +841,7 @@
   \brief Initialize a codec handle
   \param codec the handle to initilize
   \param codec_name the name of the codec module to use
+  \param fmtp codec parameters to send
   \param rate the desired rate (0 for any)
   \param ms the desired number of milliseconds (0 for any)
   \param channels the desired number of channels (0 for any)
Index: src/include/switch_types.h
===================================================================
--- src/include/switch_types.h	(revision 3059)
+++ src/include/switch_types.h	(working copy)
@@ -659,6 +659,7 @@
 	SWITCH_EVENT_MESSAGE,
 	SWITCH_EVENT_PRESENCE_IN,
 	SWITCH_EVENT_PRESENCE_OUT,
+	SWITCH_EVENT_ROSTER,
 	SWITCH_EVENT_CODEC,
 	SWITCH_EVENT_BACKGROUND_JOB,
 	SWITCH_EVENT_ALL
Index: src/include/switch_rtp.h
===================================================================
--- src/include/switch_rtp.h	(revision 3059)
+++ src/include/switch_rtp.h	(working copy)
@@ -72,6 +72,7 @@
   \param ms_per_packet time in microseconds per packet
   \param flags flags to control behaviour
   \param crypto_key optional crypto key
+  \param timer_name timer interface to use
   \param err a pointer to resolve error messages
   \param pool a memory pool to use for the session
   \return the new RTP session or NULL on failure
@@ -98,6 +99,7 @@
   \param ms_per_packet time in microseconds per packet
   \param flags flags to control behaviour
   \param crypto_key optional crypto key
+  \param timer_name timer interface to use
   \param err a pointer to resolve error messages
   \param pool a memory pool to use for the session
   \return the new RTP session or NULL on failure
Index: src/switch_event.c
===================================================================
--- src/switch_event.c	(revision 3059)
+++ src/switch_event.c	(working copy)
@@ -125,6 +125,7 @@
 	"MESSAGE",
 	"PRESENCE_IN",
 	"PRESENCE_OUT",
+	"ROSTER",
 	"CODEC",
 	"BACKGROUND_JOB",
 	"ALL"
@@ -587,6 +588,8 @@
 		(*event)->body = DUP(todup->body);
 	}
 
+	(*event)->key = todup->key;
+
 	return SWITCH_STATUS_SUCCESS;
 }
 
Index: src/switch_core.c
===================================================================
--- src/switch_core.c	(revision 3059)
+++ src/switch_core.c	(working copy)
@@ -1315,19 +1315,19 @@
 
 	if (endpoint_interface->io_routines->outgoing_channel) {
 		if (session) {
-			char *ecaller_id_name = NULL, *ecaller_id_number = NULL;
 			channel = switch_core_session_get_channel(session);
+			if (caller_profile) {			
+				char *ecaller_id_name = NULL, *ecaller_id_number = NULL;
+
+				ecaller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name");
+				ecaller_id_number = switch_channel_get_variable(channel, "effective_caller_id_number");
 			
-			ecaller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name");
-			ecaller_id_number = switch_channel_get_variable(channel, "effective_caller_id_number");
-			
-			if (ecaller_id_name || ecaller_id_number) {
-				if (caller_profile) {
+				if (ecaller_id_name || ecaller_id_number) {
 					outgoing_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
 																 caller_profile->username,
 																 caller_profile->dialplan,
-																 ecaller_id_name ? ecaller_id_name : caller_profile->caller_id_name,
-																 ecaller_id_number ? ecaller_id_number : caller_profile->caller_id_number,
+																 ecaller_id_name,
+																 ecaller_id_number,
 																 caller_profile->network_addr,
 																 caller_profile->ani,
 																 caller_profile->ani2, 
@@ -1336,8 +1336,11 @@
 																 caller_profile->context,
 																 caller_profile->destination_number);
 					outgoing_profile->flags = caller_profile->flags;
-				}
+				} 
 			}
+			if (!outgoing_profile) {
+				outgoing_profile = switch_channel_get_caller_profile(channel);
+			}
 		}
 		
 		if ((status = endpoint_interface->io_routines->outgoing_channel(session,
@@ -1361,14 +1364,13 @@
 
 	if (*new_session) {
 		switch_caller_profile_t *profile = NULL, *peer_profile = NULL, *cloned_profile = NULL;
-		switch_channel_t *peer_channel = NULL;
 		switch_event_t *event;
-		switch_channel_t *new_channel = switch_core_session_get_channel(*new_session);
+		switch_channel_t *peer_channel = switch_core_session_get_channel(*new_session);
 
 		if (session && channel) {
 			profile = switch_channel_get_caller_profile(channel);
 		}
-		if ((peer_channel = switch_core_session_get_channel(*new_session)) != 0) {
+		if (peer_channel) {
 			peer_profile = switch_channel_get_caller_profile(peer_channel);
 		}
 
@@ -1386,7 +1388,7 @@
 		}
 
 		if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_OUTGOING) == SWITCH_STATUS_SUCCESS) {
-			switch_channel_event_set_data(new_channel, event);
+			switch_channel_event_set_data(peer_channel, event);
 			switch_event_fire(&event);
 		}
 	}
Index: src/switch_ivr.c
===================================================================
--- src/switch_ivr.c	(revision 3059)
+++ src/switch_ivr.c	(working copy)
@@ -1823,6 +1823,7 @@
 															   caller_caller_profile->source,
 															   caller_caller_profile->context,
 															   chan_data);
+				caller_profiles[i]->flags = caller_caller_profile->flags;
 				pool = NULL;
 			} else {
 				if (!cid_name_override) {
Index: libs/libdingaling/configure
===================================================================
--- libs/libdingaling/configure	(revision 3059)
+++ libs/libdingaling/configure	(working copy)
@@ -1947,6 +1947,8 @@
 
 
 
+          ac_config_headers="$ac_config_headers src/config.h"
+
 #AC_CONFIG_HEADER([])
 
 # Checks for programs.
@@ -3689,7 +3691,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 3692 "configure"' > conftest.$ac_ext
+  echo '#line 3694 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5268,7 +5270,7 @@
 
 
 # Provide some information about the compiler.
-echo "$as_me:5271:" \
+echo "$as_me:5273:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -6366,11 +6368,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6369: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6371: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6373: \$? = $ac_status" >&5
+   echo "$as_me:6375: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6628,11 +6630,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6631: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6633: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6635: \$? = $ac_status" >&5
+   echo "$as_me:6637: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6690,11 +6692,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6693: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6695: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:6697: \$? = $ac_status" >&5
+   echo "$as_me:6699: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8938,7 +8940,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8941 "configure"
+#line 8943 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -9036,7 +9038,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 9039 "configure"
+#line 9041 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11291,11 +11293,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11294: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11296: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:11298: \$? = $ac_status" >&5
+   echo "$as_me:11300: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -11353,11 +11355,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11356: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11358: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:11360: \$? = $ac_status" >&5
+   echo "$as_me:11362: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12730,7 +12732,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 12733 "configure"
+#line 12735 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12828,7 +12830,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 12831 "configure"
+#line 12833 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13713,11 +13715,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13716: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13718: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13720: \$? = $ac_status" >&5
+   echo "$as_me:13722: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13775,11 +13777,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13778: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13780: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13782: \$? = $ac_status" >&5
+   echo "$as_me:13784: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15905,11 +15907,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15908: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15910: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15912: \$? = $ac_status" >&5
+   echo "$as_me:15914: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16167,11 +16169,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16170: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16172: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16174: \$? = $ac_status" >&5
+   echo "$as_me:16176: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16229,11 +16231,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16232: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16234: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:16236: \$? = $ac_status" >&5
+   echo "$as_me:16238: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -18477,7 +18479,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 18480 "configure"
+#line 18482 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18575,7 +18577,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 18578 "configure"
+#line 18580 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -21107,6 +21109,251 @@
 
 #AC_CHECK_FUNCS([gethostname gettimeofday localtime_r memmove memset socket strcasecmp strchr strdup strncasecmp strstr])
 
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+main ()
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define __BYTE_ORDER __BIG_ENDIAN
+_ACEOF
+ ;;
+  no)
+
+cat >>confdefs.h <<\_ACEOF
+#define __BYTE_ORDER __LITTLE_ENDIAN
+_ACEOF
+ ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define __LITTLE_ENDIAN 1234
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define __BIG_ENDIAN 4321
+_ACEOF
+
+
           ac_config_files="$ac_config_files Makefile"
 
 
@@ -21184,39 +21431,8 @@
 }'
 fi
 
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
-t quote
-s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
+DEFS=-DHAVE_CONFIG_H
 
-
 ac_libobjs=
 ac_ltlibobjs=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
@@ -21570,10 +21786,15 @@
       --recheck    update $as_me by reconfiguring in the same conditions
   --file=FILE[:TEMPLATE]
 		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
 
 Configuration files:
 $config_files
 
+Configuration headers:
+$config_headers
+
 Configuration commands:
 $config_commands
 
@@ -21694,6 +21915,7 @@
   # Handling of arguments.
   "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
   "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+  "src/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
    { (exit 1); exit 1; }; };;
@@ -21706,6 +21928,7 @@
 # bizarre bug on SunOS 4.1.3.
 if $ac_need_defaults; then
   test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
   test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
 fi
 
@@ -22086,6 +22309,251 @@
 cat >>$CONFIG_STATUS <<\_ACEOF
 
 #
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
+ac_dB='[	 ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X$ac_file : 'X\(//\)[^/]' \| \
+	 X$ac_file : 'X\(//\)$' \| \
+	 X$ac_file : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X$ac_file |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`/stamp-h$_am_stamp_count
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
 # CONFIG_COMMANDS section.
 #
 for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
Index: libs/libdingaling/Makefile.in
===================================================================
--- libs/libdingaling/Makefile.in	(revision 3059)
+++ libs/libdingaling/Makefile.in	(working copy)
@@ -39,9 +39,9 @@
 host_triplet = @host@
 DIST_COMMON = README $(am__configure_deps) $(library_include_HEADERS) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-	$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
-	compile config.guess config.sub depcomp install-sh ltmain.sh \
-	missing mkinstalldirs
+	$(top_srcdir)/configure $(top_srcdir)/src/config.h.in AUTHORS \
+	COPYING ChangeLog INSTALL NEWS compile config.guess config.sub \
+	depcomp install-sh ltmain.sh missing mkinstalldirs
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.in
@@ -50,6 +50,7 @@
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno configure.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
 CONFIG_CLEAN_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -62,9 +63,10 @@
 libLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libdingaling_la_LIBADD =
-am_libdingaling_la_OBJECTS = libdingaling_la-libdingaling.lo
+am_libdingaling_la_OBJECTS = libdingaling_la-libdingaling.lo \
+	libdingaling_la-sha1.lo
 libdingaling_la_OBJECTS = $(am_libdingaling_la_OBJECTS)
-DEFAULT_INCLUDES = -I. -I$(srcdir)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@@ -210,7 +212,7 @@
 APR_CONFIG = $(prefix)/bin/apr-1-config
 APU_CONFIG = $(prefix)/bin/apu-1-config
 lib_LTLIBRARIES = libdingaling.la
-libdingaling_la_SOURCES = src/libdingaling.c
+libdingaling_la_SOURCES = src/libdingaling.c src/sha1.c
 libdingaling_la_CFLAGS = $(AM_CFLAGS)
 libdingaling_la_LDFLAGS = 
 library_includedir = $(prefix)/include
@@ -252,6 +254,23 @@
 	cd $(srcdir) && $(AUTOCONF)
 $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
 	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+src/config.h: src/stamp-h1
+	@if test ! -f $@; then \
+	  rm -f src/stamp-h1; \
+	  $(MAKE) src/stamp-h1; \
+	else :; fi
+
+src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
+	@rm -f src/stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(top_srcdir)/src/config.h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f src/stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f src/config.h src/stamp-h1
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@@ -289,6 +308,7 @@
 	-rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdingaling_la-libdingaling.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdingaling_la-sha1.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@@ -318,6 +338,13 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdingaling_la_CFLAGS) $(CFLAGS) -c -o libdingaling_la-libdingaling.lo `test -f 'src/libdingaling.c' || echo '$(srcdir)/'`src/libdingaling.c
 
+libdingaling_la-sha1.lo: src/sha1.c
+@am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdingaling_la_CFLAGS) $(CFLAGS) -MT libdingaling_la-sha1.lo -MD -MP -MF "$(DEPDIR)/libdingaling_la-sha1.Tpo" -c -o libdingaling_la-sha1.lo `test -f 'src/sha1.c' || echo '$(srcdir)/'`src/sha1.c; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/libdingaling_la-sha1.Tpo" "$(DEPDIR)/libdingaling_la-sha1.Plo"; else rm -f "$(DEPDIR)/libdingaling_la-sha1.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='src/sha1.c' object='libdingaling_la-sha1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdingaling_la_CFLAGS) $(CFLAGS) -c -o libdingaling_la-sha1.lo `test -f 'src/sha1.c' || echo '$(srcdir)/'`src/sha1.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -661,7 +688,7 @@
 	-rm -rf ./$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
-	distclean-libtool distclean-tags
+	distclean-hdr distclean-libtool distclean-tags
 
 dvi: dvi-recursive
 
@@ -713,11 +740,11 @@
 	clean-libtool clean-recursive ctags ctags-recursive dist \
 	dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \
 	distcheck distclean distclean-compile distclean-generic \
-	distclean-libtool distclean-recursive distclean-tags \
-	distcleancheck distdir distuninstallcheck dvi dvi-am html \
-	html-am info info-am install install-am install-data \
-	install-data-am install-exec install-exec-am install-info \
-	install-info-am install-libLTLIBRARIES \
+	distclean-hdr distclean-libtool distclean-recursive \
+	distclean-tags distcleancheck distdir distuninstallcheck dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-libLTLIBRARIES \
 	install-library_includeHEADERS install-man install-strip \
 	installcheck installcheck-am installdirs installdirs-am \
 	maintainer-clean maintainer-clean-generic \
Index: libs/libdingaling/configure.in
===================================================================
--- libs/libdingaling/configure.in	(revision 3059)
+++ libs/libdingaling/configure.in	(working copy)
@@ -5,6 +5,7 @@
 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 AM_INIT_AUTOMAKE(libdingaling,0.1)
 AC_CONFIG_SRCDIR([src])
+AC_CONFIG_HEADER([src/config.h])
 #AC_CONFIG_HEADER([])
 
 # Checks for programs.
@@ -32,6 +33,10 @@
 AC_FUNC_STRFTIME
 #AC_CHECK_FUNCS([gethostname gettimeofday localtime_r memmove memset socket strcasecmp strchr strdup strncasecmp strstr])
 
+AC_C_BIGENDIAN(AC_DEFINE([__BYTE_ORDER],__BIG_ENDIAN,[Big Endian]),AC_DEFINE([__BYTE_ORDER],__LITTLE_ENDIAN,[Little Endian]))
+AC_DEFINE([__LITTLE_ENDIAN],1234,[for the places where it is not defined])
+AC_DEFINE([__BIG_ENDIAN],4321,[for the places where it is not defined])
+
 AC_CONFIG_FILES([Makefile])
 
 AC_OUTPUT
Index: libs/libdingaling/src/sha1.h
===================================================================
--- libs/libdingaling/src/sha1.h	(revision 0)
+++ libs/libdingaling/src/sha1.h	(revision 0)
@@ -0,0 +1,58 @@
+/* 
+ * libDingaLing XMPP Jingle Library
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is libDingaLing XMPP Jingle Library
+ *
+ * The Initial Developer of the Original Code is
+ * Steve Reid <steve@edmweb.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Steve Reid <steve@edmweb.com>
+ *
+ * sha1.h
+ *
+ */
+/*! \file sha1.h
+    \brief SHA1
+*/
+
+#ifndef __SHA1_H
+#define __SHA1_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __STUPIDFORMATBUG__
+}
+#endif
+
+typedef struct {
+    unsigned long state[5];
+    unsigned long count[2];
+    unsigned char buffer[64];
+} sha_context_t;
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
+void SHA1Init(sha_context_t* context);
+void SHA1Update(sha_context_t* context, unsigned char* data, unsigned int len);
+void SHA1Final(unsigned char digest[20], sha_context_t* context);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: libs/libdingaling/src/libdingaling.c
===================================================================
--- libs/libdingaling/src/libdingaling.c	(revision 3059)
+++ libs/libdingaling/src/libdingaling.c	(working copy)
@@ -60,6 +60,7 @@
 
 #include "ldl_compat.h"
 #include "libdingaling.h"
+#include "sha1.h"
 
 #define microsleep(x) apr_sleep(x * 1000)
 
@@ -89,6 +90,12 @@
 	int hit;
 };
 
+typedef enum {
+	CS_NEW,
+	CS_START,
+	CS_CONNECTED
+} ldl_handle_state_t;
+
 struct ldl_handle {
 	iksparser *parser;
 	iksid *acc;
@@ -116,6 +123,7 @@
 	apr_pool_t *pool;
 	void *private_info;
 	FILE *log_stream;
+	ldl_handle_state_t state;
 };
 
 struct ldl_session {
@@ -125,6 +133,7 @@
 	char *initiator;
 	char *them;
 	char *ip;
+	char *login;
 	ldl_payload_t payloads[LDL_MAX_PAYLOADS];
 	unsigned int payload_len;
 	ldl_candidate_t candidates[LDL_MAX_CANDIDATES];
@@ -193,7 +202,7 @@
 
 void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body)
 {
-	ldl_handle_send_msg(session->handle, session->them, subject, body);
+	ldl_handle_send_msg(session->handle, session->login, session->them, subject, body);
 }
 
 ldl_status ldl_session_destroy(ldl_session_t **session_p)
@@ -235,14 +244,21 @@
 		*session_p = NULL;
 		return LDL_STATUS_MEMERR;
 	}
-	
 	memset(session, 0, sizeof(ldl_session_t));
 	apr_pool_create(&session->pool, globals.memory_pool);
 	session->id = apr_pstrdup(session->pool, id);
 	session->them = apr_pstrdup(session->pool, them);
-	if (me) {
-		session->initiator = apr_pstrdup(session->pool, me);
+	
+	//if (me) {
+	//session->initiator = apr_pstrdup(session->pool, them);
+	//} 
+
+	if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+		session->login = apr_pstrdup(session->pool, me);
+	} else {
+		session->login = apr_pstrdup(session->pool, handle->login);
 	}
+
 	apr_hash_set(handle->sessions, session->id, APR_HASH_KEY_STRING, session);
 	apr_hash_set(handle->sessions, session->them, APR_HASH_KEY_STRING, session);
 	session->handle = handle;
@@ -259,7 +275,7 @@
 	return LDL_STATUS_SUCCESS;
 }
 
-static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from, iks *xml, char *xtype)
+static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from, char *to, iks *xml, char *xtype)
 {
 	ldl_session_t *session = NULL;
 	ldl_signal_t signal = LDL_SIGNAL_NONE;
@@ -267,7 +283,7 @@
 	char *msg = NULL;
 
 	if (!(session = apr_hash_get(handle->sessions, id, APR_HASH_KEY_STRING))) {
-		ldl_session_create(&session, handle, id, from, initiator);
+		ldl_session_create(&session, handle, id, from, to);
 		if (!session) {
 			return LDL_STATUS_MEMERR;
 		}
@@ -433,7 +449,7 @@
 	}
 
 	if (handle->session_callback && signal) {
-		handle->session_callback(handle, session, signal, from, id, msg); 
+		handle->session_callback(handle, session, signal, to, from, id, msg); 
 	}
 
 	return LDL_STATUS_SUCCESS;
@@ -441,10 +457,208 @@
 
 const char *marker = "TRUE";
 
+static int on_disco_info(void *user_data, ikspak *pak)
+{
+	ldl_handle_t *handle = user_data;
+
+	if (pak->subtype == IKS_TYPE_RESULT) {
+		if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
+			char *from = iks_find_attrib(pak->x, "from");
+			char id[1024];
+			char *resource;
+			struct ldl_buffer *buffer;
+			size_t x;
+
+			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);
+				msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling...."); 
+				apr_queue_push(handle->queue, msg);
+			}
+
+			apr_cpystrn(id, from, sizeof(id));
+			if ((resource = strchr(id, '/'))) {
+				*resource++ = '\0';
+			}
+
+			if (resource) {
+				for (x = 0; x < strlen(resource); x++) {
+					resource[x] = (char)tolower((int)resource[x]);
+				}
+			}
+
+			if (resource && strstr(resource, "talk") && (buffer = apr_hash_get(handle->probe_hash, id, APR_HASH_KEY_STRING))) {
+				apr_cpystrn(buffer->buf, from, buffer->len);
+				fflush(stderr);
+				buffer->hit = 1;
+			}
+		}
+		return IKS_FILTER_EAT;
+	}
+	
+	if (pak->subtype == IKS_TYPE_GET) {
+		iks *iq, *query, *tag;
+		uint8_t send = 0;
+
+		if ((iq = iks_new("iq"))) {
+			do {
+				iks_insert_attrib(iq, "from", handle->login);
+				iks_insert_attrib(iq, "to", pak->from->full);
+				iks_insert_attrib(iq, "id", pak->id);
+				iks_insert_attrib(iq, "type", "result");
+
+				if (!(query = iks_insert (iq, "query"))) {
+					break;
+				}
+				iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
+					
+				if (!(tag = iks_insert (query, "identity"))) {
+					break;
+				}
+				iks_insert_attrib(tag, "category", "client");
+				iks_insert_attrib(tag, "type", "voice");
+				iks_insert_attrib(tag, "name", "LibDingaLing");
+				
+
+				if (!(tag = iks_insert (query, "feature"))) {
+					break;
+				}
+				iks_insert_attrib(tag, "var", "http://jabber.org/protocol/disco#info");
+
+				if (!(tag = iks_insert (query, "feature"))) {
+					break;
+				}
+				iks_insert_attrib(tag, "var", "http://www.google.com/xmpp/protocol/voice/v1");
+				
+				iks_send(handle->parser, iq);
+				send = 1;
+			} while (0);
+
+			iks_delete(iq);
+		}
+
+		if (!send) {
+			globals.logger(DL_LOG_DEBUG, "Memory Error!\n");
+		}		
+	}
+
+	return IKS_FILTER_EAT;
+}
+
+static int on_component_disco_info(void *user_data, ikspak *pak)
+{
+	char *node = iks_find_attrib(pak->query, "node");
+	ldl_handle_t *handle = user_data;
+
+	if (pak->subtype == IKS_TYPE_RESULT) {
+		globals.logger(DL_LOG_DEBUG, "FixME!!! node=[%s]\n", node?node:"");		
+	} else if (pak->subtype == IKS_TYPE_GET) {
+		//	if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+		if (node) {
+			
+		} else {
+			iks *iq, *query, *tag;
+			uint8_t send = 0;
+
+			if ((iq = iks_new("iq"))) {
+				do {
+					iks_insert_attrib(iq, "from", handle->login);
+					iks_insert_attrib(iq, "to", pak->from->full);
+					iks_insert_attrib(iq, "id", pak->id);
+					iks_insert_attrib(iq, "type", "result");
+
+					if (!(query = iks_insert (iq, "query"))) {
+						break;
+					}
+					iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
+					
+					if (!(tag = iks_insert (query, "identity"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "category", "gateway");
+					iks_insert_attrib(tag, "type", "voice");
+					iks_insert_attrib(tag, "name", "LibDingaLing");
+				
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "http://jabber.org/protocol/disco");
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "jabber:iq:register");
+				
+					/*
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "http://jabber.org/protocol/commands");
+					*/
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "jabber:iq:gateway");
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "jabber:iq:version");
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "vcard-temp");
+
+					if (!(tag = iks_insert (query, "feature"))) {
+						break;
+					}
+					iks_insert_attrib(tag, "var", "jabber:iq:search");
+
+					iks_send(handle->parser, iq);
+					send = 1;
+				} while (0);
+
+				iks_delete(iq);
+			}
+
+			if (!send) {
+				globals.logger(DL_LOG_DEBUG, "Memory Error!\n");
+			}
+			
+		}
+	}
+
+	return IKS_FILTER_EAT;
+}
+
+
+
+static int on_disco_items(void *user_data, ikspak *pak)
+{
+	globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
+	return IKS_FILTER_EAT;
+}
+
+static int on_disco_reg_in(void *user_data, ikspak *pak)
+{	
+	globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
+	return IKS_FILTER_EAT;
+}
+
+static int on_disco_reg_out(void *user_data, ikspak *pak)
+{
+	globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
+	return IKS_FILTER_EAT;
+}
+
 static int on_presence(void *user_data, ikspak *pak)
 {
 	ldl_handle_t *handle = user_data;
 	char *from = iks_find_attrib(pak->x, "from");
+	char *to = iks_find_attrib(pak->x, "to");
 	char *type = iks_find_attrib(pak->x, "type");
 	char *show = iks_find_cdata(pak->x, "show");
 	char *status = iks_find_cdata(pak->x, "status");
@@ -454,6 +668,7 @@
 	size_t x;
 	ldl_signal_t signal;
 
+	
 	if (type && !strcasecmp(type, "unavailable")) {
 		signal = LDL_SIGNAL_PRESENCE_OUT;
 	} else {
@@ -464,9 +679,7 @@
 		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;
@@ -491,20 +704,88 @@
 		fflush(stderr);
 		buffer->hit = 1;
 	}
+	
+	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");
+		}
+	}
+
+
 	return IKS_FILTER_EAT;
 }
 
+static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message) 
+{
+	iks *pres;
+	char buf[512];
 
+	if (!strchr(from, '/')) {
+		snprintf(buf, sizeof(buf), "%s/talk", from);
+		from = buf;
+	}
 
+	if ((pres = iks_new("presence"))) {
+		iks_insert_attrib(pres, "xmlns", "jabber:client");
+		if (from) {
+			iks_insert_attrib(pres, "from", from);
+		}
+		if (to) {
+			iks_insert_attrib(pres, "to", to);
+		}
+		if (type) {
+			iks_insert_attrib(pres, "type", type);
+		}
+		if (message) {
+			iks *tag;
+			if ((tag = iks_insert (pres, "status"))) {
+				iks_insert_cdata(tag, 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", "libdingaling");
+					iks_insert_attrib(tag, "xmlns", "http://jabber.org/protocol/caps");
+				}
+			}
+		}
+
+		apr_queue_push(handle->queue, pres);
+	}
+}
+
+static void do_roster(ldl_handle_t *handle) 
+{
+	if (handle->session_callback) {
+        handle->session_callback(handle, NULL, LDL_SIGNAL_ROSTER, NULL, handle->login, NULL, NULL);
+    }
+}
+
 static int on_subscribe(void *user_data, ikspak *pak)
 {
 	ldl_handle_t *handle = user_data;
 	char *from = iks_find_attrib(pak->x, "from");
+	char *to = iks_find_attrib(pak->x, "to");
 	iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling...."); 
+
+	if (to && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+		iks_insert_attrib(msg, "from", to);
+	}
+
 	apr_queue_push(handle->queue, msg);
 	msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, from, "Ding A Ling...."); 
+
+	if (to && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+		iks_insert_attrib(msg, "from", to);
+	}
+
 	apr_queue_push(handle->queue, msg);
+
+	if (handle->session_callback) {
+		handle->session_callback(handle, NULL, LDL_SIGNAL_SUBSCRIBE, to, from, NULL, NULL);
+	}
+
 	return IKS_FILTER_EAT;
 }
 
@@ -526,7 +807,7 @@
 {
 	ldl_handle_t *handle = user_data;
 	char *from = iks_find_attrib(pak->x, "from");
-	//char *to = iks_find_attrib(pak->x, "to");
+	char *to = iks_find_attrib(pak->x, "to");
 	char *iqid = iks_find_attrib(pak->x, "id");
 	char *type = iks_find_attrib(pak->x, "type");
 	uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
@@ -540,9 +821,10 @@
 			if (!strcasecmp(iks_name(tag), "bind")) {
 				char *jid = iks_find_cdata(tag, "jid");
 				char *resource = strchr(jid, '/');
-				iks *iq, *x;
+				//iks *iq, *x;
 				handle->acc->resource = apr_pstrdup(handle->pool, resource);
 				handle->login = apr_pstrdup(handle->pool, jid);
+#if 0
 				if ((iq = iks_new("iq"))) {
 					iks_insert_attrib(iq, "type", "get");
 					iks_insert_attrib(iq, "id", "roster");
@@ -555,6 +837,7 @@
 					iks_delete(iq);
 					break;
 				}
+#endif
 			}
 			tag = iks_next_tag(tag);
 		}
@@ -579,10 +862,11 @@
 		if (!strcasecmp(name, "session")) {
 			char *id = iks_find_attrib(xml, "id");
 			//printf("SESSION type=%s name=%s id=%s\n", type, name, id);
-			if (parse_session_code(handle, id, from, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
+			if (parse_session_code(handle, id, from, to, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
 				iks *reply;
 				reply = iks_make_iq(IKS_TYPE_RESULT, NULL); 
 				iks_insert_attrib(reply, "to", from);
+				iks_insert_attrib(reply, "from", to);
 				iks_insert_attrib(reply, "id", iqid);
 				apr_queue_push(handle->queue, reply);
 			}
@@ -644,8 +928,89 @@
 	return 0;
 }
 
-static int on_stream(ldl_handle_t *handle, int type, iks * node)
+static void sha1_hash(char *out, char *in)
 {
+	sha_context_t sha;
+	char *p;
+	int x;
+	unsigned char digest[20];
+
+	SHA1Init(&sha);
+	
+	SHA1Update(&sha, (unsigned char *) in, strlen(in));
+
+	SHA1Final(digest, &sha);
+
+	p = out;
+	for (x = 0; x < 20; x++) {
+		p += sprintf(p, "%2.2x", digest[x]);
+	}
+}
+
+
+static int on_stream_component(ldl_handle_t *handle, int type, iks *node)
+{
+	ikspak *pak = iks_packet(node);
+
+	switch (type) {
+	case IKS_NODE_START:
+		if (handle->state == CS_NEW) {
+			char secret[256];
+			char hash[256];
+			char handshake[512];
+			snprintf(secret, sizeof(secret), "%s%s", pak->id, handle->password);
+			sha1_hash(hash, secret);
+			snprintf(handshake, sizeof(handshake), "<handshake>%s</handshake>", hash);
+			iks_send_raw(handle->parser, handshake);
+			handle->state = CS_START;
+			if (iks_recv(handle->parser, 1) == 2) {
+				handle->state = CS_CONNECTED;
+				if (!ldl_test_flag(handle, LDL_FLAG_AUTHORIZED)) {
+					ldl_set_flag_locked(handle, LDL_FLAG_READY);
+					do_roster(handle);
+					if (handle->session_callback) {
+						handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "user", "core", "Login Success", handle->login);
+					}
+					globals.logger(DL_LOG_DEBUG, "XMPP authenticated\n");
+					ldl_set_flag_locked(handle, LDL_FLAG_AUTHORIZED);
+				}
+			} else {
+				globals.logger(DL_LOG_ERR, "LOGIN ERROR!\n");
+				handle->state = CS_NEW;
+			}
+			break;
+		}
+		break;
+
+	case IKS_NODE_NORMAL:
+		break;
+
+	case IKS_NODE_ERROR:
+		globals.logger(DL_LOG_ERR, "NODE ERROR!\n");
+		return IKS_HOOK;
+
+	case IKS_NODE_STOP:
+		globals.logger(DL_LOG_ERR, "DISCONNECTED!\n");
+		return IKS_HOOK;
+	}
+	
+	
+	pak = iks_packet(node);
+	iks_filter_packet(handle->filter, pak);
+
+	if (handle->job_done == 1) {
+		return IKS_HOOK;
+	}
+    
+	if (node) {
+        iks_delete(node);
+	}
+
+	return IKS_OK;
+}
+
+static int on_stream(ldl_handle_t *handle, int type, iks *node)
+{
 	handle->counter = opt_timeout;
 
 	switch (type) {
@@ -708,20 +1073,20 @@
 		} else if (strcmp("failure", iks_name(node)) == 0) {
 			globals.logger(DL_LOG_DEBUG, "sasl authentication failed\n");
 			if (handle->session_callback) {
-				handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_FAILURE, "core", "Login Failure", handle->login);
+				handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_FAILURE, "user", "core", "Login Failure", handle->login);
 			}
 		} else if (strcmp("success", iks_name(node)) == 0) {
 			globals.logger(DL_LOG_DEBUG, "XMPP server connected\n");
 			iks_send_header(handle->parser, handle->acc->server);
 			ldl_set_flag_locked(handle, LDL_FLAG_CONNECTED);
 			if (handle->session_callback) {
-				handle->session_callback(handle, NULL, LDL_SIGNAL_CONNECTED, "core", "Server Connected", handle->login);
+				handle->session_callback(handle, NULL, LDL_SIGNAL_CONNECTED, "user", "core", "Server Connected", handle->login);
 			}
 		} else {
 			ikspak *pak;
 			if (!ldl_test_flag(handle, LDL_FLAG_AUTHORIZED)) {
 				if (handle->session_callback) {
-					handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "core", "Login Success", handle->login);
+					handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "user", "core", "Login Success", handle->login);
 				}
 				globals.logger(DL_LOG_DEBUG, "XMPP authenticated\n");
 				ldl_set_flag_locked(handle, LDL_FLAG_AUTHORIZED);
@@ -754,6 +1119,7 @@
 static int on_msg(void *user_data, ikspak *pak)
 {
 	char *cmd = iks_find_cdata(pak->x, "body");
+	char *to = iks_find_attrib(pak->x, "to");
 	char *from = iks_find_attrib(pak->x, "from");
 	char *subject = iks_find_attrib(pak->x, "subject");
 	ldl_handle_t *handle = user_data;
@@ -764,7 +1130,7 @@
 	}
 
 	if (handle->session_callback) {
-		handle->session_callback(handle, session, LDL_SIGNAL_MSG, from, subject ? subject : "N/A", cmd); 
+		handle->session_callback(handle, session, LDL_SIGNAL_MSG, to, from, subject ? subject : "N/A", cmd); 
 	}
 	
 	return 0;
@@ -789,18 +1155,13 @@
 	fprintf(stderr, "[%s]\n", data);
 }
 
-static void j_setup_filter(ldl_handle_t *handle, char *login)
+static void j_setup_filter(ldl_handle_t *handle)
 {
 	if (handle->filter) {
 		iks_filter_delete(handle->filter);
 	}
 	handle->filter = iks_filter_new();
 
-	/*
-	iks_filter_add_rule(handle->filter, on_msg, 0,
-						IKS_RULE_TYPE, IKS_PAK_MESSAGE,
-						IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_FROM, login, IKS_RULE_DONE);
-	*/
 	iks_filter_add_rule(handle->filter, on_msg, handle, IKS_RULE_TYPE, IKS_PAK_MESSAGE, IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_DONE);
 
 	iks_filter_add_rule(handle->filter, on_result, handle,
@@ -835,6 +1196,23 @@
 	iks_filter_add_rule(handle->filter, on_error, handle,
 						IKS_RULE_TYPE, IKS_PAK_IQ,
 						IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_ID, "auth", IKS_RULE_DONE);
+
+
+
+	if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+		iks_filter_add_rule(handle->filter, on_component_disco_info, handle, 
+							IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
+		iks_filter_add_rule(handle->filter, on_disco_items, handle,
+							IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
+		iks_filter_add_rule(handle->filter, on_disco_reg_in, handle,
+							IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
+		iks_filter_add_rule(handle->filter, on_disco_reg_out, handle,
+							IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
+	} else {
+		iks_filter_add_rule(handle->filter, on_disco_info, handle, 
+							IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
+	}
+	
 }
 
 static void ldl_flush_queue(ldl_handle_t *handle)
@@ -928,26 +1306,35 @@
 {
 	while (ldl_test_flag(handle, LDL_FLAG_RUNNING)) {
 		int e;
+		char tmp[512], *sl;
 
-		handle->parser = iks_stream_new(IKS_NS_CLIENT, handle, (iksStreamHook *) on_stream);
+		handle->parser = iks_stream_new(ldl_test_flag(handle, LDL_FLAG_COMPONENT) ? IKS_NS_COMPONENT : IKS_NS_CLIENT,
+										handle,
+										(iksStreamHook *) (ldl_test_flag(handle, LDL_FLAG_COMPONENT) ? on_stream_component : on_stream));
+
 		if (globals.debug) {
 			iks_set_log_hook(handle->parser, (iksLogHook *) on_log);
 		}
-		handle->acc = iks_id_new(iks_parser_stack(handle->parser), jabber_id);
-		if (NULL == handle->acc->resource) {
+		
+		strncpy(tmp, jabber_id, sizeof(tmp)-1);
+		sl = strchr(tmp, '/');
+
+		if (!sl && !ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
 			/* user gave no resource name, use the default */
-			char tmp[512];
-			sprintf(tmp, "%s@%s/%s", handle->acc->user, handle->acc->server, "dingaling");
-			handle->acc = iks_id_new(iks_parser_stack(handle->parser), tmp);
+			snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), "/%s", "talk");
+		} else if (sl && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
+			*sl = '\0';
 		}
+
+		handle->acc = iks_id_new(iks_parser_stack(handle->parser), tmp);
+
 		handle->password = pass;
 
-		j_setup_filter(handle, "fixme");
+		j_setup_filter(handle);
 
 		e = iks_connect_via(handle->parser,
 							handle->server ? handle->server : handle->acc->server,
 							handle->port ? handle->port : IKS_JABBER_PORT,
-							//handle->server ? handle->server : handle->acc->server);
 							handle->acc->server);
 
 		switch (e) {
@@ -1040,7 +1427,7 @@
 	snprintf(idbuf, sizeof(idbuf), "%u", myid);
 	iq = iks_new("iq");
 	iks_insert_attrib(iq, "xmlns", "jabber:client");
-	iks_insert_attrib(iq, "from", session->handle->login);
+	iks_insert_attrib(iq, "from", session->login);
 	iks_insert_attrib(iq, "to", session->them);
 	iks_insert_attrib(iq, "type", "set");
 	iks_insert_attrib(iq, "id", idbuf);
@@ -1092,6 +1479,11 @@
 	return session->them;
 }
 
+char *ldl_session_get_callee(ldl_session_t *session)
+{
+	return session->login;
+}
+
 void ldl_session_set_ip(ldl_session_t *session, char *ip)
 {
 	session->ip = apr_pstrdup(session->pool, ip);
@@ -1123,7 +1515,7 @@
 	iq = iks_new("iq");
 	iks_insert_attrib(iq, "type", "set");
 	iks_insert_attrib(iq, "id", idbuf);
-	iks_insert_attrib(iq, "from", session->handle->login);
+	iks_insert_attrib(iq, "from", session->login);
 	iks_insert_attrib(iq, "to", session->them);
 	sess = iks_insert (iq, "session");
     iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
@@ -1142,8 +1534,13 @@
 	return handle->private_info;
 }
 
-void ldl_handle_send_msg(ldl_handle_t *handle, char *to, char *subject, char *body)
+void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message)
 {
+	do_presence(handle, from, to, type, message);
+}
+
+void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body)
+{
 	iks *msg;
 
 	assert(handle != NULL);
@@ -1153,6 +1550,12 @@
 	msg = iks_make_msg(IKS_TYPE_NONE, to, body);
 	iks_insert_attrib(msg, "type", "chat");
 
+	if (!from) {
+		from = handle->login;
+	}
+
+	iks_insert_attrib(msg, "from", from);
+
 	if (subject) {
 		iks_insert_attrib(msg, "subject", subject);
 	}
@@ -1235,7 +1638,7 @@
 	return id;
 }
 
-char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len)
+char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
 {
 	iks *pres, *msg;
 	char *lid = NULL;
@@ -1251,11 +1654,13 @@
 
 	pres = iks_new("presence");
 	iks_insert_attrib(pres, "type", "probe");
+	iks_insert_attrib(pres, "from", from);
 	iks_insert_attrib(pres, "to", id);
 
 
 	apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, &buffer);
 	msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice); 
+	iks_insert_attrib(pres, "from", from);
 	apr_queue_push(handle->queue, msg);
 	msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, id, notice); 
 	apr_queue_push(handle->queue, msg);
@@ -1268,6 +1673,7 @@
 		elapsed = (unsigned int)((apr_time_now() - started) / 1000);
 		if (elapsed > 5000 && ! again) {
 			msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice); 
+			iks_insert_attrib(pres, "from", from);
 			apr_queue_push(handle->queue, msg);
 			again++;
 		}
@@ -1286,6 +1692,74 @@
 }
 
 
+char *ldl_handle_disco(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
+{
+	iks *iq, *query, *msg;
+	char *lid = NULL;
+	struct ldl_buffer buffer;
+	apr_time_t started;
+	unsigned int elapsed;
+	char *notice = "Call Me!";
+	int again = 0;
+	unsigned int myid;
+    char idbuf[80];
+
+	myid = next_id();
+    snprintf(idbuf, sizeof(idbuf), "%u", myid);
+
+	buffer.buf = buf;
+	buffer.len = len;
+	buffer.hit = 0;
+
+	if ((iq = iks_new("iq"))) {
+		if ((query = iks_insert(iq, "query"))) {
+			iks_insert_attrib(iq, "type", "get");
+			iks_insert_attrib(iq, "to", id);
+			iks_insert_attrib(iq,"from", from);
+			iks_insert_attrib(iq, "id", idbuf);
+			iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
+		} else {
+			iks_delete(iq);
+			globals.logger(DL_LOG_DEBUG, "Memory ERROR!\n");
+			return NULL;
+		}
+	} else {
+		globals.logger(DL_LOG_DEBUG, "Memory ERROR!\n");
+		return NULL;
+	}
+	
+	apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, &buffer);
+	msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice); 
+	apr_queue_push(handle->queue, msg);
+	msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, id, notice); 
+	apr_queue_push(handle->queue, msg);
+	apr_queue_push(handle->queue, iq);
+
+	//schedule_packet(handle, next_id(), pres, LDL_RETRY);
+
+	started = apr_time_now();
+	for(;;) {
+		elapsed = (unsigned int)((apr_time_now() - started) / 1000);
+		if (elapsed > 5000 && ! again) {
+			msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice); 
+			apr_queue_push(handle->queue, msg);
+			again++;
+		}
+		if (elapsed > 10000) {
+			break;
+		}
+		if (buffer.hit) {
+			lid = buffer.buf;
+			break;
+		}
+		ldl_yield(1000);
+	}
+
+	apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, NULL);
+	return lid;
+}
+
+
 unsigned int ldl_session_describe(ldl_session_t *session,
 								ldl_payload_t *payloads,
 								unsigned int plen,
Index: libs/libdingaling/src/libdingaling.h
===================================================================
--- libs/libdingaling/src/libdingaling.h	(revision 3059)
+++ libs/libdingaling/src/libdingaling.h	(working copy)
@@ -50,6 +50,7 @@
 #define LDL_MAX_CANDIDATES 10
 #define LDL_MAX_PAYLOADS 50
 #define LDL_RETRY 3
+#define IKS_NS_COMPONENT "jabber:component:accept"
 
 /*! \brief A structure to store a jingle candidate */
 struct ldl_candidate {
@@ -105,13 +106,14 @@
 	LDL_FLAG_AUTHORIZED = (1 << 2),
 	LDL_FLAG_READY = (1 << 3),
 	LDL_FLAG_CONNECTED = (1 << 4),
-	LDL_FLAG_QUEUE_RUNNING = (1 << 5),
+	LDL_FLAG_QUEUE_RUNNING = (1 << 5)
 } ldl_flag_t;
 
 typedef enum {
 	LDL_FLAG_TLS = (1 << 10),
 	LDL_FLAG_SASL_PLAIN = (1 << 11),
-	LDL_FLAG_SASL_MD5 = (1 << 12)
+	LDL_FLAG_SASL_MD5 = (1 << 12),
+	LDL_FLAG_COMPONENT = (1 << 13),
 } ldl_user_flag_t;
 
 typedef enum {
@@ -121,6 +123,8 @@
 	LDL_SIGNAL_MSG,
 	LDL_SIGNAL_PRESENCE_IN,
 	LDL_SIGNAL_PRESENCE_OUT,
+	LDL_SIGNAL_ROSTER,
+	LDL_SIGNAL_SUBSCRIBE,
 	LDL_SIGNAL_TERMINATE,
 	LDL_SIGNAL_ERROR,
 	LDL_SIGNAL_LOGIN_SUCCESS,
@@ -156,7 +160,7 @@
 #define DL_LOG_EMERG DL_PRE, 0
 
 typedef ldl_status (*ldl_loop_callback_t)(ldl_handle_t *);
-typedef ldl_status (*ldl_session_callback_t)(ldl_handle_t *, ldl_session_t *, ldl_signal_t, char *, char *, char *);
+typedef ldl_status (*ldl_session_callback_t)(ldl_handle_t *, ldl_session_t *, ldl_signal_t, char *, char *, char *, char *);
 typedef ldl_status (*ldl_response_callback_t)(ldl_handle_t *, char *);
 typedef void (*ldl_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...);
 
@@ -266,6 +270,13 @@
 char *ldl_session_get_caller(ldl_session_t *session);
 
 /*!
+  \brief Get the callee name of a session
+  \param session the session to get the callee from
+  \return the callee name
+*/
+char *ldl_session_get_callee(ldl_session_t *session);
+
+/*!
   \brief Set the ip of a session
   \param session the session to set the ip on
   \param ip the ip
@@ -310,13 +321,25 @@
   \brief Perform a probe on a given id to resolve the proper Jingle Resource
   \param handle the connection handle to use.
   \param id the id to probe
+  \param from the from string
   \param buf a string to store the result
   \param len the size in bytes of the string
   \return a pointer to buf if a successful lookup was made otherwise NULL
 */
-char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len);
+char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len);
 
 /*!
+  \brief Perform a discovery on a given id to resolve the proper Jingle Resource
+  \param handle the connection handle to use.
+  \param id the id to probe
+  \param from the from string
+  \param buf a string to store the result
+  \param len the size in bytes of the string
+  \return a pointer to buf if a successful lookup was made otherwise NULL
+*/
+char *ldl_handle_disco(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len);
+
+/*!
   \brief Signal a termination request on a given session
   \param session the session to terminate
   \return TRUE if the signal was sent.
@@ -340,13 +363,24 @@
 void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body);
 
 /*!
+  \brief Send a presence notification to a target
+  \param handle the handle to send with
+  \param from the from address
+  \param to the to address
+  \param type the type of presence
+  \param message a status message
+*/
+void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message);
+
+/*!
   \brief Send a message
   \param handle the conection handle
+  \param from the message sender
   \param to the message recipiant
   \param subject optional subject
   \param body body of the message
 */
-void ldl_handle_send_msg(ldl_handle_t *handle, char *to, char *subject, char *body);
+void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body);
 
 /*!
   \brief Offer candidates to a potential session
Index: libs/libdingaling/src/sha1.c
===================================================================
--- libs/libdingaling/src/sha1.c	(revision 0)
+++ libs/libdingaling/src/sha1.c	(revision 0)
@@ -0,0 +1,203 @@
+/* 
+ * libDingaLing XMPP Jingle Library
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is libDingaLing XMPP Jingle Library
+ *
+ * The Initial Developer of the Original Code is
+ * Steve Reid <steve@edmweb.com>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Steve Reid <steve@edmweb.com>
+ *
+ * sha1.h
+ *
+ */
+/*! \file sha1.c
+    \brief SHA1
+*/
+
+/*
+ORIGINAL HEADERS
+----------------------------------------------------------------------------------------------
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+#include "sha1.h"
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
+{
+unsigned long a, b, c, d, e;
+typedef union {
+    unsigned char c[64];
+    unsigned long l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+    block = (CHAR64LONG16*)workspace;
+    memcpy(block, buffer, 64);
+#else
+    block = (CHAR64LONG16*)buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(sha_context_t* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(sha_context_t* context, unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+    j = (context->count[0] >> 3) & 63;
+    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+    context->count[1] += (len >> 29);
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], sha_context_t* context)
+{
+unsigned long i, j;
+unsigned char finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+    SHA1Update(context, (unsigned char *)"\200", 1);
+    while ((context->count[0] & 504) != 448) {
+        SHA1Update(context, (unsigned char *)"\0", 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (unsigned char)
+         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+    }
+    /* Wipe variables */
+    i = j = 0;
+    memset(context->buffer, 0, 64);
+    memset(context->state, 0, 20);
+    memset(context->count, 0, 8);
+    memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
+    SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+
Index: libs/libdingaling/Makefile.am
===================================================================
--- libs/libdingaling/Makefile.am	(revision 3059)
+++ libs/libdingaling/Makefile.am	(working copy)
@@ -17,7 +17,7 @@
 AM_LDFLAGS += $(shell $(APU_CONFIG) --link-ld --libs )
 
 lib_LTLIBRARIES		= libdingaling.la
-libdingaling_la_SOURCES	= src/libdingaling.c
+libdingaling_la_SOURCES	= src/libdingaling.c src/sha1.c
 libdingaling_la_CFLAGS	= $(AM_CFLAGS)
 libdingaling_la_LDFLAGS	= 
 
