*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-11-18 22:33:50 +00:00
parent 0659b267cf
commit b29e378f22
17 changed files with 150 additions and 81 deletions

View File

@ -20,7 +20,7 @@ project torrent
<variant>release:<define>NDEBUG <variant>release:<define>NDEBUG
<define>BOOST_ALL_NO_LIB <define>BOOST_ALL_NO_LIB
<define>_FILE_OFFSET_BITS=64 <define>_FILE_OFFSET_BITS=64
<library>/boost/thread//boost_thread/ <library>/boost/thread//boost_thread
<library>/boost/filesystem//boost_filesystem/<link>static <library>/boost/filesystem//boost_filesystem/<link>static
<library>/boost/date_time//boost_date_time/<link>static <library>/boost/date_time//boost_date_time/<link>static
<link>static <link>static

View File

@ -2193,7 +2193,7 @@ The file format is a bencoded dictionary containing the following fields:
| | greater than 4 megabytes, the block size will increase. | | | greater than 4 megabytes, the block size will increase. |
| | | | | |
+----------------------+--------------------------------------------------------------+ +----------------------+--------------------------------------------------------------+
| ``slots`` | list of integers. The list mappes slots ti piece indices. It | | ``slots`` | list of integers. The list mappes slots to piece indices. It |
| | tells which piece is on which slot. If piece index is -2 it | | | tells which piece is on which slot. If piece index is -2 it |
| | means it is free, that there's no piece there. If it is -1, | | | means it is free, that there's no piece there. If it is -1, |
| | means the slot isn't allocated on disk yet. The pieces have | | | means the slot isn't allocated on disk yet. The pieces have |

View File

@ -23,5 +23,5 @@ exe make_torrent
; ;
stage bin : dump_torrent make_torrent simple_client client_test ; stage . : dump_torrent make_torrent simple_client client_test ;

View File

@ -78,6 +78,7 @@ int main(int argc, char* argv[])
std::cout << "number of pieces: " << t.num_pieces() << "\n"; std::cout << "number of pieces: " << t.num_pieces() << "\n";
std::cout << "piece length: " << t.piece_length() << "\n"; std::cout << "piece length: " << t.piece_length() << "\n";
std::cout << "info hash: " << t.info_hash() << "\n";
std::cout << "files:\n"; std::cout << "files:\n";
for (torrent_info::file_iterator i = t.begin_files(); for (torrent_info::file_iterator i = t.begin_files();
i != t.end_files(); i != t.end_files();

View File

@ -77,8 +77,7 @@ int main(int argc, char* argv[])
if (argc != 4) if (argc != 4)
{ {
std::cerr << "usage: make_torrent <output torrent-file> <announce url> <file or directory to create torrent from>\n\n" std::cerr << "usage: make_torrent <output torrent-file> <announce url> <file or directory to create torrent from>\n";
"the torrent file will be written to stdout.\n";
return 1; return 1;
} }
@ -112,7 +111,7 @@ int main(int argc, char* argv[])
t.set_creator(creator_str); t.set_creator(creator_str);
// create the torrent and print it to stdout // create the torrent and print it to out
entry e = t.create_torrent(); entry e = t.create_torrent();
libtorrent::bencode(std::ostream_iterator<char>(out), e); libtorrent::bencode(std::ostream_iterator<char>(out), e);
} }

View File

