*** 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
# : src/main.cpp <lib>torrent
# $(BOOST_ROOT)/libs/filesystem/build//boost_filesystem
# : <include>$(BOOST_ROOT)
# <sysinclude>$(BOOST_ROOT)
# <include>./
# <threading>multi
# : debug release
# ;
exe client_test
: examples/client_test.cpp
<lib>torrent
# <lib>$(BOOST_ROOT)/libs/filesystem/build/boost_filesystem
# <dll>$(BOOST_ROOT)/libs/thread/build/boost_thread
: <include>$(BOOST_ROOT)
<sysinclude>$(BOOST_ROOT)
<include>./include
<threading>multi
: debug release
;

View File

@ -10,6 +10,19 @@
<body>
<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>
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

View File

@ -150,6 +150,14 @@ namespace libtorrent
int index;
std::bitset<max_blocks_per_piece> requested_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
@ -172,8 +180,12 @@ namespace libtorrent
// that no peer have, the vector at index 1 contains
// all pieces that exactly one peer have, index 2 contains
// all pieces exactly two peers have and so on.
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;
// 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
// 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
{
friend class storage;

View File

@ -61,7 +61,7 @@ namespace libtorrent
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
// TODO: There should be a maximum number of peers that
// 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
// replaced to maximize bandwidth usage. It wil also have to
// 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
@ -119,7 +120,8 @@ namespace libtorrent
int bytes_left() const { return m_storage.bytes_left(); }
// 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
{
return bytes_downloaded() / static_cast<float>(m_torrent_file.total_size());
@ -238,11 +240,13 @@ namespace libtorrent
// blocks when requested
int m_block_size;
// is set to true when the torrent has
// been aborted.
bool m_abort;
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
// the number of bytes left to be downloaded
@ -266,9 +270,6 @@ namespace libtorrent
std::string m_failed;
std::vector<peer_connection*> m_connections;
// TODO: move to a local function?
std::vector<peer> m_peer_list;
// -----------------------------
boost::shared_ptr<policy> m_policy;

View File

@ -402,9 +402,12 @@ bool libtorrent::peer_connection::dispatch_message()
}
else
{
// TODO: we have to let the piece_picker know that
// this piece failed the check os it can restore it
// we have to let the piece_picker know that
// this piece failed the check as it can restore it
// 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);
}
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
// 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);
start_offset +=5;
@ -685,6 +686,7 @@ void libtorrent::peer_connection::receive_data()
{
// verify 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()))
{
#ifndef NDEBUG

View File

@ -90,7 +90,6 @@ namespace libtorrent
// TODO: random_shuffle
}
// TODO: add a check to make sure m_downloads is intact
#ifndef NDEBUG
void piece_picker::integrity_check(const torrent* t) const
@ -304,6 +303,13 @@ namespace libtorrent
#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)
{
assert(i >= 0);
@ -337,10 +343,6 @@ namespace libtorrent
if (index == 0xffffff) return;
move(m_piece_map[i].downloading, peer_count, index);
#ifndef NDEBUG
integrity_check();
#endif
}
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
{
// TODO: modify this!
assert(pieces.size() == m_piece_map.size());
// free refers to pieces that are free to download, noone else
// is downloading them.
// partial is pieces that are partially being downloaded, and

View File

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

View File

@ -82,8 +82,9 @@ namespace
{
peer_id ret;
std::srand(std::time(0));
// unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0";
unsigned char fingerprint[] = "h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
// TODO: add ability to control fingerprint
// 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;
std::copy(fingerprint, fingerprint+len, ret.begin());
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
// 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
@ -236,7 +239,9 @@ namespace libtorrent
// ************************
// 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);
// the connection may have been disconnected in the receive phase
@ -269,7 +274,9 @@ namespace libtorrent
// 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);
@ -439,7 +446,7 @@ namespace libtorrent
boost::mutex::scoped_lock l(m_impl.m_mutex);
// 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())
return torrent_handle(&m_impl, ti.info_hash());

View File

@ -71,7 +71,7 @@ namespace
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;
}
@ -154,10 +154,63 @@ namespace libtorrent
void torrent::tracker_response(const entry& e)
{
std::vector<peer> peer_list;
try
{
// 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)
{
@ -168,30 +221,6 @@ namespace libtorrent
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
@ -223,7 +252,6 @@ namespace libtorrent
m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration);
std::vector<char> buffer;
// TODO: temporary! support multi-tracker
std::string request = m_torrent_file.trackers()[m_currently_trying_tracker].url;
request += "?info_hash=";
@ -255,7 +283,7 @@ namespace libtorrent
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");
if (i != e.dict().end())
@ -272,15 +300,14 @@ namespace libtorrent
i = msg.find("peers");
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();
for(entry::list_type::const_iterator i = peer_list.begin(); i != peer_list.end(); ++i)
const entry::list_type& l = i->second.list();
for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++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)
@ -328,20 +355,6 @@ namespace libtorrent
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
logger* torrent::spawn_logger(const char* title)
{