*** empty log message ***

This commit is contained in:
Arvid Norberg 2003-12-01 21:27:27 +00:00
parent f21d6a0f7f
commit 6402fd4a14
9 changed files with 157 additions and 45 deletions

View File

@ -66,6 +66,11 @@ namespace libtorrent
struct session_impl;
}
struct protocol_error: std::runtime_error
{
protocol_error(const std::string& msg): std::runtime_error(msg) {};
};
struct peer_request
{
int piece;
@ -181,13 +186,28 @@ namespace libtorrent
// peer.
int send_quota() const { return m_send_quota; }
void received_valid_data()
{
m_trust_points++;
if (m_trust_points > 20) m_trust_points = 20;
}
void received_invalid_data()
{
m_trust_points--;
if (m_trust_points < 5) m_trust_points = 5;
}
int trust_points() const
{ return m_trust_points; }
#ifndef NDEBUG
boost::shared_ptr<logger> m_logger;
#endif
private:
bool dispatch_message();
void dispatch_message();
void send_buffer_updated();
void send_bitfield();
@ -314,6 +334,14 @@ namespace libtorrent
// speed
int m_send_quota;
int m_send_quota_left;
// for every valid piece we receive where this
// peer was one of the participants, we increase
// this value. For every invalid piece we receive
// where this peer was a participant, we decrease
// this value. If it sinks below a threshold, its
// considered a bad peer and will be banned.
int m_trust_points;
};
// this is called each time this peer generates some

View File

@ -62,7 +62,8 @@ namespace libtorrent
void pulse();
// called when an incoming connection is accepted
void new_connection(const boost::weak_ptr<peer_connection>& c);
// return false if the connection closed
bool new_connection(const boost::weak_ptr<peer_connection>& c);
// this is called once for every peer we get from
// the tracker
@ -71,6 +72,10 @@ namespace libtorrent
// the given connection was just closed
void connection_closed(const peer_connection& c);
// is called when a peer is believed to have
// sent invalid data
void ban_peer(const peer_connection& c);
// the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c);
@ -105,6 +110,7 @@ namespace libtorrent
, optimistic_unchokes(0)
, prev_amount_upload(0)
, prev_amount_download(0)
, banned(false)
{}
bool operator==(const peer_id& pid) const
@ -140,6 +146,9 @@ namespace libtorrent
int prev_amount_upload;
int prev_amount_download;
// is set to true if this peer has been banned
bool banned;
// if the peer is connected now, this
// will refer to a valid peer_connection
boost::weak_ptr<peer_connection> connection;

View File

@ -216,6 +216,11 @@ namespace libtorrent
piece_picker& picker() { return m_picker; }
// this is called from the peer_connection
// each time a piece has failed the hash
// test
void piece_failed(int index);
// DEBUG
#ifndef NDEBUG
logger* spawn_logger(const char* title);

View File

