예제 #1
0
/**
 * Writes the browse host data of the context ``ctx'' to the buffer
 * ``dest''. This must be called multiple times to retrieve the complete
 * data until zero is returned i.e., the end of file is reached.
 *
 * This routine deals with query hit data generation.
 *
 * @param ctx an initialized browse host context.
 * @param dest the destination buffer.
 * @param size the amount of bytes ``dest'' can hold.
 *
 * @return -1 on failure, zero at the end-of-file condition or if size
 *         was zero. On success, the amount of bytes copied to ``dest''
 *         is returned.
 */
static ssize_t
browse_host_read_qhits(struct special_upload *ctx,
	void *const dest, size_t size)
{
	struct browse_host_upload *bh = cast_to_browse_host_upload(ctx);
	size_t remain = size;
	char *p = dest;

	/*
	 * If we have no hit pending that we can send, build some more.
	 */

	if (NULL == bh->hits) {
		pslist_t *files = NULL, *sl;
		int i;

		for (i = 0; i < BH_SCAN_AHEAD; i++) {
			shared_file_t *sf;

			do {
				/* Skip holes in indices */
				bh->file_index++;
				sf = shared_file_sorted(bh->file_index);
			} while (NULL == sf && bh->file_index <= shared_files_scanned());

			if (SHARE_REBUILDING == sf || NULL == sf)
				break;

			files = pslist_prepend(files, sf);
		}

		if (NULL == files)		/* Did not find any more file to include */
			return 0;			/* We're done */

		/*
		 * Now build the query hits containing the files we selected.
		 */

		files = pslist_reverse(files);			/* Preserve order */

		if (bh->flags & BH_F_G2) {
			g2_build_qh2_results(files, i, BH_MAX_QH2_SIZE,
				browse_host_record_qh2, bh, &blank_guid, 0);
		} else {
			qhit_build_results(files, i, BH_MAX_QHIT_SIZE,
				browse_host_record_hit, bh, &blank_guid, 0, &zero_array);
		}

		g_assert(bh->hits != NULL);		/* At least 1 hit enqueued */

		bh->hits = pslist_reverse(bh->hits);	/* Preserve order */
		PSLIST_FOREACH(files, sl) {
			shared_file_t *sf = sl->data;
			shared_file_unref(&sf);
		}
예제 #2
0
static pslist_t *
resolve_hostname(const char *host, enum net_type net)
#ifdef HAS_GETADDRINFO
{
	static const struct addrinfo zero_hints;
	struct addrinfo hints, *ai, *ai0 = NULL;
	hset_t *hs;
	pslist_t *sl_addr;
	int error;

	g_assert(host);

	hints = zero_hints;
	hints.ai_family = net_type_to_pf(net);

	error = getaddrinfo(host, NULL, &hints, &ai0);
	if (error) {
		g_message("getaddrinfo() failed for \"%s\": %s",
				host, gai_strerror(error));
		return NULL;
	}

	sl_addr = NULL;
	hs = hset_create_any(host_addr_hash_func, NULL, host_addr_eq_func);
	for (ai = ai0; ai; ai = ai->ai_next) {
		host_addr_t addr;

		if (!ai->ai_addr)
			continue;

		addr = addrinfo_to_addr(ai);

		if (is_host_addr(addr) && !hset_contains(hs, &addr)) {
			host_addr_t *addr_copy;

			addr_copy = WCOPY(&addr);
			sl_addr = pslist_prepend(sl_addr, addr_copy);
			hset_insert(hs, addr_copy);
		}
	}
	hset_free_null(&hs);

	if (ai0)
		freeaddrinfo(ai0);

	return pslist_reverse(sl_addr);
}