@ -57,10 +57,10 @@ namespace libtorrent
, tag_version(tag) , tag_version(tag)
{ {
assert(id_string); assert(id_string);
assert(major >= 0 && major < 10); assert(major >= 0);
assert(minor >= 0 && minor < 10); assert(minor >= 0);
assert(revision >= 0 && revision < 10); assert(revision >= 0);
assert(tag >= 0 && tag < 10); assert(tag >= 0);
assert(std::strlen(id_string) == 2); assert(std::strlen(id_string) == 2);
id[0] = id_string[0]; id[0] = id_string[0];
id[1] = id_string[1]; id[1] = id_string[1];
@ -70,10 +70,10 @@ namespace libtorrent
{ {
std::stringstream s; std::stringstream s;
s << "-" << id[0] << id[1] s << "-" << id[0] << id[1]
<< (int)major_version << version_to_char(major_version)
<< (int)minor_version << version_to_char(minor_version)
<< (int)revision_version << version_to_char(revision_version)
<< (int)tag_version << "-"; << version_to_char(tag_version) << "-";
return s.str(); return s.str();
} }
@ -83,6 +83,15 @@ namespace libtorrent
char revision_version; char revision_version;
char tag_version; char tag_version;
private:
char version_to_char(int v) const
{
if (v >= 0 && v < 10) return '0' + v;
else if (v >= 10) return 'A' + (v - 10);
assert(false);
}
}; };
} }

View File

