From 46fa884e5ef647f7ab9255819fd2a42308357d10 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 13:32:35 +0000 Subject: [PATCH 1/9] configure.ac comments --- configure.ac | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configure.ac b/configure.ac index c6850d48..e8ec1f6f 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ AC_CONFIG_HEADERS([config.h]) AC_PROG_CC AC_PROG_CXX AC_LANG([C++]) +# Check dependencies with pkgconfig PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([GEOIP], [geoip], [AC_DEFINE([HAVE_GEOIP], [1], [Define to 1 if you have geoip])], [true]) PKG_CHECK_MODULES([GETDNS], [getdns], [AC_DEFINE([HAVE_GETDNS], [1], [Define to 1 if you have getdns])], [true]) @@ -19,25 +20,31 @@ AS_IF([test "x$YAMLCPP_LIBS" == "x"], [ ]) AM_CONDITIONAL([LIBSYSTEMD],[test "$HAVE_LIBSYSTEMD" = "1"]) AC_PROG_LIBTOOL +# Boost-specific checks BOOST_REQUIRE([1.42]) BOOST_DATE_TIME BOOST_REGEX BOOST_FOREACH +# Check for dependent programs AC_CHECK_PROG(PERL, perl, perl) AC_CHECK_PROG(HAVE_WGET, wget, wget) AS_IF([test "x$HAVE_WGET" == "x"], [ AC_MSG_ERROR([wget not found, wget needed for downloading regexes.yaml and is not optional]) ]) AX_PROG_PERL_MODULES( Swagger2::Markdown, , AC_MSG_WARN(Need to install Perl Swagger2::Markdown)) +# Look for protobuf PDNS_WITH_PROTOBUF AS_IF([test "x$PROTOBUF_LIBS" == "x" -o "x$PROTOC" == "x"], [ AC_MSG_ERROR([Protobuf not found, protobuf support is not optional]) ]) +# Setup variables for locally built libraries AC_SUBST([YAHTTP_CFLAGS], ['-I$(top_srcdir)/ext/yahttp']) AC_SUBST([YAHTTP_LIBS], ['-L$(top_builddir)/ext/yahttp/yahttp -lyahttp']) AC_SUBST([JSON11_CFLAGS], ['-I$(top_srcdir)/ext/json11']) AC_SUBST([JSON11_LIBS], ['-L$(top_builddir)/ext/json11 -ljson11']) +# We need libcrypto for hash functions PDNS_CHECK_LIBCRYPTO +# Check for LuaJIT first then Lua PDNS_WITH_LUAJIT AS_IF([test "x$with_luajit" = "xno"], [ PDNS_WITH_LUA @@ -46,11 +53,15 @@ AS_IF([test "x$LUAPC" = "x" -a "x$LUAJITPC" = "x"], [ AC_MSG_ERROR([Neither Lua nor LuaJIT found, Lua support is not optional]) ]) PDNS_CHECK_LUA_HPP +# Need pandoc to build documentation PDNS_CHECK_PANDOC +# Check for C++ 2011 support AX_CXX_COMPILE_STDCXX_11(ext,mandatory) AM_CONDITIONAL([CXX2011],[test "$HAVE_CXX11" = "1"]) +# Check for systemd AX_AVAILABLE_SYSTEMD AM_CONDITIONAL([HAVE_SYSTEMD], [ test x"$systemd" = "xy" ]) +# We need a working libcurl package LIBCURL_CHECK_CONFIG AC_CONFIG_FILES([Makefile ext/Makefile From 164dd3ec04d045e5a9fc87389e7aff4900dd1d05 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 13:48:12 +0000 Subject: [PATCH 2/9] Make libhiredis non-optional --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e8ec1f6f..386e8b1f 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,12 @@ PKG_CHECK_MODULES([GETDNS], [getdns], [AC_DEFINE([HAVE_GETDNS], [1], [Define to PKG_CHECK_MODULES([libsodium], [libsodium], [AC_DEFINE([HAVE_LIBSODIUM], [1], [Define to 1 if you have libsodium])]) PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define to 1 if you have libsystemd-dev])], [true]) PKG_CHECK_MODULES([LIBHIREDIS], [libhiredis], [AC_DEFINE([HAVE_LIBHIREDIS], [1], [Define to 1 if you have libhiredis-dev])], [true]) -PKG_CHECK_MODULES([LIBHIREDIS], [hiredis], [AC_DEFINE([HAVE_LIBHIREDIS], [1], [Define to 1 if you have hiredis])], [true]) +AS_IF([test "x$LIBHIREDIS_LIBS" == "x"], [ + PKG_CHECK_MODULES([LIBHIREDIS], [hiredis], [AC_DEFINE([HAVE_LIBHIREDIS], [1], [Define to 1 if you have hiredis])]) +]) +AS_IF([test "x$LIBHIREDIS_LIBS" == "x"], [ + AC_MSG_ERROR([libhiredis not found, libhiredis support is not optional]) +]) PDNS_CHECK_YAMLCPP([AC_DEFINE([HAVE_YAMLCPP], [1], [Define to 1 if you have yaml-cpp])], [true]) AS_IF([test "x$YAMLCPP_LIBS" == "x"], [ AC_MSG_ERROR([yaml-cpp not found, yaml-cpp support is not optional]) From d8ca4cc2e4d2500364a337924ab8562c27704e60 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 13:49:52 +0000 Subject: [PATCH 3/9] Make getdns package mandatory --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 386e8b1f..58a17a43 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ AC_LANG([C++]) # Check dependencies with pkgconfig PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([GEOIP], [geoip], [AC_DEFINE([HAVE_GEOIP], [1], [Define to 1 if you have geoip])], [true]) -PKG_CHECK_MODULES([GETDNS], [getdns], [AC_DEFINE([HAVE_GETDNS], [1], [Define to 1 if you have getdns])], [true]) +PKG_CHECK_MODULES([GETDNS], [getdns], [AC_DEFINE([HAVE_GETDNS], [1], [Define to 1 if you have getdns])]) PKG_CHECK_MODULES([libsodium], [libsodium], [AC_DEFINE([HAVE_LIBSODIUM], [1], [Define to 1 if you have libsodium])]) PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], [AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define to 1 if you have libsystemd-dev])], [true]) PKG_CHECK_MODULES([LIBHIREDIS], [libhiredis], [AC_DEFINE([HAVE_LIBHIREDIS], [1], [Define to 1 if you have libhiredis-dev])], [true]) From a29f962d3753fd2c13ea67902decd63c9783606c Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 13:58:05 +0000 Subject: [PATCH 4/9] Synchronize LuaContext.hpp with latest pdns version --- ext/luawrapper/include/LuaContext.hpp | 154 ++++++++++++++------------ 1 file changed, 86 insertions(+), 68 deletions(-) diff --git a/ext/luawrapper/include/LuaContext.hpp b/ext/luawrapper/include/LuaContext.hpp index 6562c0df..9cf72ca2 100644 --- a/ext/luawrapper/include/LuaContext.hpp +++ b/ext/luawrapper/include/LuaContext.hpp @@ -58,6 +58,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include "misc/exception.hpp" #endif +#ifdef __GNUC__ +# define ATTR_UNUSED __attribute__((unused)) +#else +# define ATTR_UNUSED +#endif + /** * Defines a Lua context * A Lua context is used to interpret Lua code. Since everything in Lua is a variable (including functions), @@ -163,10 +169,10 @@ class LuaContext { class WrongTypeException : public std::runtime_error { public: - WrongTypeException(std::string luaType, const std::type_info& destination) : - std::runtime_error("Trying to cast a lua variable from \"" + luaType + "\" to \"" + destination.name() + "\""), - luaType(luaType), - destination(destination) + WrongTypeException(std::string luaType_, const std::type_info& destination_) : + std::runtime_error("Trying to cast a lua variable from \"" + luaType_ + "\" to \"" + destination_.name() + "\""), + luaType(luaType_), + destination(destination_) { } @@ -420,12 +426,12 @@ class LuaContext { * @tparam TVarType Type of the member * @param name Name of the member to register * @param readFunction Function of type "TVarType (const TObject&)" - * @param writeFunction Function of type "void (TObject&, const TVarType&)" + * @param writeFunction_ Function of type "void (TObject&, const TVarType&)" */ template - void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction) + void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) { - registerMemberImpl(name, std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(name, std::move(readFunction), std::move(writeFunction_)); } /** @@ -434,13 +440,13 @@ class LuaContext { * @tparam TMemberType Pointer to member object representing the type * @param name Name of the member to register * @param readFunction Function of type "TVarType (const TObject&)" - * @param writeFunction Function of type "void (TObject&, const TVarType&)" + * @param writeFunction_ Function of type "void (TObject&, const TVarType&)" */ template - void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction) + void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) { static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); - registerMemberImpl(tag{}, name, std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(tag{}, name, std::move(readFunction), std::move(writeFunction_)); } /** @@ -477,12 +483,12 @@ class LuaContext { * @tparam TObject Type to register the member to * @tparam TVarType Type of the member * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" - * @param writeFunction Function of type "void (TObject&, const std::string&, const TVarType&)" + * @param writeFunction_ Function of type "void (TObject&, const std::string&, const TVarType&)" */ template - void registerMember(TReadFunction readFunction, TWriteFunction writeFunction) + void registerMember(TReadFunction readFunction, TWriteFunction writeFunction_) { - registerMemberImpl(std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(std::move(readFunction), std::move(writeFunction_)); } /** @@ -490,13 +496,13 @@ class LuaContext { * This is the version "registerMember(getter, setter)" * @tparam TMemberType Pointer to member object representing the type * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" - * @param writeFunction Function of type "void (TObject&, const std::string&, const TVarType&)" + * @param writeFunction_ Function of type "void (TObject&, const std::string&, const TVarType&)" */ template - void registerMember(TReadFunction readFunction, TWriteFunction writeFunction) + void registerMember(TReadFunction readFunction, TWriteFunction writeFunction_) { static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); - registerMemberImpl(tag{}, std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(tag{}, std::move(readFunction), std::move(writeFunction_)); } /** @@ -560,7 +566,7 @@ class LuaContext { * @sa writeVariable * * Readable types are all types accepted by writeVariable except nullptr, std::unique_ptr and function pointers - * Additionaly supported: + * Additionally supported: * - LuaFunctionCaller, which is an alternative to std::function * - references to custom objects, in which case it will return the object in-place * @@ -637,7 +643,7 @@ class LuaContext { /** * Equivalent to writeVariable(varName, ..., std::function(data)); - * This version is more effecient than writeVariable if you want to write functions + * This version is more efficient than writeVariable if you want to write functions */ template void writeFunction(TData&&... data) noexcept { @@ -674,7 +680,7 @@ class LuaContext { /* PUSH OBJECT */ /**************************************************/ struct PushedObject { - PushedObject(lua_State* state, int num = 1) : state(state), num(num) {} + PushedObject(lua_State* state_, int num_ = 1) : state(state_), num(num_) {} ~PushedObject() { assert(lua_gettop(state) >= num); if (num >= 1) lua_pop(state, num); } PushedObject& operator=(const PushedObject&) = delete; @@ -735,7 +741,7 @@ class LuaContext { // equivalent of lua_settable with t[k]=n, where t is the value at the index in the template parameter, k is the second parameter, n is the last parameter, and n is pushed by the function in the first parameter // if there are more than 3 parameters, parameters 3 to n-1 are considered as sub-indices into the array // the dataPusher MUST push only one thing on the stack - // TTableIndex must be either LUA_REGISTERYINDEX, LUA_GLOBALSINDEX, LUA_ENVINDEX, or the position of the element on the stack + // TTableIndex must be either LUA_REGISTRYINDEX, LUA_GLOBALSINDEX, LUA_ENVINDEX, or the position of the element on the stack template static void setTable(lua_State* state, const PushedObject&, TIndex&& index, TData&& data) noexcept { @@ -1041,7 +1047,7 @@ class LuaContext { template void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag, tag) { - static_assert(std::is_class::value || std::is_pointer::value || std::is_union::value , "registerFunction can only be used for a class or a pointer"); + static_assert(std::is_class::value || std::is_pointer::value || std::is_union::value , "registerFunction can only be used for a class a union or a pointer"); checkTypeRegistration(mState, &typeid(TObject)); setTable(mState, Registry, &typeid(TObject), 0, functionName, std::move(function)); @@ -1126,29 +1132,29 @@ class LuaContext { } template - void registerMemberImpl(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction) + void registerMemberImpl(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) { registerMemberImpl(name, readFunction); - setTable(mState, Registry, &typeid(TObject), 4, name, [writeFunction](TObject& object, const TVarType& value) { - writeFunction(object, value); + setTable(mState, Registry, &typeid(TObject), 4, name, [writeFunction_](TObject& object, const TVarType& value) { + writeFunction_(object, value); }); - setTable(mState, Registry, &typeid(TObject*), 4, name, [writeFunction](TObject* object, const TVarType& value) { + setTable(mState, Registry, &typeid(TObject*), 4, name, [writeFunction_](TObject* object, const TVarType& value) { assert(object); - writeFunction(*object, value); + writeFunction_(*object, value); }); - setTable, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 4, name, [writeFunction](std::shared_ptr object, const TVarType& value) { + setTable, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 4, name, [writeFunction_](std::shared_ptr object, const TVarType& value) { assert(object); - writeFunction(*object, value); + writeFunction_(*object, value); }); } template - void registerMemberImpl(tag, const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction) + void registerMemberImpl(tag, const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) { - registerMemberImpl(name, std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(name, std::move(readFunction), std::move(writeFunction_)); } template @@ -1192,29 +1198,29 @@ class LuaContext { } template - void registerMemberImpl(TReadFunction readFunction, TWriteFunction writeFunction) + void registerMemberImpl(TReadFunction readFunction, TWriteFunction writeFunction_) { registerMemberImpl(readFunction); - setTable(mState, Registry, &typeid(TObject), 5, [writeFunction](TObject& object, const std::string& name, const TVarType& value) { - writeFunction(object, name, value); + setTable(mState, Registry, &typeid(TObject), 5, [writeFunction_](TObject& object, const std::string& name, const TVarType& value) { + writeFunction_(object, name, value); }); - setTable(mState, Registry, &typeid(TObject*), 2, [writeFunction](TObject* object, const std::string& name, const TVarType& value) { + setTable(mState, Registry, &typeid(TObject*), 2, [writeFunction_](TObject* object, const std::string& name, const TVarType& value) { assert(object); - writeFunction(*object, name, value); + writeFunction_(*object, name, value); }); - setTable, std::string, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 2, [writeFunction](const std::shared_ptr& object, const std::string& name, const TVarType& value) { + setTable, std::string, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 2, [writeFunction_](const std::shared_ptr& object, const std::string& name, const TVarType& value) { assert(object); - writeFunction(*object, name, value); + writeFunction_(*object, name, value); }); } template - void registerMemberImpl(tag, TReadFunction readFunction, TWriteFunction writeFunction) + void registerMemberImpl(tag, TReadFunction readFunction, TWriteFunction writeFunction_) { - registerMemberImpl(std::move(readFunction), std::move(writeFunction)); + registerMemberImpl(std::move(readFunction), std::move(writeFunction_)); } template @@ -1304,7 +1310,7 @@ class LuaContext { RealReturnType; // we push the parameters on the stack - auto inArguments = Pusher>::push(state, std::make_tuple(std::forward(input)...)); + auto inArguments = Pusher>::push(state, std::forward_as_tuple((input)...)); // const int outArgumentsCount = std::tuple_size::value; @@ -1339,10 +1345,13 @@ class LuaContext { // an exception_ptr was pushed on the stack // rethrowing it with an additional ExecutionErrorException try { - std::rethrow_exception(readTopAndPop(state, std::move(errorCode))); + if (const auto exp = readTopAndPop(state, std::move(errorCode))) { + std::rethrow_exception(exp); + } } catch(...) { std::throw_with_nested(ExecutionErrorException{"Exception thrown by a callback function called by Lua"}); } + throw ExecutionErrorException{"Unknown Lua error"}; } } } @@ -1630,13 +1639,13 @@ class LuaContext { /**************************************************/ /* UTILITIES */ /**************************************************/ - // structure that will ensure that a certain is stored somewhere in the registry + // structure that will ensure that a certain value is stored somewhere in the registry struct ValueInRegistry { - // this constructor will clone and hold the value at the top of the stack in the registry - ValueInRegistry(lua_State* lua) : lua{lua} + // this constructor will clone and hold the value at the specified index (or by default at the top of the stack) in the registry + ValueInRegistry(lua_State* lua_, int index=-1) : lua{lua_} { lua_pushlightuserdata(lua, this); - lua_pushvalue(lua, -2); + lua_pushvalue(lua, -1 + index); lua_settable(lua, LUA_REGISTRYINDEX); } @@ -1702,11 +1711,11 @@ class LuaContext { }; /// @deprecated -//static LuaContext::EmptyArray_t -// LuaEmptyArray {}; +static LuaContext::EmptyArray_t ATTR_UNUSED + LuaEmptyArray {}; /// @deprecated -//static LuaContext::Metatable_t -// LuaMetatable {}; +static LuaContext::Metatable_t ATTR_UNUSED + LuaMetatable {}; /**************************************************/ /* PARTIAL IMPLEMENTATIONS */ @@ -1756,10 +1765,18 @@ template<> struct LuaContext::PusherTotalMaxSize<> { static const int size = 0; }; // implementation of PusherMinSize -template -struct LuaContext::PusherMinSize { static const int size = Pusher::type>::minSize < PusherTotalMaxSize::size ? Pusher::type>::minSize : PusherMinSize::size; }; -template<> -struct LuaContext::PusherMinSize<> { static const int size = 0; }; +template +struct LuaContext::PusherMinSize +{ + static const int size = Pusher::type>::minSize < Pusher::type>::minSize + ? + PusherMinSize::type, TTypes...>::size + : + PusherMinSize::type, TTypes...>::size; +}; + +template +struct LuaContext::PusherMinSize { static const int size = Pusher::type>::minSize; }; // implementation of PusherMaxSize template @@ -1804,9 +1821,9 @@ class LuaContext::LuaFunctionCaller private: friend LuaContext; - explicit LuaFunctionCaller(lua_State* state) : - valueHolder(std::make_shared(state)), - state(state) + explicit LuaFunctionCaller(lua_State* state_, int index) : + valueHolder(std::make_shared(state_, index)), + state(state_) {} }; @@ -1835,7 +1852,7 @@ struct LuaContext::Pusher { static const int maxSize = 1; static PushedObject push(lua_State* state, const std::string& value) noexcept { - lua_pushstring(state, value.c_str()); + lua_pushlstring(state, value.c_str(), value.length()); return PushedObject{state, 1}; } }; @@ -2126,11 +2143,11 @@ struct LuaContext::Pusher // since "fn" doesn't need to be destroyed, we simply push it on the stack // this is the cfunction that is the callback - const auto function = [](lua_State* state) -> int + const auto function = [](lua_State* state_) -> int { // the function object is an upvalue - const auto toCall = static_cast(lua_touserdata(state, lua_upvalueindex(1))); - return callback(state, toCall, lua_gettop(state)).release(); + const auto toCall = static_cast(lua_touserdata(state_, lua_upvalueindex(1))); + return callback(state_, toCall, lua_gettop(state_)).release(); }; // we copy the function object onto the stack @@ -2150,11 +2167,11 @@ struct LuaContext::Pusher // since "fn" doesn't need to be destroyed, we simply push it on the stack // this is the cfunction that is the callback - const auto function = [](lua_State* state) -> int + const auto function = [](lua_State* state_) -> int { // the function object is an upvalue - const auto toCall = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); - return callback(state, toCall, lua_gettop(state)).release(); + const auto toCall = reinterpret_cast(lua_touserdata(state_, lua_upvalueindex(1))); + return callback(state_, toCall, lua_gettop(state_)).release(); }; // we copy the function object onto the stack @@ -2307,7 +2324,7 @@ struct LuaContext::Pusher> obj = Pusher::type>::push(state, std::move(value)); } - VariantWriter(lua_State* state, PushedObject& obj) : state(state), obj(obj) {} + VariantWriter(lua_State* state_, PushedObject& obj_) : state(state_), obj(obj_) {} lua_State* state; PushedObject& obj; }; @@ -2469,10 +2486,11 @@ struct LuaContext::Reader static auto read(lua_State* state, int index) -> boost::optional { - const auto val = lua_tostring(state, index); + size_t len; + const auto val = lua_tolstring(state, index, &len); if (val == 0) return boost::none; - return std::string(val); + return std::string(val, len); } }; @@ -2486,7 +2504,7 @@ struct LuaContext::Reader< static auto read(lua_State* state, int index) -> boost::optional { - if (!lua_isnumber(state, index) != 0 || fmod(lua_tonumber(state, index), 1.) != 0) + if (!lua_isnumber(state, index) || fmod(lua_tonumber(state, index), 1.) != 0) return boost::none; return static_cast(lua_tointeger(state, index)); } @@ -2504,7 +2522,7 @@ struct LuaContext::Reader Date: Wed, 15 Mar 2017 14:48:34 +0000 Subject: [PATCH 5/9] typedef alias PDNSException to WforceException --- wforce_exception.hh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wforce_exception.hh b/wforce_exception.hh index f6ff12e5..4edcbe0e 100644 --- a/wforce_exception.hh +++ b/wforce_exception.hh @@ -28,3 +28,6 @@ class WforceException: public std::runtime_error public: WforceException(const std::string &a) : std::runtime_error(a) {} }; + +// This means we can use PDNS classes that emit PDNSException +typedef WforceException PDNSException; From 44471539729632beb32de46021afa15f3db7834a Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 14:50:13 +0000 Subject: [PATCH 6/9] Add wforce_exception.hh to wforce.hh so WforceException is generally available --- wforce.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/wforce.hh b/wforce.hh index 236f9401..1a204ea9 100644 --- a/wforce.hh +++ b/wforce.hh @@ -33,6 +33,7 @@ #include "sstuff.hh" #include "replication.hh" #include "webhook.hh" +#include "wforce_exception.hh" #include "ext/json11/json11.hpp" #include #include From 16a332d81989aa78cd7a85706967f8ff2d147c9b Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 15 Mar 2017 17:30:22 +0000 Subject: [PATCH 7/9] Sync iputils.cc, iputils.hh and related files from pdns repo Pull the latest changes to iputils.hh and .cc from pdns repo. This also involves changes to: misc.hh misc.cc Since iputils.xx use updated functions from misc.xx Also changes to wforce-lua.cc catch clauses for ComboAddress since the iputils.xx changes involve throwing a new PDNSException class. --- iputils.cc | 202 ++++++++++++++++++++++++++++++++++++++++++++++++-- iputils.hh | 123 ++++++++++++++++++++---------- misc.cc | 19 +++-- misc.hh | 5 +- wforce-lua.cc | 26 ++++--- 5 files changed, 310 insertions(+), 65 deletions(-) diff --git a/iputils.cc b/iputils.cc index 0a740c95..98e1985e 100644 --- a/iputils.cc +++ b/iputils.cc @@ -19,7 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -45,16 +44,61 @@ int SSocket(int family, int type, int flags) int SConnect(int sockfd, const ComboAddress& remote) { int ret = connect(sockfd, (struct sockaddr*)&remote, remote.getSocklen()); - if(ret < 0) - RuntimeError(boost::format("connecting socket to %s: %s") % remote.toStringWithPort() % strerror(errno)); + if(ret < 0) { + int savederrno = errno; + RuntimeError(boost::format("connecting socket to %s: %s") % remote.toStringWithPort() % strerror(savederrno)); + } + return ret; +} + +int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout) +{ + int ret = connect(sockfd, (struct sockaddr*)&remote, remote.getSocklen()); + if(ret < 0) { + int savederrno = errno; + if (savederrno == EINPROGRESS) { + /* we wait until the connection has been established */ + bool error = false; + bool disconnected = false; + int res = waitForRWData(sockfd, false, timeout, 0, &error, &disconnected); + if (res == 1) { + if (error) { + savederrno = 0; + socklen_t errlen = sizeof(savederrno); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&savederrno, &errlen) == 0) { + RuntimeError(boost::format("connecting to %s failed: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + else { + RuntimeError(boost::format("connecting to %s failed") % remote.toStringWithPort()); + } + } + if (disconnected) { + RuntimeError(boost::format("%s closed the connection") % remote.toStringWithPort()); + } + return 0; + } + else if (res == 0) { + RuntimeError(boost::format("timeout while connecting to %s") % remote.toStringWithPort()); + } else if (res < 0) { + savederrno = errno; + RuntimeError(boost::format("waiting to connect to %s: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + } + else { + RuntimeError(boost::format("connecting to %s: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + } + return ret; } int SBind(int sockfd, const ComboAddress& local) { int ret = bind(sockfd, (struct sockaddr*)&local, local.getSocklen()); - if(ret < 0) - RuntimeError(boost::format("binding socket to %s: %s") % local.toStringWithPort() % strerror(errno)); + if(ret < 0) { + int savederrno = errno; + RuntimeError(boost::format("binding socket to %s: %s") % local.toStringWithPort() % strerror(savederrno)); + } return ret; } @@ -119,7 +163,6 @@ bool HarvestDestinationAddress(struct msghdr* msgh, ComboAddress* destination) return true; } #endif - #if defined(IPV6_PKTINFO) if ((cmsg->cmsg_level == IPPROTO_IPV6) && (cmsg->cmsg_type == IPV6_PKTINFO)) { struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg); @@ -158,7 +201,7 @@ ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const Comb msgh.msg_namelen = to.getSocklen(); if(from.sin4.sin_family) { - addCMsgSrcAddr(&msgh, cbuf, &from); + addCMsgSrcAddr(&msgh, cbuf, &from, 0); } else { msgh.msg_control=NULL; @@ -185,7 +228,8 @@ void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufs msgh->msg_flags = 0; } -void ComboAddress::truncate(unsigned int bits) +// warning: various parts of PowerDNS assume 'truncate' will never throw +void ComboAddress::truncate(unsigned int bits) noexcept { uint8_t* start; int len=4; @@ -214,5 +258,147 @@ void ComboAddress::truncate(unsigned int bits) *place &= (~((1<(buffer), len, &dest); + addCMsgSrcAddr(&msgh, cbuf, &local, localItf); + + do { + ssize_t written = sendmsg(fd, &msgh, 0); + + if (written > 0) + return written; + + if (errno == EAGAIN) { + if (firstTry) { + int res = waitForRWData(fd, false, timeout, 0); + if (res > 0) { + /* there is room available */ + firstTry = false; + } + else if (res == 0) { + throw runtime_error("Timeout while waiting to write data"); + } else { + throw runtime_error("Error while waiting for room to write data"); + } + } + else { + throw runtime_error("Timeout while waiting to write data"); + } + } + else { + unixDie("failed in write2WithTimeout"); + } + } + while (firstTry); + + return 0; +} + template class NetmaskTree; +bool sendSizeAndMsgWithTimeout(int sock, uint16_t bufferLen, const char* buffer, int idleTimeout, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int totalTimeout, int flags) +{ + uint16_t size = htons(bufferLen); + char cbuf[256]; + struct msghdr msgh; + struct iovec iov[2]; + int remainingTime = totalTimeout; + time_t start = 0; + if (totalTimeout) { + start = time(NULL); + } + + /* Set up iov and msgh structures. */ + memset(&msgh, 0, sizeof(struct msghdr)); + msgh.msg_control = nullptr; + msgh.msg_controllen = 0; + if (dest) { + msgh.msg_name = reinterpret_cast(const_cast(dest)); + msgh.msg_namelen = dest->getSocklen(); + } + else { + msgh.msg_name = nullptr; + msgh.msg_namelen = 0; + } + + msgh.msg_flags = 0; + + if (localItf != 0 && local) { + addCMsgSrcAddr(&msgh, cbuf, local, localItf); + } + + iov[0].iov_base = &size; + iov[0].iov_len = sizeof(size); + iov[1].iov_base = reinterpret_cast(const_cast(buffer)); + iov[1].iov_len = bufferLen; + + size_t pos = 0; + size_t sent = 0; + size_t nbElements = sizeof(iov)/sizeof(*iov); + while (true) { + msgh.msg_iov = &iov[pos]; + msgh.msg_iovlen = nbElements - pos; + + ssize_t res = sendmsg(sock, &msgh, flags); + if (res > 0) { + size_t written = static_cast(res); + sent += written; + + if (sent == (sizeof(size) + bufferLen)) { + return true; + } + /* partial write, we need to keep only the (parts of) elements + that have not been written. + */ + do { + if (written < iov[pos].iov_len) { + iov[pos].iov_len -= written; + written = 0; + } + else { + written -= iov[pos].iov_len; + iov[pos].iov_len = 0; + pos++; + } + } + while (written > 0 && pos < nbElements); + } + else if (res == -1) { + if (errno == EINTR) { + continue; + } + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) { + /* EINPROGRESS might happen with non blocking socket, + especially with TCP Fast Open */ + int ret = waitForRWData(sock, false, (totalTimeout == 0 || idleTimeout <= remainingTime) ? idleTimeout : remainingTime, 0); + if (ret > 0) { + /* there is room available */ + } + else if (ret == 0) { + throw runtime_error("Timeout while waiting to send data"); + } else { + throw runtime_error("Error while waiting for room to send data"); + } + } + else { + unixDie("failed in sendSizeAndMsgWithTimeout"); + } + } + if (totalTimeout) { + time_t now = time(NULL); + int elapsed = now - start; + if (elapsed >= remainingTime) { + throw runtime_error("Timeout while sending data"); + } + start = now; + remainingTime -= elapsed; + } + } + + return false; +} diff --git a/iputils.hh b/iputils.hh index cfd03426..8c199748 100644 --- a/iputils.hh +++ b/iputils.hh @@ -31,6 +31,7 @@ #include #include #include +#include "wforce_exception.hh" #include "misc.hh" #include #include @@ -64,18 +65,18 @@ #define htobe16(x) BE_16(x) #define htole16(x) LE_16(x) -#define be16toh(x) BE_IN16(x) -#define le16toh(x) LE_IN16(x) +#define be16toh(x) BE_IN16(&(x)) +#define le16toh(x) LE_IN16(&(x)) #define htobe32(x) BE_32(x) #define htole32(x) LE_32(x) -#define be32toh(x) BE_IN32(x) -#define le32toh(x) LE_IN32(x) +#define be32toh(x) BE_IN32(&(x)) +#define le32toh(x) LE_IN32(&(x)) #define htobe64(x) BE_64(x) #define htole64(x) LE_64(x) -#define be64toh(x) BE_IN64(x) -#define le64toh(x) LE_IN64(x) +#define be64toh(x) BE_IN64(&(x)) +#define le64toh(x) LE_IN64(&(x)) #endif @@ -198,7 +199,7 @@ union ComboAddress { }; void setSockaddr(const struct sockaddr *sa, socklen_t salen) { - if (salen > sizeof(struct sockaddr_in6)) throw std::runtime_error("ComboAddress can't handle other than sockaddr_in or sockaddr_in6"); + if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6"); memcpy(this, sa, salen); } @@ -210,14 +211,23 @@ union ComboAddress { sin4.sin_port = 0; if(makeIPv4sockaddr(str, &sin4)) { sin6.sin6_family = AF_INET6; - if(makeIPv6sockaddr(str, &sin6) < 0) { - throw std::runtime_error("Unable to convert presentation address '"+ str +"'"); - } + if(makeIPv6sockaddr(str, &sin6) < 0) + throw PDNSException("Unable to convert presentation address '"+ str +"'"); + } if(!sin4.sin_port) // 'str' overrides port! sin4.sin_port=htons(port); } + bool isIpv6() const + { + return sin6.sin6_family == AF_INET6; + } + bool isIpv4() const + { + return sin4.sin_family == AF_INET; + } + bool isMappedIPv4() const { if(sin4.sin_family!=AF_INET6) @@ -239,7 +249,7 @@ union ComboAddress { ComboAddress mapToIPv4() const { if(!isMappedIPv4()) - throw std::runtime_error("ComboAddress can't map non-mapped IPv6 address back to IPv4"); + throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4"); ComboAddress ret; ret.sin4.sin_family=AF_INET; ret.sin4.sin_port=sin4.sin_port; @@ -266,24 +276,15 @@ union ComboAddress { else return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port)); } - - bool isIpv6() const - { - return sin6.sin6_family == AF_INET6; - } - bool isIpv4() const - { - return sin4.sin_family == AF_INET; - } - void truncate(unsigned int bits); + void truncate(unsigned int bits) noexcept; }; /** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */ -class NetmaskException: public std::runtime_error +class NetmaskException: public PDNSException { public: - NetmaskException(const string &a) : std::runtime_error(a) {} + NetmaskException(const string &a) : PDNSException(a) {} }; inline ComboAddress makeComboAddress(const string& str) @@ -438,11 +439,34 @@ public: { return d_network; } + const ComboAddress getMaskedNetwork() const + { + ComboAddress result(d_network); + if(isIpv4()) { + result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask); + } + else if(isIpv6()) { + size_t idx; + uint8_t bytes=d_bits/8; + uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr; + uint8_t bits= d_bits % 8; + uint8_t mask= (uint8_t) ~(0xFF>>bits); + + if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) { + us[bytes] &= mask; + } + + for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) { + us[idx] = 0; + } + } + return result; + } int getBits() const { return d_bits; } - bool isIpv6() const + bool isIpv6() const { return d_network.sin6.sin6_family == AF_INET6; } @@ -486,7 +510,7 @@ private: * To erase something copy values to new tree sans the value you want to erase. * * Use swap if you need to move the tree to another NetmaskTree instance, it is WAY faster - * than using copy ctor or assigment operator, since it moves the nodes and tree root to + * than using copy ctor or assignment operator, since it moves the nodes and tree root to * new home instead of actually recreating the tree. * * Please see NetmaskGroup for example of simple use case. Other usecases can be found @@ -719,8 +743,12 @@ public: bits++; } if (node) { - for(auto it = _nodes.begin(); it != _nodes.end(); it++) - if (node->node4.get() == *it) _nodes.erase(it); + for(auto it = _nodes.begin(); it != _nodes.end(); ) { + if (node->node4.get() == *it) + it = _nodes.erase(it); + else + it++; + } node->node4.reset(); } } else { @@ -740,8 +768,12 @@ public: bits++; } if (node) { - for(auto it = _nodes.begin(); it != _nodes.end(); it++) - if (node->node6.get() == *it) _nodes.erase(it); + for(auto it = _nodes.begin(); it != _nodes.end(); ) { + if (node->node6.get() == *it) + it = _nodes.erase(it); + else + it++; + } node->node6.reset(); } } @@ -797,7 +829,9 @@ public: bool match(const ComboAddress *ip) const { - return tree.match(*ip); + const auto &ret = tree.lookup(*ip); + if(ret) return ret->second; + return false; } bool match(const ComboAddress& ip) const @@ -806,15 +840,19 @@ public: } //! Add this string to the list of possible matches - void addMask(const std::string &ip) + void addMask(const std::string &ip, bool positive=true) { - addMask(Netmask(ip)); + if(!ip.empty() && ip[0] == '!') { + addMask(Netmask(ip.substr(1)), false); + } else { + addMask(Netmask(ip), positive); + } } //! Add this Netmask to the list of possible matches - void addMask(const Netmask& nm) + void addMask(const Netmask& nm, bool positive=true) { - tree.insert(nm); + tree.insert(nm).second=positive; } void clear() @@ -838,6 +876,8 @@ public: for(auto iter = tree.begin(); iter != tree.end(); ++iter) { if(iter != tree.begin()) str <<", "; + if(!((*iter)->second)) + str<<"!"; str<<(*iter)->first.toString(); } return str.str(); @@ -845,8 +885,9 @@ public: void toStringVector(std::vector* vec) const { - for(auto iter = tree.begin(); iter != tree.end(); ++iter) - vec->push_back((*iter)->first.toString()); + for(auto iter = tree.begin(); iter != tree.end(); ++iter) { + vec->push_back(((*iter)->second ? "" : "!") + (*iter)->first.toString()); + } } void toMasks(const std::string &ips) @@ -880,6 +921,11 @@ struct SComboAddress int SSocket(int family, int type, int flags); int SConnect(int sockfd, const ComboAddress& remote); +/* tries to connect to remote for a maximum of timeout seconds. + sockfd should be set to non-blocking beforehand. + returns 0 on success (the socket is writable), throw a + runtime_error otherwise */ +int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout); int SBind(int sockfd, const ComboAddress& local); int SAccept(int sockfd, ComboAddress& remote); int SListen(int sockfd, int limit); @@ -896,7 +942,8 @@ bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv); void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr); ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to); ssize_t sendMsgWithTimeout(int fd, const char* buffer, size_t len, int timeout, ComboAddress& dest, const ComboAddress& local, unsigned int localItf); - -#endif +bool sendSizeAndMsgWithTimeout(int sock, uint16_t bufferLen, const char* buffer, int idleTimeout, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int totalTimeout, int flags); extern template class NetmaskTree; + +#endif diff --git a/misc.cc b/misc.cc index 0bd9962f..81c5376e 100644 --- a/misc.cc +++ b/misc.cc @@ -186,7 +186,7 @@ int waitForData(int fd, int seconds, int useconds) return waitForRWData(fd, true, seconds, useconds); } -int waitForRWData(int fd, bool waitForRead, int seconds, int useconds) +int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error, bool* disconnected) { int ret; @@ -202,7 +202,15 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds) ret = poll(&pfd, 1, seconds * 1000 + useconds/1000); if ( ret == -1 ) errno = ETIMEDOUT; // ??? - + else if (ret > 0) { + if (error && (pfd.revents & POLLERR)) { + *error = true; + } + if (disconnected && (pfd.revents & POLLHUP)) { + *disconnected = true; + } + } + return ret; } @@ -652,7 +660,7 @@ Regex::Regex(const string &expr) throw std::runtime_error("Regular expression did not compile"); } -void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source) +void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex) { struct cmsghdr *cmsg = NULL; @@ -671,7 +679,7 @@ void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* sour pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg); memset(pkt, 0, sizeof(*pkt)); pkt->ipi6_addr = source->sin6.sin6_addr; - msgh->msg_controllen = cmsg->cmsg_len; // makes valgrind happy and is slightly better style + pkt->ipi6_ifindex = itfIndex; #endif } else { @@ -689,7 +697,7 @@ void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* sour pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); memset(pkt, 0, sizeof(*pkt)); pkt->ipi_spec_dst = source->sin4.sin_addr; - msgh->msg_controllen = cmsg->cmsg_len; + pkt->ipi_ifindex = itfIndex; #endif #ifdef IP_SENDSRCADDR struct in_addr *in; @@ -704,7 +712,6 @@ void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* sour in = (struct in_addr *) CMSG_DATA(cmsg); *in = source->sin4.sin_addr; - msgh->msg_controllen = cmsg->cmsg_len; #endif } } diff --git a/misc.hh b/misc.hh index 19817a4a..04301b47 100644 --- a/misc.hh +++ b/misc.hh @@ -52,7 +52,7 @@ string getHostname(); string urlEncode(const string &text); int waitForData(int fd, int seconds, int useconds=0); int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd); -int waitForRWData(int fd, bool waitForRead, int seconds, int useconds); +int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr); uint16_t getShort(const unsigned char *p); uint16_t getShort(const char *p); uint32_t getLong(const unsigned char *p); @@ -505,7 +505,8 @@ private: }; union ComboAddress; -void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source); +/* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */ +void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex); unsigned int getFilenumLimit(bool hardOrSoft=0); void setFilenumLimit(unsigned int lim); diff --git a/wforce-lua.cc b/wforce-lua.cc index 449f9338..63907244 100644 --- a/wforce-lua.cc +++ b/wforce-lua.cc @@ -74,7 +74,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { ca = ComboAddress(address, 4501); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("addReportSink() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", address); return; } @@ -95,7 +95,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { v.push_back(std::make_shared(ComboAddress(p.second, 4501))); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("setReportSinks() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", p.second); return; } @@ -115,7 +115,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { ca = ComboAddress(address, 4501); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("addNamedReportSink() error parsing address/port [%s] for report sink [%s]. Make sure to use IP addresses not hostnames", address, sink_name); return; } @@ -145,7 +145,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { v.push_back(std::make_shared(ComboAddress(p.second, 4501))); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("setNamedReportSinks() error parsing address/port [%s] for report sink [%s]. Make sure to use IP addresses not hostnames", p.second, sink_name); return; } @@ -171,7 +171,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { ca = ComboAddress(address, 4001); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("addSibling() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", address); return; } @@ -201,7 +201,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { ca = ComboAddress(address, 4001); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("siblingListener() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", address); return; } @@ -258,7 +258,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { local = ComboAddress(address); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("webserver() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", address); return; } @@ -292,7 +292,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { local = ComboAddress(str, 5199); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("controlSocket() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", str); return; } @@ -609,7 +609,7 @@ vector> setupLua(bool client, bool allow_report, LuaCo try { return ComboAddress(address); } - catch (const std::runtime_error& e) { + catch (const WforceException& e) { errlog("newCA() error parsing address/port [%s]. Make sure to use IP addresses not hostnames", address); return ComboAddress(); } @@ -617,8 +617,12 @@ vector> setupLua(bool client, bool allow_report, LuaCo c_lua.writeFunction("newNetmaskGroup", []() { return NetmaskGroup(); } ); - c_lua.registerFunction("addMask", static_cast(&NetmaskGroup::addMask)); - c_lua.registerFunction("match", static_cast(&NetmaskGroup::match)); + c_lua.registerFunction("addMask", [](NetmaskGroup& nmg, const std::string& mask) { + nmg.addMask(mask); + }); + c_lua.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); + g_lua.registerFunction("size", &NetmaskGroup::size); + g_lua.registerFunction("clear", &NetmaskGroup::clear); if (allow_report) { c_lua.writeFunction("setAllow", [&allow_func](allow_t func) { allow_func=func;}); From 4e0b82b9580766b1615729c51af13d183e815d33 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 16 Mar 2017 08:41:35 +0000 Subject: [PATCH 8/9] Change error message for mandatory packages from "not optional" to "mandatory" --- configure.ac | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 58a17a43..e86a8866 100644 --- a/configure.ac +++ b/configure.ac @@ -17,11 +17,11 @@ AS_IF([test "x$LIBHIREDIS_LIBS" == "x"], [ PKG_CHECK_MODULES([LIBHIREDIS], [hiredis], [AC_DEFINE([HAVE_LIBHIREDIS], [1], [Define to 1 if you have hiredis])]) ]) AS_IF([test "x$LIBHIREDIS_LIBS" == "x"], [ - AC_MSG_ERROR([libhiredis not found, libhiredis support is not optional]) + AC_MSG_ERROR([libhiredis not found, libhiredis support is mandatory]) ]) PDNS_CHECK_YAMLCPP([AC_DEFINE([HAVE_YAMLCPP], [1], [Define to 1 if you have yaml-cpp])], [true]) AS_IF([test "x$YAMLCPP_LIBS" == "x"], [ - AC_MSG_ERROR([yaml-cpp not found, yaml-cpp support is not optional]) + AC_MSG_ERROR([yaml-cpp not found, yaml-cpp support is mandatory]) ]) AM_CONDITIONAL([LIBSYSTEMD],[test "$HAVE_LIBSYSTEMD" = "1"]) AC_PROG_LIBTOOL @@ -34,13 +34,13 @@ BOOST_FOREACH AC_CHECK_PROG(PERL, perl, perl) AC_CHECK_PROG(HAVE_WGET, wget, wget) AS_IF([test "x$HAVE_WGET" == "x"], [ - AC_MSG_ERROR([wget not found, wget needed for downloading regexes.yaml and is not optional]) + AC_MSG_ERROR([wget not found, wget needed for downloading regexes.yaml and is mandatory]) ]) AX_PROG_PERL_MODULES( Swagger2::Markdown, , AC_MSG_WARN(Need to install Perl Swagger2::Markdown)) # Look for protobuf PDNS_WITH_PROTOBUF AS_IF([test "x$PROTOBUF_LIBS" == "x" -o "x$PROTOC" == "x"], [ - AC_MSG_ERROR([Protobuf not found, protobuf support is not optional]) + AC_MSG_ERROR([Protobuf not found, protobuf support is mandatory]) ]) # Setup variables for locally built libraries AC_SUBST([YAHTTP_CFLAGS], ['-I$(top_srcdir)/ext/yahttp']) @@ -55,7 +55,7 @@ AS_IF([test "x$with_luajit" = "xno"], [ PDNS_WITH_LUA ]) AS_IF([test "x$LUAPC" = "x" -a "x$LUAJITPC" = "x"], [ - AC_MSG_ERROR([Neither Lua nor LuaJIT found, Lua support is not optional]) + AC_MSG_ERROR([Neither Lua nor LuaJIT found, Lua support is mandatory]) ]) PDNS_CHECK_LUA_HPP # Need pandoc to build documentation From 88d67b586d24c2dc21ed47d5921f9acf5ed4855c Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 16 Mar 2017 09:25:48 +0000 Subject: [PATCH 9/9] Make libcurl mandatory in configure.ac --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index e86a8866..81974d6c 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,9 @@ AX_AVAILABLE_SYSTEMD AM_CONDITIONAL([HAVE_SYSTEMD], [ test x"$systemd" = "xy" ]) # We need a working libcurl package LIBCURL_CHECK_CONFIG +AS_IF([test "x$LIBCURL" = "x"], [ + AC_MSG_ERROR([Libcurl not found, libcurl support is mandatory]) +]) AC_CONFIG_FILES([Makefile ext/Makefile ext/json11/Makefile