fixed bug in udp_socket when the sockets own lifetime was dependent on the callback
This commit is contained in:
parent
67bed1407f
commit
ba8163ca9c
|
@ -64,6 +64,10 @@ namespace libtorrent
|
||||||
void set_proxy_settings(proxy_settings const& ps);
|
void set_proxy_settings(proxy_settings const& ps);
|
||||||
proxy_settings const& get_proxy_settings() { return m_proxy_settings; }
|
proxy_settings const& get_proxy_settings() { return m_proxy_settings; }
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
~udp_socket() { m_magic = 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
callback_t m_callback;
|
callback_t m_callback;
|
||||||
|
@ -94,6 +98,7 @@ namespace libtorrent
|
||||||
char m_v4_buf[1600];
|
char m_v4_buf[1600];
|
||||||
char m_v6_buf[1600];
|
char m_v6_buf[1600];
|
||||||
int m_bind_port;
|
int m_bind_port;
|
||||||
|
uint8_t m_outstanding;
|
||||||
|
|
||||||
tcp::socket m_socks5_sock;
|
tcp::socket m_socks5_sock;
|
||||||
int m_connection_ticket;
|
int m_connection_ticket;
|
||||||
|
@ -103,6 +108,9 @@ namespace libtorrent
|
||||||
char m_tmp_buf[100];
|
char m_tmp_buf[100];
|
||||||
bool m_tunnel_packets;
|
bool m_tunnel_packets;
|
||||||
udp::endpoint m_proxy_addr;
|
udp::endpoint m_proxy_addr;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
int m_magic;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,33 @@ udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c
|
||||||
, m_ipv4_sock(ios)
|
, m_ipv4_sock(ios)
|
||||||
, m_ipv6_sock(ios)
|
, m_ipv6_sock(ios)
|
||||||
, m_bind_port(0)
|
, m_bind_port(0)
|
||||||
|
, m_outstanding(0)
|
||||||
, m_socks5_sock(ios)
|
, m_socks5_sock(ios)
|
||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
, m_cc(cc)
|
, m_cc(cc)
|
||||||
, m_resolver(ios)
|
, m_resolver(ios)
|
||||||
, m_tunnel_packets(false)
|
, m_tunnel_packets(false)
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
m_magic = 0x1337;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define CHECK_MAGIC check_magic_ cm_(m_magic)
|
||||||
|
struct check_magic_
|
||||||
|
{
|
||||||
|
check_magic_(int& m_): m(m_) { TORRENT_ASSERT(m == 0x1337); }
|
||||||
|
~check_magic_() { TORRENT_ASSERT(m == 0x1337); }
|
||||||
|
int& m;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#define CHECK_MAGIC (void)
|
||||||
|
#endif
|
||||||
|
|
||||||
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
||||||
{
|
{
|
||||||
if (ec == asio::error::operation_aborted) return;
|
CHECK_MAGIC;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
|
|
||||||
if (m_tunnel_packets)
|
if (m_tunnel_packets)
|
||||||
{
|
{
|
||||||
// send udp packets through SOCKS5 server
|
// send udp packets through SOCKS5 server
|
||||||
|
@ -47,10 +60,26 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_cod
|
||||||
|
|
||||||
void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred)
|
void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if (e == asio::error::operation_aborted) return;
|
TORRENT_ASSERT(m_magic == 0x1337);
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_outstanding > 0);
|
||||||
|
--m_outstanding;
|
||||||
|
|
||||||
|
if (e == asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
if (m_outstanding == 0)
|
||||||
|
{
|
||||||
|
// "this" may be destructed in the callback
|
||||||
|
// that's why we need to unlock
|
||||||
|
l.unlock();
|
||||||
|
callback_t tmp = m_callback;
|
||||||
|
m_callback.clear();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_MAGIC;
|
||||||
if (!m_callback) return;
|
if (!m_callback) return;
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
|
@ -59,9 +88,9 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
if (s == &m_ipv4_sock)
|
if (s == &m_ipv4_sock)
|
||||||
get_io_service().post(boost::bind(m_callback, e, m_v4_ep, (char*)0, 0));
|
m_callback(e, m_v4_ep, 0, 0);
|
||||||
else
|
else
|
||||||
get_io_service().post(boost::bind(m_callback, e, m_v6_ep, (char*)0, 0));
|
m_callback(e, m_v6_ep, 0, 0);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch(std::exception&) {}
|
} catch(std::exception&) {}
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,7 +123,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_
|
||||||
if (m_tunnel_packets && m_v4_ep == m_proxy_addr)
|
if (m_tunnel_packets && m_v4_ep == m_proxy_addr)
|
||||||
unwrap(e, m_v4_buf, bytes_transferred);
|
unwrap(e, m_v4_buf, bytes_transferred);
|
||||||
else
|
else
|
||||||
get_io_service().post(boost::bind(m_callback, e, m_v4_ep, m_v4_buf, bytes_transferred));
|
m_callback(e, m_v4_ep, m_v4_buf, bytes_transferred);
|
||||||
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch(std::exception&) {}
|
} catch(std::exception&) {}
|
||||||
|
@ -111,7 +140,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_
|
||||||
if (m_tunnel_packets && m_v6_ep == m_proxy_addr)
|
if (m_tunnel_packets && m_v6_ep == m_proxy_addr)
|
||||||
unwrap(e, m_v6_buf, bytes_transferred);
|
unwrap(e, m_v6_buf, bytes_transferred);
|
||||||
else
|
else
|
||||||
get_io_service().post(boost::bind(m_callback, e, m_v6_ep, m_v6_buf, bytes_transferred));
|
m_callback(e, m_v6_ep, m_v6_buf, bytes_transferred);
|
||||||
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch(std::exception&) {}
|
} catch(std::exception&) {}
|
||||||
|
@ -119,10 +148,12 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_
|
||||||
s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
||||||
, m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2));
|
, m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2));
|
||||||
}
|
}
|
||||||
|
++m_outstanding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
|
|
||||||
char header[20];
|
char header[20];
|
||||||
|
@ -147,6 +178,7 @@ void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_cod
|
||||||
// unwrap the UDP packet from the SOCKS5 header
|
// unwrap the UDP packet from the SOCKS5 header
|
||||||
void udp_socket::unwrap(error_code const& e, char const* buf, int size)
|
void udp_socket::unwrap(error_code const& e, char const* buf, int size)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
|
|
||||||
// the minimum socks5 header size
|
// the minimum socks5 header size
|
||||||
|
@ -177,27 +209,37 @@ void udp_socket::unwrap(error_code const& e, char const* buf, int size)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_io_service().post(boost::bind(m_callback, e, sender, p, size - (p - buf)));
|
m_callback(e, sender, p, size - (p - buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::close()
|
void udp_socket::close()
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(m_magic == 0x1337);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
m_ipv4_sock.close(ec);
|
m_ipv4_sock.close(ec);
|
||||||
m_ipv6_sock.close(ec);
|
m_ipv6_sock.close(ec);
|
||||||
m_socks5_sock.close(ec);
|
m_socks5_sock.close(ec);
|
||||||
m_callback.clear();
|
|
||||||
if (m_connection_ticket >= 0)
|
if (m_connection_ticket >= 0)
|
||||||
{
|
{
|
||||||
m_cc.done(m_connection_ticket);
|
m_cc.done(m_connection_ticket);
|
||||||
m_connection_ticket = -1;
|
m_connection_ticket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_outstanding == 0)
|
||||||
|
{
|
||||||
|
// "this" may be destructed in the callback
|
||||||
|
// that's why we need to unlock
|
||||||
|
l.unlock();
|
||||||
|
callback_t tmp = m_callback;
|
||||||
|
m_callback.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
|
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
||||||
|
@ -221,11 +263,13 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
|
||||||
m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
||||||
, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
|
, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
|
||||||
}
|
}
|
||||||
|
++m_outstanding;
|
||||||
m_bind_port = ep.port();
|
m_bind_port = ep.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::bind(int port)
|
void udp_socket::bind(int port)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -239,6 +283,7 @@ void udp_socket::bind(int port)
|
||||||
m_ipv4_sock.bind(udp::endpoint(address_v4::any(), port), ec);
|
m_ipv4_sock.bind(udp::endpoint(address_v4::any(), port), ec);
|
||||||
m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf))
|
m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf))
|
||||||
, m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2));
|
, m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2));
|
||||||
|
++m_outstanding;
|
||||||
}
|
}
|
||||||
m_ipv6_sock.open(udp::v6(), ec);
|
m_ipv6_sock.open(udp::v6(), ec);
|
||||||
if (!ec)
|
if (!ec)
|
||||||
|
@ -247,12 +292,14 @@ void udp_socket::bind(int port)
|
||||||
m_ipv6_sock.bind(udp::endpoint(address_v6::any(), port), ec);
|
m_ipv6_sock.bind(udp::endpoint(address_v6::any(), port), ec);
|
||||||
m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
|
||||||
, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
|
, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
|
||||||
|
++m_outstanding;
|
||||||
}
|
}
|
||||||
m_bind_port = port;
|
m_bind_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -275,6 +322,7 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
||||||
void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i)
|
void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i)
|
||||||
{
|
{
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
CHECK_MAGIC;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
|
@ -286,6 +334,7 @@ void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i)
|
||||||
|
|
||||||
void udp_socket::on_timeout()
|
void udp_socket::on_timeout()
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -295,6 +344,7 @@ void udp_socket::on_timeout()
|
||||||
|
|
||||||
void udp_socket::on_connect(int ticket)
|
void udp_socket::on_connect(int ticket)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
m_connection_ticket = ticket;
|
m_connection_ticket = ticket;
|
||||||
|
@ -306,12 +356,13 @@ void udp_socket::on_connect(int ticket)
|
||||||
|
|
||||||
void udp_socket::on_connected(error_code const& e)
|
void udp_socket::on_connected(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
|
|
||||||
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
m_cc.done(m_connection_ticket);
|
m_cc.done(m_connection_ticket);
|
||||||
m_connection_ticket = -1;
|
m_connection_ticket = -1;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
|
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
|
|
||||||
// send SOCKS5 authentication methods
|
// send SOCKS5 authentication methods
|
||||||
|
@ -335,6 +386,7 @@ void udp_socket::on_connected(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::handshake1(error_code const& e)
|
void udp_socket::handshake1(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -345,6 +397,7 @@ void udp_socket::handshake1(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::handshake2(error_code const& e)
|
void udp_socket::handshake2(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
|
@ -390,6 +443,7 @@ void udp_socket::handshake2(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::handshake3(error_code const& e)
|
void udp_socket::handshake3(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -400,6 +454,7 @@ void udp_socket::handshake3(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::handshake4(error_code const& e)
|
void udp_socket::handshake4(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -418,6 +473,7 @@ void udp_socket::handshake4(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::socks_forward_udp()
|
void udp_socket::socks_forward_udp()
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -437,6 +493,7 @@ void udp_socket::socks_forward_udp()
|
||||||
|
|
||||||
void udp_socket::connect1(error_code const& e)
|
void udp_socket::connect1(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -447,6 +504,7 @@ void udp_socket::connect1(error_code const& e)
|
||||||
|
|
||||||
void udp_socket::connect2(error_code const& e)
|
void udp_socket::connect2(error_code const& e)
|
||||||
{
|
{
|
||||||
|
CHECK_MAGIC;
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
Loading…
Reference in New Issue