static void _resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { BonjourBuddy *buddy; PurpleAccount *account = userdata; AvahiStringList *l; size_t size; char *key, *value; int ret; g_return_if_fail(r != NULL); switch (event) { case AVAHI_RESOLVER_FAILURE: purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n", avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); avahi_service_resolver_free(r); break; case AVAHI_RESOLVER_FOUND: /* create a buddy record */ buddy = bonjour_buddy_new(name, account); ((AvahiBuddyImplData *)buddy->mdns_impl_data)->resolver = r; /* Get the ip as a string */ buddy->ip = g_malloc(AVAHI_ADDRESS_STR_MAX); avahi_address_snprint(buddy->ip, AVAHI_ADDRESS_STR_MAX, a); buddy->port_p2pj = port; /* Obtain the parameters from the text_record */ clear_bonjour_buddy_values(buddy); l = txt; while (l != NULL) { ret = avahi_string_list_get_pair(l, &key, &value, &size); l = l->next; if (ret < 0) continue; set_bonjour_buddy_value(buddy, key, value, size); /* TODO: Since we're using the glib allocator, I think we * can use the values instead of re-copying them */ avahi_free(key); avahi_free(value); } if (!bonjour_buddy_check(buddy)) bonjour_buddy_delete(buddy); else /* Add or update the buddy in our buddy list */ bonjour_buddy_add_to_purple(buddy); break; default: purple_debug_info("bonjour", "Unrecognized Service Resolver event: %d.\n", event); } }
static void _resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { PurpleBuddy *pb; BonjourBuddy *bb; PurpleAccount *account = userdata; AvahiStringList *l; size_t size; char *key, *value; char ip[AVAHI_ADDRESS_STR_MAX]; AvahiBuddyImplData *b_impl; AvahiSvcResolverData *rd; GSList *res; g_return_if_fail(r != NULL); pb = purple_find_buddy(account, name); bb = (pb != NULL) ? purple_buddy_get_protocol_data(pb) : NULL; switch (event) { case AVAHI_RESOLVER_FAILURE: purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n", avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); avahi_service_resolver_free(r); if (bb != NULL) { b_impl = bb->mdns_impl_data; res = g_slist_find_custom(b_impl->resolvers, r, _find_resolver_data_by_resolver); if (res != NULL) { rd = res->data; b_impl->resolvers = g_slist_remove_link(b_impl->resolvers, res); /* We've already freed the resolver */ rd->resolver = NULL; _cleanup_resolver_data(rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) bonjour_buddy_signed_off(pb); } } break; case AVAHI_RESOLVER_FOUND: purple_debug_info("bonjour", "_resolve_callback - name:%s account:%p bb:%p\n", name, account, bb); /* create a buddy record */ if (bb == NULL) bb = bonjour_buddy_new(name, account); b_impl = bb->mdns_impl_data; /* If we're reusing an existing buddy, it may be a new resolver or an existing one. */ res = g_slist_find_custom(b_impl->resolvers, r, _find_resolver_data_by_resolver); if (res != NULL) rd = res->data; else { rd = g_new0(AvahiSvcResolverData, 1); rd->resolver = r; rd->interface = interface; rd->protocol = protocol; rd->name = g_strdup(name); rd->type = g_strdup(type); rd->domain = g_strdup(domain); b_impl->resolvers = g_slist_prepend(b_impl->resolvers, rd); } /* Get the ip as a string */ ip[0] = '\0'; avahi_address_snprint(ip, AVAHI_ADDRESS_STR_MAX, a); purple_debug_info("bonjour", "_resolve_callback - name:%s ip:%s prev_ip:%s\n", name, ip, rd->ip); if (rd->ip == NULL || strcmp(rd->ip, ip) != 0) { /* We store duplicates in bb->ips, so we always remove the one */ if (rd->ip != NULL) { bb->ips = g_slist_remove(bb->ips, rd->ip); g_free((gchar *) rd->ip); } /* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */ if (protocol == AVAHI_PROTO_INET6) { rd->ip = g_strdup_printf("%s%%%d", ip, interface); bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip); } else { rd->ip = g_strdup(ip); bb->ips = g_slist_append(bb->ips, (gchar *) rd->ip); } } bb->port_p2pj = port; /* Obtain the parameters from the text_record */ clear_bonjour_buddy_values(bb); for(l = txt; l != NULL; l = l->next) { if (avahi_string_list_get_pair(l, &key, &value, &size) < 0) continue; set_bonjour_buddy_value(bb, key, value, size); /* TODO: Since we're using the glib allocator, I think we * can use the values instead of re-copying them */ avahi_free(key); avahi_free(value); } if (!bonjour_buddy_check(bb)) { b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd); _cleanup_resolver_data(rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) { if (pb != NULL) bonjour_buddy_signed_off(pb); else bonjour_buddy_delete(bb); } } else /* Add or update the buddy in our buddy list */ bonjour_buddy_add_to_purple(bb, pb); break; default: purple_debug_info("bonjour", "Unrecognized Service Resolver event: %d.\n", event); } }