changeset 18845:09f52521ff5b

Fix bonjour buddy icons to work with iChat.
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 08 Aug 2007 18:14:46 +0000
parents 7bf6b9a70b41
children 44ad08a02ead
files libpurple/protocols/bonjour/issues.txt libpurple/protocols/bonjour/mdns_avahi.c libpurple/protocols/bonjour/mdns_common.c libpurple/protocols/bonjour/mdns_common.h libpurple/protocols/bonjour/mdns_howl.c libpurple/protocols/bonjour/mdns_interface.h libpurple/protocols/bonjour/mdns_win32.c
diffstat 7 files changed, 63 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/issues.txt	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/issues.txt	Wed Aug 08 18:14:46 2007 +0000
@@ -3,6 +3,5 @@
 ==========================================
 
 * Status changes don't work
-* Avatars
 * File transfers
 * Typing notifications
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Wed Aug 08 18:14:46 2007 +0000
@@ -317,10 +317,10 @@
 	return TRUE;
 }
 
-void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+	return FALSE;
 }
 
-
 void _mdns_stop(BonjourDnsSd *data) {
 	AvahiSessionImplData *idata = data->mdns_impl_data;
 
@@ -344,5 +344,5 @@
 void _mdns_delete_buddy(BonjourBuddy *buddy) {
 }
 
-void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+void _mdns_retrieve_retrieve_buddy_icon(BonjourBuddy* buddy) {
 }
--- a/libpurple/protocols/bonjour/mdns_common.c	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Wed Aug 08 18:14:46 2007 +0000
@@ -67,40 +67,11 @@
 	_mdns_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */
 }
 
-void
-bonjour_dns_sd_buddy_icon_data_set(BonjourDnsSd *data) {
-	PurpleStoredImage *img = purple_buddy_icons_find_account_icon(data->account);
-	gconstpointer avatar_data;
-	gsize avatar_len;
-	gchar *enc;
-	int i;
-	unsigned char hashval[20];
-	char *p, hash[41];
-
-	g_return_if_fail(img != NULL);
-
-	avatar_data = purple_imgstore_get_data(img);
-	avatar_len = purple_imgstore_get_size(img);
-
-	enc = purple_base64_encode(avatar_data, avatar_len);
-
-	purple_cipher_digest_region("sha1", avatar_data,
-				    avatar_len, sizeof(hashval),
-				    hashval, NULL);
-
-	purple_imgstore_unref(img);
-
-	p = hash;
-	for(i=0; i<20; i++, p+=2)
-		snprintf(p, 3, "%02x", hashval[i]);
-
-	g_free(data->phsh);
-	data->phsh = g_strdup(hash);
-
-	g_free(enc);
-
-	/* Update our TXT record */
-	_mdns_publish(data, PUBLISH_UPDATE);
+/**
+ * Retrieve the buddy icon blob
+ */
+void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+	_mdns_retrieve_retrieve_buddy_icon(buddy);
 }
 
 void
@@ -114,7 +85,30 @@
 		avatar_data = purple_imgstore_get_data(img);
 		avatar_len = purple_imgstore_get_size(img);
 
-		_mdns_set_buddy_icon_data(data, avatar_data, avatar_len);
+		if (_mdns_set_buddy_icon_data(data, avatar_data, avatar_len)) {
+			int i;
+			gchar *enc;
+			char *p, hash[41];
+			unsigned char hashval[20];
+
+			enc = purple_base64_encode(avatar_data, avatar_len);
+
+			purple_cipher_digest_region("sha1", avatar_data,
+						    avatar_len, sizeof(hashval),
+						    hashval, NULL);
+
+			p = hash;
+			for(i=0; i<20; i++, p+=2)
+				snprintf(p, 3, "%02x", hashval[i]);
+
+			g_free(data->phsh);
+			data->phsh = g_strdup(hash);
+
+			g_free(enc);
+
+			/* Update our TXT record */
+			_mdns_publish(data, PUBLISH_UPDATE);
+		}
 
 		purple_imgstore_unref(img);
 	} else {
--- a/libpurple/protocols/bonjour/mdns_common.h	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Wed Aug 08 18:14:46 2007 +0000
@@ -47,11 +47,6 @@
 void bonjour_dns_sd_update_buddy_icon(BonjourDnsSd *data);
 
 /**
- * The buddy icon blob has been set, notify everyone watching the TXT record
- */
-void bonjour_dns_sd_buddy_icon_data_set(BonjourDnsSd *data);
-
-/**
  * Advertise our presence within the dns-sd daemon and start
  * browsing for other bonjour peers.
  */
--- a/libpurple/protocols/bonjour/mdns_howl.c	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Wed Aug 08 18:14:46 2007 +0000
@@ -287,10 +287,10 @@
 	return FALSE;
 }
 
