*** empty log message ***

This commit is contained in:
Arvid Norberg 2003-10-23 16:55:52 +00:00
parent ec34b1bfdb
commit 1800e63c09
10 changed files with 132 additions and 86 deletions

20
Jamfile
View File

@ -26,13 +26,15 @@ lib torrent
; ;
#exe torrent_test exe client_test
# : src/main.cpp <lib>torrent : examples/client_test.cpp
# $(BOOST_ROOT)/libs/filesystem/build//boost_filesystem <lib>torrent
# : <include>$(BOOST_ROOT) # <lib>$(BOOST_ROOT)/libs/filesystem/build/boost_filesystem
# <sysinclude>$(BOOST_ROOT) # <dll>$(BOOST_ROOT)/libs/thread/build/boost_thread
# <include>./ : <include>$(BOOST_ROOT)
# <threading>multi <sysinclude>$(BOOST_ROOT)
# : debug release <include>./include
# ; <threading>multi
: debug release
;

View File

@ -10,6 +10,19 @@
<body> <body>
<h1>libtorrent</h1> <h1>libtorrent</h1>
<table style="margin-left:auto;margin-right:auto" cellpadding="10">
<tr>
<td>
<a href="http://www.sourceforge.net/projects/libtorrent">sourceforge page</a>
</td>
<td>
<a href="http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss">mailing list</a>
</td>
</tr>
</table>
<p> <p>
libtorrent is a C++ library that aims to be a good alternative to all the libtorrent is a C++ library that aims to be a good alternative to all the
<a href="links.html">other bittorrent implementations</a> around. It is a <a href="links.html">other bittorrent implementations</a> around. It is a

View File

@ -150,6 +150,14 @@ namespace libtorrent
int index; int index;
std::bitset<max_blocks_per_piece> requested_blocks; std::bitset<max_blocks_per_piece> requested_blocks;
std::bitset<max_blocks_per_piece> finished_blocks; std::bitset<max_blocks_per_piece> finished_blocks;
// TODO: store a hash and a peer_connection reference
// for each block. Then if the hash test fails on the
// piece, redownload one block from another peer
// then the first time, and check the hash again.
// also maintain a counter how many times a piece-hash
// has been confirmed. Download blocks that hasn't
// been confirmed (since they are most probably the
// invalid blocks)
}; };
struct has_index struct has_index
@ -172,8 +180,12 @@ namespace libtorrent
// that no peer have, the vector at index 1 contains // that no peer have, the vector at index 1 contains
// all pieces that exactly one peer have, index 2 contains // all pieces that exactly one peer have, index 2 contains
// all pieces exactly two peers have and so on. // all pieces exactly two peers have and so on.
std::vector<std::vector<int> > m_piece_info; std::vector<std::vector<int> > m_piece_info;
// this vector has the same structure as m_piece_info
// but only contains pieces we are currently downloading
// they have higher priority than pieces we aren't downloading
// during piece picking
std::vector<std::vector<int> > m_downloading_piece_info; std::vector<std::vector<int> > m_downloading_piece_info;
// this maps indices to number of peers that has this piece and // this maps indices to number of peers that has this piece and

View File

