fixed bug caused when sockets were bound to non-local interface
This commit is contained in:
parent
2e851505f8
commit
564ae78012
|
@ -1,3 +1,4 @@
|
|||
* fixed bug caused when binding outgoing connections to a non-local interface.
|
||||
* add_torrent() will now throw if called while the session object is
|
||||
being closed.
|
||||
* added the ability to limit the number of simultaneous half-open
|
||||
|
|
|
@ -420,6 +420,7 @@ int main(int ac, char* av[])
|
|||
std::string ip_filter_file;
|
||||
std::string allocation_mode;
|
||||
std::string in_monitor_dir;
|
||||
std::string bind_to_interface;
|
||||
int poll_interval;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
@ -461,6 +462,9 @@ int main(int ac, char* av[])
|
|||
"in seconds) between two refreshes of the directory listing")
|
||||
("half-open-limit,a", po::value<int>(&half_open_limit)->default_value(-1)
|
||||
, "Sets the maximum number of simultaneous half-open tcp connections")
|
||||
("bind,b", po::value<std::string>(&bind_to_interface)->default_value("")
|
||||
, "Sets the local interface to bind outbound and the listen "
|
||||
"socket to")
|
||||
;
|
||||
|
||||
po::positional_options_description p;
|
||||
|
@ -519,7 +523,8 @@ int main(int ac, char* av[])
|
|||
ses.set_max_half_open_connections(half_open_limit);
|
||||
ses.set_download_rate_limit(download_limit);
|
||||
ses.set_upload_rate_limit(upload_limit);
|
||||
ses.listen_on(std::make_pair(listen_port, listen_port + 10));
|
||||
ses.listen_on(std::make_pair(listen_port, listen_port + 10)
|
||||
, bind_to_interface.c_str());
|
||||
ses.set_http_settings(settings);
|
||||
if (log_level == "debug")
|
||||
ses.set_severity_level(alert::debug);
|
||||
|
|
|
@ -201,6 +201,15 @@ namespace libtorrent
|
|||
// is reached.
|
||||
void process_connection_queue();
|
||||
|
||||
void connection_failed(boost::shared_ptr<socket> const& s
|
||||
, address const& a, char const* message);
|
||||
|
||||
// this is where all active sockets are stored.
|
||||
// the selector can sleep while there's no activity on
|
||||
// them
|
||||
selector m_selector;
|
||||
|
||||
|
||||
// this maps sockets to their peer_connection
|
||||
// object. It is the complete list of all connected
|
||||
// peers.
|
||||
|
@ -243,11 +252,6 @@ namespace libtorrent
|
|||
// interface to listen on
|
||||
address m_listen_interface;
|
||||
|
||||
// this is where all active sockets are stored.
|
||||
// the selector can sleep while there's no activity on
|
||||
// them
|
||||
selector m_selector;
|
||||
|
||||
boost::shared_ptr<socket> m_listen_socket;
|
||||
|
||||
// the entries in this array maps the
|
||||
|
|
|
@ -1180,6 +1180,7 @@ namespace libtorrent
|
|||
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int listen_port = detail::read_uint16(ptr);
|
||||
(void)listen_port;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
|
|
|
@ -1169,6 +1169,7 @@ namespace libtorrent
|
|||
|
||||
bool policy::connect_peer(peer *p)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
try
|
||||
{
|
||||
assert(!p->connection);
|
||||
|
|
121
src/session.cpp
121
src/session.cpp
|
@ -560,6 +560,69 @@ namespace libtorrent { namespace detail
|
|||
}
|
||||
}
|
||||
|
||||
void session_impl::connection_failed(boost::shared_ptr<socket> const& s
|
||||
, address const& a, char const* message)
|
||||
{
|
||||
connection_map::iterator p = m_connections.find(s);
|
||||
|
||||
// the connection may have been disconnected in the receive or send phase
|
||||
if (p != m_connections.end())
|
||||
{
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
a
|
||||
, p->second->id()
|
||||
, message));
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*p->second->m_logger) << "*** CONNECTION EXCEPTION\n";
|
||||
#endif
|
||||
p->second->set_failed();
|
||||
m_connections.erase(p);
|
||||
}
|
||||
else if (s == m_listen_socket)
|
||||
{
|
||||
if (m_alerts.should_post(alert::fatal))
|
||||
{
|
||||
std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'";
|
||||
m_alerts.post_alert(listen_failed_alert(msg));
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'";
|
||||
(*m_logger) << msg << "\n";
|
||||
#endif
|
||||
assert(m_listen_socket.unique());
|
||||
m_listen_socket.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the error was not in one of the connected
|
||||
// conenctions. Look among the half-open ones.
|
||||
p = m_half_open.find(s);
|
||||
if (p != m_half_open.end())
|
||||
{
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
a
|
||||
, p->second->id()
|
||||
, message));
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << "FAILED: " << a.as_string() << "\n";
|
||||
#endif
|
||||
p->second->set_failed();
|
||||
m_half_open.erase(p);
|
||||
process_connection_queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void session_impl::operator()()
|
||||
{
|
||||
eh_initializer();
|
||||
|
@ -834,63 +897,7 @@ namespace libtorrent { namespace detail
|
|||
for (std::vector<boost::shared_ptr<socket> >::iterator i = error_clients.begin();
|
||||
i != error_clients.end(); ++i)
|
||||
{
|
||||
connection_map::iterator p = m_connections.find(*i);
|
||||
|
||||
// the connection may have been disconnected in the receive or send phase
|
||||
if (p != m_connections.end())
|
||||
{
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
p->first->sender()
|
||||
, p->second->id()
|
||||
, "connection closed"));
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*p->second->m_logger) << "*** CONNECTION EXCEPTION\n";
|
||||
#endif
|
||||
p->second->set_failed();
|
||||
m_connections.erase(p);
|
||||
}
|
||||
else if (*i == m_listen_socket)
|
||||
{
|
||||
if (m_alerts.should_post(alert::fatal))
|
||||
{
|
||||
std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'";
|
||||
m_alerts.post_alert(listen_failed_alert(msg));
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'";
|
||||
(*m_logger) << msg << "\n";
|
||||
#endif
|
||||
assert(m_listen_socket.unique());
|
||||
m_listen_socket.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the error was not in one of the connected
|
||||
// conenctions. Look among the half-open ones.
|
||||
p = m_half_open.find(*i);
|
||||
if (p != m_half_open.end())
|
||||
{
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
p->first->sender()
|
||||
, p->second->id()
|
||||
, "connection attempt failed"));
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << "FAILED: " << (*i)->sender().as_string() << "\n";
|
||||
#endif
|
||||
p->second->set_failed();
|
||||
m_half_open.erase(p);
|
||||
process_connection_queue();
|
||||
}
|
||||
}
|
||||
connection_failed(*i, (*i)->sender(), "connection exception");
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -864,7 +864,7 @@ namespace libtorrent
|
|||
assert(p != 0);
|
||||
|
||||
peer_iterator i = m_connections.find(p->remote());
|
||||
assert(i != m_connections.end());
|
||||
if (i == m_connections.end()) return;
|
||||
|
||||
if (ready_for_connections())
|
||||
{
|
||||
|
@ -920,16 +920,27 @@ namespace libtorrent
|
|||
m_policy->check_invariant();
|
||||
#endif
|
||||
|
||||
// add the newly connected peer to this torrent's peer list
|
||||
m_connections.insert(
|
||||
std::make_pair(a, boost::get_pointer(c)));
|
||||
try
|
||||
{
|
||||
// add the newly connected peer to this torrent's peer list
|
||||
m_connections.insert(
|
||||
std::make_pair(a, boost::get_pointer(c)));
|
||||
|
||||
#ifndef NDEBUG
|
||||
m_policy->check_invariant();
|
||||
m_policy->check_invariant();
|
||||
#endif
|
||||
|
||||
m_ses.m_selector.monitor_errors(s);
|
||||
m_ses.process_connection_queue();
|
||||
m_ses.m_selector.monitor_errors(s);
|
||||
m_ses.process_connection_queue();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// TODO: post an error alert!
|
||||
std::map<address, peer_connection*>::iterator i = m_connections.find(a);
|
||||
if (i != m_connections.end()) m_connections.erase(i);
|
||||
m_ses.connection_failed(s, a, e.what());
|
||||
throw;
|
||||
}
|
||||
return *c;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue