changed the way connections are disconnected. improved logging. Does not depend on exceptions anymore

This commit is contained in:
Arvid Norberg 2008-01-07 01:10:46 +00:00
parent 4271eda751
commit cf4036310b
11 changed files with 405 additions and 205 deletions

View File

@ -194,10 +194,18 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(
torrent*, void*)> ext);
#endif
#ifndef NDEBUG
bool has_peer(peer_connection const* p) const
{
return std::find_if(m_connections.begin(), m_connections.end()
, boost::bind(&boost::intrusive_ptr<peer_connection>::get, _1) == p)
!= m_connections.end();
}
#endif
void operator()();
void open_listen_port() throw();
void open_listen_port();
// if we are listening on an IPv6 interface
// this will return one of the IPv6 addresses on this
@ -216,9 +224,8 @@ namespace libtorrent
boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
peer_id const& get_peer_id() const { return m_peer_id; }
void close_connection(boost::intrusive_ptr<peer_connection> const& p);
void connection_failed(boost::intrusive_ptr<peer_connection> const& p
, tcp::endpoint const& a, char const* message);
void close_connection(peer_connection const* p
, char const* message);
void set_settings(session_settings const& s);
session_settings const& settings() const { return m_settings; }

View File

@ -224,7 +224,7 @@ namespace libtorrent
void add_stat(size_type downloaded, size_type uploaded);
// is called once every second by the main loop
void second_tick(float tick_interval) throw();
void second_tick(float tick_interval);
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
tcp::endpoint const& remote() const { return m_remote; }
@ -235,7 +235,7 @@ namespace libtorrent
void timed_out();
// this will cause this peer_connection to be disconnected.
void disconnect();
void disconnect(char const* message);
bool is_disconnecting() const { return m_disconnecting; }
// this is called when the connection attempt has succeeded

View File

@ -85,10 +85,13 @@ namespace libtorrent
// the tracker, pex, lsd or dht.
policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, int source, char flags);
void update_peer_port(int port, policy::peer* p, int src);
// false means duplicate connection
bool update_peer_port(int port, policy::peer* p, int src);
// called when an incoming connection is accepted
void new_connection(peer_connection& c);
// false means the connection was refused or failed
bool new_connection(peer_connection& c);
// the given connection was just closed
void connection_closed(const peer_connection& c) throw();

View File

@ -133,6 +133,11 @@ namespace libtorrent
, void* userdata);
#endif
#ifndef NDEBUG
bool has_peer(peer_connection* p) const
{ return m_connections.find(p) != m_connections.end(); }
#endif
// this is called when the torrent has metadata.
// it will initialize the storage and the piece-picker
void init();

View File

