示例#1
0
/**
 * Finalize hashing and optionally store calculated hash into the given array.
 * If the result parameter is NULL, the hash is not stored, but it is
 * accessible by torrent_get_btih().
 *
 * @param ctx the algorithm context containing current hashing state
 * @param result pointer to the array store message hash into
 */
void torrent_final(torrent_ctx *ctx, unsigned char result[20])
{
  unsigned char hash[20];
  if(ctx->index > 0) {
    SHA1_FINAL(ctx, hash);
    BT_ADD_HASH(ctx, hash);
  }

  make_torrent(ctx);
  if(result) memcpy(result, ctx->btih, btih_hash_size);
}
示例#2
0
文件: torrent.c 项目: cicku/RHash
/**
 * Store a SHA1 hash of a processed file piece.
 *
 * @param ctx torrent algorithm context
 * @return non-zero on success, zero on fail
 */
static int bt_store_piece_sha1(torrent_ctx *ctx)
{
	unsigned char* block;
	unsigned char* hash;

	if((ctx->piece_count % BT_BLOCK_SIZE) == 0) {
		block = (unsigned char*)malloc(BT_HASH_SIZE * BT_BLOCK_SIZE);
		if(block == NULL || !bt_vector_add_ptr(&ctx->hash_blocks, block)) {
			if(block) free(block);
			return 0;
		}
	} else {
		block = (unsigned char*)(ctx->hash_blocks.array[ctx->piece_count / BT_BLOCK_SIZE]);
	}

	hash = &block[BT_HASH_SIZE * (ctx->piece_count % BT_BLOCK_SIZE)];
	SHA1_FINAL(ctx, hash); /* write the hash */
	ctx->piece_count++;
	return 1;
}
示例#3
0
/**
 * Calculate message hash.
 * Can be called repeatedly with chunks of the message to be hashed.
 *
 * @param ctx the algorithm context containing current hashing state
 * @param msg message chunk
 * @param size length of the message chunk
 */
void torrent_update(torrent_ctx *ctx, const void* msg, size_t size)
{
  unsigned char hash[20];
  const unsigned char* pmsg = (const unsigned char*)msg;
  size_t rest = (size_t)(ctx->piece_length - ctx->index);
  assert(ctx->index < ctx->piece_length);

  while(size > 0) {
    size_t left = (size < rest ? size : rest);
    SHA1_UPDATE(ctx, pmsg, left);
    if(size < rest) {
      ctx->index += left;
      break;
    }
    SHA1_FINAL(ctx, hash);
    BT_ADD_HASH(ctx, hash); /* store a piece hash */
    SHA1_INIT(ctx);
    ctx->index = 0;

    pmsg += rest;
    size -= rest;
    rest = ctx->piece_length;
  }
}
示例#4
0
文件: torrent.c 项目: cicku/RHash
/**
 * Generate torrent file content
 * @see http://wiki.theory.org/BitTorrentSpecification
 *
 * @param ctx the torrent algorithm context
 */