-void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+	return FALSE;
 }
 
-
 void _mdns_stop(BonjourDnsSd *data) {
 	HowlSessionImplData *idata = data->mdns_impl_data;
 
@@ -315,7 +315,7 @@
 void _mdns_delete_buddy(BonjourBuddy *buddy) {
 }
 
-void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+void _mdns_retrieve_retrieve_buddy_icon(BonjourBuddy* buddy) {
 }
 
 
--- a/libpurple/protocols/bonjour/mdns_interface.h	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_interface.h	Wed Aug 08 18:14:46 2007 +0000
@@ -28,13 +28,12 @@
 
 void _mdns_stop(BonjourDnsSd *data);
 
-void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len);
+gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len);
 
 void _mdns_init_buddy(BonjourBuddy *buddy);
 
 void _mdns_delete_buddy(BonjourBuddy *buddy);
 
-/* This doesn't quite belong here, but there really isn't any shared functionality */
-void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy);
+void _mdns_retrieve_retrieve_buddy_icon(BonjourBuddy* buddy);
 
 #endif
--- a/libpurple/protocols/bonjour/mdns_win32.c	Wed Aug 08 01:50:01 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Wed Aug 08 18:14:46 2007 +0000
@@ -37,14 +37,12 @@
 
 /* data used by win32 bonjour implementation */
 typedef struct _win32_session_impl_data {
-	DNSServiceRef advertisement_svc;
+	DNSServiceRef presence_svc;
 	DNSServiceRef browser_svc;
-	DNSServiceRef buddy_icon_svc;
 	DNSRecordRef buddy_icon_rec;
 
-	guint advertisement_handler; /* hack... windows bonjour is broken, so we have to have this */
+	guint presence_handler; /* hack... windows bonjour is broken, so we have to have this */
 	guint browser_handler;
-	guint buddy_icon_handler;
 } Win32SessionImplData;
 
 typedef struct _win32_buddy_impl_data {
@@ -199,17 +197,6 @@
 }
 
 static void DNSSD_API
-_mdns_set_buddy_icon_cb(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
-			void *context) {
-	if (kDNSServiceErr_NoError != errorCode)
-		purple_debug_error("bonjour", "Error (%d) registering buddy icon data.\n", errorCode);
-	else {
-		purple_debug_info("bonjour", "Registered buddy icon data.\n");
-		bonjour_dns_sd_buddy_icon_data_set((BonjourDnsSd *) context);
-	}
-}
-
-static void DNSSD_API
 _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
     DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context)
 {
@@ -321,14 +308,15 @@
 
 		switch (type) {
 			case PUBLISH_START:
-				purple_debug_info("bonjour", "Registering service on port %d\n", data->port_p2pj);
-				err = DNSServiceRegister(&idata->advertisement_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
+				purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj);
+				err = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
 					NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data),
 					_mdns_service_register_callback, NULL);
 				break;
 
 			case PUBLISH_UPDATE:
-				err = DNSServiceUpdateRecord(idata->advertisement_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
+				purple_debug_info("bonjour", "Updating presence.\n");
+				err = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
 				break;
 		}
 
@@ -337,8 +325,8 @@
 			ret = FALSE;
 		} else if (type == PUBLISH_START) {
 			/* hack: Bonjour on windows is broken. We don't care about the callback but we have to listen anyway */
-			idata->advertisement_handler = purple_input_add(DNSServiceRefSockFD(idata->advertisement_svc),
-				PURPLE_INPUT_READ, _mdns_handle_event, idata->advertisement_svc);
+			idata->presence_handler = purple_input_add(DNSServiceRefSockFD(idata->presence_svc),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_svc);
 		}
 	}
 
@@ -369,10 +357,10 @@
 	if (idata == NULL)
 		return;
 