@ -72,9 +72,6 @@ namespace libtorrent
}; };
// wraps access to pieces with a file-like interface // wraps access to pieces with a file-like interface
// TODO: add functionality for switching piece
// that's optimized not to closing the file if the
// new piece is in the same file
class piece_file class piece_file
{ {
friend class storage; friend class storage;

View File

@ -61,7 +61,7 @@ namespace libtorrent
struct session_impl; struct session_impl;
} }
// TODO: each torrent should have a status string that // TODO: each torrent should have a status value that
// reflects what's happening to it // reflects what's happening to it
// TODO: There should be a maximum number of peers that // TODO: There should be a maximum number of peers that
// is maintained (if someone disconnects, try to connect to // is maintained (if someone disconnects, try to connect to
@ -70,6 +70,7 @@ namespace libtorrent
// speed than one of the peers currently connected, it will be // speed than one of the peers currently connected, it will be
// replaced to maximize bandwidth usage. It wil also have to // replaced to maximize bandwidth usage. It wil also have to
// depend on how many and which pieces the peers have. // depend on how many and which pieces the peers have.
// TODO: In debug mode all pieces that are sent should be checked.
// a torrent is a class that holds information // a torrent is a class that holds information
@ -119,7 +120,8 @@ namespace libtorrent
int bytes_left() const { return m_storage.bytes_left(); } int bytes_left() const { return m_storage.bytes_left(); }
// TODO: temporary implementation. Should count the actually // TODO: temporary implementation. Should count the actually
// verified pieces // verified pieces and should support the different states
// a torrent can be in.
float progress() const float progress() const
{ {
return bytes_downloaded() / static_cast<float>(m_torrent_file.total_size()); return bytes_downloaded() / static_cast<float>(m_torrent_file.total_size());
@ -238,11 +240,13 @@ namespace libtorrent
// blocks when requested // blocks when requested
int m_block_size; int m_block_size;
// is set to true when the torrent has
// been aborted.
bool m_abort; bool m_abort;
event_id m_event; event_id m_event;
void parse_response(const entry& e); void parse_response(const entry& e, std::vector<peer>& peer_list);
// total amount of bytes uploaded, downloaded and // total amount of bytes uploaded, downloaded and
// the number of bytes left to be downloaded // the number of bytes left to be downloaded
@ -266,9 +270,6 @@ namespace libtorrent
std::string m_failed; std::string m_failed;
std::vector<peer_connection*> m_connections; std::vector<peer_connection*> m_connections;
// TODO: move to a local function?
std::vector<peer> m_peer_list;
// ----------------------------- // -----------------------------
boost::shared_ptr<policy> m_policy; boost::shared_ptr<policy> m_policy;

View File

@ -402,9 +402,12 @@ bool libtorrent::peer_connection::dispatch_message()
} }
else else
{ {
// TODO: we have to let the piece_picker know that // we have to let the piece_picker know that
// this piece failed the check os it can restore it // this piece failed the check as it can restore it
// and mark it as being interesting for download // and mark it as being interesting for download
// TODO: do this more intelligently! and keep track
// of how much crap (data that failed hash-check) and
// how much redundant data we have downloaded
picker.restore_piece(index); picker.restore_piece(index);
} }
m_torrent->get_policy().piece_finished(*this, index, verified); m_torrent->get_policy().piece_finished(*this, index, verified);
@ -464,8 +467,6 @@ void libtorrent::peer_connection::request_block(piece_block block)
// TODO: add a timeout to disconnect peer if we don't get any piece messages when // TODO: add a timeout to disconnect peer if we don't get any piece messages when
// we have requested. // we have requested.
// TODO: there must be a way to ask the storage if a given
// piece already has some data (and how much). To avoid requesting
std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset); std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset);
start_offset +=5; start_offset +=5;
@ -685,6 +686,7 @@ void libtorrent::peer_connection::receive_data()
{ {
// verify peer_id // verify peer_id
// TODO: It seems like the original client ignores to check the peer id // TODO: It seems like the original client ignores to check the peer id
// can this be correct?
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (const char*)m_peer_id.begin())) if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (const char*)m_peer_id.begin()))
{ {
#ifndef NDEBUG #ifndef NDEBUG

View File

@ -90,7 +90,6 @@ namespace libtorrent
// TODO: random_shuffle // TODO: random_shuffle
} }
// TODO: add a check to make sure m_downloads is intact
#ifndef NDEBUG #ifndef NDEBUG
void piece_picker::integrity_check(const torrent* t) const void piece_picker::integrity_check(const torrent* t) const
@ -304,6 +303,13 @@ namespace libtorrent
#endif #endif
} }
// TODO: since inc_refcount is called
// with sequential indices when peers
// connect, it will sort the pieces
// that is not good. one solution is
// to insert the element at a random
// index when moving it to another
// vector.
bool piece_picker::inc_refcount(int i) bool piece_picker::inc_refcount(int i)
{ {
assert(i >= 0); assert(i >= 0);
@ -337,10 +343,6 @@ namespace libtorrent
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);
#ifndef NDEBUG
integrity_check();
#endif
} }
void piece_picker::we_have(int index) void piece_picker::we_have(int index)
@ -360,10 +362,8 @@ namespace libtorrent
void piece_picker::pick_pieces(const std::vector<bool>& pieces, std::vector<piece_block>& interesting_pieces) const void piece_picker::pick_pieces(const std::vector<bool>& pieces, std::vector<piece_block>& interesting_pieces) const
{ {
// TODO: modify this!
assert(pieces.size() == m_piece_map.size()); assert(pieces.size() == m_piece_map.size());
// free refers to pieces that are free to download, noone else // free refers to pieces that are free to download, noone else
// is downloading them. // is downloading them.
// partial is pieces that are partially being downloaded, and // partial is pieces that are partially being downloaded, and

View File

@ -71,9 +71,8 @@ namespace
return; return;
} }
// TODO: // TODO: compare this peer's bandwidth against the
// compare this peer's bandwidth against the ones downloading // ones downloading these pieces (busy_pieces)
// these pieces (busy_pieces)
} }
} }

