changeset 18843:7bf6b9a70b41

Some more minor mdns implementation abstraction tweaks and implementation of setting buddy icons for the win32 bonjour implementation.
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 08 Aug 2007 01:50:01 +0000
parents 03a0054954bb
children a53992a4437a 09f52521ff5b
files libpurple/protocols/bonjour/bonjour.c libpurple/protocols/bonjour/buddy.c libpurple/protocols/bonjour/buddy.h 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 9 files changed, 222 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/bonjour.c	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Wed Aug 08 01:50:01 2007 +0000
@@ -138,6 +138,8 @@
 		return;
 	}
 
+	bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
+
 	/* Create a group for bonjour buddies */
 	bonjour_group = purple_group_new(BONJOUR_GROUP_NAME);
 	purple_blist_add_group(bonjour_group, NULL);
@@ -283,6 +285,14 @@
 	bb->conversation = NULL;
 }
 
+static
+void bonjour_set_buddy_icon(PurpleConnection *conn, PurpleStoredImage *img)
+{
+	BonjourData *bd = conn->proto_data;
+	bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
+}
+
+
 static char *
 bonjour_status_text(PurpleBuddy *buddy)
 {
@@ -339,8 +349,7 @@
 	OPT_PROTO_NO_PASSWORD,
 	NULL,                                                    /* user_splits */
 	NULL,                                                    /* protocol_options */
-	/* {"png", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, */ /* icon_spec */
-	NO_BUDDY_ICONS, /* not yet */                            /* icon_spec */
+	{"png,gif,jpeg", 0, 0, 96, 96, 65535, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
 	bonjour_list_icon,                                       /* list_icon */
 	NULL,													 /* list_emblem */
 	bonjour_status_text,                                     /* status_text */
@@ -384,7 +393,7 @@
 	NULL,                                                    /* buddy_free */
 	bonjour_convo_closed,                                    /* convo_closed */
 	NULL,                                                    /* normalize */
-	NULL,                                                    /* set_buddy_icon */
+	bonjour_set_buddy_icon,                                  /* set_buddy_icon */
 	NULL,                                                    /* remove_group */
 	NULL,                                                    /* get_cb_real_name */
 	NULL,                                                    /* set_chat_topic */
@@ -533,7 +542,7 @@
 	{
 		default_firstname = g_strndup(fullname, splitpoint - fullname);
 		tmp = &splitpoint[1];
-		
+
 		/* The last name may be followed by a comma and additional data.
 		 * Only use the last name itself.
 		 */
--- a/libpurple/protocols/bonjour/buddy.c	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Wed Aug 08 01:50:01 2007 +0000
@@ -179,8 +179,6 @@
 {
 	g_free(buddy->name);
 	g_free(buddy->ip);
-	g_free(buddy->full_service_name);
-
 	g_free(buddy->first);
 	g_free(buddy->phsh);
 	g_free(buddy->status);
--- a/libpurple/protocols/bonjour/buddy.h	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Wed Aug 08 01:50:01 2007 +0000
@@ -29,7 +29,6 @@
 	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_avahi.c	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Wed Aug 08 01:50:01 2007 +0000
@@ -317,11 +317,10 @@
 	return TRUE;
 }
 
-/* This is done differently than with Howl/Apple Bonjour */
-guint _mdns_register_to_mainloop(BonjourDnsSd *data) {
-	return 0;
+void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
 }
 
+
 void _mdns_stop(BonjourDnsSd *data) {
 	AvahiSessionImplData *idata = data->mdns_impl_data;
 
--- a/libpurple/protocols/bonjour/mdns_common.c	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Wed Aug 08 01:50:01 2007 +0000
@@ -17,11 +17,13 @@
 #include <string.h>
 
 #include "internal.h"
+#include "cipher.h"
+#include "debug.h"
+
 #include "mdns_common.h"
 #include "mdns_interface.h"
 #include "bonjour.h"
 #include "buddy.h"
-#include "debug.h"
 
 
 /**
@@ -54,8 +56,7 @@
  * Send a new dns-sd packet updating our status.
  */
 void
-bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message)
-{
+bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message) {
 	g_free(data->status);
 	g_free(data->msg);
 
@@ -66,6 +67,70 @@
 	_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);
+}
+
+void
+bonjour_dns_sd_update_buddy_icon(BonjourDnsSd *data) {
+	PurpleStoredImage *img;
+
+	if ((img = purple_buddy_icons_find_account_icon(data->account))) {
+		gconstpointer avatar_data;
+		gsize avatar_len;
+
+		avatar_data = purple_imgstore_get_data(img);
+		avatar_len = purple_imgstore_get_size(img);
+
+		_mdns_set_buddy_icon_data(data, avatar_data, avatar_len);
+
+		purple_imgstore_unref(img);
+	} else {
+		/* We need to do this regardless of whether data->phsh is set so that we
+		 * cancel any icons that are currently in the process of being set */
+		_mdns_set_buddy_icon_data(data, NULL, 0);
+		if (data->phsh != NULL) {
+			/* Clear the buddy icon */
+			g_free(data->phsh);
+			data->phsh = NULL;
+			/* Update our TXT record */
+			_mdns_publish(data, PUBLISH_UPDATE);
+		}
+	}
+}
+
 /**
  * Advertise our presence within the dns-sd daemon and start browsing
  * for other bonjour peers.
@@ -91,11 +156,6 @@
 		return FALSE;
 	}
 
-
-	/* Get the socket that communicates with the mDNS daemon and bind it to a */
-	/* callback that will handle the dns_sd packets */
-	gc->inpa = _mdns_register_to_mainloop(data);
-
 	return TRUE;
 }
 
@@ -104,13 +164,6 @@
  */
 
 void
-bonjour_dns_sd_stop(BonjourDnsSd *data)
-{
-	PurpleConnection *gc;
-
+bonjour_dns_sd_stop(BonjourDnsSd *data) {
 	_mdns_stop(data);
-
-	gc = purple_account_get_connection(data->account);
-	if (gc->inpa > 0)
-		purple_input_remove(gc->inpa);
 }
--- a/libpurple/protocols/bonjour/mdns_common.h	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Wed Aug 08 01:50:01 2007 +0000
@@ -42,6 +42,16 @@
 void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy);
 
 /**
+ * Deal with a buddy icon update
+ */
+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:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Wed Aug 08 01:50:01 2007 +0000
@@ -26,6 +26,7 @@
 typedef struct _howl_impl_data {
 	sw_discovery session;
 	sw_discovery_oid session_id;
+	guint session_handler;
 } HowlSessionImplData;
 
 static sw_result HOWL_API
@@ -276,18 +277,19 @@
 
 	g_return_val_if_fail(idata != NULL, FALSE);
 
-	return (sw_discovery_browse(idata->session, 0, ICHAT_SERVICE, NULL, _browser_reply,
-				    data->account, &session_id) == SW_OKAY);
+	if (sw_discovery_browse(idata->session, 0, ICHAT_SERVICE, NULL, _browser_reply,
+				    data->account, &session_id) == SW_OKAY) {
+		idata->session_handler = purple_input_add(sw_discovery_socket(idata->session),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->session);
+		return TRUE;
+	}
+
+	return FALSE;
 }
 