@ -790,7 +790,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
throw protocol_error("'choke' message size != 1");
{
disconnect("'choke' message size != 1");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -821,7 +824,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
throw protocol_error("'unchoke' message size != 1");
{
disconnect("'unchoke' message size != 1");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -838,7 +844,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
throw protocol_error("'interested' message size != 1");
{
disconnect("'interested' message size != 1");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -855,7 +864,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
throw protocol_error("'not interested' message size != 1");
{
disconnect("'not interested' message size != 1");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -872,7 +884,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 5)
throw protocol_error("'have' message size != 5");
{
disconnect("'have' message size != 5");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -901,7 +916,10 @@ namespace libtorrent
// verify the bitfield size
if (t->valid_metadata()
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
throw protocol_error("bitfield with invalid size");
{
disconnect("bitfield with invalid size");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -935,7 +953,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 13)
throw protocol_error("'request' message size != 13");
{
disconnect("'request' message size != 13");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1004,7 +1025,10 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 13)
throw protocol_error("'cancel' message size != 13");
{
disconnect("'cancel' message size != 13");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1028,11 +1052,17 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_dht_port)
throw protocol_error("got 'dht_port' message from peer that doesn't support it");
{
disconnect("got 'dht_port' message from peer that doesn't support it");
return;
}
TORRENT_ASSERT(received > 0);
if (packet_size() != 3)
throw protocol_error("'dht_port' message size != 3");
{
disconnect("'dht_port' message size != 3");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1049,7 +1079,10 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'suggest_piece' without FAST extension support");
{
disconnect("got 'suggest_piece' without FAST excension support");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1066,7 +1099,10 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'have_all' without FAST extension support");
{
disconnect("got 'have_all' without FAST extension support");
return;
}
m_statistics.received_bytes(0, received);
incoming_have_all();
}
@ -1076,7 +1112,10 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'have_none' without FAST extension support");
{
disconnect("got 'have_none' without FAST extension support");
return;
}
m_statistics.received_bytes(0, received);
incoming_have_none();
}
@ -1086,7 +1125,10 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'reject_request' without FAST extension support");
{
disconnect("got 'reject_request' without FAST extension support");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1107,7 +1149,10 @@ namespace libtorrent
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'allowed_fast' without FAST extension support");
{
disconnect("got 'allowed_fast' without FAST extension support");
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
@ -1129,10 +1174,16 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
m_statistics.received_bytes(0, received);
if (packet_size() < 2)
throw protocol_error("'extended' message smaller than 2 bytes");
{
disconnect("'extended' message smaller than 2 bytes");
return;
}
if (associated_torrent().expired())
throw protocol_error("'extended' message sent before proper handshake");
{
disconnect("'extended' message sent before proper handshake");
return;
}
buffer::const_interval recv_buffer = receive_buffer();
if (recv_buffer.left() < 2) return;
@ -1158,8 +1209,10 @@ namespace libtorrent
}
#endif
throw protocol_error("unknown extended message id: "
+ boost::lexical_cast<std::string>(extended_id));
std::stringstream msg;
msg << "unknown extended message id: " << extended_id;
disconnect(msg.str().c_str());
return;
}
void bt_peer_connection::on_extended_handshake()
@ -1258,9 +1311,10 @@ namespace libtorrent
}
#endif
throw protocol_error("unknown message id: "
+ boost::lexical_cast<std::string>(packet_type)
+ " size: " + boost::lexical_cast<std::string>(packet_size()));
std::stringstream msg;
msg << "unkown message id: " << packet_type << " size: " << packet_size();
disconnect(msg.str().c_str());
return packet_finished();
}
TORRENT_ASSERT(m_message_handler[packet_type] != 0);
@ -1712,10 +1766,7 @@ namespace libtorrent
if (recv_buffer.left() < 20)
{
if (packet_finished())
{
throw protocol_error ("sync hash not found");
}
// else
disconnect("sync hash not found");
return;
}
@ -1740,7 +1791,10 @@ namespace libtorrent
std::size_t bytes_processed = recv_buffer.left() - 20;
m_sync_bytes_read += bytes_processed;
if (m_sync_bytes_read >= 512)
throw protocol_error("sync hash not found within 532 bytes");
{
disconnect("sync hash not found within 532 bytes");
return;
}
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read));
@ -1807,6 +1861,8 @@ namespace libtorrent
if (!t)
{
attach_to_torrent(info_hash);
if (is_disconnecting()) return;
t = associated_torrent().lock();
TORRENT_ASSERT(t);
}
@ -1820,7 +1876,10 @@ namespace libtorrent
}
if (!m_RC4_handler.get())
throw protocol_error("invalid streamkey identifier (info hash) in encrypted handshake");
{
disconnect("invalid streamkey identifier (info hash) in encrypted handshake");
return;
}
// verify constant
buffer::interval wr_recv_buf = wr_recv_buffer();
@ -1830,7 +1889,8 @@ namespace libtorrent
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20))
{
throw protocol_error("unable to verify constant");
disconnect("unable to verify constant");
return;
}
#ifdef TORRENT_VERBOSE_LOGGING
@ -1851,10 +1911,7 @@ namespace libtorrent
if (recv_buffer.left() < 8)
{
if (packet_finished())
{
throw protocol_error ("sync verification constant not found");
}
// else
disconnect("sync verification constant not found");
return;
}
@ -1878,7 +1935,10 @@ namespace libtorrent
std::size_t bytes_processed = recv_buffer.left() - 8;
m_sync_bytes_read += bytes_processed;
if (m_sync_bytes_read >= 512)
throw protocol_error("sync verification constant not found within 520 bytes");
{
disconnect("sync verification constant not found within 520 bytes");
return;
}
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read));
@ -1939,14 +1999,20 @@ namespace libtorrent
case (pe_settings::plaintext):
{
if (!(crypto_field & 0x01))
throw protocol_error("plaintext not provided");
{
disconnect("plaintext not provided");
return;
}
crypto_select = 0x01;
}
break;
case (pe_settings::rc4):
{
if (!(crypto_field & 0x02))
throw protocol_error("rc4 not provided");
{
disconnect("rc4 not provided");
return;
}
crypto_select = 0x02;
}
break;
@ -1967,7 +2033,10 @@ namespace libtorrent
crypto_select = 0x02;
}
if (!crypto_select)
throw protocol_error("rc4/plaintext not provided");
{
disconnect("rc4/plaintext not provided");
return;
}
}
} // switch
@ -1982,22 +2051,34 @@ namespace libtorrent
if (crypto_field == 0x02)
{
if (allowed_enc_level == pe_settings::plaintext)
throw protocol_error("rc4 selected by peer when not provided");
{
disconnect("rc4 selected by peer when not provided");
return;
}
m_rc4_encrypted = true;
}
else if (crypto_field == 0x01)
{
if (allowed_enc_level == pe_settings::rc4)
throw protocol_error("plaintext selected by peer when not provided");
{
disconnect("plaintext selected by peer when not provided");
return;
}
m_rc4_encrypted = false;
}
else
throw protocol_error("unsupported crypto method selected by peer");
{
disconnect("unsupported crypto method selected by peer");
return;
}
}
int len_pad = detail::read_int16(recv_buffer.begin);
if (len_pad < 0 || len_pad > 512)
throw protocol_error("invalid pad length");
{
disconnect("invalid pad length");
return;
}
m_state = read_pe_pad;
if (!is_local())
@ -2031,7 +2112,11 @@ namespace libtorrent
recv_buffer.begin += pad_size;
int len_ia = detail::read_int16(recv_buffer.begin);
if (len_ia < 0) throw protocol_error("invalid len_ia in handshake");
if (len_ia < 0)
{
disconnect("invalid len_ia in handshake");
return;
}
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " len(IA) : " << len_ia << "\n";
@ -2141,7 +2226,10 @@ namespace libtorrent
{
#ifndef TORRENT_DISABLE_ENCRYPTION
if (!is_local() && m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled)
throw protocol_error("encrypted incoming connections disabled");
{
disconnect("encrypted incoming connections disabled");
return;
}
// Don't attempt to perform an encrypted handshake
// within an encrypted connection
@ -2158,7 +2246,8 @@ namespace libtorrent
assert ((!is_local() && m_encrypted) || is_local());
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
throw protocol_error("incorrect protocol identifier");
disconnect("incorrect protocol identifier");
return;
}
#ifndef TORRENT_DISABLE_ENCRYPTION
@ -2167,7 +2256,10 @@ namespace libtorrent
if (!is_local() &&
(m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) &&
!m_encrypted)
throw protocol_error("non encrypted incoming connections disabled");
{
disconnect("non encrypted incoming connections disabled");
return;
}
#endif
#ifdef TORRENT_VERBOSE_LOGGING
@ -2226,6 +2318,7 @@ namespace libtorrent
, (char*)info_hash.begin());
attach_to_torrent(info_hash);
if (is_disconnecting()) return;
}
else
{
@ -2236,7 +2329,8 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " received invalid info_hash\n";
#endif
throw protocol_error("invalid info-hash in handshake");
disconnect("invalid info-hash in handshake");
return;
}
#ifdef TORRENT_VERBOSE_LOGGING
@ -2253,6 +2347,8 @@ namespace libtorrent
// if (t->valid_metadata())
// write_bitfield(t->pieces());
if (is_disconnecting()) return;
TORRENT_ASSERT(t->get_policy().has_connection(this));
m_state = read_peer_id;
@ -2310,18 +2406,20 @@ namespace libtorrent
// if not, we should close the outgoing one.
if (pid < m_ses.get_peer_id() && is_local())
{
i->second.connection->disconnect();
i->second.connection->disconnect("duplicate peer-id, connection closed");
}
else
{
throw protocol_error("duplicate peer-id, connection closed");
disconnect("duplicate peer-id, connection closed");
return;
}
}
}
if (pid == m_ses.get_peer_id())
{
throw protocol_error("closing connection to ourself");
disconnect("closing connection to ourself");
return;
}
m_client_version = identify_client(pid);
@ -2335,7 +2433,10 @@ namespace libtorrent
// disconnect if the peer has the same peer-id as ourself
// since it most likely is ourself then
if (pid == m_ses.get_peer_id())
throw std::runtime_error("closing connection to ourself");
{
disconnect("closing connection to ourself");
return;
}
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
@ -2405,9 +2506,10 @@ namespace libtorrent
if (packet_size > 1024*1024 || packet_size < 0)
{
// packet too large
throw std::runtime_error("packet > 1 MB ("
+ boost::lexical_cast<std::string>(
(unsigned int)packet_size) + " bytes)");
std::stringstream msg;
msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)";
disconnect(msg.str().c_str());
return;
}
if (packet_size == 0)

