fixed bug caused when sockets were bound to non-local interface

This commit is contained in:
Arvid Norberg 2006-01-06 20:20:20 +00:00
parent 2e851505f8
commit 564ae78012
7 changed files with 100 additions and 70 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -1169,6 +1169,7 @@ namespace libtorrent
bool policy::connect_peer(peer *p)
{
INVARIANT_CHECK;
try
{
assert(!p->connection);

View File

@ -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

View File

@ -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;
}