Example #1
0
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);
	}

}
Example #2
0
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);
	}

}