View File

@ -208,15 +208,26 @@ namespace libtorrent
#endif
{
tcp::socket::non_blocking_io ioc(true);
m_socket->io_control(ioc);
asio::error_code ec;
m_socket->io_control(ioc, ec);
if (ec)
{
disconnect(ec.message().c_str());
return;
}
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
std::fill(m_country, m_country + 2, 0);
#endif
m_remote = m_socket->remote_endpoint();
m_remote = m_socket->remote_endpoint(ec);
if (ec)
{
disconnect(ec.message().c_str());
return;
}
#ifdef TORRENT_VERBOSE_LOGGING
TORRENT_ASSERT(m_socket->remote_endpoint() == remote());
m_logger = m_ses.create_log(remote().address().to_string() + "_"
TORRENT_ASSERT(m_socket->remote_endpoint() == remote() || ec);
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
(*m_logger) << "*** INCOMING CONNECTION\n";
#endif
@ -354,7 +365,8 @@ namespace libtorrent
// if we're a seed too, disconnect
if (t->is_finished())
{
throw std::runtime_error("seed to seed connection redundant, disconnecting");
disconnect("seed to seed connection redundant");
return;
}
m_num_pieces = num_pieces;
t->peer_has_all();
@ -396,7 +408,11 @@ namespace libtorrent
<< " *** CONNECTION CLOSED\n";
}
#endif
TORRENT_ASSERT(!m_ses.has_peer(this));
#ifndef NDEBUG
for (aux::session_impl::torrent_map::const_iterator i = m_ses.m_torrents.begin()
, end(m_ses.m_torrents.end()); i != end; ++i)
TORRENT_ASSERT(!i->second->has_peer(this));
if (m_peer_info)
TORRENT_ASSERT(m_peer_info->connection == 0);
@ -486,7 +502,11 @@ namespace libtorrent
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
#ifdef BOOST_NO_EXCEPTIONS
(*i)->on_piece_pass(index);
#else
try { (*i)->on_piece_pass(index); } catch (std::exception&) {}
#endif
}
#endif
}
@ -499,7 +519,11 @@ namespace libtorrent
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
#ifdef BOOST_NO_EXCEPTIONS
(*i)->on_piece_failed(index);
#else
try { (*i)->on_piece_failed(index); } catch (std::exception&) {}
#endif
}
#endif
@ -587,7 +611,8 @@ namespace libtorrent
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
}
#endif
throw std::runtime_error("got info-hash that is not in our session");
disconnect("got invalid info-hash");
return;
}
if (t->is_paused())
@ -597,7 +622,8 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " rejected connection to paused torrent\n";
#endif
throw std::runtime_error("connection rejected by paused torrent");
disconnect("connection rejected bacause torrent is paused");
return;
}
TORRENT_ASSERT(m_torrent.expired());
@ -929,8 +955,10 @@ namespace libtorrent
// if we got an invalid message, abort
if (index >= int(m_have_piece.size()) || index < 0)
throw protocol_error("got 'have'-message with higher index "
"than the number of pieces");
{
disconnect("got 'have'-message with higher index than the number of pieces");
return;
}
if (m_have_piece[index])
{
@ -974,7 +1002,8 @@ namespace libtorrent
m_peer_info->seed = true;
if (t->is_finished())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
disconnect("seed to seed connection redundant");
return;
}
}
}
@ -1014,11 +1043,14 @@ namespace libtorrent
// verify the bitfield size
if (t->valid_metadata()
&& (bitfield.size() / 8) != (m_have_piece.size() / 8))
throw protocol_error("got bitfield with invalid size: "
+ boost::lexical_cast<std::string>(bitfield.size() / 8)
+ "bytes. expected: "
+ boost::lexical_cast<std::string>(m_have_piece.size() / 8)
+ "bytes");
{
std::stringstream msg;
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
<< "bytes. expected: " << (m_have_piece.size() / 8)
<< " bytes";
disconnect(msg.str().c_str());
return;
}
// if we don't have metadata yet
// just remember the bitmask
@ -1045,7 +1077,8 @@ namespace libtorrent
// if we're a seed too, disconnect
if (t->is_finished())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
disconnect("seed to seed connection redundant, disconnecting");
return;
}
std::fill(m_have_piece.begin(), m_have_piece.end(), true);
@ -1325,7 +1358,8 @@ namespace libtorrent
"start: " << p.start << " | "
"length: " << p.length << " ]\n";
#endif
throw protocol_error("got invalid piece packet");
disconnect("got invalid piece packet");
return;
}
// if we're already seeding, don't bother,
@ -1433,8 +1467,8 @@ namespace libtorrent
TORRENT_ASSERT(m_outstanding_writing_bytes >= 0);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_ses.m_logger) << time_now_string() << " *** DISK_WRITE_COMPLETE [ p: "
<< p.piece << " o: " << p.start << " ]\n";
// (*m_ses.m_logger) << time_now_string() << " *** DISK_WRITE_COMPLETE [ p: "
// << p.piece << " o: " << p.start << " ]\n";
#endif
// in case the outstanding bytes just dropped down
// to allow to receive more data
@ -1448,7 +1482,7 @@ namespace libtorrent
if (!t)
{
m_ses.connection_failed(self(), remote(), j.str.c_str());
disconnect(j.str.c_str());
return;
}
@ -1474,11 +1508,6 @@ namespace libtorrent
block_finished.block_index, block_finished.piece_index, "block finished"));
}
#ifndef NDEBUG
try
{
#endif
// did we just finish the piece?
if (picker.is_piece_finished(p.piece))
{
@ -1489,15 +1518,6 @@ namespace libtorrent
, p.piece, _1));
}
#ifndef NDEBUG
}
catch (std::exception const& e)
{
std::cerr << e.what() << std::endl;
TORRENT_ASSERT(false);
}
#endif
if (!t->is_seed() && !m_torrent.expired())
{
// this is a free function defined in policy.cpp
@ -1614,7 +1634,10 @@ namespace libtorrent
// if we're a seed too, disconnect
if (t->is_finished())
throw protocol_error("seed to seed connection redundant, disconnecting");
{
disconnect("seed to seed connection redundant, disconnecting");
return;
}
TORRENT_ASSERT(!m_have_piece.empty());
std::fill(m_have_piece.begin(), m_have_piece.end(), true);
@ -2004,7 +2027,8 @@ namespace libtorrent
void close_socket_ignore_error(boost::shared_ptr<socket_type> s)
{
try { s->close(); } catch (std::exception& e) {}
asio::error_code ec;
s->close(ec);
}
void peer_connection::timed_out()
@ -2013,14 +2037,17 @@ namespace libtorrent
(*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string()
<< "\n";
#endif
m_ses.connection_failed(self(), m_remote, "timed out");
disconnect("timed out");
}
void peer_connection::disconnect()
void peer_connection::disconnect(char const* message)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
boost::intrusive_ptr<peer_connection> me(this);
#if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << "*** CONNECTION FAILED " << message << "\n";
#endif
// boost::intrusive_ptr<peer_connection> me(this);
INVARIANT_CHECK;
@ -2033,6 +2060,15 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
if (message && m_ses.m_alerts.should_post(alert::debug))
{
m_ses.m_alerts.post_alert(
peer_error_alert(
remote()
, pid()
, message));
}
if (t)
{
if (t->has_picker())
@ -2055,7 +2091,7 @@ namespace libtorrent
m_torrent.reset();
}
m_ses.close_connection(me);
m_ses.close_connection(this, message);
}
void peer_connection::set_upload_limit(int limit)
@ -2207,7 +2243,7 @@ namespace libtorrent
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
}
void peer_connection::second_tick(float tick_interval) throw()
void peer_connection::second_tick(float tick_interval)
{
INVARIANT_CHECK;
@ -2365,7 +2401,7 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "**ERROR**: " << e.what() << "\n";
#endif
m_ses.connection_failed(self(), remote(), e.what());
disconnect(e.what());
}
}
@ -2415,7 +2451,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t)
{
m_ses.connection_failed(self(), remote(), j.str.c_str());
disconnect(j.str.c_str());
return;
}
@ -2714,7 +2750,9 @@ namespace libtorrent
#endif
set_failed();
on_receive(error, bytes_transferred);
throw std::runtime_error(error.message());
set_failed();
disconnect(error.message().c_str());
return;
}
do
@ -2757,7 +2795,10 @@ namespace libtorrent
bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos]
, max_receive), ec);
if (ec && ec != asio::error::would_block)
throw asio::system_error(ec);
{
disconnect(ec.message().c_str());
return;
}
}
while (bytes_transferred > 0);
@ -2770,7 +2811,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t)
{
m_ses.connection_failed(self(), remote(), e.what());
disconnect(e.what());
return;
}
@ -2785,14 +2826,14 @@ namespace libtorrent
catch (std::exception& e)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), e.what());
disconnect(e.what());
}
catch (...)
{
// all exceptions should derive from std::exception
TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), "connection failed for unknown reason");
disconnect("connection failed for unknown reason");
}
bool peer_connection::can_write() const
@ -2828,8 +2869,9 @@ namespace libtorrent
{
INVARIANT_CHECK;
asio::error_code ec;
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string()
(*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec)
<< ":" << m_remote.port() << "\n";
#endif
@ -2839,13 +2881,28 @@ namespace libtorrent
m_queued = false;
TORRENT_ASSERT(m_connecting);
m_socket->open(t->get_interface().protocol());
m_socket->open(t->get_interface().protocol(), ec);
if (ec)
{
disconnect(ec.message().c_str());
return;
}
// set the socket to non-blocking, so that we can
// read the entire buffer on each read event we get
tcp::socket::non_blocking_io ioc(true);
m_socket->io_control(ioc);
m_socket->bind(t->get_interface());
m_socket->io_control(ioc, ec);
if (ec)
{
disconnect(ec.message().c_str());
return;
}
m_socket->bind(t->get_interface(), ec);
if (ec)
{
disconnect(ec.message().c_str());
return;
}
m_socket->async_connect(m_remote
, bind(&peer_connection::on_connection_complete, self(), _1));
@ -2874,7 +2931,7 @@ namespace libtorrent
<< ": " << e.message() << "\n";
#endif
set_failed();
m_ses.connection_failed(self(), m_remote, e.message().c_str());
disconnect(e.message().c_str());
return;
}
@ -2894,14 +2951,14 @@ namespace libtorrent
catch (std::exception& ex)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), ex.what());
disconnect(ex.what());
}
catch (...)
{
// all exceptions should derive from std::exception
TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), "connection failed for unkown reason");
disconnect("connection failed for unkown reason");
}
// --------------------------
@ -2935,7 +2992,8 @@ namespace libtorrent
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
#endif
set_failed();
throw std::runtime_error(error.message());
disconnect(error.message().c_str());
return;
}
if (m_disconnecting) return;
@ -2952,17 +3010,16 @@ namespace libtorrent
catch (std::exception& e)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), e.what());
disconnect(e.what());
}
catch (...)
{
// all exceptions should derive from std::exception
TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(self(), remote(), "connection failed for unknown reason");
disconnect("connection failed for unknown reason");
}
#ifndef NDEBUG
void peer_connection::check_invariant() const
{

View File

@ -361,7 +361,7 @@ namespace libtorrent
if (i->second.connection)
{
i->second.connection->disconnect();
i->second.connection->disconnect("peer banned by IP filter");
if (ses.m_alerts.should_post(alert::info))
{
ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address()
@ -914,7 +914,7 @@ namespace libtorrent
return ret;
}
void policy::new_connection(peer_connection& c)
bool policy::new_connection(peer_connection& c)
{
TORRENT_ASSERT(!c.is_local());
@ -926,13 +926,15 @@ namespace libtorrent
// TODO: only allow _one_ connection to use this
// override at a time
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint());
asio::error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
if (m_torrent->num_peers() >= m_torrent->max_connections()
&& m_torrent->session().num_connections() >= m_torrent->session().max_connections()
&& c.remote().address() != m_torrent->current_tracker().address())
{
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
c.disconnect("too many connections, refusing incoming connection");
return false;
}
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
@ -960,7 +962,10 @@ namespace libtorrent
if (i != m_peers.end())
{
if (i->second.banned)
throw protocol_error("ip address banned, closing");
{
c.disconnect("ip address banned, closing");
return false;
}
if (i->second.connection != 0)
{
@ -969,7 +974,8 @@ namespace libtorrent
// or the current one is already connected
if (!i->second.connection->is_connecting() || c.is_local())
{
throw protocol_error("duplicate connection, closing");
c.disconnect("duplicate connection, closing");
return false;
}
else
{
@ -978,7 +984,8 @@ namespace libtorrent
" is connecting and this connection is incoming. closing existing "
"connection in favour of this one");
#endif
i->second.connection->disconnect();
i->second.connection->disconnect("incoming duplicate connection "
"with higher priority, closing");
}
}
}
@ -986,7 +993,8 @@ namespace libtorrent
{
// we don't have any info about this peer.
// add a new entry
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint());
asio::error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
peer p(c.remote(), peer::not_connectable, 0);
i = m_peers.insert(std::make_pair(c.remote().address(), p));
@ -1002,12 +1010,15 @@ namespace libtorrent
if (!c.fast_reconnect())
i->second.connected = time_now();
// m_last_optimistic_disconnect = time_now();
return true;
}
void policy::update_peer_port(int port, policy::peer* p, int src)
bool policy::update_peer_port(int port, policy::peer* p, int src)
{
TORRENT_ASSERT(p != 0);
if (p->ip.port() == port) return;
TORRENT_ASSERT(p->connection);
if (p->ip.port() == port) return true;
if (m_torrent->settings().allow_multiple_connections_per_ip)
{
@ -1020,7 +1031,8 @@ namespace libtorrent
policy::peer& pp = i->second;
if (pp.connection)
{
throw protocol_error("duplicate connection");
p->connection->disconnect("duplicate connection");
return false;
}
if (m_torrent->has_picker())
m_torrent->picker().clear_peer(&i->second);
@ -1033,6 +1045,7 @@ namespace libtorrent
}
p->ip.port(port);
p->source |= src;
return true;
}
bool policy::has_peer(policy::peer const* p) const
@ -1362,7 +1375,7 @@ namespace libtorrent
(*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
#endif
p->second.connection->disconnect();
p->second.connection->disconnect("too many connections, closing");
return true;
}

