예제 #1
0
static size_t
thex_upload_prepare_xml(char **data_ptr, const struct tth *tth,
	filesize_t filesize)
{
	struct dime_record *dime;
	char buf[512];
	size_t len, size;
	unsigned depth;

	depth = tt_good_depth(filesize);
	len = concat_strings(buf, sizeof buf,
		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
		"<!DOCTYPE hashtree S"	/* NOTE: HIDE FROM METACONFIG */
			"YSTEM \""			THEX_DOCTYPE "\">\r\n"
		"<hashtree>\r\n"
		"<file"
			" size=\"",			filesize_to_string(filesize), "\""
			" segmentsize=\""	THEX_SEGMENT_SIZE "\"/>\r\n"
		"<digest"
			" algorithm=\""		THEX_HASH_ALGO "\""
			" outputsize=\""	THEX_HASH_SIZE "\"/>\r\n"
		"<serializedtree"
			" depth=\"",		uint32_to_string(depth), "\""
			" type=\""			THEX_TREE_TYPE "\""
			" uri=\"",			thex_upload_uuid(tth), "\"/>\r\n"
		"</hashtree>\r\n",
		(void *) 0);

	dime = dime_record_alloc();
	dime_record_set_data(dime, buf, len);
	dime_record_set_type_mime(dime, "text/xml");
	size = dime_create_record(dime, data_ptr, TRUE, FALSE);
	dime_record_free(&dime);
	return size;
}
예제 #2
0
filesize_t
tt_good_slice_size(filesize_t filesize)
{
	filesize_t n_blocks;
	size_t n_nodes;
	
	n_blocks = tt_block_count(filesize);
   	n_nodes = (1 << tt_good_depth(filesize));
	return (n_blocks / n_nodes) * TTH_BLOCKSIZE;
}
예제 #3
0
void
tt_init(TTH_CONTEXT *ctx, filesize_t filesize)
{
	g_assert(ctx);

	ctx->block_fill = 1;
	ctx->block.bytes[0] = 0x00;
	ctx->si = 0;
	ctx->li = 0;
	ctx->n = 0;
	ctx->bpl = tt_blocks_per_leaf(filesize);
	ctx->depth = 0;
	ctx->good_depth = tt_good_depth(filesize);
	ctx->flags = TTH_F_INITIALIZED;
}
예제 #4
0
static filesize_t 
tt_blocks_per_leaf(filesize_t filesize)
{
	unsigned full_depth, good_depth;
	filesize_t n_bpl;

	good_depth = tt_good_depth(filesize);
	full_depth = tt_full_depth(filesize);
	if (full_depth > good_depth) {
		n_bpl = (filesize_t) 1 << (full_depth - good_depth);
	} else {
		n_bpl = 1;
	}
	return n_bpl; 
}
예제 #5
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;
}
예제 #6
0
size_t
tt_good_node_count(filesize_t filesize)
{
	return tt_node_count_at_depth(filesize, tt_good_depth(filesize));
}