changeset 18799:83719d57a8ee

Implement bonjour buddy icons in the win32 implementation. Avahi's howl wrapper doesn't implement sw_discovery_query_record(), so we can't do it elsewhere yet.
author Daniel Atallah <daniel.atallah@gmail.com>
date Sun, 05 Aug 2007 02:50:48 +0000
parents ed1def07d86e
children 355f24d20501
files libpurple/protocols/bonjour/buddy.c libpurple/protocols/bonjour/buddy.h libpurple/protocols/bonjour/mdns_common.h libpurple/protocols/bonjour/mdns_howl.c libpurple/protocols/bonjour/mdns_win32.c
diffstat 5 files changed, 73 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/buddy.c	Sun Aug 05 02:44:53 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Sun Aug 05 02:50:48 2007 +0000
@@ -156,6 +156,19 @@
 		purple_prpl_got_user_status(account, buddy->name, status_id, NULL);
 
 	purple_prpl_got_user_idle(account, buddy->name, FALSE, 0);
+
+	/* TODO: Because we don't save Bonjour buddies in blist.xml,
+	 * we will always have to look up the buddy icon at login time.
+	 * I think we should figure out a way to do something about this. */
+
+	/* Deal with the buddy icon */
+	old_hash = purple_buddy_icons_get_checksum_for_user(buddy);
+	new_hash = (bonjour_buddy->phsh && *(bonjour_buddy->phsh)) ? bonjour_buddy->phsh : NULL;
+	if (new_hash && (!old_hash || strcmp(old_hash, new_hash) != 0)) {
+		/* Look up the new icon data */
+		bonjour_dns_sd_retrieve_buddy_icon(bonjour_buddy);
+	} else
+		purple_buddy_icons_set_for_user(account, buddy->name, NULL, 0, NULL);
 }
 
 /**
@@ -166,6 +179,7 @@
 {
 	g_free(buddy->name);
 	g_free(buddy->ip);
+	g_free(buddy->full_service_name);
 
 	g_free(buddy->first);
 	g_free(buddy->phsh);
--- a/libpurple/protocols/bonjour/buddy.h	Sun Aug 05 02:44:53 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Sun Aug 05 02:50:48 2007 +0000
@@ -27,7 +27,9 @@
 	PurpleAccount *account;
 
 	gchar *name;
+	/* TODO: Remove and just use the hostname */
 	gchar *ip;
+	gchar *full_service_name;
 	gint port_p2pj;
 
 	gchar *first;
--- a/libpurple/protocols/bonjour/mdns_common.h	Sun Aug 05 02:44:53 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Sun Aug 05 02:50:48 2007 +0000
@@ -37,6 +37,11 @@
 void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message);
 
 /**
+ * Retrieve the buddy icon blob
+ */
+void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy);
+
+/**
  * Advertise our presence within the dns-sd daemon and start
  * browsing for other bonjour peers.
  */
--- a/libpurple/protocols/bonjour/mdns_howl.c	Sun Aug 05 02:44:53 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Sun Aug 05 02:50:48 2007 +0000
@@ -312,3 +312,5 @@
 void _mdns_delete_buddy(BonjourBuddy *buddy) {
 }
 
+void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+}
--- a/libpurple/protocols/bonjour/mdns_win32.c	Sun Aug 05 02:44:53 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Sun Aug 05 02:50:48 2007 +0000
@@ -29,7 +29,6 @@
 	guint resolver_handler;
 
 	PurpleDnsQueryData *query;
-	gchar *fqn;
 
 	BonjourBuddy* buddy;
 } ResolveCallbackArgs;
@@ -45,6 +44,8 @@
 typedef struct _win32_buddy_impl_data {
 	DNSServiceRef txt_query;
 	guint txt_query_handler;
+	DNSServiceRef null_query;
+	guint null_query_handler;
 } Win32BuddyImplData;
 
 static void
@@ -77,10 +78,27 @@
 		purple_debug_error("bonjour", "record query - callback error.\n");
 	else if (flags & kDNSServiceFlagsAdd)
 	{
-		/* New Buddy */
-		BonjourBuddy *buddy = (BonjourBuddy*) context;
-		_mdns_parse_text_record(buddy, rdata, rdlen);
-		bonjour_buddy_add_to_purple(buddy);
+		if (rrtype == kDNSServiceType_TXT) {
+			/* New Buddy */
+			BonjourBuddy *buddy = (BonjourBuddy*) context;
+			_mdns_parse_text_record(buddy, rdata, rdlen);
+			bonjour_buddy_add_to_purple(buddy);
+		} else if (rrtype == kDNSServiceType_NULL) {
+			/* Buddy Icon response */
+			BonjourBuddy *buddy = (BonjourBuddy*) context;
+			Win32BuddyImplData *idata = buddy->mdns_impl_data;
+
+			g_return_if_fail(idata != NULL);
+
+			purple_buddy_icons_set_for_user(buddy->account, buddy->name,
+							g_memdup(rdata, rdlen), rdlen, buddy->phsh);
+
+			/* We've got what we need; stop listening */
+			purple_input_remove(idata->null_query_handler);
+			idata->null_query_handler = -1;
+			DNSServiceRefDeallocate(idata->null_query);
+			idata->null_query = NULL;
+		}
 	}
 }
 
@@ -120,7 +138,6 @@
 
 	/* free the remaining args memory */
 	purple_dnsquery_destroy(args->query);
-	g_free(args->fqn);
 	g_free(args);
 }
 
@@ -148,14 +165,13 @@
 		_mdns_parse_text_record(args->buddy, txtRecord, txtLen);
 
 		/* set more arguments, and start the host resolver */
-		args->fqn = g_strdup(fullname);
+		args->buddy->full_service_name = g_strdup(fullname);
 
 		if (!(args->query =
 			purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)))
 		{
 			purple_debug_error("bonjour", "service resolver - host resolution failed.\n");
 			bonjour_buddy_delete(args->buddy);
-			g_free(args->fqn);
 			g_free(args);
 		}
 	}
@@ -361,8 +377,34 @@
 		DNSServiceRefDeallocate(idata->txt_query);
 	}
 
+	if (idata->null_query != NULL) {
+		purple_input_remove(idata->null_query_handler);
+		DNSServiceRefDeallocate(idata->null_query);
+	}
+
 	g_free(idata);
 
 	buddy->mdns_impl_data = NULL;
 }
 
+void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+	Win32BuddyImplData *idata = buddy->mdns_impl_data;
+
+	g_return_if_fail(idata != NULL);
+
+	/* Cancel any existing query */
+	if (idata->null_query != NULL) {
+		purple_input_remove(idata->null_query_handler);
+		idata->null_query_handler = 0;
+		DNSServiceRefDeallocate(idata->null_query);
+		idata->null_query = NULL;
+	}
+
+	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, buddy->full_service_name,
+			kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) {
+		int fd = DNSServiceRefSockFD(idata->null_query);
+		idata->null_query_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
+	}
+
+}
+