View File

@ -754,7 +754,7 @@ namespace detail
#ifndef NDEBUG
int conn = m_connections.size();
#endif
(*m_connections.begin())->disconnect();
(*m_connections.begin())->disconnect("stopping torrent");
TORRENT_ASSERT(conn == int(m_connections.size()) + 1);
}
@ -895,7 +895,7 @@ namespace detail
return s;
}
void session_impl::open_listen_port() throw()
void session_impl::open_listen_port()
{
// close the open listen sockets
m_listen_sockets.clear();
@ -1110,70 +1110,62 @@ namespace detail
c->m_in_constructor = false;
#endif
m_connections.insert(c);
if (!c->is_disconnecting()) m_connections.insert(c);
}
catch (std::exception& exc)
{
#ifndef NDEBUG
std::string err = exc.what();
#endif
};
}
void session_impl::connection_failed(boost::intrusive_ptr<peer_connection> const& peer
, tcp::endpoint const& a, char const* message)
#ifndef NDEBUG
try
#endif
/*
namespace
{
struct compare_peer_ptr
{
bool operator()(peer_connection const* lhs
, intrusive_ptr<peer_connection const> const& rhs)
{
return lhs < rhs.get();
}
bool operator()(intrusive_ptr<peer_connection const> const& lhs
, peer_connection const* rhs)
{
return lhs.get() < rhs;
}
};
}
*/
void session_impl::close_connection(peer_connection const* p
, char const* message)
{
mutex_t::scoped_lock l(m_mutex);
// too expensive
// INVARIANT_CHECK;
connection_map::iterator p = m_connections.find(peer);
// the connection may have been disconnected in the receive or send phase
if (p == m_connections.end()) return;
if (m_alerts.should_post(alert::debug))
{
m_alerts.post_alert(
peer_error_alert(
a
, (*p)->pid()
, message));
}
#if defined(TORRENT_VERBOSE_LOGGING)
(*(*p)->m_logger) << "*** CONNECTION FAILED " << message << "\n";
#endif
(*p)->set_failed();
(*p)->disconnect();
}
#ifndef NDEBUG
catch (...)
{
TORRENT_ASSERT(false);
};
// for (aux::session_impl::torrent_map::const_iterator i = m_torrents.begin()
// , end(m_torrents.end()); i != end; ++i)
// TORRENT_ASSERT(!i->second->has_peer((peer_connection*)p));
#endif
void session_impl::close_connection(boost::intrusive_ptr<peer_connection> const& p)
{
mutex_t::scoped_lock l(m_mutex);
// too expensive
// INVARIANT_CHECK;
#if defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " CLOSING CONNECTION " << p->remote() << "\n";
(*m_logger) << time_now_string() << " CLOSING CONNECTION "
<< p->remote() << " : " << message << "\n";
#endif
TORRENT_ASSERT(p->is_disconnecting());
connection_map::iterator i = m_connections.find(p);
if (i != m_connections.end())
{
if (!(*i)->is_choked()) --m_num_unchoked;
m_connections.erase(i);
}
if (!p->is_choked()) --m_num_unchoked;
// connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end()
// , p, bind(&boost::intrusive_ptr<peer_connection>::get, _1) < p);
// if (i->get() != p) i == m_connections.end();
connection_map::iterator i = std::find_if(m_connections.begin(), m_connections.end()
, bind(&boost::intrusive_ptr<peer_connection>::get, _1) == p);
if (i != m_connections.end()) m_connections.erase(i);
}
void session_impl::set_peer_id(peer_id const& id)
@ -1334,7 +1326,7 @@ namespace detail
#endif
c.set_failed();
c.disconnect();
c.disconnect("timed out");
continue;
}

