# HG changeset patch # User Daniel Atallah # Date 1186282248 0 # Node ID 83719d57a8eea1f39d7a8ea1b336eba923f1d0d2 # Parent ed1def07d86e1a71b33dd225481f94eb4f7bab92 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. diff -r ed1def07d86e -r 83719d57a8ee libpurple/protocols/bonjour/buddy.c --- 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); diff -r ed1def07d86e -r 83719d57a8ee libpurple/protocols/bonjour/buddy.h --- 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; diff -r ed1def07d86e -r 83719d57a8ee libpurple/protocols/bonjour/mdns_common.h --- 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. */ diff -r ed1def07d86e -r 83719d57a8ee libpurple/protocols/bonjour/mdns_howl.c --- 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) { +} diff -r ed1def07d86e -r 83719d57a8ee libpurple/protocols/bonjour/mdns_win32.c --- 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); + } + +} +