Merge pull request #1307 from tewinget/libunbound-upstream-dns

Implement upstream DNS using libunbound
pull/1315/head
Jeff 4 years ago committed by GitHub
commit 7afa852d96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,7 +1,10 @@
local default_deps_base='libsystemd-dev python3-dev libcurl4-openssl-dev libuv1-dev';
local default_deps_base='libsystemd-dev python3-dev libcurl4-openssl-dev libuv1-dev libunbound-dev nettle-dev libssl-dev libevent-dev';
local default_deps_nocxx='libsodium-dev ' + default_deps_base; // libsodium-dev needs to be >= 1.0.18
local default_deps='g++ ' + default_deps_nocxx; // g++ sometimes needs replacement
local default_windows_deps='mingw-w64-binutils mingw-w64-gcc mingw-w64-crt mingw-w64-headers mingw-w64-winpthreads perl openssh bash'; // deps for windows cross compile
local submodules = {
name: 'submodules',
image: 'drone/git',
@ -50,51 +53,15 @@ local debian_pipeline(name, image,
],
};
// 32-bit windows build on alpine:
local alpine_wow64_pipeline(name, image,
arch='amd64',
deps='mingw-w64-binutils mingw-w64-gcc mingw-w64-crt mingw-w64-headers mingw-w64-winpthreads',
build_type='Release',
lto=false,
werror=false,
cmake_extra='',
extra_cmds=[],
allow_fail=false) = {
kind: 'pipeline',
type: 'docker',
name: name,
platform: { arch: arch },
trigger: { branch: { exclude: ['debian/*', 'ubuntu/*'] } },
steps: [
submodules,
{
name: 'build',
image: image,
[if allow_fail then "failure"]: "ignore",
environment: { SSH_KEY: { from_secret: "SSH_KEY" } },
commands: [
'apk add cmake git ninja pkgconf ccache patch make ' + deps,
'git clone https://github.com/despair86/libuv.git win32-setup/libuv',
'mkdir build',
'cd build',
'cmake .. -G Ninja -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector -DLIBUV_ROOT=$PWD/../win32-setup/libuv -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_TOOLCHAIN_FILE=../contrib/cross/mingw32.cmake -DCMAKE_BUILD_TYPE='+build_type+' ' +
(if werror then '-DWARNINGS_AS_ERRORS=ON ' else '') +
(if lto then '' else '-DWITH_LTO=OFF ') +
cmake_extra,
'ninja -v',
] + extra_cmds,
}
],
};
// 64-bit windows build on alpine:
local alpine_win32_pipeline(name, image,
// windows cross compile on alpine linux
local windows_cross_pipeline(name, image,
arch='amd64',
deps='mingw-w64-binutils mingw-w64-gcc mingw-w64-crt mingw-w64-headers mingw-w64-winpthreads',
deps=default_windows_deps,
build_type='Release',
lto=false,
werror=false,
cmake_extra='',
toolchain='mingw32',
extra_cmds=[],
allow_fail=false) = {
kind: 'pipeline',
@ -114,9 +81,10 @@ local alpine_win32_pipeline(name, image,
'git clone https://github.com/despair86/libuv.git win32-setup/libuv',
'mkdir build',
'cd build',
'cmake .. -G Ninja -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector -DLIBUV_ROOT=$PWD/../win32-setup/libuv -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_TOOLCHAIN_FILE=../contrib/cross/mingw64.cmake -DCMAKE_BUILD_TYPE='+build_type+' ' +
'cmake .. -G Ninja -DCMAKE_CROSSCOMPILE=ON -DCMAKE_EXE_LINKER_FLAGS=-fstack-protector -DLIBUV_ROOT=$PWD/../win32-setup/libuv -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_TOOLCHAIN_FILE=../contrib/cross/'+toolchain+'.cmake -DCMAKE_BUILD_TYPE='+build_type+' ' +
(if werror then '-DWARNINGS_AS_ERRORS=ON ' else '') +
(if lto then '' else '-DWITH_LTO=OFF ') +
"-DBUILD_STATIC_DEPS=ON -DDOWNLOAD_SODIUM=ON -DBUILD_PACKAGE=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=ON -DNATIVE_BUILD=OFF -DSTATIC_LINK=ON" +
cmake_extra,
'ninja -v',
] + extra_cmds,
@ -230,12 +198,18 @@ local mac_builder(name, build_type='Release', werror=true, cmake_extra='', extra
debian_pipeline("Debian buster (armhf)", "arm32v7/debian:buster", arch="arm64", cmake_extra='-DDOWNLOAD_SODIUM=ON'),
// Windows builds (WOW64 and native)
alpine_win32_pipeline("win32 on alpine (amd64)", "alpine:edge", cmake_extra="-DDOWNLOAD_SODIUM=ON -DBUILD_PACKAGE=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=ON -DNATIVE_BUILD=OFF -DSTATIC_LINK=ON", lto=false),
alpine_wow64_pipeline("win32 on alpine (i386)", "i386/alpine:edge", cmake_extra="-DDOWNLOAD_SODIUM=ON -DBUILD_PACKAGE=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=ON -DNATIVE_BUILD=OFF -DSTATIC_LINK=ON", lto=false),
windows_cross_pipeline("win32 on alpine (amd64)", "alpine:edge",
toolchain='mingw64', extra_cmds=[
'../contrib/ci/drone-static-upload.sh'
]),
windows_cross_pipeline("win32 on alpine (i386)", "i386/alpine:edge",
toolchain='mingw32', extra_cmds=[
'../contrib/ci/drone-static-upload.sh'
]),
// Static build (on bionic) which gets uploaded to builds.lokinet.dev:
debian_pipeline("Static (bionic amd64)", "ubuntu:bionic", deps='g++-8 python3-dev', lto=true,
cmake_extra='-DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 ' +
cmake_extra='-DBUILD_STATIC_DEPS=ON -DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 ' +
'-DDOWNLOAD_SODIUM=ON -DDOWNLOAD_CURL=ON -DDOWNLOAD_UV=ON -DWITH_SYSTEMD=OFF',
extra_cmds=[
'../contrib/ci/drone-check-static-libs.sh',
@ -255,7 +229,7 @@ local mac_builder(name, build_type='Release', werror=true, cmake_extra='', extra
// Macos builds:
mac_builder('macOS (Release)'),
mac_builder('macOS (Debug)', build_type='Debug'),
mac_builder('macOS (Static)', cmake_extra='-DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON -DDOWNLOAD_SODIUM=FORCE -DDOWNLOAD_CURL=FORCE -DDOWNLOAD_UV=FORCE',
mac_builder('macOS (Static)', cmake_extra='-DBUILD_STATIC_DEPS=ON -DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON -DDOWNLOAD_SODIUM=FORCE -DDOWNLOAD_CURL=FORCE -DDOWNLOAD_UV=FORCE',
extra_cmds=[
'../contrib/ci/drone-check-static-libs.sh',
'../contrib/ci/drone-static-upload.sh'

@ -29,6 +29,9 @@ if(RELEASE_MOTTO)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# Core options
option(USE_AVX2 "enable avx2 code" OFF)
option(USE_NETNS "enable networking namespace support. Linux only" OFF)
@ -94,8 +97,6 @@ endif()
include(cmake/solaris.cmake)
include(cmake/win32.cmake)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# No in-source building
include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out-of-source build. Create a build directory and run 'cmake ${CMAKE_SOURCE_DIR} [options]'.")
@ -225,21 +226,25 @@ endif()
string(REGEX REPLACE "^fatal.*$" nogit GIT_VERSION_REAL "${GIT_VERSION}")
find_package(PkgConfig REQUIRED)
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(SD libsystemd)
# Default WITH_SYSTEMD to true if we found it
option(WITH_SYSTEMD "enable systemd integration for sd_notify" ${SD_FOUND})
if (NOT BUILD_STATIC_DEPS)
pkg_check_modules(UNBOUND libunbound REQUIRED IMPORTED_TARGET)
add_library(libunbound INTERFACE)
target_link_libraries(libunbound INTERFACE PkgConfig::UNBOUND)
endif()
if(WITH_SYSTEMD)
if(NOT SD_FOUND)
message(FATAL_ERROR "libsystemd not found")
endif()
add_definitions(-DWITH_SYSTEMD)
include_directories(${SD_INCLUDE_DIRS})
set(SD_LIBS ${SD_LDFLAGS})
endif()
pkg_check_modules(SD libsystemd)
# Default WITH_SYSTEMD to true if we found it
option(WITH_SYSTEMD "enable systemd integration for sd_notify" ${SD_FOUND})
if(WITH_SYSTEMD)
if(NOT SD_FOUND)
message(FATAL_ERROR "libsystemd not found")
endif()
add_definitions(-DWITH_SYSTEMD)
include_directories(${SD_INCLUDE_DIRS})
set(SD_LIBS ${SD_LDFLAGS})
endif()
option(SUBMODULE_CHECK "Enables checking that vendored library submodules are up to date" ON)

@ -139,9 +139,9 @@ endfunction()
set(openssl_system_env "")
if(CMAKE_CROSSCOMPILING)
if(ARCH_TRIPLET STREQUAL x86_64-w64-mingw32)
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER})
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
elseif(ARCH_TRIPLET STREQUAL i686-w64-mingw32)
set(openssl_system_env SYSTEM=MINGW64 RC=${CMAKE_RC_COMPILER})
set(openssl_system_env SYSTEM=MINGW32 RC=${CMAKE_RC_COMPILER} AR=${ARCH_TRIPLET}-ar RANLIB=${ARCH_TRIPLET}-ranlib)
endif()
endif()
build_external(openssl
@ -156,6 +156,10 @@ build_external(openssl
)
add_static_target(OpenSSL::SSL openssl_external libssl.a)
add_static_target(OpenSSL::Crypto openssl_external libcrypto.a)
if(WIN32)
target_link_libraries(OpenSSL::Crypto INTERFACE "ws2_32;crypt32;iphlpapi")
endif()
set(OPENSSL_INCLUDE_DIR ${DEPS_DESTDIR}/include)
set(OPENSSL_VERSION 1.1.1)
@ -178,8 +182,10 @@ build_external(unbound
"CC=${deps_cc}" "CFLAGS=-O2 ${flto}"
)
add_static_target(libunbound unbound_external libunbound.a)
if(WIN32)
set_target_properties(libunbound PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32;crypt32;iphlpapi")
if(NOT WIN32)
set_target_properties(libunbound PROPERTIES INTERFACE_LINK_LIBRARIES "OpenSSL::SSL;OpenSSL::Crypto")
else()
set_target_properties(libunbound PROPERTIES INTERFACE_LINK_LIBRARIES "OpenSSL::SSL;OpenSSL::Crypto;ws2_32;crypt32;iphlpapi")
endif()
@ -189,8 +195,8 @@ add_static_target(sodium sodium_external libsodium.a)
if(ZMQ_VERSION VERSION_LESS 4.3.3 AND CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw)
set(zmq_patch PATCH_COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/utils/build_scripts/libzmq-pr3601-mingw-build-fix.patch
COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/utils/build_scripts/libzmq-pr3613-fix-funcptr-call.patch)
set(zmq_patch PATCH_COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/contrib/cross/patches/libzmq-pr3601-mingw-build-fix.patch
COMMAND patch -p1 -i ${PROJECT_SOURCE_DIR}/contrib/cross/patches/libzmq-pr3613-fix-funcptr-call.patch)
endif()
build_external(zmq
DEPENDS sodium_external

@ -29,8 +29,11 @@ else
fi
mkdir -v "$base"
mv -v daemon/lokinet "$base"
cp -av ../lokinet-bootstrap "$base"
# copy lokinet-bootstrap.ps1 and lokinet.exe if we are a windows build
test -e daemon/lokinet.exe && cp -av daemon/lokinet.exe ../lokinet-bootstrap.ps1 "$base"
# copy lokinet-bootstrap shell script and built binary if we aren't a windows build
test -e daemon/lokinet && cp -av daemon/lokinet ../lokinet-bootstrap "$base"
# tar dat shiz up yo
tar cJvf "${base}.tar.xz" "$base"
upload_to="builds.lokinet.dev/${DRONE_REPO// /_}/${DRONE_BRANCH// /_}"

@ -23,3 +23,5 @@ else()
endif()
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
set(CMAKE_CROSSCOMPILE ON)
set(ARCH_TRIPLET ${CROSS_TARGET})

@ -0,0 +1,69 @@
diff --git a/src/thread.cpp b/src/thread.cpp
index b14d70757..3675899be 100644
--- a/src/thread.cpp
+++ b/src/thread.cpp
@@ -32,6 +32,10 @@
#include "thread.hpp"
#include "err.hpp"
+#ifdef ZMQ_HAVE_WINDOWS
+#include <winnt.h>
+#endif
+
bool zmq::thread_t::get_started () const
{
return _started;
@@ -113,10 +117,22 @@ struct thread_info_t
#pragma pack(pop)
}
+typedef struct _MY_EXCEPTION_REGISTRATION_RECORD
+{
+ struct _MY_EXCEPTION_REGISTRATION_RECORD *Next;
+ void *Handler;
+} MY_EXCEPTION_REGISTRATION_RECORD;
+
+static EXCEPTION_DISPOSITION NTAPI continue_execution (EXCEPTION_RECORD *rec,
+ void *frame, CONTEXT *ctx, void *disp)
+{
+ return ExceptionContinueExecution;
+}
+
void zmq::thread_t::
applyThreadName () // to be called in secondary thread context
{
- if (!_name[0])
+ if (!_name[0] || !IsDebuggerPresent())
return;
thread_info_t thread_info;
@@ -125,17 +141,19 @@ void zmq::thread_t::
thread_info._thread_id = -1;
thread_info._flags = 0;
-#pragma warning(push)
-#pragma warning(disable : 6320 6322)
- __try {
- DWORD MS_VC_EXCEPTION = 0x406D1388;
+ NT_TIB *tib = ((NT_TIB*)NtCurrentTeb());
+
+ MY_EXCEPTION_REGISTRATION_RECORD rec;
+ rec.Next = (MY_EXCEPTION_REGISTRATION_RECORD *)tib->ExceptionList;
+ rec.Handler = continue_execution;
+
+ // push our handler, raise, and finally pop our handler
+ tib->ExceptionList = (_EXCEPTION_REGISTRATION_RECORD *)&rec;
+ DWORD MS_VC_EXCEPTION = 0x406D1388;
RaiseException (MS_VC_EXCEPTION, 0,
- sizeof (thread_info) / sizeof (ULONG_PTR),
- (ULONG_PTR *) &thread_info);
- }
- __except (EXCEPTION_CONTINUE_EXECUTION) {
- }
-#pragma warning(pop)
+ sizeof (thread_info) / sizeof (ULONG_PTR),
+ (ULONG_PTR *) &thread_info);
+ tib->ExceptionList = (_EXCEPTION_REGISTRATION_RECORD *)(((MY_EXCEPTION_REGISTRATION_RECORD *)tib->ExceptionList)->Next);
}
#elif defined ZMQ_HAVE_VXWORKS

@ -0,0 +1,43 @@
diff --git a/RELICENSE/tomzbench.md b/RELICENSE/tomzbench.md
new file mode 100644
index 000000000..1cbcc4fdb
--- /dev/null
+++ b/RELICENSE/tomzbench.md
@@ -0,0 +1,14 @@
+# Permission to Relicense under MPLv2
+
+This is a statement by Thomas Chiantia
+that grants permission to relicense its copyrights in the libzmq C++
+library (ZeroMQ) under the Mozilla Public License v2 (MPLv2).
+
+A portion of the commits made by the Github handle "tomzbench", with
+commit author "Thomas<Thomas@Altronix.com>", are copyright of
+Thomas Chiantia.
+This document hereby grants the libzmq project team to relicense libzmq,
+including all past, present and future contributions of the author listed above.
+
+Thomas Chiantia
+2019/08/10
diff --git a/src/thread.cpp b/src/thread.cpp
index 2cad2adaa..6f07e9cee 100644
--- a/src/thread.cpp
+++ b/src/thread.cpp
@@ -117,11 +117,14 @@ struct thread_info_t
#pragma pack(pop)
}
-typedef struct _MY_EXCEPTION_REGISTRATION_RECORD
+struct MY_EXCEPTION_REGISTRATION_RECORD
{
- struct _MY_EXCEPTION_REGISTRATION_RECORD *Next;
- void *Handler;
-} MY_EXCEPTION_REGISTRATION_RECORD;
+ typedef EXCEPTION_DISPOSITION (NTAPI *HandlerFunctionType) (
+ EXCEPTION_RECORD *, void *, CONTEXT *, void *);
+
+ MY_EXCEPTION_REGISTRATION_RECORD *Next;
+ HandlerFunctionType Handler;
+};
static EXCEPTION_DISPOSITION NTAPI continue_execution (EXCEPTION_RECORD *rec,
void *frame,

@ -70,11 +70,11 @@ endif()
option(DOWNLOAD_SODIUM "Allow libsodium to be downloaded and built locally if not found on the system" OFF)
# Allow -DDOWNLOAD_SODIUM=FORCE to download without even checking for a local libsodium
if(NOT DOWNLOAD_SODIUM STREQUAL "FORCE")
if((NOT BUILD_STATIC_DEPS) AND (NOT DOWNLOAD_SODIUM STREQUAL "FORCE"))
find_package(Sodium 1.0.18)
endif()
if(sodium_FOUND)
if(sodium_FOUND OR BUILD_STATIC_DEPS)
target_link_libraries(lokinet-cryptography PUBLIC sodium)
elseif(DOWNLOAD_SODIUM)
message(STATUS "Sodium >= 1.0.18 not found, but DOWNLOAD_SODIUM specified, so downloading it")

@ -101,6 +101,7 @@ add_library(liblokinet
dns/rr.cpp
dns/serialize.cpp
dns/server.cpp
dns/unbound_resolver.cpp
consensus/table.cpp
@ -222,6 +223,8 @@ endif()
target_link_libraries(liblokinet PUBLIC cxxopts abyss lokinet-platform lokinet-util lokinet-cryptography)
target_link_libraries(liblokinet PRIVATE libunbound)
if(BUILD_SHARED_LIBS)
install(TARGETS lokinet-util lokinet-platform liblokinet LIBRARY DESTINATION lib)
if(WIN32)

@ -48,9 +48,6 @@ namespace llarp
Message(Message&& other);
Message(const Message& other);
void
UpdateHeader();
void
AddNXReply(RR_TTL_t ttl = 1);

@ -37,8 +37,14 @@ namespace llarp
bool
Proxy::Start(const IpAddress& addr, const std::vector<IpAddress>& resolvers)
{
m_Resolvers.clear();
m_Resolvers = resolvers;
if (resolvers.size())
{
if (not SetupUnboundResolver(resolvers))
{
return false;
}
}
const IpAddress any("0.0.0.0", 0);
auto self = shared_from_this();
LogicCall(m_ClientLogic, [=]() {
@ -89,29 +95,85 @@ namespace llarp
return *itr;
}
bool
Proxy::SetupUnboundResolver(const std::vector<IpAddress>& resolvers)
{
auto failFunc = [self = weak_from_this()](SockAddr to, Message msg) {
auto this_ptr = self.lock();
if (this_ptr)
{
this_ptr->SendServerMessageTo(to, std::move(msg));
}
};
auto replyFunc = [self = weak_from_this()](SockAddr to, std::vector<byte_t> buf) {
auto this_ptr = self.lock();
if (this_ptr)
{
this_ptr->HandleUpstreamResponse(to, std::move(buf));
}
};
m_UnboundResolver = std::make_shared<UnboundResolver>(
m_ServerLoop, std::move(replyFunc), std::move(failFunc));
if (not m_UnboundResolver->Init())
{
llarp::LogError("Failed to initialize upstream DNS resolver.");
m_UnboundResolver = nullptr;
return false;
}
for (const auto& resolver : resolvers)
{
if (not m_UnboundResolver->AddUpstreamResolver(resolver.toString()))
{
llarp::LogError("Failed to add upstream DNS server: ", resolver.toString());
m_UnboundResolver = nullptr;
return false;
}
}
return true;
}
void
Proxy::HandleTick(llarp_udp_io*)
{
}
void
Proxy::SendServerMessageBufferTo(const SockAddr& to, const llarp_buffer_t& buf)
{
llarp_ev_udp_sendto(&m_Server, to, buf);
}
void
Proxy::SendServerMessageTo(const SockAddr& to, Message msg)
{
auto self = shared_from_this();
LogicCall(m_ServerLogic, [to, msg, self]() {
LogicCall(m_ServerLogic, [to, msg = std::move(msg), self]() {
std::array<byte_t, 1500> tmp = {{0}};
llarp_buffer_t buf(tmp);
if (msg.Encode(&buf))
{
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
llarp_ev_udp_sendto(&self->m_Server, to, buf);
self->SendServerMessageBufferTo(to, buf);
}
else
llarp::LogWarn("failed to encode dns message when sending");
});
}
void
Proxy::HandleUpstreamResponse(SockAddr to, std::vector<byte_t> buf)
{
auto self = shared_from_this();
LogicCall(m_ServerLogic, [to, buffer = std::move(buf), self]() {
llarp_buffer_t buf(buffer);
self->SendServerMessageBufferTo(to, buf);
});
}
void
Proxy::SendClientMessageTo(const SockAddr& to, Message msg)
{
@ -186,7 +248,6 @@ namespace llarp
}
TX tx = {hdr.id, from};
auto itr = m_Forwarded.find(tx);
Message msg(hdr);
if (!msg.Decode(&pkt))
{
@ -222,7 +283,7 @@ namespace llarp
llarp::LogWarn("failed to handle hooked dns");
}
}
else if (m_Resolvers.size() == 0)
else if (not m_UnboundResolver)
{
// no upstream resolvers
// let's serv fail it
@ -230,26 +291,9 @@ namespace llarp
SendServerMessageTo(from, std::move(msg));
}
else if (itr == m_Forwarded.end())
{
// new forwarded query
tx.from = PickRandomResolver();
m_Forwarded[tx] = from;
LogicCall(m_ClientLogic, [=] {
// do query
const llarp_buffer_t tmpbuf(buf);
llarp_ev_udp_sendto(&self->m_Client, tx.from.createSockAddr(), tmpbuf);
});
}
else
{
// send the query again because it's probably FEC from the requester
const auto resolver = itr->first.from;
LogicCall(m_ClientLogic, [=] {
// send it
const llarp_buffer_t tmpbuf(buf);
llarp_ev_udp_sendto(&self->m_Client, resolver.createSockAddr(), tmpbuf);
});
m_UnboundResolver->Lookup(from, std::move(msg));
}
}

@ -5,6 +5,7 @@
#include <ev/ev.h>
#include <net/net.hpp>
#include <util/thread/logic.hpp>
#include <dns/unbound_resolver.hpp>
#include <unordered_map>
@ -55,9 +56,6 @@ namespace llarp
static void
HandleTick(llarp_udp_io*);
void
Tick(llarp_time_t now);
void
HandlePktClient(const SockAddr& from, Buffer_t buf);
@ -67,12 +65,24 @@ namespace llarp
void
SendClientMessageTo(const SockAddr& to, Message msg);
void
SendServerMessageBufferTo(const SockAddr& to, const llarp_buffer_t& buf);
void
SendServerMessageTo(const SockAddr& to, Message msg);
void
HandleUpstreamResponse(SockAddr to, std::vector<byte_t> buf);
void
HandleUpstreamFailure(const SockAddr& to, Message msg);
IpAddress
PickRandomResolver() const;
bool
SetupUnboundResolver(const std::vector<IpAddress>& resolvers);
private:
llarp_udp_io m_Server;
llarp_udp_io m_Client;
@ -82,6 +92,7 @@ namespace llarp
Logic_ptr m_ClientLogic;
IQueryHandler* m_QueryHandler;
std::vector<IpAddress> m_Resolvers;
std::shared_ptr<UnboundResolver> m_UnboundResolver;
struct TX
{

@ -0,0 +1,150 @@
#include <dns/unbound_resolver.hpp>
#include <dns/server.hpp>
#include <util/buffer.hpp>
namespace llarp::dns
{
struct PendingUnboundLookup
{
std::weak_ptr<UnboundResolver> resolver;
Message msg;
SockAddr source;
};
void
UnboundResolver::Reset()
{
started = false;
if (unboundContext)
{
DeregisterPollFD();
ub_ctx_delete(unboundContext);
}
unboundContext = nullptr;
}
void
UnboundResolver::DeregisterPollFD()
{
eventLoop->deregister_poll_fd_readable(ub_fd(unboundContext));
}
void
UnboundResolver::RegisterPollFD()
{
eventLoop->register_poll_fd_readable(
ub_fd(unboundContext), [=]() { ub_process(unboundContext); });
}
UnboundResolver::UnboundResolver(
llarp_ev_loop_ptr eventLoop, ReplyFunction replyFunc, FailFunction failFunc)
: unboundContext(nullptr)
, started(false)
, eventLoop(eventLoop)
, replyFunc(replyFunc)
, failFunc(failFunc)
{
}
// static callback
void
UnboundResolver::Callback(void* data, int err, ub_result* result)
{
std::unique_ptr<PendingUnboundLookup> lookup{static_cast<PendingUnboundLookup*>(data)};
auto this_ptr = lookup->resolver.lock();
if (not this_ptr)
return; // resolver is gone, so we don't reply.
if (err != 0)
{
Message& msg = lookup->msg;
msg.AddServFail();
this_ptr->failFunc(lookup->source, msg);
ub_resolve_free(result);
return;
}
llarp_buffer_t buf;
buf.base = buf.cur = static_cast<byte_t*>(result->answer_packet);
buf.sz = result->answer_len;
MessageHeader hdr;
hdr.Decode(&buf);
hdr.id = lookup->msg.hdr_id;
buf.cur = buf.base;
hdr.Encode(&buf);
std::vector<byte_t> buf_copy(buf.sz);
std::copy_n(buf.base, buf.sz, buf_copy.begin());
this_ptr->replyFunc(lookup->source, std::move(buf_copy));
ub_resolve_free(result);
}
bool
UnboundResolver::Init()
{
if (started)
{
Reset();
}
unboundContext = ub_ctx_create();
if (not unboundContext)
{
return false;
}
RegisterPollFD();
return true;
}
bool
UnboundResolver::AddUpstreamResolver(const std::string& upstreamResolverIP)
{
if (ub_ctx_set_fwd(unboundContext, upstreamResolverIP.c_str()) != 0)
{
Reset();
return false;
}
return true;
}
void
UnboundResolver::Lookup(const SockAddr& source, Message msg)
{
if (not unboundContext)
{
msg.AddServFail();
failFunc(source, std::move(msg));
return;
}
started = true;
const auto& q = msg.questions[0];
auto* lookup = new PendingUnboundLookup{weak_from_this(), msg, source};
int err = ub_resolve_async(
unboundContext,
q.Name().c_str(),
q.qtype,
q.qclass,
(void*)lookup,
&UnboundResolver::Callback,
nullptr);
if (err != 0)
{
msg.AddServFail();
failFunc(source, std::move(msg));
return;
}
}
} // namespace llarp::dns

@ -0,0 +1,55 @@
#pragma once
#include <unbound.h>
#include <mutex>
#include <atomic>
#include <memory>
#include <queue>
#include <ev/ev.hpp>
#include <util/thread/logic.hpp>
#include <dns/message.hpp>
namespace llarp::dns
{
using ReplyFunction = std::function<void(SockAddr source, std::vector<byte_t> buf)>;
using FailFunction = std::function<void(SockAddr source, Message msg)>;
class UnboundResolver : public std::enable_shared_from_this<UnboundResolver>
{
private:
ub_ctx* unboundContext;
bool started;
llarp_ev_loop_ptr eventLoop;
ReplyFunction replyFunc;
FailFunction failFunc;
void
Reset();
void
DeregisterPollFD();
void
RegisterPollFD();
public:
UnboundResolver(llarp_ev_loop_ptr eventLoop, ReplyFunction replyFunc, FailFunction failFunc);
static void
Callback(void* data, int err, ub_result* result);
// upstream resolver IP can be IPv4 or IPv6
bool
Init();
bool
AddUpstreamResolver(const std::string& upstreamResolverIP);
void
Lookup(const SockAddr& source, Message msg);
};
} // namespace llarp::dns

@ -810,6 +810,12 @@ struct llarp_ev_loop
virtual void
call_soon(std::function<void(void)> f) = 0;
virtual void
register_poll_fd_readable(int fd, std::function<void(void)> callback) = 0;
virtual void
deregister_poll_fd_readable(int fd) = 0;
};
#endif

@ -957,7 +957,7 @@ namespace libuv
[](uv_handle_t* h, void*) {
if (uv_is_closing(h))
return;
if (h->data && uv_is_active(h) && h->type != UV_TIMER)
if (h->data && uv_is_active(h) && h->type != UV_TIMER && h->type != UV_POLL)
{
static_cast<glue*>(h->data)->Close();
}
@ -1056,4 +1056,51 @@ namespace libuv
uv_async_send(&m_WakeUp);
}
void
OnUVPollFDReadable(uv_poll_t* handle, int status, [[maybe_unused]] int events)
{
if (status < 0)
return; // probably fd was closed
auto func = static_cast<libuv::Loop::Callback*>(handle->data);
(*func)();
}
void
Loop::register_poll_fd_readable(int fd, Callback callback)
{
if (m_Polls.count(fd))
{
llarp::LogError(
"Attempting to create event loop poll on fd ",
fd,
", but an event loop poll for that fd already exists.");
return;
}
// new a copy as the one passed in here will go out of scope
auto function_ptr = new Callback(callback);
auto& new_poll = m_Polls[fd];
uv_poll_init(&m_Impl, &new_poll, fd);
new_poll.data = (void*)function_ptr;
uv_poll_start(&new_poll, UV_READABLE, &OnUVPollFDReadable);
}
void
Loop::deregister_poll_fd_readable(int fd)
{
auto itr = m_Polls.find(fd);
if (itr != m_Polls.end())
{
uv_poll_stop(&(itr->second));
auto func = static_cast<Callback*>(itr->second.data);
delete func;
m_Polls.erase(itr);
}
}
} // namespace libuv

@ -125,6 +125,12 @@ namespace libuv
void
call_soon(std::function<void(void)> f) override;
void
register_poll_fd_readable(int fd, Callback callback) override;
void
deregister_poll_fd_readable(int fd) override;
void
FlushLogic();
@ -144,6 +150,8 @@ namespace libuv
std::map<uint32_t, Callback> m_pendingCalls;
std::unordered_map<int, uv_poll_t> m_Polls;
llarp::thread::Queue<PendingTimer> m_timerQueue;
llarp::thread::Queue<uint32_t> m_timerCancelQueue;
};

Loading…
Cancel
Save