@ -225,11 +225,11 @@ void libtorrent::peer_connection::send_handshake()
send_buffer_updated();
}
bool libtorrent::peer_connection::dispatch_message()
void libtorrent::peer_connection::dispatch_message()
{
int packet_type = m_recv_buffer[0];
if (packet_type > 8 || packet_type < 0)
return false;
throw protocol_error("unknown message id");
switch (packet_type)
{
@ -295,7 +295,7 @@ bool libtorrent::peer_connection::dispatch_message()
std::size_t index = read_int(&m_recv_buffer[1]);
// if we got an invalid message, abort
if (index >= m_have_piece.size())
return false;
throw protocol_error("have message with higher index than the number of pieces");
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== HAVE [ piece: " << index << "]\n";
@ -323,7 +323,7 @@ bool libtorrent::peer_connection::dispatch_message()
case msg_bitfield:
{
if (m_packet_size - 1 != (m_have_piece.size() + 7) / 8)
return false;
throw protocol_error("bitfield with invalid size");
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== BITFIELD\n";
@ -390,7 +390,7 @@ bool libtorrent::peer_connection::dispatch_message()
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece index invalid\n";
#endif
return false;
throw protocol_error("invalid piece index in piece message");
}
int offset = read_int(&m_recv_buffer[5]);
int len = m_packet_size - 9;
@ -400,7 +400,7 @@ bool libtorrent::peer_connection::dispatch_message()
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " offset < 0\n";
#endif
return false;
throw protocol_error("offset < 0 in piece message");
}
if (offset + len > m_torrent->torrent_file().piece_size(index))
@ -408,7 +408,7 @@ bool libtorrent::peer_connection::dispatch_message()
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains more data than the piece size\n";
#endif
return false;
throw protocol_error("piece message contains more data than the piece size");
}
if (offset % m_torrent->block_size() != 0)
@ -416,7 +416,7 @@ bool libtorrent::peer_connection::dispatch_message()
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unaligned offset\n";
#endif
return false;
throw protocol_error("piece message contains unaligned offset");
}
/*
piece_block req = m_download_queue.front();
@ -471,6 +471,8 @@ bool libtorrent::peer_connection::dispatch_message()
picker.mark_as_finished(block_finished, m_peer_id);
m_torrent->get_policy().block_finished(*this, block_finished);
// did we just finish the piece?
if (picker.is_piece_finished(index))
{
@ -483,26 +485,10 @@ bool libtorrent::peer_connection::dispatch_message()
}
else
{
#ifndef NDEBUG
std::cout << "hash-test failed. Some of these peers sent invalid data:\n";
std::vector<peer_id> downloaders;
picker.get_downloaders(downloaders, index);
std::copy(downloaders.begin(), downloaders.end(), std::ostream_iterator<peer_id>(std::cout, "\n"));
#endif
// 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
// if some clients has sent more than one piece
// start with redownloading the pieces that the client
// that has sent the least number of pieces
picker.restore_piece(index);
m_torrent->piece_failed(index);
}
m_torrent->get_policy().piece_finished(*this, index, verified);
}
m_torrent->get_policy().block_finished(*this, block_finished);
break;
}
@ -534,8 +520,6 @@ bool libtorrent::peer_connection::dispatch_message()
break;
}
}
return true;
}
void libtorrent::peer_connection::cancel_block(piece_block block)
@ -932,14 +916,9 @@ void libtorrent::peer_connection::receive_data()
case read_packet:
if (!dispatch_message())
{
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " received invalid packet\n";
#endif
// invalid message
throw network_error(0);
}
// TODO: dispatch should throw instead of returning status
// and instead of throwing network_error, throw protocol_error
dispatch_message();
m_state = read_packet_size;
m_packet_size = 4;

View File

@ -197,9 +197,11 @@ namespace libtorrent
void peer_connection::request_piece(int index);
const std::vector<int>& peer_connection::download_queue();
TODO: to implement choking/unchoking we need a list with all
connected peers. Something like this:
TODO: implement a limit of the number of unchoked peers.
TODO: implement some kind of limit of the number of sockets
opened, to use for systems where a user has a limited number
of open file descriptors
*/
@ -238,6 +240,10 @@ namespace libtorrent
else if (uploaded - downloaded <= m_torrent->block_size()
&& c->is_choked() && c->is_peer_interested())
{
// TODO: if we're not interested in this peer
// we should only unchoke it if it' its turn
// to be optimistically unchoked.
// we have catched up. We have now shared the same amount
// to eachother. Unchoke this peer.
c->unchoke();
@ -245,11 +251,19 @@ namespace libtorrent
}
}
void policy::new_connection(const boost::weak_ptr<peer_connection>& c)
void policy::ban_peer(const peer_connection& c)
{
std::vector<peer>::iterator i = std::find(m_peers.begin(), m_peers.end(), c.get_peer_id());
assert(i != m_peers.end());
i->banned = true;
}
bool policy::new_connection(const boost::weak_ptr<peer_connection>& c)
{
boost::shared_ptr<peer_connection> con = c.lock();
assert(con.get() != 0);
if (con.get() == 0) return;
if (con.get() == 0) return false;
std::vector<peer>::iterator i
= std::find(m_peers.begin(), m_peers.end(), con->get_peer_id());
@ -264,10 +278,12 @@ namespace libtorrent
else
{
assert(i->connection.expired());
if (i->banned) return false;
}
i->connected = boost::posix_time::second_clock::local_time();
i->connection = c;
return true;
}
void policy::peer_from_tracker(const address& remote, const peer_id& id)
@ -291,11 +307,14 @@ namespace libtorrent
return;
}
if (i->banned) return;
i->connected = boost::posix_time::second_clock::local_time();
i->connection = m_torrent->connect_to_peer(remote, id);
}
catch(network_error&) {}
catch(protocol_error&) {}
}
// this is called when we are choked by a peer

