--- a/libpurple/protocols/bonjour/mdns_win32.c Sat Oct 02 23:04:49 2010 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Mon Oct 04 00:35:26 2010 +0000 @@ -25,7 +25,6 @@ #include "buddy.h" #include "mdns_interface.h" #include "dns_sd_proxy.h" -#include "dnsquery.h" #include "mdns_common.h" static GSList *pending_buddies = NULL; @@ -65,7 +64,6 @@ BonjourBuddy *bb; Win32SvcResolverData *res_data; gchar *full_service_name; - PurpleDnsQueryData *dns_query; } ResolveCallbackArgs; @@ -135,7 +133,7 @@ { if (errorCode != kDNSServiceErr_NoError) { - purple_debug_error("bonjour", "record query - callback error.\n"); + purple_debug_error("bonjour", "record query - callback error (%d).\n", errorCode); /* TODO: Probably should remove the buddy when this happens */ } else if (flags & kDNSServiceFlagsAdd) { if (rrtype == kDNSServiceType_TXT) { @@ -161,14 +159,22 @@ } } -static void -_mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) +static void DNSSD_API +_mdns_resolve_host_callback(DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *hostname, const struct sockaddr *address, + uint32_t ttl, void *context) { - ResolveCallbackArgs *args = (ResolveCallbackArgs*) data; + ResolveCallbackArgs *args = (ResolveCallbackArgs*) context; Win32BuddyImplData *idata = args->bb->mdns_impl_data; gboolean delete_buddy = FALSE; PurpleBuddy *pb = NULL; + purple_input_remove(args->resolver_query->input_handler); + DNSServiceRefDeallocate(args->resolver_query->sdRef); + g_free(args->resolver_query); + args->resolver_query = NULL; + if ((pb = purple_find_buddy(args->account, args->res_data->name))) { if (pb->proto_data != args->bb) { purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.", @@ -181,12 +187,10 @@ goto cleanup; } - if (!hosts || !hosts->data) { - purple_debug_error("bonjour", "host resolution - callback error.\n"); + if (errorCode != kDNSServiceErr_NoError) { + purple_debug_error("bonjour", "host resolution - callback error (%d).\n", errorCode); delete_buddy = TRUE; } else { - struct sockaddr_in *addr = g_slist_nth_data(hosts, 1); - DNSServiceErrorType errorCode; DNSServiceRef txt_query_sr; /* finally, set up the continuous txt record watcher, and add the buddy to purple */ @@ -194,7 +198,7 @@ kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, kDNSServiceClass_IN, _mdns_record_query_callback, args->bb); if (errorCode == kDNSServiceErr_NoError) { - const char *ip = inet_ntoa(addr->sin_addr); + const char *ip = inet_ntoa(((struct sockaddr_in *) address)->sin_addr); purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); @@ -218,13 +222,6 @@ cleanup: - /* free the hosts list*/ - while (hosts != NULL) { - hosts = g_slist_remove(hosts, hosts->data); - g_free(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - } - if (delete_buddy) { idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); _cleanup_resolver_data(args->res_data); @@ -259,17 +256,20 @@ /* remove the input fd and destroy the service ref */ purple_input_remove(args->resolver_query->input_handler); DNSServiceRefDeallocate(args->resolver_query->sdRef); - g_free(args->resolver_query); - args->resolver_query = NULL; if (errorCode != kDNSServiceErr_NoError) - purple_debug_error("bonjour", "service resolver - callback error.\n"); + purple_debug_error("bonjour", "service resolver - callback error. (%d)\n", errorCode); else { + DNSServiceRef getaddrinfo_sr; /* set more arguments, and start the host resolver */ - - if ((args->dns_query = - purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) { - + errorCode = DNSServiceGetAddrInfo(&getaddrinfo_sr, 0, interfaceIndex, + kDNSServiceProtocol_IPv4, hosttarget, _mdns_resolve_host_callback, args); + if (errorCode != kDNSServiceErr_NoError) + purple_debug_error("bonjour", "service resolver - host resolution failed.\n"); + else { + args->resolver_query->sdRef = getaddrinfo_sr; + args->resolver_query->input_handler = purple_input_add(DNSServiceRefSockFD(getaddrinfo_sr), + PURPLE_INPUT_READ, _mdns_handle_event, args->resolver_query); args->full_service_name = g_strdup(fullname); /* TODO: Should this be per resolver? */ @@ -277,12 +277,14 @@ /* We don't want to hit the cleanup code */ return; - } else - purple_debug_error("bonjour", "service resolver - host resolution failed.\n"); + } } /* If we get this far, clean up */ + g_free(args->resolver_query); + args->resolver_query = NULL; + idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); _cleanup_resolver_data(args->res_data); @@ -334,7 +336,7 @@ serviceName, interfaceIndex, regtype ? regtype : "", replyDomain ? replyDomain : ""); - resErrorCode = DNSServiceResolve(&resolver_sr, 0, 0, serviceName, regtype, + resErrorCode = DNSServiceResolve(&resolver_sr, 0, interfaceIndex, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args); if (resErrorCode == kDNSServiceErr_NoError) { GSList *tmp = pending_buddies; @@ -483,7 +485,8 @@ switch (type) { case PUBLISH_START: purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); - errorCode = DNSServiceRegister(&presence_sr, 0, 0, purple_account_get_username(data->account), LINK_LOCAL_RECORD_NAME, + errorCode = DNSServiceRegister(&presence_sr, kDNSServiceInterfaceIndexAny, + 0, purple_account_get_username(data->account), LINK_LOCAL_RECORD_NAME, NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), _mdns_service_register_callback, NULL); break; @@ -522,8 +525,9 @@ g_return_val_if_fail(idata != NULL, FALSE); - errorCode = DNSServiceBrowse(&browser_sr, 0, 0, LINK_LOCAL_RECORD_NAME, NULL, - _mdns_service_browse_callback, data->account); + errorCode = DNSServiceBrowse(&browser_sr, 0, kDNSServiceInterfaceIndexAny, + LINK_LOCAL_RECORD_NAME, NULL,_mdns_service_browse_callback, + data->account); if (errorCode == kDNSServiceErr_NoError) { idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1); idata->browser_query->sdRef = browser_sr;