Commit 57297d08 authored by Vladimír Čunát's avatar Vladimír Čunát

lua net.list(): change output and docs

Now we hopefully won't need to touch it for a long time.
parent 047ace4d
......@@ -23,7 +23,7 @@
#include <stdlib.h>
/** Append 'addr = {port = int, udp = bool, tcp = bool}' */
/** Table and next index on top of stack -> append entries for given endpoint_array_t. */
static int net_list_add(const char *key, void *val, void *ext)
{
lua_State *L = (lua_State *)ext;
......@@ -33,46 +33,58 @@ static int net_list_add(const char *key, void *val, void *ext)
struct endpoint *ep = &ep_array->at[j];
lua_newtable(L); // connection tuple
lua_pushstring(L, key);
lua_setfield(L, -2, "ip");
if (ep->flags.kind) {
lua_pushstring(L, ep->flags.kind);
} else if (ep->flags.tls) {
lua_pushliteral(L, "tls");
} else {
lua_pushliteral(L, "dns");
}
lua_setfield(L, -2, "kind");
lua_newtable(L); // "transport" table
switch (ep->flags.sock_type) {
case SOCK_DGRAM:
lua_pushliteral(L, "udp");
lua_setfield(L, -2, "protocol");
lua_pushinteger(L, ep->port);
lua_setfield(L, -2, "port");
lua_pushliteral(L, "none");
lua_setfield(L, -2, "security");
switch (ep->family) {
case AF_INET:
lua_pushliteral(L, "inet4");
break;
case SOCK_STREAM:
lua_pushliteral(L, "tcp");
lua_setfield(L, -2, "protocol");
lua_pushinteger(L, ep->port);
lua_setfield(L, -2, "port");
if (ep->flags.tls) {
lua_pushliteral(L, "tls");
} else {
lua_pushliteral(L, "none");
}
lua_setfield(L, -2, "security");
case AF_INET6:
lua_pushliteral(L, "inet6");
break;
case AF_UNIX:
lua_pushliteral(L, "unix");
break;
default:
lua_pushliteral(L, "invalid");
assert(!EINVAL);
lua_pushliteral(L, "unknown");
lua_setfield(L, -2, "protocol");
}
lua_setfield(L, -2, "transport");
lua_setfield(L, -2, "family");
lua_newtable(L); // "application" table
if (ep->flags.kind) {
lua_pushstring(L, ep->flags.kind);
lua_pushstring(L, key);
if (ep->family != AF_UNIX) {
lua_setfield(L, -2, "ip");
} else {
lua_pushliteral(L, "dns");
lua_setfield(L, -2, "path");
}
if (ep->family != AF_UNIX) {
lua_pushinteger(L, ep->port);
lua_setfield(L, -2, "port");
}
if (ep->family == AF_UNIX) {
lua_pushliteral(L, "stream");
} else if (ep->flags.sock_type == SOCK_STREAM) {
lua_pushliteral(L, "tcp");
} else if (ep->flags.sock_type == SOCK_DGRAM) {
lua_pushliteral(L, "udp");
} else {
assert(!EINVAL);
lua_pushliteral(L, "invalid");
}
lua_setfield(L, -2, "protocol");
lua_setfield(L, -2, "application");
lua_setfield(L, -2, "transport");
lua_settable(L, -3);
i++;
......@@ -178,7 +190,7 @@ static int net_listen(lua_State *L)
bool tls = (port == KR_DNS_TLS_PORT);
const char *kind = NULL;
if (n > 2) {
if (n > 2 && !lua_isnil(L, 3)) {
if (!lua_istable(L, 3))
lua_error_p(L, "wrong type of third parameter (table expected)");
tls = table_get_flag(L, 3, "tls", tls);
......
......@@ -136,11 +136,33 @@ configured in the config file.
.. code-block:: none
[127.0.0.1] => {
[port] => 53
[tcp] => true
[udp] => true
}
[1] => {
[kind] => tls
[transport] => {
[family] => inet4
[ip] => 127.0.0.1
[port] => 853
[protocol] => tcp
}
}
[2] => {
[kind] => dns
[transport] => {
[family] => inet6
[ip] => ::1
[port] => 53
[protocol] => udp
}
}
[3] => {
[kind] => dns
[transport] => {
[family] => inet6
[ip] => ::1
[port] => 53
[protocol] => tcp
}
}
.. function:: net.interfaces()
......
......@@ -356,6 +356,7 @@ typedef struct {
struct endpoint {
void *handle;
int fd;
int family;
uint16_t port;
_Bool engaged;
endpoint_flags_t flags;
......
......@@ -40,7 +40,7 @@ void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog)
/** Notify the registered function about endpoint getting open.
* If log_port < 1, don't log it. */
static int endpoint_open_lua_cb(struct network *net, struct endpoint *ep,
const char *log_addr, int log_port)
const char *log_addr)
{
const bool ok = ep->flags.kind && !ep->handle && !ep->engaged && ep->fd != -1;
if (!ok) {
......@@ -55,8 +55,8 @@ static int endpoint_open_lua_cb(struct network *net, struct endpoint *ep,
if (!pp && net->missing_kind_is_error) {
kr_log_error("warning: network socket kind '%s' not handled when opening '%s",
ep->flags.kind, log_addr);
if (log_port >= 0)
kr_log_error("#%d", log_port);
if (ep->family != AF_UNIX)
kr_log_error("#%d", ep->port);
kr_log_error("'. Likely causes: typo or not loading 'http' module.\n");
/* No hard error, for now. LATER: perhaps differentiate between
* explicit net.listen() calls and "just unused" systemd sockets.
......@@ -70,10 +70,10 @@ static int endpoint_open_lua_cb(struct network *net, struct endpoint *ep,
lua_rawgeti(L, LUA_REGISTRYINDEX, fun_id);
lua_pushboolean(L, true /* open */);
lua_pushpointer(L, ep);
if (log_port < 0) {
if (ep->family == AF_UNIX) {
lua_pushstring(L, log_addr);
} else {
lua_pushfstring(L, "%s#%d", log_addr, log_port);
lua_pushfstring(L, "%s#%d", log_addr, ep->port);
}
if (lua_pcall(L, 3, 0, 0)) {
kr_log_error("error opening %s: %s\n", log_addr, lua_tostring(L, -1));
......@@ -90,7 +90,7 @@ static int engage_endpoint_array(const char *key, void *endpoints, void *net)
struct endpoint *ep = &eps->at[i];
const bool match = !ep->engaged && ep->flags.kind;
if (!match) continue;
int ret = endpoint_open_lua_cb(net, ep, key, ep->port);
int ret = endpoint_open_lua_cb(net, ep, key);
if (ret) return ret;
}
return 0;
......@@ -238,10 +238,9 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin
/** Open endpoint protocols. ep->flags were pre-set. */
static int open_endpoint(struct network *net, struct endpoint *ep,
const struct sockaddr *sa, int fd,
const char *log_addr, uint16_t log_port)
const struct sockaddr *sa, const char *log_addr)
{
if ((sa != NULL) == (fd != -1)) {
if ((sa != NULL) == (ep->fd != -1)) {
assert(!EINVAL);
return kr_error(EINVAL);
}
......@@ -250,13 +249,12 @@ static int open_endpoint(struct network *net, struct endpoint *ep,
}
if (sa) {
fd = io_bind(sa, ep->flags.sock_type);
if (fd < 0) return fd;
ep->fd = io_bind(sa, ep->flags.sock_type);
if (ep->fd < 0) return ep->fd;
}
ep->fd = fd;
if (ep->flags.kind) {
/* This EP isn't to be managed internally after binding. */
return endpoint_open_lua_cb(net, ep, log_addr, log_port);
return endpoint_open_lua_cb(net, ep, log_addr);
} else {
ep->engaged = true;
/* .engaged seems not really meaningful with .kind == NULL, but... */
......@@ -272,7 +270,7 @@ static int open_endpoint(struct network *net, struct endpoint *ep,
if (!ep->handle) {
return kr_error(ENOMEM);
}
return io_listen_udp(net->loop, ep_handle, fd);
return io_listen_udp(net->loop, ep_handle, ep->fd);
} /* else */
if (ep->flags.sock_type == SOCK_STREAM) {
......@@ -281,7 +279,8 @@ static int open_endpoint(struct network *net, struct endpoint *ep,
if (!ep->handle) {
return kr_error(ENOMEM);
}
return io_listen_tcp(net->loop, ep_handle, fd, net->tcp_backlog, ep->flags.tls);
return io_listen_tcp(net->loop, ep_handle, ep->fd,
net->tcp_backlog, ep->flags.tls);
} /* else */
assert(!EINVAL);
......@@ -306,24 +305,18 @@ static struct endpoint * endpoint_get(struct network *net, const char *addr,
return NULL;
}
/** \note pass either sa != NULL xor fd != -1;
* \note ownership of flags.* is taken on success. */
/** \note pass either sa != NULL xor ep.fd != -1;
* \note ownership of ep.flags.* is taken on success. */
static int create_endpoint(struct network *net, const char *addr_str,
uint16_t port, endpoint_flags_t flags,
const struct sockaddr *sa, int fd)
struct endpoint *ep, const struct sockaddr *sa)
{
/* Bind interfaces */
struct endpoint ep = {
.handle = NULL,
.port = port,
.flags = flags,
};
int ret = open_endpoint(net, &ep, sa, fd, addr_str, port);
int ret = open_endpoint(net, ep, sa, addr_str);
if (ret == 0) {
ret = insert_endpoint(net, addr_str, &ep);
ret = insert_endpoint(net, addr_str, ep);
}
if (ret != 0 && ep.handle) {
endpoint_close(net, &ep, false);
if (ret != 0 && ep->handle) {
endpoint_close(net, ep, false);
}
return ret;
}
......@@ -351,21 +344,27 @@ int network_listen_fd(struct network *net, int fd, endpoint_flags_t flags)
if (ret != 0) {
return kr_error(errno);
}
int port = 0;
struct endpoint ep = {
.flags = flags,
.family = ss.ss_family,
.fd = fd,
};
/* Extract address string and port. */
char addr_str[INET6_ADDRSTRLEN]; /* https://tools.ietf.org/html/rfc4291 */
if (ss.ss_family == AF_INET) {
uv_ip4_name((const struct sockaddr_in*)&ss, addr_str, sizeof(addr_str));
port = ntohs(((struct sockaddr_in *)&ss)->sin_port);
ep.port = ntohs(((struct sockaddr_in *)&ss)->sin_port);
} else if (ss.ss_family == AF_INET6) {
uv_ip6_name((const struct sockaddr_in6*)&ss, addr_str, sizeof(addr_str));
port = ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
ep.port = ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
} else {
return kr_error(EAFNOSUPPORT);
}
/* always create endpoint for supervisor supplied fd
* even if addr+port is not unique */
return create_endpoint(net, addr_str, port, flags, NULL, fd);
return create_endpoint(net, addr_str, &ep, NULL);
}
int network_listen(struct network *net, const char *addr, uint16_t port,
......@@ -390,7 +389,13 @@ int network_listen(struct network *net, const char *addr, uint16_t port,
if (ret != 0) {
return ret;
}
return create_endpoint(net, addr, port, flags, &sa.ip, -1);
struct endpoint ep = {
.flags = flags,
.fd = -1,
.port = port,
.family = sa.ip.sa_family,
};
return create_endpoint(net, addr, &ep, &sa.ip);
}
int network_close(struct network *net, const char *addr, int port)
......
......@@ -30,8 +30,8 @@ struct engine;
/** Ways to listen on a socket. */
typedef struct {
int sock_type; /**< SOCK_DGRAM or SOCK_STREAM */
bool tls; /**< only used together with .tcp; TODO: meaningful if kind != NULL? */
int sock_type; /**< SOCK_DGRAM or SOCK_STREAM */
bool tls; /**< only used together with .kind == NULL and .tcp */
const char *kind; /**< tag for other types than the three usual */
} endpoint_flags_t;
......@@ -47,12 +47,15 @@ static inline bool endpoint_flags_eq(endpoint_flags_t f1, endpoint_flags_t f2)
/** Wrapper for a single socket to listen on.
* There are two types: normal have handle, special have flags.kind (and never both).
*
* LATER: .family might be unexpected for IPv4-in-IPv6 addresses.
*/
struct endpoint {
uv_handle_t *handle; /**< uv_udp_t or uv_tcp_t */
int fd;
uint16_t port;
bool engaged; /**< to some module or internally */
uv_handle_t *handle; /**< uv_udp_t or uv_tcp_t; NULL in case flags.kind != NULL */
int fd; /**< POSIX file-descriptor; always used. */
int family; /**< AF_INET or AF_INET6 or (in future) AF_UNIX */
uint16_t port; /**< TCP/UDP port. Meaningless with AF_UNIX. */
bool engaged; /**< to some module or internally */
endpoint_flags_t flags;
};
......@@ -101,7 +104,7 @@ int network_listen(struct network *net, const char *addr, uint16_t port,
/** Start listenting on an open file-descriptor.
* \note flags.sock_type isn't meaningful here.
* \note ownership of flags.* is taken on success.
* \note ownership of flags.* is taken on success. TODO: non-success?
*/
int network_listen_fd(struct network *net, int fd, endpoint_flags_t flags);
......
......@@ -79,7 +79,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -50,7 +50,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -51,7 +51,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -49,7 +49,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -49,7 +49,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -49,7 +49,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -99,7 +99,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -44,7 +44,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -53,7 +53,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
......@@ -55,7 +55,7 @@ assert(cache.backends() ~= nil)
assert(worker.stats() ~= nil)
assert(net.interfaces() ~= nil)
-- Self-checks on loaded stuff
assert(net.list()[1].ip == '{{SELF_ADDR}}')
assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
assert(#modules.list() > 0)
-- Self-check timers
ev = event.recurrent(1 * sec, function (ev) return 1 end)
......
Subproject commit 6edfef4f65e846f3aef0cbf3b80e88f39658a1c9
Subproject commit 947858cb649a4d477c93441ca96d894f0e545e4a
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment