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 #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>( void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(
torrent*, void*)> ext); 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 #endif
void operator()(); void operator()();
void open_listen_port() throw(); void open_listen_port();
// if we are listening on an IPv6 interface // if we are listening on an IPv6 interface
// this will return one of the IPv6 addresses on this // 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); boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
peer_id const& get_peer_id() const { return m_peer_id; } peer_id const& get_peer_id() const { return m_peer_id; }
void close_connection(boost::intrusive_ptr<peer_connection> const& p); void close_connection(peer_connection const* p
void connection_failed(boost::intrusive_ptr<peer_connection> const& p , char const* message);
, tcp::endpoint const& a, char const* message);
void set_settings(session_settings const& s); void set_settings(session_settings const& s);
session_settings const& settings() const { return m_settings; } 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); void add_stat(size_type downloaded, size_type uploaded);
// is called once every second by the main loop // 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; } boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
tcp::endpoint const& remote() const { return m_remote; } tcp::endpoint const& remote() const { return m_remote; }
@ -235,7 +235,7 @@ namespace libtorrent
void timed_out(); void timed_out();
// this will cause this peer_connection to be disconnected. // this will cause this peer_connection to be disconnected.
void disconnect(); void disconnect(char const* message);
bool is_disconnecting() const { return m_disconnecting; } bool is_disconnecting() const { return m_disconnecting; }
// this is called when the connection attempt has succeeded // this is called when the connection attempt has succeeded

View File

@ -85,10 +85,13 @@ namespace libtorrent
// the tracker, pex, lsd or dht. // the tracker, pex, lsd or dht.
policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, int source, char flags); , 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 // 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 // the given connection was just closed
void connection_closed(const peer_connection& c) throw(); void connection_closed(const peer_connection& c) throw();

View File

@ -133,6 +133,11 @@ namespace libtorrent
, void* userdata); , void* userdata);
#endif #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. // this is called when the torrent has metadata.
// it will initialize the storage and the piece-picker // it will initialize the storage and the piece-picker
void init(); void init();

View File

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

View File

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

View File

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

View File

@ -754,7 +754,7 @@ namespace detail
#ifndef NDEBUG #ifndef NDEBUG
int conn = m_connections.size(); int conn = m_connections.size();
#endif #endif
(*m_connections.begin())->disconnect(); (*m_connections.begin())->disconnect("stopping torrent");
TORRENT_ASSERT(conn == int(m_connections.size()) + 1); TORRENT_ASSERT(conn == int(m_connections.size()) + 1);
} }
@ -895,7 +895,7 @@ namespace detail
return s; return s;
} }
void session_impl::open_listen_port() throw() void session_impl::open_listen_port()
{ {
// close the open listen sockets // close the open listen sockets
m_listen_sockets.clear(); m_listen_sockets.clear();
@ -1110,70 +1110,62 @@ namespace detail
c->m_in_constructor = false; c->m_in_constructor = false;
#endif #endif
m_connections.insert(c); if (!c->is_disconnecting()) m_connections.insert(c);
} }
catch (std::exception& exc) catch (std::exception& exc)
{ {
#ifndef NDEBUG #ifndef NDEBUG
std::string err = exc.what(); std::string err = exc.what();
#endif #endif
};
void session_impl::connection_failed(boost::intrusive_ptr<peer_connection> const& peer
, tcp::endpoint const& a, char const* message)
#ifndef NDEBUG
try
#endif
{
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);
};
#endif
void session_impl::close_connection(boost::intrusive_ptr<peer_connection> const& p) /*
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); mutex_t::scoped_lock l(m_mutex);
// too expensive // too expensive
// INVARIANT_CHECK; // INVARIANT_CHECK;
#ifndef NDEBUG
// 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
#if defined(TORRENT_LOGGING) #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 #endif
TORRENT_ASSERT(p->is_disconnecting()); TORRENT_ASSERT(p->is_disconnecting());
connection_map::iterator i = m_connections.find(p);
if (i != m_connections.end()) if (!p->is_choked()) --m_num_unchoked;
{ // connection_map::iterator i = std::lower_bound(m_connections.begin(), m_connections.end()
if (!(*i)->is_choked()) --m_num_unchoked; // , p, bind(&boost::intrusive_ptr<peer_connection>::get, _1) < p);
m_connections.erase(i); // 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) void session_impl::set_peer_id(peer_id const& id)
@ -1334,7 +1326,7 @@ namespace detail
#endif #endif
c.set_failed(); c.set_failed();
c.disconnect(); c.disconnect("timed out");
continue; continue;
} }

View File

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

View File

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

View File

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