Пример #1
0
static bool
thex_download_handle_hashtree(struct thex_download *ctx,
	const char *data, size_t size)
{
	bool success = FALSE;
	size_t n_nodes, n_leaves, n, start;
	unsigned good_depth;
	const struct tth *leaves;
	struct tth tth;

	if (size <= 0) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree record has no data");
		}
		goto finish;
	}
	if (size < TTH_RAW_SIZE) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree record is too small");
		}
		goto finish;
	}
	if (size % TTH_RAW_SIZE) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree has bad size");
		}
		goto finish;
	}
	memcpy(tth.data, data, TTH_RAW_SIZE);
	if (!tth_eq(&tth, ctx->tth)) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree has different root hash %s",
				tth_base32(&tth));
		}
		goto finish;
	}

	n_nodes = size / TTH_RAW_SIZE;
	n_leaves = tt_node_count_at_depth(ctx->filesize, ctx->depth);

	/* Shareaza uses a fixed depth of 9, allow one level less like others */
	good_depth = tt_good_depth(ctx->filesize);

	ctx->depth = MIN(ctx->depth, good_depth);
	if (n_nodes < n_leaves * 2 - 1) {
		ctx->depth = good_depth;
		n = tt_node_count_at_depth(ctx->filesize, ctx->depth);
		n = n * 2 - 1; /* All nodes, not just leaves */
		while (n > n_nodes) {
			n = (n + 1) / 2;
			ctx->depth--;
		}
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH calculated depth of hashtree: %u", ctx->depth);
		}
		n_leaves = tt_node_count_at_depth(ctx->filesize, ctx->depth);
	}

	if (ctx->depth < good_depth) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH tree depth (%u) is below the good depth (%u)",
				ctx->depth, good_depth);
		}
	}

	start = 0;
	n = n_leaves;
	while (n > 1) {
		n = (n + 1) / 2;
		start += n;
	}

	if (n_nodes < start + n_leaves) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree has too few nodes "
				"(filesize=%s depth=%u nodes=%zu expected=%zu)",
				filesize_to_string(ctx->filesize),
				ctx->depth, n_nodes, n_leaves * 2 - 1);
		}
		goto finish;
	}
	
	STATIC_ASSERT(TTH_RAW_SIZE == sizeof(struct tth));
	leaves = (const struct tth *) &data[start * TTH_RAW_SIZE];

	tth = tt_root_hash(leaves, n_leaves);
	if (!tth_eq(&tth, ctx->tth)) {
		if (GNET_PROPERTY(tigertree_debug)) {
			g_debug("TTH hashtree does not match root hash %s",
				tth_base32(&tth));
		}
		goto finish;
	}

	ctx->leaves = g_memdup(leaves, TTH_RAW_SIZE * n_leaves);
	ctx->num_leaves = n_leaves;
	success = TRUE;

finish:
	return success;
}
Пример #2
0
size_t
tt_good_node_count(filesize_t filesize)
{
	return tt_node_count_at_depth(filesize, tt_good_depth(filesize));
}