View File

@ -205,7 +205,7 @@ namespace libtorrent { namespace
<< " | ip: " << p->ip << " ]\n";
#endif
p->banned = true;
if (p->connection) p->connection->disconnect();
if (p->connection) p->connection->disconnect("banning peer for sending bad data");
}
// we already have this exact entry in the map
// we don't have to insert it
@ -267,7 +267,7 @@ namespace libtorrent { namespace
<< " | ip: " << p->ip << " ]\n";
#endif
p->banned = true;
if (p->connection) p->connection->disconnect();
if (p->connection) p->connection->disconnect("banning peer for sending bad data");
}
torrent& m_torrent;

View File

@ -1086,7 +1086,7 @@ namespace libtorrent
<< " ] 'too many corrupt pieces'\n";
#endif
#endif
p->connection->disconnect();
p->connection->disconnect("too many corrupt pieces, banning peer");
}
}
}
@ -1828,10 +1828,7 @@ namespace libtorrent
#endif
// TODO: post an error alert!
// std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
// if (i != m_connections.end()) m_connections.erase(i);
m_ses.connection_failed(c, a, e.what());
c->disconnect();
c->disconnect(e.what());
}
}
catch (std::exception& exc)
@ -2130,8 +2127,7 @@ namespace libtorrent
std::set<peer_connection*>::iterator i
= m_connections.find(boost::get_pointer(c));
if (i != m_connections.end()) m_connections.erase(i);
m_ses.connection_failed(c, a, e.what());
c->disconnect();
c->disconnect(e.what());
return false;
}
peerinfo->connection = c.get();
@ -2216,7 +2212,11 @@ namespace libtorrent
#endif
TORRENT_ASSERT(m_connections.find(p) == ci);
TORRENT_ASSERT(*ci == p);
m_policy.new_connection(**ci);
if (!m_policy.new_connection(**ci))
{
m_connections.erase(ci);
return;
}
}
catch (std::exception& e)
{
@ -2261,7 +2261,7 @@ namespace libtorrent
#ifndef NDEBUG
std::size_t size = m_connections.size();
#endif
p->disconnect();
p->disconnect(m_abort?"stopping torrent":"pausing torrent");
TORRENT_ASSERT(m_connections.size() <= size);
}
}
@ -2371,7 +2371,7 @@ namespace libtorrent
}
}
std::for_each(seeds.begin(), seeds.end()
, bind(&peer_connection::disconnect, _1));
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed"));
TORRENT_ASSERT(m_storage);
// we need to keep the object alive during this operation
@ -2586,7 +2586,7 @@ namespace libtorrent
// the connection failed, close it
torrent::peer_iterator j = i;
++j;
m_ses.connection_failed(*i, (*i)->remote(), e.what());
(*i)->disconnect(e.what());
i = j;
}
}
@ -2663,6 +2663,8 @@ namespace libtorrent
std::map<piece_block, int> num_requests;
for (const_peer_iterator i = begin(); i != end(); ++i)
{
// make sure this peer is not a dangling pointer
TORRENT_ASSERT(m_ses.has_peer(*i));
peer_connection const& p = *(*i);
for (std::deque<piece_block>::const_iterator i = p.request_queue().begin()
, end(p.request_queue().end()); i != end; ++i)
@ -2997,7 +2999,7 @@ namespace libtorrent
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
#endif
p->set_failed();
p->disconnect();
p->disconnect(e.what());
}
}
accumulator += m_stat;