View File

@ -190,7 +190,7 @@ namespace libtorrent
{
listener->listen(m_listen_port, 5);
}
catch(network_error&)
catch(std::exception&)
{
if (m_listen_port > max_port)
throw;
@ -299,7 +299,7 @@ namespace libtorrent
// (*m_logger) << "readable: " << p->first->sender().as_string() << "\n";
p->second->receive_data();
}
catch(network_error&)
catch(std::exception&)
{
// the connection wants to disconnect for some reason, remove it
// from the connection-list
@ -338,7 +338,7 @@ namespace libtorrent
// (*m_logger) << "writable: " << p->first->sender().as_string() << "\n";
p->second->send_data();
}
catch(network_error&)
catch(std::exception&)
{
// the connection wants to disconnect for some reason, remove it
// from the connection-list

View File

@ -366,6 +366,7 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
int read_bytes = left_to_read;
if (m_file_offset + read_bytes > m_file_iter->size)
read_bytes = m_file_iter->size - m_file_offset;
assert(read_bytes > 0);
m_file.read(buf + buf_pos, read_bytes);
@ -505,7 +506,10 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
{
int write_bytes = left_to_write;
if (m_file_offset + write_bytes > m_file_iter->size)
{
assert(m_file_iter->size > m_file_offset);
write_bytes = m_file_iter->size - m_file_offset;
}
assert(buf_pos >= 0);
assert(write_bytes > 0);
@ -515,6 +519,7 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
buf_pos += write_bytes;
assert(buf_pos >= 0);
m_file_offset += write_bytes;
assert(m_file_offset < m_file_iter->size);
m_piece_offset += write_bytes;
if (left_to_write > 0)
@ -522,6 +527,7 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
++m_file_iter;
assert(m_file_iter != m_storage->m_torrent_file->end_files());
assert(m_file_iter->size > m_file_offset);
boost::filesystem::path path = m_storage->m_save_path /
m_file_iter->path / m_file_iter->filename;

View File

@ -240,8 +240,69 @@ namespace libtorrent
!= m_connections.end();
}
void torrent::piece_failed(int index)
{
std::vector<peer_id> downloaders;
m_picker.get_downloaders(downloaders, index);
#ifndef NDEBUG
std::cout << "hash-test failed. Some of these peers sent invalid data:\n";
std::copy(downloaders.begin(), downloaders.end(), std::ostream_iterator<peer_id>(std::cout, "\n"));
#endif
// decrease the trust point of all peers that sent
// parts of this piece.
// TODO: implement this loop more efficient
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_peer_id())
!= downloaders.end())
{
(*i)->received_invalid_data();
if ((*i)->trust_points() <= -5)
{
// we don't trust this peer anymore
// ban it.
m_policy->ban_peer(*(*i));
}
}
}
// 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
// if some clients has sent more than one piece
// start with redownloading the pieces that the client
// that has sent the least number of pieces
m_picker.restore_piece(index);
}
void torrent::announce_piece(int index)
{
std::vector<peer_id> downloaders;
m_picker.get_downloaders(downloaders, index);
// increase the trust point of all peers that sent
// parts of this piece.
// TODO: implement this loop more efficient
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_peer_id())
!= downloaders.end())
{
(*i)->received_valid_data();
}
}
m_picker.we_have(index);
for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index);
@ -378,7 +439,7 @@ namespace libtorrent
= m_ses->m_connections.find(p->get_socket());
assert(i != m_ses->m_connections.end());
m_policy->new_connection(i->second);
if (!m_policy->new_connection(i->second)) throw network_error(0);
}
void torrent::close_all_connections()

View File

@ -156,6 +156,11 @@ namespace libtorrent
++i)
{
peer_connection* peer = *i;
// peers that hasn't finished the handshake should
// not be included in this list
if (peer->associated_torrent() == 0) continue;
v.push_back(peer_info());
peer_info& p = v.back();