@ -145,8 +145,8 @@ namespace libtorrent
mutable boost::mutex m_mutex; mutable boost::mutex m_mutex;
boost::condition m_cond; boost::condition m_cond;
// a list of all torrents that are currently checking // a list of all torrents that are currently in queue
// their files (in separate threads) // or checking their files
std::deque<piece_checker_data> m_torrents; std::deque<piece_checker_data> m_torrents;
bool m_abort; bool m_abort;
@ -260,7 +260,6 @@ namespace libtorrent
boost::shared_ptr<logger> m_logger; boost::shared_ptr<logger> m_logger;
#endif #endif
}; };
} }
struct http_settings; struct http_settings;
@ -296,6 +295,8 @@ namespace libtorrent
~session(); ~session();
std::vector<torrent_handle> get_torrents();
// all torrent_handles must be destructed before the session is destructed! // all torrent_handles must be destructed before the session is destructed!
torrent_handle add_torrent( torrent_handle add_torrent(
entry const& metadata entry const& metadata

View File

@ -33,6 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_VERSION_HPP_INCLUDED #ifndef TORRENT_VERSION_HPP_INCLUDED
#define TORRENT_VERSION_HPP_INCLUDED #define TORRENT_VERSION_HPP_INCLUDED
#define LIBTORRENT_VERSION "0.1.0.0" #define LIBTORRENT_VERSION "0.9.0.0"
#endif #endif

View File

@ -97,24 +97,21 @@ namespace libtorrent
// section 2.3 // section 2.3
// some trackers seems to require that ' is escaped // some trackers seems to require that ' is escaped
// static const char unreserved_chars[] = "-_.!~*'()"; // static const char unreserved_chars[] = "-_.!~*'()";
static const char unreserved_chars[] = "-_.!~*()"; static const char unreserved_chars[] = "-_.!~*()"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789";
std::stringstream ret; std::stringstream ret;
ret << std::hex << std::setfill('0'); ret << std::hex << std::setfill('0');
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
{ {
if (std::isalnum(static_cast<unsigned char>(*str)) if (std::count(
|| std::count(
unreserved_chars unreserved_chars
, unreserved_chars+sizeof(unreserved_chars)-1 , unreserved_chars+sizeof(unreserved_chars)-1
, *str)) , *str))
{ {
ret << *str; ret << *str;
} }
else if (*str == ' ')
{
ret << '+';
}
else else
{ {
ret << '%' ret << '%'

View File

@ -1710,7 +1710,8 @@ namespace libtorrent
// if we have an infinite ratio, just say we have downloaded // if we have an infinite ratio, just say we have downloaded
// much more than we have uploaded. And we'll keep uploading. // much more than we have uploaded. And we'll keep uploading.
if (ratio == 0.f) return std::numeric_limits<int>::max(); if (ratio == 0.f)
return std::numeric_limits<size_type>::max();
return m_free_upload return m_free_upload
+ static_cast<size_type>(m_statistics.total_payload_download() * ratio) + static_cast<size_type>(m_statistics.total_payload_download() * ratio)

View File

@ -133,7 +133,7 @@ namespace libtorrent
} }
} }
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }
@ -368,7 +368,7 @@ namespace libtorrent
move(true, m_piece_map[index].peer_count, m_piece_map[index].index); move(true, m_piece_map[index].peer_count, m_piece_map[index].index);
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }
@ -389,7 +389,7 @@ namespace libtorrent
move(m_piece_map[i].downloading, peer_count, index); move(m_piece_map[i].downloading, peer_count, index);
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
return; return;
} }
@ -403,7 +403,8 @@ namespace libtorrent
int index = m_piece_map[i].index; int index = m_piece_map[i].index;
assert(m_piece_map[i].peer_count > 0); assert(m_piece_map[i].peer_count > 0);
m_piece_map[i].peer_count--; if (m_piece_map[i].peer_count > 0)
m_piece_map[i].peer_count--;
if (index == 0xffffff) return; if (index == 0xffffff) return;
move(m_piece_map[i].downloading, peer_count, index); move(m_piece_map[i].downloading, peer_count, index);
@ -422,7 +423,7 @@ namespace libtorrent
assert(info_index != 0xffffff); assert(info_index != 0xffffff);
remove(m_piece_map[index].downloading, peer_count, info_index); remove(m_piece_map[index].downloading, peer_count, info_index);
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }
@ -434,7 +435,7 @@ namespace libtorrent
assert(pieces.size() == m_piece_map.size()); assert(pieces.size() == m_piece_map.size());
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
// free refers to pieces that are free to download, noone else // free refers to pieces that are free to download, noone else
@ -581,7 +582,7 @@ namespace libtorrent
void piece_picker::mark_as_downloading(piece_block block, const address& peer) void piece_picker::mark_as_downloading(piece_block block, const address& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
assert(block.piece_index >= 0); assert(block.piece_index >= 0);
assert(block.block_index >= 0); assert(block.block_index >= 0);
@ -610,14 +611,14 @@ namespace libtorrent
i->requested_blocks[block.block_index] = 1; i->requested_blocks[block.block_index] = 1;
} }
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }
void piece_picker::mark_as_finished(piece_block block, const address& peer) void piece_picker::mark_as_finished(piece_block block, const address& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
assert(block.piece_index >= 0); assert(block.piece_index >= 0);
assert(block.block_index >= 0); assert(block.block_index >= 0);
@ -647,7 +648,7 @@ namespace libtorrent
i->finished_blocks[block.block_index] = 1; i->finished_blocks[block.block_index] = 1;
} }
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }
/* /*
@ -716,7 +717,7 @@ namespace libtorrent
void piece_picker::abort_download(piece_block block) void piece_picker::abort_download(piece_block block)
{ {
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
assert(block.piece_index >= 0); assert(block.piece_index >= 0);
@ -751,7 +752,7 @@ namespace libtorrent
move(true, m_piece_map[block.piece_index].peer_count, m_piece_map[block.piece_index].index); move(true, m_piece_map[block.piece_index].peer_count, m_piece_map[block.piece_index].index);
} }
#ifndef NDEBUG #ifndef NDEBUG
// integrity_check(); integrity_check();
#endif #endif
} }

View File

@ -237,9 +237,10 @@ namespace
{ {
// if the peer is interested in us, it means it may // if the peer is interested in us, it means it may
// want to trade it's surplus uploads for downloads itself // want to trade it's surplus uploads for downloads itself
// (and we should consider it free). If the share diff is // (and we should not consider it free). If the share diff is
// negative, there's no free download to get from this peer. // negative, there's no free download to get from this peer.
size_type diff = i->second->share_diff(); size_type diff = i->second->share_diff();
assert(diff < std::numeric_limits<size_type>::max());
if (i->second->is_peer_interested() || diff <= 0) if (i->second->is_peer_interested() || diff <= 0)
continue; continue;
@ -265,7 +266,9 @@ namespace
size_type total_diff = 0; size_type total_diff = 0;
for (torrent::peer_iterator i = start; i != end; ++i) for (torrent::peer_iterator i = start; i != end; ++i)
{ {
total_diff += i->second->share_diff(); size_type d = i->second->share_diff();
assert(d < std::numeric_limits<size_type>::max());
total_diff += d;
if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue; if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue;
++num_peers; ++num_peers;
} }
@ -481,14 +484,18 @@ namespace libtorrent
// first choice candidate. // first choice candidate.
// it is a candidate we owe nothing to and which has been unchoked // it is a candidate we owe nothing to and which has been unchoked
// the longest. // the longest.
using namespace boost::posix_time;
using namespace boost::gregorian;
peer* candidate = 0; peer* candidate = 0;
boost::posix_time::ptime last_unchoke // not valid when candidate==0
= boost::posix_time::ptime(boost::posix_time::ptime(boost::gregorian::date(1970, boost::gregorian::Jan, 1))); // not valid when candidate == 0
ptime last_unchoke = ptime(date(1970, Jan, 1));
// second choice candidate. // second choice candidate.
// if there is no first choice candidate, this candidate will be chosen. // if there is no first choice candidate, this candidate will be chosen.
// it is the candidate that we owe the least to. // it is the candidate that we owe the least to.
peer* secondCandidate = 0; peer* second_candidate = 0;
size_type lowest_share_diff = 0; // not valid when secondCandidate==0 size_type lowest_share_diff = 0; // not valid when secondCandidate==0
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
@ -502,14 +509,14 @@ namespace libtorrent
if (c->is_choked()) continue; if (c->is_choked()) continue;
size_type share_diff=c->share_diff(); size_type share_diff = c->share_diff();
// select as second candidate the one that we owe the least // select as second candidate the one that we owe the least
// to // to
if(!secondCandidate || share_diff <= lowest_share_diff) if(!second_candidate || share_diff <= lowest_share_diff)
{ {
lowest_share_diff = share_diff; lowest_share_diff = share_diff;
secondCandidate=&(*i); second_candidate = &(*i);
} }
// select as first candidate the one that we don't owe anything to // select as first candidate the one that we don't owe anything to
@ -521,8 +528,8 @@ namespace libtorrent
candidate = &(*i); candidate = &(*i);
} }
} }
if(candidate) return candidate; if (candidate) return candidate;
if(secondCandidate) return secondCandidate; if (second_candidate) return second_candidate;
assert(false); assert(false);
return 0; return 0;
} }
@ -700,22 +707,25 @@ namespace libtorrent
// ---------------------------- // ----------------------------
else else
{ {
// choke peers that have leeched too much without giving anything back if (m_torrent->ratio() != 0)
for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end();
++i)
{ {
peer_connection* c = i->connection; // choke peers that have leeched too much without giving anything back
if (c == 0) continue; for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end();
size_type diff = i->connection->share_diff(); ++i)
if (diff < -free_upload_amount
&& !c->is_choked())
{ {
// if we have uploaded more than a piece for free, choke peer and peer_connection* c = i->connection;
// wait until we catch up with our download. if (c == 0) continue;
c->send_choke();
--m_num_unchoked; size_type diff = i->connection->share_diff();
if (diff < -free_upload_amount
&& !c->is_choked())
{
// if we have uploaded more than a piece for free, choke peer and
// wait until we catch up with our download.
c->send_choke();
--m_num_unchoked;
}
} }
} }
@ -969,7 +979,7 @@ namespace libtorrent
{ {
if (m_torrent->ratio() != 0.f) if (m_torrent->ratio() != 0.f)
{ {
assert(c.share_diff() < std::numeric_limits<int>::max()); assert(c.share_diff() < std::numeric_limits<size_type>::max());
size_type diff = c.share_diff(); size_type diff = c.share_diff();
if (diff > 0 && c.is_seed()) if (diff > 0 && c.is_seed())
{ {
@ -1076,7 +1086,8 @@ namespace libtorrent
// because it isn't necessary. // because it isn't necessary.
if (m_torrent->ratio() != 0.f) if (m_torrent->ratio() != 0.f)
{ {
assert(i->connection->share_diff() < std::numeric_limits<int>::max()); assert(i->connection->associated_torrent() == m_torrent);
assert(i->connection->share_diff() < std::numeric_limits<size_type>::max());
m_available_free_upload += i->connection->share_diff(); m_available_free_upload += i->connection->share_diff();
} }
i->prev_amount_download += c.statistics().total_payload_download(); i->prev_amount_download += c.statistics().total_payload_download();

View File

@ -662,6 +662,7 @@ namespace libtorrent { namespace detail
if (t.is_aborted()) if (t.is_aborted())
{ {
tracker_request req = t.generate_tracker_request(); tracker_request req = t.generate_tracker_request();
assert(req.event == tracker_request::stopped);
req.listen_port = m_listen_interface.port; req.listen_port = m_listen_interface.port;
req.key = m_key; req.key = m_key;
m_tracker_manager.queue_request(req); m_tracker_manager.queue_request(req);
@ -876,6 +877,35 @@ namespace libtorrent
m_impl.m_extension_enabled[i] = true; m_impl.m_extension_enabled[i] = true;
} }
std::vector<torrent_handle> session::get_torrents()
{
std::vector<torrent_handle> ret;
{
boost::mutex::scoped_lock l(m_checker_impl.m_mutex);
for (std::deque<detail::piece_checker_data>::iterator i
= m_checker_impl.m_torrents.begin()
, end(m_checker_impl.m_torrents.end()); i != end; ++i)
{
ret.push_back(torrent_handle(&m_impl, &m_checker_impl
, i->info_hash));
}
}
{
boost::mutex::scoped_lock l(m_impl.m_mutex);
for (detail::session_impl::torrent_map::iterator i
= m_impl.m_torrents.begin(), end(m_impl.m_torrents.end());
i != end; ++i)
{
if (i->second->is_aborted()) continue;
ret.push_back(torrent_handle(&m_impl, &m_checker_impl
, i->first));
}
}
return ret;
}
// TODO: add a check to see if filenames are accepted on the // TODO: add a check to see if filenames are accepted on the
// current platform. // current platform.
// if the torrent already exists, this will throw duplicate_torrent // if the torrent already exists, this will throw duplicate_torrent
@ -1270,6 +1300,25 @@ namespace libtorrent
, std::back_inserter(file_sizes) , std::back_inserter(file_sizes)
, boost::bind((mem_fun_type)&entry::integer, _1)); , boost::bind((mem_fun_type)&entry::integer, _1));
#endif #endif
if (tmp_pieces.size() == info.num_pieces()
&& std::find_if(tmp_pieces.begin(), tmp_pieces.end()
, boost::bind(std::less<int>(), _1, 0)) == tmp_pieces.end())
{
if (info.num_files() != file_sizes.size())
return;
std::vector<size_type>::iterator fs = file_sizes.begin();
// the resume data says we have the entire torrent
// make sure the file sizes are the right ones
for (torrent_info::file_iterator i = info.begin_files()
, end(info.end_files()); i != end; ++i, ++fs)
{
if (i->size != *fs) return;
}
}
if (!match_filesizes(info, save_path, file_sizes)) if (!match_filesizes(info, save_path, file_sizes))
return; return;

View File

@ -254,7 +254,8 @@ namespace libtorrent
} }
int ret = std::rename(old_path.c_str(), new_path.c_str()); int ret = std::rename(old_path.c_str(), new_path.c_str());
if (ret == 0) // This seems to return -1 even when it successfully moves the file
// if (ret == 0)
{ {
m_pimpl->save_path = save_path; m_pimpl->save_path = save_path;
return true; return true;
@ -522,11 +523,9 @@ namespace libtorrent
bool move_storage(path save_path) bool move_storage(path save_path)
{ {
m_save_path = complete(save_path);
if (m_storage.move_storage(save_path)) if (m_storage.move_storage(save_path))
{ {
m_save_path = save_path; m_save_path = complete(save_path);
return true; return true;
} }
return false; return false;

View File

@ -240,6 +240,8 @@ namespace libtorrent
void torrent::init() void torrent::init()
{ {
assert(m_torrent_file.is_valid()); assert(m_torrent_file.is_valid());
assert(m_torrent_file.num_files() > 0);
assert(m_torrent_file.total_size() > 0);
m_have_pieces.resize(m_torrent_file.num_pieces(), false); m_have_pieces.resize(m_torrent_file.num_pieces(), false);
m_storage = std::auto_ptr<piece_manager>(new piece_manager(m_torrent_file, m_save_path)); m_storage = std::auto_ptr<piece_manager>(new piece_manager(m_torrent_file, m_save_path));
@ -542,6 +544,7 @@ namespace libtorrent
req.left = bytes_left(); req.left = bytes_left();
if (req.left == -1) req.left = 1000; if (req.left == -1) req.left = 1000;
req.event = m_event; req.event = m_event;
m_event = tracker_request::none;
req.url = m_trackers[m_currently_trying_tracker].url; req.url = m_trackers[m_currently_trying_tracker].url;
req.num_want = std::max( req.num_want = std::max(
(m_connections_quota.given (m_connections_quota.given
@ -743,7 +746,9 @@ namespace libtorrent
bool torrent::move_storage(boost::filesystem::path const& save_path) bool torrent::move_storage(boost::filesystem::path const& save_path)
{ {
return m_storage->move_storage(save_path); bool ret = m_storage->move_storage(save_path);
m_save_path = m_storage->save_path();
return ret;
} }
piece_manager& torrent::filesystem() piece_manager& torrent::filesystem()

View File

@ -197,6 +197,8 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
assert(max_connections >= 2 || max_connections == -1);
call_member<void>(m_ses, m_chk, m_info_hash call_member<void>(m_ses, m_chk, m_info_hash
, bind(&torrent::set_max_connections, _1, max_connections)); , bind(&torrent::set_max_connections, _1, max_connections));
} }

View File

@ -293,20 +293,14 @@ namespace libtorrent
parse_info_section(info); parse_info_section(info);
} }
boost::optional<boost::posix_time::ptime> boost::optional<ptime>
torrent_info::creation_date() const torrent_info::creation_date() const
{ {
if (m_creation_date != if (m_creation_date != ptime(date(not_a_date_time)))
boost::posix_time::ptime(
boost::gregorian::date(
boost::date_time::not_a_date_time)))
{ {
return boost::optional<boost::posix_time::ptime>(m_creation_date); return boost::optional<ptime>(m_creation_date);
} }
return boost::optional<ptime>();
// if there's no timestamp in the torrent file, this will return a date of january 1:st 1970.
boost::optional<boost::posix_time::ptime> pt(boost::gregorian::date(1970,1,1));
return pt;
} }
void torrent_info::add_tracker(std::string const& url, int tier) void torrent_info::add_tracker(std::string const& url, int tier)
@ -515,8 +509,8 @@ namespace libtorrent
} }
if (!m_comment.empty()) if (!m_comment.empty())
os << "comment: " << m_comment << "\n"; os << "comment: " << m_comment << "\n";
if (m_creation_date != boost::posix_time::ptime(boost::gregorian::date(1970, boost::gregorian::Jan, 1))) if (m_creation_date != ptime(date(not_a_date_time)))
os << "creation date: " << boost::posix_time::to_simple_string(m_creation_date) << "\n"; os << "creation date: " << to_simple_string(m_creation_date) << "\n";
os << "number of pieces: " << num_pieces() << "\n"; os << "number of pieces: " << num_pieces() << "\n";
os << "piece length: " << piece_length() << "\n"; os << "piece length: " << piece_length() << "\n";
os << "files:\n"; os << "files:\n";