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
|
* add_torrent() will now throw if called while the session object is
|
||||||
being closed.
|
being closed.
|
||||||
* added the ability to limit the number of simultaneous half-open
|
* 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 ip_filter_file;
|
||||||
std::string allocation_mode;
|
std::string allocation_mode;
|
||||||
std::string in_monitor_dir;
|
std::string in_monitor_dir;
|
||||||
|
std::string bind_to_interface;
|
||||||
int poll_interval;
|
int poll_interval;
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
@ -461,6 +462,9 @@ int main(int ac, char* av[])
|
||||||
"in seconds) between two refreshes of the directory listing")
|
"in seconds) between two refreshes of the directory listing")
|
||||||
("half-open-limit,a", po::value<int>(&half_open_limit)->default_value(-1)
|
("half-open-limit,a", po::value<int>(&half_open_limit)->default_value(-1)
|
||||||
, "Sets the maximum number of simultaneous half-open tcp connections")
|
, "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;
|
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_max_half_open_connections(half_open_limit);
|
||||||
ses.set_download_rate_limit(download_limit);
|
ses.set_download_rate_limit(download_limit);
|
||||||
ses.set_upload_rate_limit(upload_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);
|
ses.set_http_settings(settings);
|
||||||
if (log_level == "debug")
|
if (log_level == "debug")
|
||||||
ses.set_severity_level(alert::debug);
|
ses.set_severity_level(alert::debug);
|
||||||
|
|
|
@ -201,6 +201,15 @@ namespace libtorrent
|
||||||
// is reached.
|
// is reached.
|
||||||
void process_connection_queue();
|
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
|
// this maps sockets to their peer_connection
|
||||||
// object. It is the complete list of all connected
|
// object. It is the complete list of all connected
|
||||||
// peers.
|
// peers.
|
||||||
|
@ -243,11 +252,6 @@ namespace libtorrent
|
||||||
// interface to listen on
|
// interface to listen on
|
||||||
address m_listen_interface;
|
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;
|
boost::shared_ptr<socket> m_listen_socket;
|
||||||
|
|
||||||
// the entries in this array maps the
|
// the entries in this array maps the
|
||||||
|
|
|
@ -1180,6 +1180,7 @@ namespace libtorrent
|
||||||
|
|
||||||
const char* ptr = &m_recv_buffer[1];
|
const char* ptr = &m_recv_buffer[1];
|
||||||
int listen_port = detail::read_uint16(ptr);
|
int listen_port = detail::read_uint16(ptr);
|
||||||
|
(void)listen_port;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
using namespace boost::posix_time;
|
using namespace boost::posix_time;
|
||||||
|
|
|
@ -1169,6 +1169,7 @@ namespace libtorrent
|
||||||
|
|
||||||
bool policy::connect_peer(peer *p)
|
bool policy::connect_peer(peer *p)
|
||||||
{
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
assert(!p->connection);
|
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()()
|
void session_impl::operator()()
|
||||||
{
|
{
|
||||||
eh_initializer();
|
eh_initializer();
|
||||||
|
@ -834,63 +897,7 @@ namespace libtorrent { namespace detail
|
||||||
for (std::vector<boost::shared_ptr<socket> >::iterator i = error_clients.begin();
|
for (std::vector<boost::shared_ptr<socket> >::iterator i = error_clients.begin();
|
||||||
i != error_clients.end(); ++i)
|
i != error_clients.end(); ++i)
|
||||||
{
|
{
|
||||||
connection_map::iterator p = m_connections.find(*i);
|
connection_failed(*i, (*i)->sender(), "connection exception");
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
|
@ -864,7 +864,7 @@ namespace libtorrent
|
||||||
assert(p != 0);
|
assert(p != 0);
|
||||||
|
|
||||||
peer_iterator i = m_connections.find(p->remote());
|
peer_iterator i = m_connections.find(p->remote());
|
||||||
assert(i != m_connections.end());
|
if (i == m_connections.end()) return;
|
||||||
|
|
||||||
if (ready_for_connections())
|
if (ready_for_connections())
|
||||||
{
|
{
|
||||||
|
@ -920,16 +920,27 @@ namespace libtorrent
|
||||||
m_policy->check_invariant();
|
m_policy->check_invariant();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// add the newly connected peer to this torrent's peer list
|
try
|
||||||
m_connections.insert(
|
{
|
||||||
std::make_pair(a, boost::get_pointer(c)));
|
// add the newly connected peer to this torrent's peer list
|
||||||
|
m_connections.insert(
|
||||||
|
std::make_pair(a, boost::get_pointer(c)));
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
m_policy->check_invariant();
|
m_policy->check_invariant();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_ses.m_selector.monitor_errors(s);
|
m_ses.m_selector.monitor_errors(s);
|
||||||
m_ses.process_connection_queue();
|
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;
|
return *c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue