From: Vladimír Čunát Date: Wed, 7 Sep 2016 12:46:16 +0000 (+0200) Subject: net.listen: make it more flexible X-Git-Tag: v1.2.0-rc1~99^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cfef5357747feb41b24ed881a42274963e1ff05e;p=thirdparty%2Fknot-resolver.git net.listen: make it more flexible As noted in #94, it feels natural to call it like: ``net.listen({net.lo, '192.168.1.1'})`` Also, minor fixes were done in that function and corresponding docs. --- diff --git a/daemon/README.rst b/daemon/README.rst index 66dcfaa97..fe455858c 100644 --- a/daemon/README.rst +++ b/daemon/README.rst @@ -472,29 +472,23 @@ For when listening on ``localhost`` just doesn't cut it. Enable/disable using IPv4 for recursion. -.. function:: net.listen(address, [port = 53, flags = {tls = false}]) +.. function:: net.listen(addressses, [port = 53, flags = {tls = (port == 853)}]) :return: boolean - Listen on address, port and flags are optional. + Listen on addresses; port and flags are optional. + The addresses can be specified as a string or device, + or a list of addresses (recursively). + The command can be given multiple times, but note that it silently skips + any addresses that have already been bound. -.. function:: net.listen({address1, ...}, [port = 53, flags = {tls = false}]) - - :return: boolean - - Listen on list of addresses. - -.. function:: net.listen(interface, [port = 53, flags = {tls = false}]) - - :return: boolean - - Listen on all addresses belonging to an interface. - - Example: + Examples: .. code-block:: lua - net.listen(net.eth0) -- listen on eth0 + net.listen('::1') + net.listen(net.lo, 5353) + net.listen({net.eth0, '127.0.0.1'}, 53853, {tls = true}) .. function:: net.close(address, [port = 53]) diff --git a/daemon/bindings.c b/daemon/bindings.c index ecc750c0d..e80b80b74 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -167,30 +167,43 @@ static int net_list(lua_State *L) return 1; } -/** Listen on interface address list. */ -static int net_listen_iface(lua_State *L, int port, int flags) +/** Listen on an address list represented by the top of lua stack. */ +static int net_listen_addrs(lua_State *L, int port, int flags) { - /* Expand 'addr' key if exists */ - lua_getfield(L, 1, "addr"); - if (lua_isnil(L, -1)) { + /* Case: table with 'addr' field; only follow that field directly. */ + lua_getfield(L, -1, "addr"); + if (!lua_isnil(L, -1)) { + lua_replace(L, -2); + kr_log_info(" .addr\n"); + } else { lua_pop(L, 1); - lua_pushvalue(L, 1); } - /* Bind to address list */ - struct engine *engine = engine_luaget(L); - size_t count = lua_rawlen(L, -1); - for (size_t i = 0; i < count; ++i) { - lua_rawgeti(L, -1, i + 1); - int ret = network_listen(&engine->net, lua_tostring(L, -1), - port, flags); + /* Case: string, representing a single address. */ + const char *str = lua_tostring(L, -1); + if (str != NULL) { + kr_log_info(" string\n"); + struct engine *engine = engine_luaget(L); + int ret = network_listen(&engine->net, str, port, flags); if (ret != 0) { - kr_log_info("[system] bind to '%s#%d' %s\n", lua_tostring(L, -1), port, kr_strerror(ret)); + kr_log_info("[system] bind to '%s#%d' %s\n", + str, port, kr_strerror(ret)); } - lua_pop(L, 1); + return ret == 0; } - lua_pushboolean(L, true); + /* Last case: table where all entries are added recursively. */ + if (!lua_istable(L, -1)) { + format_error(L, "bad type for address"); + lua_error(L); + return 0; + } + lua_pushnil(L); + while (lua_next(L, -2)) { + if (net_listen_addrs(L, port, flags) == 0) + return 0; + lua_pop(L, 1); + } return 1; } @@ -210,34 +223,28 @@ static int net_listen(lua_State *L) { /* Check parameters */ int n = lua_gettop(L); + if (n < 1 || n > 3) { + format_error(L, "expected one to three arguments; usage:\n" + "net.listen(addressses, [port = 53, flags = {tls = (port == 853)}])\n"); + lua_error(L); + } + int port = KR_DNS_PORT; if (n > 1 && lua_isnumber(L, 2)) { port = lua_tointeger(L, 2); } + bool tls = (port == KR_DNS_TLS_PORT); if (n > 2 && lua_istable(L, 3)) { tls = table_get_flag(L, 3, "tls", tls); } - - /* Process interface or (address, port, flags) triple. */ int flags = tls ? (NET_TCP|NET_TLS) : (NET_TCP|NET_UDP); - if (lua_istable(L, 1)) { - return net_listen_iface(L, port, flags); - } else if (n < 1 || !lua_isstring(L, 1)) { - format_error(L, "expected 'listen(string addr, number port = 53[, bool tls = false])'"); - lua_error(L); - } - - /* Open resolution context cache */ - struct engine *engine = engine_luaget(L); - int ret = network_listen(&engine->net, lua_tostring(L, 1), port, flags); - if (ret != 0) { - format_error(L, kr_strerror(ret)); - lua_error(L); - } - - lua_pushboolean(L, true); - return 1; + + /* Now focus on the first argument. */ + lua_pop(L, n - 1); + int res = net_listen_addrs(L, port, flags); + lua_pushboolean(L, res); + return res; } /** Close endpoint. */