static void bt_generate_torrent(torrent_ctx *ctx)
{
	uint64_t total_size = 0;
	size_t info_start_pos;

	assert(ctx->content.str == NULL);

	if(ctx->piece_length == 0) {
		if(ctx->files.size == 1) {
			total_size = ((bt_file_info*)ctx->files.array[0])->size;
		}
		ctx->piece_length = bt_default_piece_length(total_size);
	}

	/* write torrent header to the ctx->torrent string buffer */
	if((ctx->options & BT_OPT_INFOHASH_ONLY) == 0) {
		bt_str_append(ctx, "d");
		if(ctx->announce) {
			bt_bencode_str(ctx, "8:announce", ctx->announce);
		}

		if(ctx->program_name) {
			bt_bencode_str(ctx, "10:created by", ctx->program_name);
		}
		bt_bencode_int(ctx, "13:creation date", (uint64_t)time(NULL));
	}

	bt_str_append(ctx, "8:encoding5:UTF-8");

	bt_str_append(ctx, "4:infod"); /* start info dictionary */
	info_start_pos = ctx->content.length - 1;

	if(ctx->files.size > 1) {
		size_t i;

		/* process batch torrent */
		bt_str_append(ctx, "5:filesl"); /* start list of files */

		/* write length and path for each file in the batch */
		for(i = 0; i < ctx->files.size; i++) {
			bt_file_info_append(ctx, "d6:length", "4:pathl",
				(bt_file_info*)ctx->files.array[i]);
			bt_str_append(ctx, "ee");
		}
		/* note: get_batch_name modifies path, so should be called here */
		bt_bencode_str(ctx, "e4:name", get_batch_name(
			((bt_file_info*)ctx->files.array[0])->path));
	}
	else if(ctx->files.size > 0) {
		/* write size and basename of the first file */
		/* in the non-batch mode other files are ignored */
		bt_file_info_append(ctx, "6:length", "4:name",
			(bt_file_info*)ctx->files.array[0]);
	}

	bt_bencode_int(ctx, "12:piece length", ctx->piece_length);
	bt_str_append(ctx, "6:pieces");
	bt_bencode_pieces(ctx);

	if(ctx->options & BT_OPT_PRIVATE) {
		bt_str_append(ctx, "7:privatei1e");
	}
	bt_str_append(ctx, "ee");

	/* calculate BTIH */
	SHA1_INIT(ctx);
	SHA1_UPDATE(ctx, (unsigned char*)ctx->content.str + info_start_pos,
		ctx->content.length - info_start_pos - 1);
	SHA1_FINAL(ctx, ctx->btih);
}
示例#5
0
/**
 * Generate torrent file content
 * @see http://wiki.theory.org/BitTorrentSpecification
 *
 * @param ctx the torrent algorithm context
 */
static void make_torrent(torrent_ctx *ctx)
{
  uint64_t total_size = 0;
  size_t info_start_pos;
  
  assert(ctx->torrent == NULL);
  assert(ctx->files.size <= 1);

  ctx->torrent = str_new();
  if(ctx->piece_length == 0) {
    if(ctx->files.size == 1) {
      total_size = ((file_n_size_info*)ctx->files.array[0])->size;
    }
    ctx->piece_length = torrent_default_piece_length(total_size);
  }

  /* write torrent header to the ctx->torrent string bufer */
  if((ctx->flags & BT_OPT_INFOHASH_ONLY) == 0) {
    str_append(ctx->torrent, "d");
    if(ctx->announce) {
      str_append(ctx->torrent, "8:announce");
      bt_bencode_str(ctx->torrent, ctx->announce);
    }

    if(ctx->program_name) {
      str_append(ctx->torrent, "10:created by");
      bt_bencode_str(ctx->torrent, ctx->program_name);
    }

    str_append(ctx->torrent, "13:creation date");
    bt_bencode_int(ctx->torrent, (uint64_t)time(NULL));
  }

  str_append(ctx->torrent, "8:encoding5:UTF-8");

  str_append(ctx->torrent, "4:infod"); /* start info dictionary */
  info_start_pos = ctx->torrent->len - 1;

  if(ctx->files.size == 1) {
    file_n_size_info* f = (file_n_size_info*)ctx->files.array[0];
    str_append(ctx->torrent, "6:length");
    bt_bencode_int(ctx->torrent, f->size);

    /* note: for one file f->path must be a basename */
    str_append(ctx->torrent, "4:name");
    bt_bencode_str(ctx->torrent, f->path);
  }
  str_append(ctx->torrent, "12:piece length");
  bt_bencode_int(ctx->torrent, ctx->piece_length);

  str_append(ctx->torrent, "6:pieces");
  bt_bencode_pieces(ctx->torrent, ctx);

  if(ctx->flags & BT_OPT_PRIVATE) {
    str_append(ctx->torrent, "7:privatei1e");
  }
  str_append(ctx->torrent, "ee");

  SHA1_INIT(ctx);
  SHA1_UPDATE(ctx, (unsigned char*)ctx->torrent->str + info_start_pos,
    ctx->torrent->len - info_start_pos - 1);
  SHA1_FINAL(ctx, ctx->btih);

}