View File

@ -348,7 +348,10 @@ namespace libtorrent
m_statistics.received_bytes(payload, protocol);
if (error)
throw std::runtime_error("failed to parse HTTP response");
{
disconnect("failed to parse HTTP response");
return;
}
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
@ -377,7 +380,8 @@ namespace libtorrent
m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
, error_msg));
}
throw std::runtime_error(error_msg);
disconnect(error_msg.c_str());
return;
}
if (!m_parser.header_finished()) break;
@ -402,7 +406,8 @@ namespace libtorrent
{
// we should not try this server again.
t->remove_url_seed(m_url);
throw std::runtime_error("got HTTP redirection status without location header");
disconnect("got HTTP redirection status without location header");
return;
}
bool single_file_request = false;
@ -422,14 +427,20 @@ namespace libtorrent
if (i == std::string::npos)
{
t->remove_url_seed(m_url);
throw std::runtime_error("got invalid HTTP redirection location (\"" + location + "\") "
"expected it to end with: " + path);
std::stringstream msg;
msg << "got invalid HTTP redirection location (\"" << location << "\") "
"expected it to end with: " << path;
disconnect(msg.str().c_str());
return;
}
location.resize(i);
}
t->add_url_seed(location);
t->remove_url_seed(m_url);
throw std::runtime_error("redirecting to " + location);
std::stringstream msg;
msg << "redirecting to \"" << location << "\"";
disconnect(msg.str().c_str());
return;
}
std::string const& server_version = m_parser.header("server");
@ -462,7 +473,10 @@ namespace libtorrent
{
// we should not try this server again.
t->remove_url_seed(m_url);
throw std::runtime_error("invalid range in HTTP response: " + range_str.str());
std::stringstream msg;
msg << "invalid range in HTTP response: " << range_str;
disconnect(msg.str().c_str());
return;
}
// the http range is inclusive
range_end++;
@ -475,7 +489,8 @@ namespace libtorrent
{
// we should not try this server again.
t->remove_url_seed(m_url);
throw std::runtime_error("no content-length in HTTP response");
disconnect("no content-length in HTTP response");
return;
}
}
@ -485,7 +500,10 @@ namespace libtorrent
torrent_info const& info = t->torrent_file();
if (m_requests.empty() || m_file_requests.empty())
throw std::runtime_error("unexpected HTTP response");
{
disconnect("unexpected HTTP response");
return;
}
int file_index = m_file_requests.front();
peer_request in_range = info.map_file(file_index, range_start
@ -516,7 +534,8 @@ namespace libtorrent
{
// this means the end of the incoming request ends _before_ the
// first expected byte (fs + m_piece.size())
throw std::runtime_error("invalid range in HTTP response");
disconnect("invalid range in HTTP response");
return;
}
// if the request is contained in the range (i.e. the entire request