-guint _mdns_register_to_mainloop(BonjourDnsSd *data) {
-	HowlSessionImplData *idata = data->mdns_impl_data;
+void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
+}
 
-	g_return_val_if_fail(idata != NULL, 0);
-
-	return purple_input_add(sw_discovery_socket(idata->session),
-				PURPLE_INPUT_READ, _mdns_handle_event, idata->session);
-}
 
 void _mdns_stop(BonjourDnsSd *data) {
 	HowlSessionImplData *idata = data->mdns_impl_data;
@@ -297,6 +299,8 @@
 
 	sw_discovery_cancel(idata->session, idata->session_id);
 
+	purple_input_remove(idata->session_handler);
+
 	/* TODO: should this really be g_free()'d ??? */
 	g_free(idata->session);
 
@@ -313,3 +317,5 @@
 
 void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
 }
+
+
--- a/libpurple/protocols/bonjour/mdns_interface.h	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_interface.h	Wed Aug 08 01:50:01 2007 +0000
@@ -26,9 +26,9 @@
 
 gboolean _mdns_browse(BonjourDnsSd *data);
 
-guint _mdns_register_to_mainloop(BonjourDnsSd *data);
+void _mdns_stop(BonjourDnsSd *data);
 
-void _mdns_stop(BonjourDnsSd *data);
+void _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len);
 
 void _mdns_init_buddy(BonjourBuddy *buddy);
 
--- a/libpurple/protocols/bonjour/mdns_win32.c	Wed Aug 08 01:35:56 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Wed Aug 08 01:50:01 2007 +0000
@@ -21,12 +21,14 @@
 #include "mdns_interface.h"
 #include "dns_sd_proxy.h"
 #include "dnsquery.h"
