[PATCH 1/1] evio: allow not only SOCK_STREAM servers
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Mon Dec 17 14:55:44 MSK 2018
evio is a useful tool for creating servers. Evio sets
all necessary flags, retries bind, parses URI. But it
does not work with SOCK_DGRAM sockets - SOCK_STREAM is
hardcoded. SWIM is going to use SOCK_DGRAM, and this
patch makes it possible to bind datagram sockets.
Needed for #3234
---
https://github.com/tarantool/tarantool/tree/gerold103/gh-3234-swim-second-preparation
https://github.com/tarantool/tarantool/issues/3234
src/box/iproto.cc | 4 ++--
src/coio.cc | 4 ++--
src/evio.c | 48 +++++++++++++++++++++++++++++++++++------------
src/evio.h | 19 ++++++++++++++++---
4 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 223469f22..157789384 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -1873,8 +1873,8 @@ net_cord_f(va_list /* ap */)
mempool_create(&iproto_connection_pool, &cord()->slabc,
sizeof(struct iproto_connection));
- evio_service_init(loop(), &binary, "binary",
- iproto_on_accept, NULL);
+ evio_service_init_tcp(loop(), &binary, "binary", iproto_on_accept,
+ NULL);
/* Init statistics counter */
diff --git a/src/coio.cc b/src/coio.cc
index 6b94cf2a6..30d18ab3c 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -632,8 +632,8 @@ void
coio_service_init(struct coio_service *service, const char *name,
fiber_func handler, void *handler_param)
{
- evio_service_init(loop(), &service->evio_service, name,
- coio_service_on_accept, service);
+ evio_service_init_tcp(loop(), &service->evio_service, name,
+ coio_service_on_accept, service);
service->handler = handler;
service->handler_param = handler_param;
}
diff --git a/src/evio.c b/src/evio.c
index 9ca14c45c..c16fc99db 100644
--- a/src/evio.c
+++ b/src/evio.c
@@ -209,7 +209,8 @@ evio_service_accept_cb(ev_loop *loop, ev_io *watcher, int events)
static int
evio_service_reuse_addr(struct evio_service *service, int fd)
{
- if ((service->addr.sa_family != AF_UNIX) || (errno != EADDRINUSE)) {
+ if (service->addr.sa_family != AF_UNIX || errno != EADDRINUSE ||
+ service->sock_type != SOCK_STREAM) {
diag_set(SocketError, sio_socketname(fd),
"evio_service_reuse_addr");
return -1;
@@ -248,13 +249,13 @@ evio_service_bind_addr(struct evio_service *service)
say_debug("%s: binding to %s...", evio_service_name(service),
sio_strfaddr(&service->addr, service->addr_len));
/* Create a socket. */
- int fd = sio_socket(service->addr.sa_family,
- SOCK_STREAM, IPPROTO_TCP);
+ int fd = sio_socket(service->addr.sa_family, service->sock_type,
+ service->sock_protocol);
if (fd < 0)
return -1;
if (evio_setsockopt_server(fd, service->addr.sa_family,
- SOCK_STREAM) != 0)
+ service->sock_type) != 0)
goto error;
if (sio_bind(fd, &service->addr, service->addr_len)) {
@@ -282,6 +283,12 @@ error:
return -1;
}
+void
+evio_service_start(struct evio_service *service)
+{
+ ev_io_start(service->loop, &service->ev);
+}
+
/**
* Listen on bounded port.
*
@@ -306,30 +313,47 @@ evio_service_listen(struct evio_service *service)
}
return -1;
}
- ev_io_start(service->loop, &service->ev);
+ evio_service_start(service);
return 0;
}
-void
+static void
evio_service_init(ev_loop *loop, struct evio_service *service, const char *name,
- evio_accept_f on_accept, void *on_accept_param)
+ int sock_type, int sock_protocol)
{
memset(service, 0, sizeof(struct evio_service));
snprintf(service->name, sizeof(service->name), "%s", name);
service->loop = loop;
-
- service->on_accept = on_accept;
- service->on_accept_param = on_accept_param;
+ service->sock_type = sock_type;
+ service->sock_protocol = sock_protocol;
/*
* Initialize libev objects to be able to detect if they
* are active or not in evio_service_stop().
*/
- ev_init(&service->ev, evio_service_accept_cb);
ev_io_set(&service->ev, -1, 0);
service->ev.data = service;
}
+void
+evio_service_init_udp(ev_loop *loop, struct evio_service *service,
+ const char *name, evio_input_f on_input)
+{
+ evio_service_init(loop, service, name, SOCK_DGRAM, IPPROTO_UDP);
+ ev_init(&service->ev, on_input);
+}
+
+void
+evio_service_init_tcp(ev_loop *loop, struct evio_service *service,
+ const char *name, evio_accept_f on_accept,
+ void *on_accept_param)
+{
+ evio_service_init(loop, service, name, SOCK_STREAM, IPPROTO_TCP);
+ service->on_accept = on_accept;
+ service->on_accept_param = on_accept_param;
+ ev_init(&service->ev, evio_service_accept_cb);
+}
+
/**
* Try to bind.
*/
@@ -366,7 +390,7 @@ evio_service_bind(struct evio_service *service, const char *uri)
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
+ hints.ai_socktype = service->sock_type;
hints.ai_flags = AI_PASSIVE|AI_ADDRCONFIG;
/* make no difference between empty string and NULL for host */
diff --git a/src/evio.h b/src/evio.h
index 69d641a60..826b6bb31 100644
--- a/src/evio.h
+++ b/src/evio.h
@@ -72,6 +72,8 @@ struct evio_service;
typedef int (*evio_accept_f)(struct evio_service *, int, struct sockaddr *,
socklen_t);
+typedef void (*evio_input_f)(struct ev_loop *, struct ev_io *, int);
+
struct evio_service
{
/** Service name. E.g. 'primary', 'secondary', etc. */
@@ -86,7 +88,9 @@ struct evio_service
struct sockaddr_storage addrstorage;
};
socklen_t addr_len;
-
+ /** Socket type (STREAM/DGRAM) and protocol (TCP/UDP). */
+ int sock_type;
+ int sock_protocol;
/**
* A callback invoked on every accepted client socket.
* If a callback returned != 0, the accepted socket is
@@ -102,8 +106,13 @@ struct evio_service
/** Initialize the service. Don't bind to the port yet. */
void
-evio_service_init(ev_loop *loop, struct evio_service *service, const char *name,
- evio_accept_f on_accept, void *on_accept_param);
+evio_service_init_tcp(ev_loop *loop, struct evio_service *service,
+ const char *name, evio_accept_f on_accept,
+ void *on_accept_param);
+
+void
+evio_service_init_udp(ev_loop *loop, struct evio_service *service,
+ const char *name, evio_input_f on_input);
/** Bind service to specified uri */
int
@@ -117,6 +126,10 @@ evio_service_bind(struct evio_service *service, const char *uri);
int
evio_service_listen(struct evio_service *service);
+/** Run IO event loop. */
+void
+evio_service_start(struct evio_service *service);
+
/** If started, stop event flow and close the acceptor socket. */
void
evio_service_stop(struct evio_service *service);
--
2.17.2 (Apple Git-113)
More information about the Tarantool-patches
mailing list