Пример #1
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);
}
Пример #2
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);

}