changeset 18848:32a44f7e9c52

merge of '27e06af9a3657aa4d9664c8f17f3aee8ebc41e65' and '7a479398307e3af8d16c684697d3ec93cd8e491c'
author Daniel Atallah <daniel.atallah@gmail.com>
date Thu, 09 Aug 2007 02:30:03 +0000
parents a53992a4437a (current diff) 2bf2bd713955 (diff)
children 1787e601aafc
files libpurple/protocols/bonjour/mdns_avahi.c
diffstat 9 files changed, 136 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/buddy.c	Wed Aug 08 01:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Thu Aug 09 02:30:03 2007 +0000
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 
 #include "internal.h"
+#include "cipher.h"
 #include "buddy.h"
 #include "account.h"
 #include "blist.h"
@@ -106,11 +107,10 @@
 	PurpleBuddy *buddy;
 	PurpleGroup *group;
 	PurpleAccount *account = bonjour_buddy->account;
-	const char *status_id, *first, *last, *old_hash, *new_hash;
-	gchar *alias = NULL;
+	const char *status_id, *old_hash, *new_hash;
 
 	/* Translate between the Bonjour status and the Purple status */
-	if (g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
+	if (bonjour_buddy->status != NULL && g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
 		status_id = BONJOUR_STATUS_ID_AWAY;
 	else
 		status_id = BONJOUR_STATUS_ID_AVAILABLE;
@@ -138,15 +138,21 @@
 	}
 
 	/* Create the alias for the buddy using the first and the last name */
-	first = bonjour_buddy->first;
-	last = bonjour_buddy->last;
-	if ((first && *first) || (last && *last))
-		alias = g_strdup_printf("%s%s%s",
-					(first && *first ? first : ""),
-					(first && *first && last && *last ? " " : ""),
-					(last && *last ? last : ""));
-	serv_got_alias(purple_account_get_connection(account), buddy->name, alias);
-	g_free(alias);
+	if (bonjour_buddy->nick)
+		serv_got_alias(purple_account_get_connection(account), buddy->name, bonjour_buddy->nick);
+	else {
+		gchar *alias = NULL;
+		const char *first, *last;
+		first = bonjour_buddy->first;
+		last = bonjour_buddy->last;
+		if ((first && *first) || (last && *last))
+			alias = g_strdup_printf("%s%s%s",
+						(first && *first ? first : ""),
+						(first && *first && last && *last ? " " : ""),
+						(last && *last ? last : ""));
+		serv_got_alias(purple_account_get_connection(account), buddy->name, alias);
+		g_free(alias);
+	}
 
 	/* Set the user's status */
 	if (bonjour_buddy->msg != NULL)
@@ -166,12 +172,46 @@
 	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 */
+		/* TODO: Make sure the hash assigned to the retrieved buddy icon is the same
+		 * as what we looked up. */
 		bonjour_dns_sd_retrieve_buddy_icon(bonjour_buddy);
-	} else
+	} else if (!new_hash)
 		purple_buddy_icons_set_for_user(account, buddy->name, NULL, 0, NULL);
 }
 
 /**
+ * We got the buddy icon data; deal with it
+ */
+void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len) {
+	/* Recalculate the hash instead of using the current phsh to make sure it is accurate for the icon. */
+	int i;
+	gchar *enc;
+	char *p, hash[41];
+	unsigned char hashval[20];
+
+	if (data == NULL || len == 0)
+		return;
+
+	enc = purple_base64_encode(data, len);
+
+	purple_cipher_digest_region("sha1", data,
+				    len, sizeof(hashval),
+				    hashval, NULL);
+
+	p = hash;
+	for(i=0; i<20; i++, p+=2)
+		snprintf(p, 3, "%02x", hashval[i]);
+
+	purple_debug_info("bonjour", "Got buddy icon for %s icon hash='%s' phsh='%s'.\n", buddy->name,
+			  hash, buddy->phsh ? buddy->phsh : "(null)");
+
+	purple_buddy_icons_set_for_user(buddy->account, buddy->name,
+		g_memdup(data, len), len, hash);
+
+	g_free(enc);
+}
+
+/**
  * Deletes a buddy from memory.
  */
 void
--- a/libpurple/protocols/bonjour/buddy.h	Wed Aug 08 01:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Thu Aug 09 02:30:03 2007 +0000
@@ -90,6 +90,11 @@
 void bonjour_buddy_add_to_purple(BonjourBuddy *buddy);
 
 /**
+ * We got the buddy icon data; deal with it
+ */
+void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len);
+
+/**
  * Deletes a buddy from memory.
  */
 void bonjour_buddy_delete(BonjourBuddy *buddy);