-	if (idata->advertisement_svc != NULL) {
+	if (idata->presence_svc != NULL) {
 		/* hack: for win32, we need to stop listening to the advertisement pipe too */
-		purple_input_remove(idata->advertisement_handler);
-		DNSServiceRefDeallocate(idata->advertisement_svc);
+		purple_input_remove(idata->presence_handler);
+		DNSServiceRefDeallocate(idata->presence_svc);
 	}
 
 	if (idata->browser_svc != NULL) {
@@ -380,68 +368,37 @@
 		DNSServiceRefDeallocate(idata->browser_svc);
 	}
 
-	if (idata->buddy_icon_svc != NULL) {
-		purple_input_remove(idata->buddy_icon_handler);
-		DNSServiceRefDeallocate(idata->buddy_icon_svc);
-	}
-
-
 	g_free(idata);
 
 	data->mdns_impl_data = NULL;
 }
 
-void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
 	Win32SessionImplData *idata = data->mdns_impl_data;
-	gboolean new_svc = FALSE;
 	DNSServiceErrorType err = kDNSServiceErr_NoError;
 
-	g_return_if_fail(idata != NULL);
-
-	if (avatar_data != NULL && idata->buddy_icon_svc == NULL) {
-		gchar *svc_name = g_strdup_printf("%s." ICHAT_SERVICE "local", purple_account_get_username(data->account));
-
-		purple_debug_info("bonjour", "Setting new buddy icon.\n");
-
-		err = DNSServiceCreateConnection(&idata->buddy_icon_svc);
-		if (err == kDNSServiceErr_NoError) {
-			err = DNSServiceRegisterRecord(idata->buddy_icon_svc,
-				&idata->buddy_icon_rec, kDNSServiceFlagsShared, kDNSServiceInterfaceIndexAny, svc_name,
-				kDNSServiceType_NULL, kDNSServiceClass_IN,
-				avatar_len, avatar_data, 10, _mdns_set_buddy_icon_cb, data);
+	g_return_val_if_fail(idata != NULL, FALSE);
 
-			if (err != kDNSServiceErr_NoError) {
-				DNSServiceRefDeallocate(idata->buddy_icon_svc);
-				idata->buddy_icon_svc = NULL;
-			}
-		}
-
-		g_free(svc_name);
-
-		if (err == kDNSServiceErr_NoError)
-			idata->buddy_icon_handler = purple_input_add(DNSServiceRefSockFD(idata->buddy_icon_svc),
-				PURPLE_INPUT_READ, _mdns_handle_event, idata->buddy_icon_svc);
-
-		new_svc = TRUE;
+	if (avatar_data != NULL && idata->buddy_icon_rec == NULL) {
+		purple_debug_info("bonjour", "Setting new buddy icon.\n");
+		err = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec,
+			0, kDNSServiceType_NULL, avatar_len, avatar_data, 0);
 	} else if (avatar_data != NULL) {
 		purple_debug_info("bonjour", "Updating existing buddy icon.\n");
-		err = DNSServiceUpdateRecord(idata->buddy_icon_svc, idata->buddy_icon_rec,
-			0, avatar_len, avatar_data, 10);
-	} else if (idata->buddy_icon_svc != NULL) {
+		err = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec,
+			0, avatar_len, avatar_data, 0);
+	} else if (idata->buddy_icon_rec != NULL) {
 		purple_debug_info("bonjour", "Removing existing buddy icon.\n");
-		/* Must be removing the buddy icon */
-		purple_input_remove(idata->buddy_icon_handler);
-		idata->buddy_icon_handler = 0;
-		DNSServiceRefDeallocate(idata->buddy_icon_svc);
-		idata->buddy_icon_svc = NULL;
+		DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0);
 		idata->buddy_icon_rec = NULL;
 	}
 
 	if (err != kDNSServiceErr_NoError)
 		purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", err);
+
+	return (err == kDNSServiceErr_NoError);
 }
 
-
 void _mdns_init_buddy(BonjourBuddy *buddy) {
 	buddy->mdns_impl_data = g_new0(Win32BuddyImplData, 1);
 }
@@ -466,9 +423,9 @@
 	buddy->mdns_impl_data = NULL;
 }
 
-void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+void _mdns_retrieve_retrieve_buddy_icon(BonjourBuddy* buddy) {
 	Win32BuddyImplData *idata = buddy->mdns_impl_data;
-	gchar *svc_name;
+	char svc_name[kDNSServiceMaxDomainName];
 
 	g_return_if_fail(idata != NULL);
 
@@ -480,13 +437,12 @@
 		idata->null_query = NULL;
 	}
 
-	svc_name = g_strdup_printf("%s." ICHAT_SERVICE "local", buddy->name);
+	DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local");
 	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, svc_name,
 			kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) {
 		idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query),
 			PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
 	}
-	g_free(svc_name);
 
 }