+#include "mdns_common.h"
 
 
 /* data structure for the resolve callback */
 typedef struct _ResolveCallbackArgs {
 	DNSServiceRef resolver;
 	guint resolver_handler;
+	gchar *full_service_name;
 
 	PurpleDnsQueryData *query;
 
@@ -35,10 +37,14 @@
 
 /* data used by win32 bonjour implementation */
 typedef struct _win32_session_impl_data {
-	DNSServiceRef advertisement;
-	DNSServiceRef browser;
+	DNSServiceRef advertisement_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 browser_handler;
+	guint buddy_icon_handler;
 } Win32SessionImplData;
 
 typedef struct _win32_buddy_impl_data {
@@ -120,7 +126,7 @@
 
 		/* finally, set up the continuous txt record watcher, and add the buddy to purple */
 
-		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, 0, 0, buddy->full_service_name,
+		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);
@@ -138,6 +144,7 @@
 
 	/* free the remaining args memory */
 	purple_dnsquery_destroy(args->query);
+	g_free(args->full_service_name);
 	g_free(args);
 }
 
@@ -165,13 +172,14 @@
 		_mdns_parse_text_record(args->buddy, txtRecord, txtLen);
 
 		/* set more arguments, and start the host resolver */
-		args->buddy->full_service_name = g_strdup(fullname);
+		args->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->full_service_name);
 			g_free(args);
 		}
 	}
@@ -180,16 +188,28 @@
 
 static void DNSSD_API
 _mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
-    const char *name, const char *regtype, const char *domain, void *context)
-{
+				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.\n");
+		purple_debug_error("bonjour", "service advertisement - callback error (%d).\n", errorCode);
 	else
 		purple_debug_info("bonjour", "service advertisement - callback.\n");
 }
 
 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)
 {
@@ -302,13 +322,13 @@
 		switch (type) {
 			case PUBLISH_START:
 				purple_debug_info("bonjour", "Registering service on port %d\n", data->port_p2pj);
-				err = DNSServiceRegister(&idata->advertisement, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
+				err = DNSServiceRegister(&idata->advertisement_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, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
+				err = DNSServiceUpdateRecord(idata->advertisement_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
 				break;
 		}
 
@@ -317,8 +337,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 */
-			gint fd = DNSServiceRefSockFD(idata->advertisement);
-			idata->advertisement_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->advertisement);
+			idata->advertisement_handler = purple_input_add(DNSServiceRefSockFD(idata->advertisement_svc),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->advertisement_svc);
 		}
 	}
 
@@ -332,37 +352,96 @@
 
 	g_return_val_if_fail(idata != NULL, FALSE);
 
-	return (DNSServiceBrowse(&idata->browser, 0, 0, ICHAT_SERVICE, NULL,
+	if (DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL,
 				 _mdns_service_browse_callback, data->account)
-			== kDNSServiceErr_NoError);
-}
+			== kDNSServiceErr_NoError) {
+		idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc),
+			PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc);
+		return TRUE;
+	}
 
-guint _mdns_register_to_mainloop(BonjourDnsSd *data) {
-	Win32SessionImplData *idata = data->mdns_impl_data;
-
-	g_return_val_if_fail(idata != NULL, 0);
-
-	return purple_input_add(DNSServiceRefSockFD(idata->browser),
-				PURPLE_INPUT_READ, _mdns_handle_event, idata->browser);
+	return FALSE;
 }
 
 void _mdns_stop(BonjourDnsSd *data) {
 	Win32SessionImplData *idata = data->mdns_impl_data;
 
-	if (idata == NULL || idata->advertisement == NULL || idata->browser == NULL)
+	if (idata == NULL)
 		return;
 
-	/* hack: for win32, we need to stop listening to the advertisement pipe too */
-	purple_input_remove(idata->advertisement_handler);
+	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);
+	}
 
-	DNSServiceRefDeallocate(idata->advertisement);
-	DNSServiceRefDeallocate(idata->browser);
+	if (idata->browser_svc != NULL) {
+		purple_input_remove(idata->browser_handler);
+		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) {
+	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);
+
+			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;
+	} 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) {
+		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;
+		idata->buddy_icon_rec = NULL;
+	}
+
+	if (err != kDNSServiceErr_NoError)
+		purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", err);
+}
+
+
 void _mdns_init_buddy(BonjourBuddy *buddy) {
 	buddy->mdns_impl_data = g_new0(Win32BuddyImplData, 1);
 }
@@ -389,6 +468,7 @@
 
 void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) {
 	Win32BuddyImplData *idata = buddy->mdns_impl_data;
+	gchar *svc_name;
 
 	g_return_if_fail(idata != NULL);
 
@@ -400,11 +480,13 @@
 		idata->null_query = NULL;
 	}
 
-	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, buddy->full_service_name,
+	svc_name = g_strdup_printf("%s." ICHAT_SERVICE "local", buddy->name);
+	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, svc_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);
+		idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query),
+			PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
 	}
+	g_free(svc_name);
 
 }