--- a/libpurple/protocols/bonjour/issues.txt	Wed Aug 08 01:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/issues.txt	Thu Aug 09 02:30:03 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:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Thu Aug 09 02:30:03 2007 +0000
@@ -341,10 +341,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;
 
@@ -379,7 +379,7 @@
 	buddy->mdns_impl_data = NULL;
 }
 
-void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
+void _mdns_retrieve_retrieve_buddy_icon(BonjourBuddy* buddy) {
 	PurpleConnection *conn = purple_account_get_connection(buddy->account);
 	BonjourData *bd = conn->proto_data;
 	AvahiSessionImplData *session_idata = bd->dns_sd_data->mdns_impl_data;
@@ -401,7 +401,7 @@
 		purple_debug_error("bonjour",
 			"Unable to initialize record browser.  Error: %s\n.",
 			avahi_strerror(avahi_client_errno(session_idata->client)));
-	}
+}
 
 }
 
--- a/libpurple/protocols/bonjour/mdns_common.c	Wed Aug 08 01:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Thu Aug 09 02:30:03 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:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Thu Aug 09 02:30:03 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:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Thu Aug 09 02:30:03 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:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_interface.h	Thu Aug 09 02:30:03 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:57:39 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Thu Aug 09 02:30:03 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;
 	guint browser_handler;
-	guint buddy_icon_handler;
 } Win32SessionImplData;
 
 typedef struct _win32_buddy_impl_data {
@@ -96,8 +94,7 @@
 
 			g_return_if_fail(idata != NULL);
 
-			purple_buddy_icons_set_for_user(buddy->account, buddy->name,
-							g_memdup(rdata, rdlen), rdlen, buddy->phsh);
+			bonjour_buddy_got_buddy_icon(buddy, rdata, rdlen);
 
 			/* We've got what we need; stop listening */
 			purple_input_remove(idata->null_query_handler);
@@ -126,14 +123,16 @@
 
 		/* finally, set up the continuous txt record watcher, and add the buddy to purple */
 
-		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, 0, 0, args->full_service_name,
-				kDNSServiceType_TXT, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) {
-			int fd = DNSServiceRefSockFD(idata->txt_query);
-			idata->txt_query_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query);
+		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, kDNSServiceFlagsLongLivedQuery,
+				kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT,
+				kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) {
+
+			purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj);
+
+			idata->txt_query_handler = purple_input_add(DNSServiceRefSockFD(idata->txt_query),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query);
 
 			bonjour_buddy_add_to_purple(buddy);
-
-			purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj);
 		} else
 			bonjour_buddy_delete(buddy);
 
@@ -190,7 +189,6 @@
 _mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
 				const char *name, const char *regtype, const char *domain, void *context) {
 
-	/* we don't actually care about anything said in this callback - this is only here because Bonjour for windows is broken */
 	/* TODO: deal with collision */
 	if (kDNSServiceErr_NoError != errorCode)
 		purple_debug_error("bonjour", "service advertisement - callback error (%d).\n", errorCode);
@@ -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;
 		}
 
@@ -336,9 +324,12 @@
 			purple_debug_error("bonjour", "Failed to publish presence service.\n");
 			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);
+			/* We need to do this because according to the Apple docs:
+			 * "the client is responsible for ensuring that DNSServiceProcessResult() is called
+			 * whenever there is a reply from the daemon - the daemon may terminate its connection
+			 * with a client that does not process the daemon's responses */
+			idata->presence_handler = purple_input_add(DNSServiceRefSockFD(idata->presence_svc),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_svc);
 		}
 	}
 
@@ -369,10 +360,9 @@
 	if (idata == NULL)
 		return;
 
-	if (idata->advertisement_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);
+	if (idata->presence_svc != NULL) {
+		purple_input_remove(idata->presence_handler);
+		DNSServiceRefDeallocate(idata->presence_svc);
 	}
 
 	if (idata->browser_svc != NULL) {
@@ -380,68 +370,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 +425,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 +439,12 @@
 		idata->null_query = NULL;
 	}
 
-	svc_name = g_strdup_printf("%s." ICHAT_SERVICE "local", buddy->name);
-	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, svc_name,
+	DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local");
+	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny, 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);
 
 }