implemented ip_change_notifier_macos (#1891)
implemented ip_change_notifier_macos
This commit is contained in:
parent
51c42adc3e
commit
e4bdd14ae7
|
@ -300,6 +300,11 @@ if (WIN32)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# for ip_notifier
|
||||
target_link_libraries(torrent-rasterbar "-framework CoreFoundation" "-framework SystemConfiguration")
|
||||
endif (APPLE)
|
||||
|
||||
if (encryption)
|
||||
target_link_libraries(torrent-rasterbar ${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
|
6
Jamfile
6
Jamfile
|
@ -160,6 +160,12 @@ rule linking ( properties * )
|
|||
result += <library>libsocket <library>libnsl ;
|
||||
}
|
||||
|
||||
if <target-os>darwin in $(properties)
|
||||
{
|
||||
# for ip_notifier
|
||||
result += <framework>CoreFoundation <framework>SystemConfiguration ;
|
||||
}
|
||||
|
||||
if <iconv>on in $(properties)
|
||||
{
|
||||
result += <library>libiconv ;
|
||||
|
|
|
@ -166,6 +166,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_USE_EXECINFO 1
|
||||
#endif
|
||||
|
||||
#define TORRENT_USE_SYSTEMCONFIGURATION 1
|
||||
|
||||
#else // __APPLE__
|
||||
// FreeBSD has a reasonable iconv signature
|
||||
// unless we're on glibc
|
||||
|
@ -436,6 +438,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_USE_COMMONCRYPTO 0
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_USE_SYSTEMCONFIGURATION
|
||||
#define TORRENT_USE_SYSTEMCONFIGURATION 0
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_USE_CRYPTOAPI
|
||||
#define TORRENT_USE_CRYPTOAPI 0
|
||||
#endif
|
||||
|
|
|
@ -31,12 +31,15 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "libtorrent/aux_/ip_notifier.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
// TODO: simulator support
|
||||
#elif TORRENT_USE_NETLINK
|
||||
#include "libtorrent/netlink.hpp"
|
||||
#include <array>
|
||||
#elif TORRENT_USE_SYSTEMCONFIGURATION
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
#elif defined TORRENT_WINDOWS
|
||||
#include "libtorrent/aux_/throw.hpp"
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
@ -55,11 +58,139 @@ namespace
|
|||
// TODO: ip_change_notifier_sim
|
||||
#elif TORRENT_USE_NETLINK
|
||||
// TODO: ip_change_notifier_nl
|
||||
#elif TORRENT_USE_SYSTEMCONFIGURATION
|
||||
// see https://developer.apple.com/library/content/technotes/tn1145/_index.html
|
||||
|
||||
template <typename T> void CFRefRetain(T h) { CFRetain(h); }
|
||||
template <typename T> void CFRefRelease(T h) { CFRelease(h); }
|
||||
|
||||
template <typename T
|
||||
, void (*Retain)(T) = CFRefRetain<T>, void (*Release)(T) = CFRefRelease<T>>
|
||||
struct CFRef
|
||||
{
|
||||
CFRef() {}
|
||||
explicit CFRef(T h) : m_h(h) {} // take ownership
|
||||
~CFRef() { release(); }
|
||||
|
||||
CFRef(CFRef const& rhs) : m_h(rhs.m_h) { retain(); }
|
||||
CFRef& operator=(CFRef const& rhs)
|
||||
{
|
||||
if (m_h == rhs.m_h) return *this;
|
||||
release();
|
||||
m_h = rhs.m_h;
|
||||
retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFRef& operator=(T h) { m_h = h; return *this;}
|
||||
CFRef& operator=(std::nullptr_t) { release(); return *this;}
|
||||
|
||||
T get() const { return m_h; }
|
||||
explicit operator bool() const { return m_h != nullptr; }
|
||||
|
||||
private:
|
||||
T m_h = nullptr; // handle
|
||||
|
||||
void retain() { if (m_h != nullptr) Retain(m_h); }
|
||||
void release() { if (m_h != nullptr) Release(m_h); m_h = nullptr; }
|
||||
};
|
||||
|
||||
void CFDispatchRetain(dispatch_queue_t q) { dispatch_retain(q); }
|
||||
void CFDispatchRelease(dispatch_queue_t q) { dispatch_release(q); }
|
||||
using CFDispatchRef = CFRef<dispatch_queue_t, CFDispatchRetain, CFDispatchRelease>;
|
||||
|
||||
CFRef<CFMutableArrayRef> create_keys_array()
|
||||
{
|
||||
CFRef<CFMutableArrayRef> keys{CFArrayCreateMutable(nullptr
|
||||
, 0, &kCFTypeArrayCallBacks)};
|
||||
|
||||
// "State:/Network/Interface/[^/]+/IPv4"
|
||||
CFRef<CFStringRef> key{SCDynamicStoreKeyCreateNetworkInterfaceEntity(nullptr
|
||||
, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4)};
|
||||
CFArrayAppendValue(keys.get(), key.get());
|
||||
|
||||
// NOTE: for IPv6, you can replicate the above setup with kSCEntNetIPv6
|
||||
// but due to the current state of most common configurations, where
|
||||
// IPv4 is used alongside with IPv6, you will end up with twice the
|
||||
// notifications for the same change
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
CFRef<SCDynamicStoreRef> create_dynamic_store(SCDynamicStoreCallBack callback, void* context_info)
|
||||
{
|
||||
TORRENT_ASSERT(callback != nullptr);
|
||||
|
||||
SCDynamicStoreContext context = {0, nullptr, nullptr, nullptr, nullptr};
|
||||
context.info = context_info;
|
||||
CFRef<SCDynamicStoreRef> store{SCDynamicStoreCreate(nullptr
|
||||
, CFSTR("libtorrent.IPChangeNotifierStore"), callback, &context)};
|
||||
if (!store)
|
||||
return CFRef<SCDynamicStoreRef>();
|
||||
|
||||
CFRef<CFMutableArrayRef> keys = create_keys_array();
|
||||
return SCDynamicStoreSetNotificationKeys(store.get(), nullptr, keys.get())
|
||||
? store : CFRef<SCDynamicStoreRef>();
|
||||
}
|
||||
|
||||
struct ip_change_notifier_macos final : ip_change_notifier
|
||||
{
|
||||
explicit ip_change_notifier_macos(io_service& ios)
|
||||
: m_ios(ios)
|
||||
{
|
||||
m_queue = dispatch_queue_create("libtorrent.IPChangeNotifierQueue", nullptr);
|
||||
m_store = create_dynamic_store(
|
||||
[](SCDynamicStoreRef /*store*/, CFArrayRef /*changedKeys*/, void *info)
|
||||
{
|
||||
auto obj = static_cast<ip_change_notifier_macos*>(info);
|
||||
obj->m_ios.post([obj]() { if (obj->m_cb) obj->m_cb(error_code()); });
|
||||
}, this);
|
||||
|
||||
if (!m_queue || !m_store
|
||||
|| !SCDynamicStoreSetDispatchQueue(m_store.get(), m_queue.get()))
|
||||
cancel();
|
||||
}
|
||||
|
||||
// noncopyable
|
||||
ip_change_notifier_macos(ip_change_notifier_macos const&) = delete;
|
||||
ip_change_notifier_macos& operator=(ip_change_notifier_macos const&) = delete;
|
||||
|
||||
~ip_change_notifier_macos() override
|
||||
{ cancel(); }
|
||||
|
||||
void async_wait(std::function<void(error_code const&)> cb) override
|
||||
{
|
||||
if (m_queue)
|
||||
m_cb = std::move(cb);
|
||||
else
|
||||
m_ios.post([cb]()
|
||||
{ cb(make_error_code(boost::system::errc::not_supported)); });
|
||||
}
|
||||
|
||||
void cancel() override
|
||||
{
|
||||
if (m_store)
|
||||
SCDynamicStoreSetDispatchQueue(m_store.get(), nullptr);
|
||||
|
||||
m_cb = nullptr;
|
||||
m_store = nullptr;
|
||||
m_queue = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
io_service& m_ios;
|
||||
CFDispatchRef m_queue;
|
||||
CFRef<SCDynamicStoreRef> m_store;
|
||||
std::function<void(error_code const&)> m_cb = nullptr;
|
||||
};
|
||||
#elif defined TORRENT_WINDOWS
|
||||
// TODO: ip_change_notifier_win
|
||||
#else
|
||||
// TODO: ip_change_notifier_default
|
||||
#endif
|
||||
|
||||
// TODO: to remove when separated per platform
|
||||
#if defined TORRENT_BUILD_SIMULATOR || TORRENT_USE_NETLINK || defined TORRENT_WINDOWS
|
||||
struct ip_change_notifier_impl final : ip_change_notifier
|
||||
{
|
||||
explicit ip_change_notifier_impl(io_service& ios);
|
||||
|
@ -170,11 +301,28 @@ namespace
|
|||
else
|
||||
cb(ec);
|
||||
}
|
||||
#endif // defined TORRENT_BUILD_SIMULATOR || TORRENT_USE_NETLINK || defined TORRENT_WINDOWS
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::unique_ptr<ip_change_notifier> create_ip_notifier(io_service& ios)
|
||||
{
|
||||
return std::unique_ptr<ip_change_notifier>(new ip_change_notifier_impl(ios));
|
||||
return std::unique_ptr<ip_change_notifier>(
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
// ip_change_notifier_sim
|
||||
new ip_change_notifier_impl(ios)
|
||||
#elif TORRENT_USE_NETLINK
|
||||
// ip_change_notifier_nl
|
||||
new ip_change_notifier_impl(ios)
|
||||
#elif TORRENT_USE_SYSTEMCONFIGURATION
|
||||
new ip_change_notifier_macos(ios)
|
||||
#elif defined TORRENT_WINDOWS
|
||||
// ip_change_notifier_win
|
||||
new ip_change_notifier_impl(ios)
|
||||
#else
|
||||
// ip_change_notifier_default
|
||||
new ip_change_notifier_impl(ios)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}}
|
||||
|
|
|
@ -38,4 +38,5 @@ project tools
|
|||
exe fuzz_torrent : fuzz_torrent.cpp ;
|
||||
exe parse_access_log : parse_access_log.cpp ;
|
||||
exe dht : dht_put.cpp : <include>../ed25519/src ;
|
||||
exe session_log_alerts : session_log_alerts.cpp ;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
tool_programs = \
|
||||
fuzz_torrent
|
||||
fuzz_torrent \
|
||||
session_log_alerts
|
||||
|
||||
if ENABLE_EXAMPLES
|
||||
bin_PROGRAMS = $(tool_programs)
|
||||
|
@ -20,6 +21,7 @@ EXTRA_DIST = Jamfile \
|
|||
parse_utp_log.py
|
||||
|
||||
fuzz_torrent_SOURCES = fuzz_torrent.cpp
|
||||
session_log_alerts_SOURCES = session_log_alerts.cpp
|
||||
|
||||
LDADD = $(top_builddir)/src/libtorrent-rasterbar.la
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2017, Arvid Norberg, Alden Torres
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cinttypes>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::printf("press Ctrl+C, kill the process or wait for 1000 alerts\n");
|
||||
|
||||
settings_pack sett;
|
||||
sett.set_int(settings_pack::alert_mask, 0xffffffff);
|
||||
session s(sett);
|
||||
|
||||
int count = 0;
|
||||
while (count <= 1000)
|
||||
{
|
||||
s.wait_for_alert(seconds(5));
|
||||
|
||||
std::vector<alert*> alerts;
|
||||
s.pop_alerts(&alerts);
|
||||
for (auto const a : alerts)
|
||||
{
|
||||
if (a->type() == log_alert::alert_type)
|
||||
{
|
||||
std::printf("log_alert - %s\n", a->message().c_str());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue