Esempio n. 1
0
/**
 * Initialize torrent context before calculating hash.
 *
 * @param ctx context to initialize
 */
void bt_init(torrent_ctx* ctx)
{
	memset(ctx, 0, sizeof(torrent_ctx));
	ctx->piece_length = BT_MIN_HASH_LENGTH;
	assert(BT_MIN_HASH_LENGTH == bt_default_piece_length(0));

#ifdef USE_OPENSSL
	{
		/* get the methods of the selected SHA1 algorithm */
		rhash_hash_info *sha1_info = &rhash_info_table[3];
		assert(sha1_info->info->hash_id == RHASH_SHA1);
		assert(sha1_info->context_size <= (sizeof(sha1_ctx) + sizeof(unsigned long)));
		ctx->sha_init = sha1_info->init;
		ctx->sha_update = sha1_info->update;
		ctx->sha_final = sha1_info->final;
	}
#endif

	SHA1_INIT(ctx);
}
Esempio n. 2
0
/**
 * Initialize torrent context before calculaing hash.
 *
 * @param ctx context to initalize
 */
void torrent_init(torrent_ctx* ctx)
{
  memset(ctx, 0, sizeof(torrent_ctx));
  ctx->blocks_hashes.blocks.destructor = free;
  ctx->files.destructor = free;
  ctx->piece_length = 65536;

#ifdef USE_OPENSSL
  {
    /* get the methods of the selected SHA1 algorithm */
    rhash_hash_info *sha1_info = &rhash_info_table[3];
    assert(sha1_info->info.hash_id == RHASH_SHA1);
    assert(sha1_info->context_size <= (sizeof(sha1_ctx) + sizeof(unsigned long)));
    ctx->sha_init = sha1_info->init;
    ctx->sha_update = sha1_info->update;
    ctx->sha_final = sha1_info->final;
  }
#endif

  SHA1_INIT(ctx);
}
Esempio n. 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 bt_update(torrent_ctx *ctx, const void* msg, size_t size)
{
	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;
		}
		bt_store_piece_sha1(ctx);
		SHA1_INIT(ctx);
		ctx->index = 0;

		pmsg += rest;
		size -= rest;
		rest = ctx->piece_length;
	}
}
Esempio n. 4
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;
  }
}
Esempio n. 5
0
/**
 * 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);
}
Esempio n. 6
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);

}