Commit 9db469c9 authored by Marek Vavruša's avatar Marek Vavruša

daemon/network: fixed early free with async close

parent 46b53293
......@@ -66,9 +66,8 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
mp_flush(worker->pkt_pool.ctx);
}
int udp_bind(struct endpoint *ep, struct sockaddr *addr)
int udp_bind(uv_udp_t *handle, struct sockaddr *addr)
{
uv_udp_t *handle = &ep->udp;
unsigned flags = UV_UDP_REUSEADDR;
if (addr->sa_family == AF_INET6) {
flags |= UV_UDP_IPV6ONLY;
......@@ -82,12 +81,6 @@ int udp_bind(struct endpoint *ep, struct sockaddr *addr)
return io_start_read((uv_handle_t *)handle);
}
void udp_unbind(struct endpoint *ep)
{
uv_udp_t *handle = &ep->udp;
uv_close((uv_handle_t *)handle, NULL);
}
static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
uv_loop_t *loop = handle->loop;
......@@ -143,9 +136,8 @@ static void tcp_accept(uv_stream_t *master, int status)
io_start_read((uv_handle_t *)client);
}
int tcp_bind(struct endpoint *ep, struct sockaddr *addr)
int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr)
{
uv_tcp_t *handle = &ep->tcp;
unsigned flags = UV_UDP_REUSEADDR;
if (addr->sa_family == AF_INET6) {
flags |= UV_UDP_IPV6ONLY;
......@@ -157,7 +149,6 @@ int tcp_bind(struct endpoint *ep, struct sockaddr *addr)
ret = uv_listen((uv_stream_t *)handle, 16, tcp_accept);
if (ret != 0) {
tcp_unbind(ep);
return ret;
}
......@@ -165,11 +156,6 @@ int tcp_bind(struct endpoint *ep, struct sockaddr *addr)
return 0;
}
void tcp_unbind(struct endpoint *ep)
{
uv_close((uv_handle_t *)&ep->tcp, NULL);
}
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type)
{
if (type == SOCK_DGRAM) {
......
......@@ -19,11 +19,8 @@
#include <uv.h>
#include <libknot/packet/pkt.h>
struct endpoint;
int udp_bind(struct endpoint *ep, struct sockaddr *addr);
void udp_unbind(struct endpoint *ep);
int tcp_bind(struct endpoint *ep, struct sockaddr *addr);
void tcp_unbind(struct endpoint *ep);
int udp_bind(uv_udp_t *handle, struct sockaddr *addr);
int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr);
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type);
int io_start_read(uv_handle_t *handle);
int io_stop_read(uv_handle_t *handle);
\ No newline at end of file
......@@ -36,20 +36,36 @@
void network_init(struct network *net, uv_loop_t *loop)
{
if (net != NULL) {
/* No multiplexing now, I/O in single thread. */
net->loop = loop;
net->endpoints = map_make();
}
}
/** Close endpoint protocols. */
static int close_endpoint(struct endpoint *ep)
static void free_handle(uv_handle_t *handle)
{
if (ep->flags & NET_UDP) {
udp_unbind(ep);
free(handle);
}
static void close_handle(uv_handle_t *handle, bool force)
{
if (force) { /* Force close if event loop isn't running. */
uv_os_fd_t fd = 0;
if (uv_fileno(handle, &fd) == 0) {
close(fd);
}
free_handle(handle);
} else { /* Asynchronous close */
uv_close(handle, free_handle);
}
}
static int close_endpoint(struct endpoint *ep, bool force)
{
if (ep->udp) {
close_handle((uv_handle_t *)ep->udp, force);
}
if (ep->flags & NET_TCP) {
tcp_unbind(ep);
if (ep->tcp) {
close_handle((uv_handle_t *)ep->tcp, force);
}
free(ep);
......@@ -57,12 +73,11 @@ static int close_endpoint(struct endpoint *ep)
}
/** Endpoint visitor (see @file map.h) */
static int visit_key(const char *key, void *val, void *ext)
static int close_key(const char *key, void *val, void *ext)
{
int (*callback)(struct endpoint *) = ext;
endpoint_array_t *ep_array = val;
for (size_t i = ep_array->len; i--;) {
callback(ep_array->at[i]);
close_endpoint(ep_array->at[i], true);
}
return 0;
}
......@@ -78,7 +93,7 @@ static int free_key(const char *key, void *val, void *ext)
void network_deinit(struct network *net)
{
if (net != NULL) {
map_walk(&net->endpoints, visit_key, close_endpoint);
map_walk(&net->endpoints, close_key, 0);
map_walk(&net->endpoints, free_key, 0);
map_clear(&net->endpoints);
}
......@@ -111,16 +126,24 @@ static int insert_endpoint(struct network *net, const char *addr, struct endpoin
static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags)
{
if (flags & NET_UDP) {
handle_init(udp, net->loop, &ep->udp, sa->sa_family);
int ret = udp_bind(ep, sa);
ep->udp = malloc(sizeof(*ep->udp));
if (!ep->udp) {
return kr_error(ENOMEM);
}
handle_init(udp, net->loop, ep->udp, sa->sa_family);
int ret = udp_bind(ep->udp, sa);
if (ret != 0) {
return ret;
}
ep->flags |= NET_UDP;
}
if (flags & NET_TCP) {
handle_init(tcp, net->loop, &ep->tcp, sa->sa_family);
int ret = tcp_bind(ep, sa);
ep->tcp = malloc(sizeof(*ep->tcp));
if (!ep->tcp) {
return kr_error(ENOMEM);
}
handle_init(tcp, net->loop, ep->tcp, sa->sa_family);
int ret = tcp_bind(ep->tcp, sa);
if (ret != 0) {
return ret;
}
......@@ -135,6 +158,11 @@ int network_listen(struct network *net, const char *addr, uint16_t port, uint32_
return kr_error(EINVAL);
}
/* Already listening */
if (map_get(&net->endpoints, addr)) {
return kr_ok();
}
/* Parse address. */
int ret = 0;
struct sockaddr_storage sa;
......@@ -157,7 +185,7 @@ int network_listen(struct network *net, const char *addr, uint16_t port, uint32_
ret = insert_endpoint(net, addr, ep);
}
if (ret != 0) {
close_endpoint(ep);
close_endpoint(ep, false);
}
return ret;
......@@ -174,7 +202,7 @@ int network_close(struct network *net, const char *addr, uint16_t port)
for (size_t i = ep_array->len; i--;) {
struct endpoint *ep = ep_array->at[i];
if (ep->port == port) {
close_endpoint(ep);
close_endpoint(ep, false);
array_del(*ep_array, i);
break;
}
......
......@@ -28,8 +28,8 @@ enum endpoint_flag {
};
struct endpoint {
uv_udp_t udp;
uv_tcp_t tcp;
uv_udp_t *udp;
uv_tcp_t *tcp;
uint16_t port;
uint16_t flags;
};
......
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