*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-10-10 00:42:48 +00:00
parent de2f1f8cfb
commit a997a43d30
12 changed files with 270 additions and 66 deletions

View File

@ -27,5 +27,14 @@ exe dump_torrent
: debug release
;
stage bin : dump_torrent simple_client client_test ;
exe make_torrent
: make_torrent.cpp
/torrent
:
<threading>multi
: debug release
;
stage bin : dump_torrent simple_client client_test make_torrent ;

126
examples/make_torrent.cpp Executable file
View File

@ -0,0 +1,126 @@
/*
Copyright (c) 2003, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <fstream>
#include <iterator>
#include <iomanip>
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
using namespace boost::filesystem;
using namespace libtorrent;
void add_files(
torrent_info& t
, path const& p
, path const& l)
{
path f(p / l);
if (is_directory(f))
{
for (directory_iterator i(f), end; i != end; ++i)
add_files(t, p, l / i->leaf());
}
else
{
file f(f, file::in);
f.seek(0, file::end);
libtorrent::size_type size = f.tell();
t.add_file(l, size);
}
}
int main(int argc, char* argv[])
{
using namespace libtorrent;
using namespace boost::filesystem;
if (argc != 4)
{
std::cerr << "usage: make_torrent <output torrent-file> <announce url> <file or directory to create torrent from>\n\n"
"the torrent file will be written to stdout.\n";
return 1;
}
path::default_name_check(native);
try
{
torrent_info t;
path full_path = initial_path() / path(argv[3]);
ofstream out(initial_path() / path(argv[1]), std::ios_base::binary);
int piece_size = 256 * 1024;
char const* creator_str = "libtorrent";
add_files(t, full_path.branch_path(), full_path.leaf());
t.set_piece_size(piece_size);
storage st(t, full_path.branch_path());
t.add_tracker(argv[2]);
// calculate the hash for all pieces
int num = t.num_pieces();
std::vector<char> buf(piece_size);
for (int i = 0; i < num; ++i)
{
st.read(&buf[0], i, 0, t.piece_size(i));
hasher h(&buf[0], t.piece_size(i));
t.set_hash(i, h.final());
std::cerr << (i+1) << "/" << num << "\r";
}
t.set_creator(creator_str);
// create the torrent and print it to stdout
entry e = t.create_torrent();
libtorrent::bencode(std::ostream_iterator<char>(out), e);
}
catch (std::exception& e)
{
std::cerr << e.what() << "\n";
}
return 0;
}

View File

@ -90,7 +90,6 @@ namespace libtorrent
torrent_handle handle;
};
struct peer_error_alert: alert
{
peer_error_alert(address const& pip, peer_id const& pid, const std::string& msg)

View File

@ -131,6 +131,13 @@ namespace libtorrent
{
char c[2];
is >> c[0] >> c[1];
if (c[0] < 0 || c[1] < 0
|| c[0] > 'f' || c[1] > 'f'
|| is.fail())
{
is.setstate(ios_base::failbit);
return is;
}
*i = ((isdigit(c[0])?c[0]-'0':c[0]-'a'+10) << 4)
+ (isdigit(c[1])?c[1]-'0':c[1]-'a'+10);
}

View File

@ -150,6 +150,7 @@ namespace libtorrent
bool is_readable() const;
bool is_writable() const;
bool has_error() const;
enum error_code
{
@ -178,6 +179,7 @@ namespace libtorrent
is_connected,
net_unreachable,
not_initialized,
host_not_found,
unknown_error
};

View File

@ -62,13 +62,13 @@ namespace libtorrent
class session;
std::vector<size_type> get_filesizes(
const torrent_info& t
, const boost::filesystem::path& p);
torrent_info const& t
, boost::filesystem::path p);
bool match_filesizes(
const torrent_info& t
, const boost::filesystem::path& p
, const std::vector<size_type>& sizes);
torrent_info const& t
, boost::filesystem::path p
, std::vector<size_type> const& sizes);
struct file_allocation_failed: std::exception
{
@ -93,7 +93,7 @@ namespace libtorrent
// may throw file_error if storage for slot hasn't been allocated
void write(const char* buf, int slot, int offset, int size);
bool move_storage(boost::filesystem::path const& save_path);
bool move_storage(boost::filesystem::path save_path);
#ifndef NDEBUG
// overwrites some slots with the

View File

@ -86,16 +86,15 @@ namespace libtorrent
{
public:
torrent_info(const entry& torrent_file);
torrent_info(
int piece_size
, const char* name
, sha1_hash const& info_hash = sha1_hash(0));
torrent_info();
torrent_info(sha1_hash const& info_hash);
torrent_info(entry const& torrent_file);
entry create_torrent() const;
entry create_info_metadata() const;
void set_comment(char const* str);
void set_creator(char const* str);
void set_piece_size(int size);
void set_hash(int index, const sha1_hash& h);
void add_tracker(std::string const& url, int tier = 0);
void add_file(boost::filesystem::path file, size_type size);

View File

@ -250,6 +250,12 @@ namespace libtorrent
m_request_time = boost::posix_time::second_clock::local_time();
}
if (m_socket->has_error())
{
if (has_requester()) requester().tracker_request_error(
-1, "connection refused");
return true;
}
// if the socket isn't ready for reading, there's no point in continuing
// trying to read from it

View File

@ -79,7 +79,7 @@ void libtorrent::stat::second_tick()
m_mean_download_rate += m_download_rate_history[i];
m_mean_upload_rate += m_upload_rate_history[i];
m_mean_download_payload_rate += m_download_payload_rate_history[i];
m_mean_upload_payload_rate += m_download_payload_rate_history[i];
m_mean_upload_payload_rate += m_upload_payload_rate_history[i];
}
m_mean_download_rate /= history;

View File

@ -70,7 +70,7 @@ namespace std
}
#endif
namespace fs = boost::filesystem;
using namespace boost::filesystem;
namespace
{
@ -82,9 +82,9 @@ namespace
log.flush();
}
fs::path get_filename(
path get_filename(
libtorrent::torrent_info const& t
, fs::path const& p)
, path const& p)
{
assert(t.num_files() > 0);
if (t.num_files() == 1)
@ -99,8 +99,9 @@ namespace libtorrent
std::vector<size_type> get_filesizes(
const torrent_info& t
, const fs::path& p)
, path p)
{
p = complete(p);
std::vector<size_type> sizes;
for (torrent_info::file_iterator i = t.begin_files();
i != t.end_files();
@ -123,11 +124,12 @@ namespace libtorrent
}
bool match_filesizes(
const torrent_info& t
, const fs::path& p
, const std::vector<size_type>& sizes)
torrent_info const& t
, path p
, std::vector<size_type> const& sizes)
{
if ((int)sizes.size() != t.num_files()) return false;
p = complete(p);
std::vector<size_type>::const_iterator s = sizes.begin();
for (torrent_info::file_iterator i = t.begin_files();
@ -188,23 +190,24 @@ namespace libtorrent
class storage::impl : public thread_safe_storage
{
public:
impl(const torrent_info& info, const fs::path& path)
impl(torrent_info const& info, path const& path)
: thread_safe_storage(info.num_pieces())
, info(info)
, save_path(path)
{}
{
save_path = complete(path);
}
impl(const impl& x)
impl(impl const& x)
: thread_safe_storage(x.info.num_pieces())
, info(x.info)
, save_path(x.save_path)
{}
torrent_info const& info;
fs::path save_path;
path save_path;
};
storage::storage(const torrent_info& info, const fs::path& path)
storage::storage(const torrent_info& info, const path& path)
: m_pimpl(new impl(info, path))
{
assert(info.begin_files() != info.end_files());
@ -216,21 +219,23 @@ namespace libtorrent
}
// returns true on success
bool storage::move_storage(fs::path const& save_path)
bool storage::move_storage(path save_path)
{
std::string old_path;
std::string new_path;
if(!fs::exists(save_path))
fs::create_directory(save_path);
else if(!fs::is_directory(save_path))
save_path = complete(save_path);
if(!exists(save_path))
create_directory(save_path);
else if(!is_directory(save_path))
return false;
if (m_pimpl->info.num_files() == 1)
{
fs::path single_file = m_pimpl->info.begin_files()->path;
path single_file = m_pimpl->info.begin_files()->path;
if (single_file.has_branch_path())
fs::create_directory(save_path / single_file.branch_path());
create_directory(save_path / single_file.branch_path());
old_path = (m_pimpl->save_path / single_file)
.native_file_string();
@ -366,7 +371,7 @@ namespace libtorrent
if (left_to_read > 0)
{
++file_iter;
fs::path path = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path);
path path = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path);
file_offset = 0;
in.open(path, file::in);
@ -406,8 +411,8 @@ namespace libtorrent
++file_iter;
}
fs::path path(m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path));
file out(path, file::out);
path p(m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path));
file out(p, file::out);
assert(file_offset < file_iter->size);
@ -462,12 +467,9 @@ namespace libtorrent
++file_iter;
assert(file_iter != m_pimpl->info.end_files());
fs::path path = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path);
path p = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path);
file_offset = 0;
out.open(path, file::out);
out.open(p, file::out);
}
}
}
@ -485,7 +487,7 @@ namespace libtorrent
impl(
const torrent_info& info
, const fs::path& path);
, const path& path);
void check_pieces(
boost::mutex& mutex
@ -513,11 +515,13 @@ namespace libtorrent
, int offset
, int size);
fs::path const& save_path() const
path const& save_path() const
{ return m_save_path; }
bool move_storage(fs::path const& save_path)
bool move_storage(path save_path)
{
m_save_path = complete(save_path);
if (m_storage.move_storage(save_path))
{
m_save_path = save_path;
@ -576,7 +580,7 @@ namespace libtorrent
// it can either be 'unassigned' or 'unallocated'
std::vector<int> m_slot_to_piece;
fs::path m_save_path;
path m_save_path;
mutable boost::recursive_mutex m_mutex;
@ -587,17 +591,17 @@ namespace libtorrent
piece_manager::impl::impl(
const torrent_info& info
, const fs::path& save_path)
, const path& save_path)
: m_storage(info, save_path)
, m_info(info)
, m_save_path(save_path)
, m_allocating(false)
{
m_save_path = complete(save_path);
}
piece_manager::piece_manager(
const torrent_info& info
, const fs::path& save_path)
, const path& save_path)
: m_pimpl(new impl(info, save_path))
{
}
@ -984,9 +988,9 @@ namespace libtorrent
for (torrent_info::file_iterator file_iter = m_info.begin_files(),
end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter)
{
fs::path dir = m_save_path / get_filename(m_info, file_iter->path);
if (!fs::exists(dir.branch_path()))
fs::create_directories(dir.branch_path());
path dir = m_save_path / get_filename(m_info, file_iter->path);
if (!exists(dir.branch_path()))
create_directories(dir.branch_path());
}
std::vector<char> piece_data(static_cast<int>(m_info.piece_length()));
@ -1402,8 +1406,6 @@ namespace libtorrent
INVARIANT_CHECK;
namespace fs = fs;
assert(!m_unallocated_slots.empty());
const int piece_size = static_cast<int>(m_info.piece_length());
@ -1441,12 +1443,12 @@ namespace libtorrent
m_pimpl->allocate_slots(num_slots);
}
fs::path const& piece_manager::save_path() const
path const& piece_manager::save_path() const
{
return m_pimpl->save_path();
}
bool piece_manager::move_storage(fs::path const& save_path)
bool piece_manager::move_storage(path const& save_path)
{
return m_pimpl->move_storage(save_path);
}

View File

@ -188,7 +188,7 @@ namespace libtorrent
, sha1_hash const& info_hash
, boost::filesystem::path const& save_path
, address const& net_interface)
: m_torrent_file(0, "", info_hash)
: m_torrent_file(info_hash)
, m_abort(false)
, m_paused(false)
, m_just_paused(false)
@ -685,6 +685,7 @@ namespace libtorrent
void torrent::try_next_tracker()
{
using namespace boost::posix_time;
++m_currently_trying_tracker;
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
@ -697,7 +698,7 @@ namespace libtorrent
++m_failed_trackers;
// if we've looped the tracker list, wait a bit before retrying
m_currently_trying_tracker = 0;
m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(delay);
m_next_request = second_clock::local_time() + seconds(delay);
}
else
{
@ -727,8 +728,7 @@ namespace libtorrent
boost::filesystem::path torrent::save_path() const
{
assert(m_storage.get());
return m_storage->save_path();
return m_save_path;
}
bool torrent::move_storage(boost::filesystem::path const& save_path)

View File

@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/date_time/time.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/next_prior.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
@ -57,6 +58,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
using namespace libtorrent;
using namespace boost::filesystem;
namespace
{
@ -87,6 +89,15 @@ namespace
+ d.minutes() * 60
+ d.seconds();
}
void remove_dir(path& p)
{
assert(p.begin() != p.end());
path tmp;
for (path::iterator i = boost::next(p.begin()); i != p.end(); ++i)
tmp /= *i;
p = tmp;
}
}
namespace libtorrent
@ -112,18 +123,39 @@ namespace libtorrent
// constructor used for creating new torrents
// will not contain any hashes, comments, creation date
// just the necessary to use it with piece manager
torrent_info::torrent_info(
int piece_size
, const char* name
, sha1_hash const& info_hash)
: m_piece_length(piece_size)
torrent_info::torrent_info(sha1_hash const& info_hash)
: m_piece_length(256 * 1024)
, m_total_size(0)
, m_info_hash(info_hash)
, m_name(name)
, m_name()
, m_creation_date(second_clock::local_time())
{
}
torrent_info::torrent_info()
: m_piece_length(256 * 1024)
, m_total_size(0)
, m_info_hash(0)
, m_name()
, m_creation_date(second_clock::local_time())
{
}
void torrent_info::set_piece_size(int size)
{
// make sure the size is an even 2 exponential
#ifndef NDEBUG
for (int i = 0; i < 32; ++i)
{
if (size & (1 << i))
{
assert((size & ~(1 << i)) == 0);
break;
}
}
#endif
m_piece_length = size;
}
void torrent_info::parse_info_section(entry const& info)
{
@ -274,6 +306,26 @@ namespace libtorrent
void torrent_info::add_file(boost::filesystem::path file, size_type size)
{
assert(file.begin() != file.end());
if (m_files.empty())
{
m_name = file.string();
}
else
{
#ifndef NDEBUG
if (m_files.size() == 1)
assert(*m_files.front().path.begin() == *file.begin());
else
assert(m_name == *file.begin());
#endif
m_name = *file.begin();
if (m_files.size() == 1)
remove_dir(m_files.front().path);
remove_dir(file);
}
file_entry e;
e.path = file;
e.size = size;
@ -313,13 +365,15 @@ namespace libtorrent
info["length"] = m_total_size;
assert(!m_files.empty());
if (m_files.size() == 1)
{
info["name"] = m_files.front().path.string();
}
else
{
info["name"] = m_name;
info["name"] = m_files.front().path.root_name();
}
if (m_files.size() > 1)