forked from premiere/premiere-libtorrent
fix IPv6 address change notification on Windows
The old NotifyAddrChange only detects IPv4 address changes. Use the newer NotifyUnicastIpAddressChange function instead which supports both v4 and v6.
This commit is contained in:
parent
caf56ea8b4
commit
a9968916ca
|
@ -1,3 +1,5 @@
|
||||||
|
* fix IPv6 address change detection on Windows
|
||||||
|
|
||||||
1.2.6 released
|
1.2.6 released
|
||||||
|
|
||||||
* fix peer timeout logic
|
* fix peer timeout logic
|
||||||
|
|
|
@ -44,8 +44,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#elif defined TORRENT_WINDOWS
|
#elif defined TORRENT_WINDOWS
|
||||||
#include "libtorrent/aux_/throw.hpp"
|
#include "libtorrent/aux_/throw.hpp"
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||||
#include <boost/asio/windows/object_handle.hpp>
|
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
|
#include <mutex>
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -348,52 +348,72 @@ private:
|
||||||
struct ip_change_notifier_impl final : ip_change_notifier
|
struct ip_change_notifier_impl final : ip_change_notifier
|
||||||
{
|
{
|
||||||
explicit ip_change_notifier_impl(io_service& ios)
|
explicit ip_change_notifier_impl(io_service& ios)
|
||||||
: m_hnd(ios, WSACreateEvent())
|
: m_ios(ios)
|
||||||
{
|
{
|
||||||
if (!m_hnd.is_open()) aux::throw_ex<system_error>(WSAGetLastError(), system_category());
|
NotifyUnicastIpAddressChange(AF_UNSPEC, address_change_cb, this, false, &m_hnd);
|
||||||
m_ovl.hEvent = m_hnd.native_handle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-copyable
|
// non-copyable
|
||||||
ip_change_notifier_impl(ip_change_notifier_impl const&) = delete;
|
ip_change_notifier_impl(ip_change_notifier_impl const&) = delete;
|
||||||
ip_change_notifier_impl& operator=(ip_change_notifier_impl const&) = delete;
|
ip_change_notifier_impl& operator=(ip_change_notifier_impl const&) = delete;
|
||||||
|
|
||||||
|
// non-moveable
|
||||||
|
ip_change_notifier_impl(ip_change_notifier_impl&&) = delete;
|
||||||
|
ip_change_notifier_impl& operator=(ip_change_notifier_impl&&) = delete;
|
||||||
|
|
||||||
~ip_change_notifier_impl() override
|
~ip_change_notifier_impl() override
|
||||||
{
|
{
|
||||||
cancel();
|
if (m_hnd != nullptr)
|
||||||
// the reason to call close() here is because the
|
{
|
||||||
// object_handle destructor doesn't close the handle
|
CancelMibChangeNotify2(m_hnd);
|
||||||
m_hnd.close();
|
m_hnd = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void async_wait(std::function<void(error_code const&)> cb) override
|
void async_wait(std::function<void(error_code const&)> cb) override
|
||||||
{
|
{
|
||||||
HANDLE hnd;
|
if (m_hnd == nullptr)
|
||||||
DWORD err = NotifyAddrChange(&hnd, &m_ovl);
|
|
||||||
if (err == ERROR_IO_PENDING)
|
|
||||||
{
|
{
|
||||||
m_hnd.async_wait([cb](error_code const& ec)
|
cb(make_error_code(boost::system::errc::not_supported));
|
||||||
{
|
return;
|
||||||
// call CancelIPChangeNotify here?
|
|
||||||
cb(ec);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lt::get_io_service(m_hnd).post([cb, err]()
|
|
||||||
{ cb(error_code(err, system_category())); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> l(m_cb_mutex);
|
||||||
|
m_cb.emplace_back(std::move(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel() override
|
void cancel() override
|
||||||
{
|
{
|
||||||
CancelIPChangeNotify(&m_ovl);
|
std::vector<std::function<void(error_code const&)>> cbs;
|
||||||
m_hnd.cancel();
|
{
|
||||||
|
std::lock_guard<std::mutex> l(m_cb_mutex);
|
||||||
|
cbs = std::move(m_cb);
|
||||||
|
}
|
||||||
|
for (auto& cb : cbs) cb(make_error_code(boost::asio::error::operation_aborted));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OVERLAPPED m_ovl = {};
|
static void WINAPI address_change_cb(void* ctx, MIB_UNICASTIPADDRESS_ROW*, MIB_NOTIFICATION_TYPE)
|
||||||
boost::asio::windows::object_handle m_hnd;
|
{
|
||||||
|
ip_change_notifier_impl* impl = static_cast<ip_change_notifier_impl*>(ctx);
|
||||||
|
std::vector<std::function<void(error_code const&)>> cbs;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l(impl->m_cb_mutex);
|
||||||
|
cbs = std::move(impl->m_cb);
|
||||||
|
}
|
||||||
|
// TODO move cbs into the lambda with C++14
|
||||||
|
impl->m_ios.post([cbs]()
|
||||||
|
{
|
||||||
|
for (auto& cb : cbs) cb(error_code());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
io_service& m_ios;
|
||||||
|
HANDLE m_hnd = nullptr;
|
||||||
|
// address_change_cb gets invoked from a separate worker thread so the callbacks
|
||||||
|
// vector must be protected by a mutex
|
||||||
|
std::mutex m_cb_mutex;
|
||||||
|
std::vector<std::function<void(error_code const&)>> m_cb;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
struct ip_change_notifier_impl final : ip_change_notifier
|
struct ip_change_notifier_impl final : ip_change_notifier
|
||||||
|
|
Loading…
Reference in New Issue