View File

@ -82,8 +82,9 @@ namespace
{ {
peer_id ret; peer_id ret;
std::srand(std::time(0)); std::srand(std::time(0));
// unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0"; // TODO: add ability to control fingerprint
unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; // unsigned char fingerprint[] = "lt.\0\0\0\0\0\0\0";
unsigned char fingerprint[] = "lt.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
const int len = sizeof(fingerprint)-1; const int len = sizeof(fingerprint)-1;
std::copy(fingerprint, fingerprint+len, ret.begin()); std::copy(fingerprint, fingerprint+len, ret.begin());
for (unsigned char* i = ret.begin()+len; i != ret.end(); ++i) *i = rand(); for (unsigned char* i = ret.begin()+len; i != ret.end(); ++i) *i = rand();
@ -181,7 +182,9 @@ namespace libtorrent
// that has been closed. Otherwise we have to wait 2 minutes for their timeout // that has been closed. Otherwise we have to wait 2 minutes for their timeout
// let the readable clients receive data // let the readable clients receive data
for (std::vector<boost::shared_ptr<socket> >::iterator i = readable_clients.begin(); i != readable_clients.end(); ++i) for (std::vector<boost::shared_ptr<socket> >::iterator i = readable_clients.begin();
i != readable_clients.end();
++i)
{ {
// special case for listener socket // special case for listener socket
@ -236,7 +239,9 @@ namespace libtorrent
// ************************ // ************************
// let the writable clients send data // let the writable clients send data
for (std::vector<boost::shared_ptr<socket> >::iterator i = writable_clients.begin(); i != writable_clients.end(); ++i) for (std::vector<boost::shared_ptr<socket> >::iterator i = writable_clients.begin();
i != writable_clients.end();
++i)
{ {
connection_map::iterator p = m_connections.find(*i); connection_map::iterator p = m_connections.find(*i);
// the connection may have been disconnected in the receive phase // the connection may have been disconnected in the receive phase
@ -269,7 +274,9 @@ namespace libtorrent
// disconnect the one we couldn't connect to // disconnect the one we couldn't connect to
for (std::vector<boost::shared_ptr<socket> >::iterator i = error_clients.begin(); i != error_clients.end(); ++i) for (std::vector<boost::shared_ptr<socket> >::iterator i = error_clients.begin();
i != error_clients.end();
++i)
{ {
connection_map::iterator p = m_connections.find(*i); connection_map::iterator p = m_connections.find(*i);
@ -439,7 +446,7 @@ namespace libtorrent
boost::mutex::scoped_lock l(m_impl.m_mutex); boost::mutex::scoped_lock l(m_impl.m_mutex);
// is the torrent already active? // is the torrent already active?
// TODO: Maybe this should throw? // TODO: this should throw
if (m_impl.m_torrents.find(ti.info_hash()) != m_impl.m_torrents.end()) if (m_impl.m_torrents.find(ti.info_hash()) != m_impl.m_torrents.end())
return torrent_handle(&m_impl, ti.info_hash()); return torrent_handle(&m_impl, ti.info_hash());

View File

@ -71,7 +71,7 @@ namespace
int calculate_block_size(const torrent_info& i) int calculate_block_size(const torrent_info& i)
{ {
// TODO: if blocks_per_piece > 64 increase block-size // TODO: if blocks_per_piece > 128 increase block-size
return 16*1024; return 16*1024;
} }
@ -154,10 +154,63 @@ namespace libtorrent
void torrent::tracker_response(const entry& e) void torrent::tracker_response(const entry& e)
{ {
std::vector<peer> peer_list;
try try
{ {
// parse the response // parse the response
parse_response(e); parse_response(e, peer_list);
m_last_working_tracker
= m_torrent_file.prioritize_tracker(m_currently_trying_tracker);
m_next_request = boost::posix_time::second_clock::local_time()
+ boost::posix_time::seconds(m_duration);
m_currently_trying_tracker = 0;
// connect to random peers from the list
std::random_shuffle(peer_list.begin(), peer_list.end());
std::cout << "interval: " << m_duration << "\n";
std::cout << "peers:\n";
for (std::vector<peer>::const_iterator i = peer_list.begin();
i != peer_list.end();
++i)
{
std::cout << " " << std::setfill(' ') << std::setw(16) << i->ip
<< " " << std::setw(5) << std::dec << i->port << " ";
for (const unsigned char* j = i->id.begin();
j != i->id.end();
++j)
{
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned int>(*j);
}
std::cout << "\n";
}
std::cout << std::dec << std::setfill(' ');
// for each of the peers we got from the tracker
for (std::vector<peer>::iterator i = peer_list.begin();
i != peer_list.end();
++i)
{
// don't make connections to ourself
if (i->id == m_ses->get_peer_id())
continue;
address a(i->ip, i->port);
// if we aleady have a connection to the person, don't make another one
if (std::find_if(m_ses->m_connections.begin(),
m_ses->m_connections.end(),
find_peer(i->id, this)) != m_ses->m_connections.end())
{
continue;
}
m_policy->peer_from_tracker(a, i->id);
}
} }
catch(type_error& e) catch(type_error& e)
{ {
@ -168,30 +221,6 @@ namespace libtorrent
tracker_request_error(e.what()); tracker_request_error(e.what());
} }
m_last_working_tracker = m_torrent_file.prioritize_tracker(m_currently_trying_tracker);
m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration);
m_currently_trying_tracker = 0;
// connect to random peers from the list
std::random_shuffle(m_peer_list.begin(), m_peer_list.end());
print(std::cout);
// for each of the peers we got from the tracker
for (std::vector<peer>::iterator i = m_peer_list.begin(); i != m_peer_list.end(); ++i)
{
// don't make connections to ourself
if (i->id == m_ses->get_peer_id())
continue;
address a(i->ip, i->port);
// if we aleady have a connection to the person, don't make another one
if (std::find_if(m_ses->m_connections.begin(), m_ses->m_connections.end(), find_peer(i->id, this)) != m_ses->m_connections.end())
continue;
m_policy->peer_from_tracker(a, i->id);
}
} }
int torrent::num_connections(const peer_id& id) const int torrent::num_connections(const peer_id& id) const
@ -223,7 +252,6 @@ namespace libtorrent
m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration); m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration);
std::vector<char> buffer; std::vector<char> buffer;
// TODO: temporary! support multi-tracker
std::string request = m_torrent_file.trackers()[m_currently_trying_tracker].url; std::string request = m_torrent_file.trackers()[m_currently_trying_tracker].url;
request += "?info_hash="; request += "?info_hash=";
@ -255,7 +283,7 @@ namespace libtorrent
return request; return request;
} }
void torrent::parse_response(const entry& e) void torrent::parse_response(const entry& e, std::vector<peer>& peer_list)
{ {
entry::dictionary_type::const_iterator i = e.dict().find("failure reason"); entry::dictionary_type::const_iterator i = e.dict().find("failure reason");
if (i != e.dict().end()) if (i != e.dict().end())
@ -272,15 +300,14 @@ namespace libtorrent
i = msg.find("peers"); i = msg.find("peers");
if (i == msg.end()) throw std::runtime_error("invalid response from tracker"); if (i == msg.end()) throw std::runtime_error("invalid response from tracker");
m_peer_list.clear(); peer_list.clear();
const entry::list_type& peer_list = i->second.list(); const entry::list_type& l = i->second.list();
for(entry::list_type::const_iterator i = peer_list.begin(); i != peer_list.end(); ++i) for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i)
{ {
peer p = extract_peer_info(*i); peer p = extract_peer_info(*i);
m_peer_list.push_back(p); peer_list.push_back(p);
} }
} }
void torrent::remove_peer(peer_connection* p) void torrent::remove_peer(peer_connection* p)
@ -328,20 +355,6 @@ namespace libtorrent
std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n"; std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n";
} }
void torrent::print(std::ostream& os) const
{
os << "interval: " << m_duration << "\n";
os << "peers:\n";
for (std::vector<peer>::const_iterator i = m_peer_list.begin(); i != m_peer_list.end(); ++i)
{
os << " " << std::setfill(' ') << std::setw(16) << i->ip << " " << std::setw(5) << std::dec << i->port << " ";
for (const unsigned char* j = i->id.begin(); j != i->id.end(); ++j)
os << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*j);
os << "\n";
}
os << std::dec << std::setfill(' ');
}
#ifndef NDEBUG #ifndef NDEBUG
logger* torrent::spawn_logger(const char* title) logger* torrent::spawn_logger(const char* title)
{ {