From 79c0fd8c50a4dc3431f9d7eda54ef9d5a8f13839 Mon Sep 17 00:00:00 2001 From: Matthieu Le Guellaut Date: Mon, 4 Jun 2018 11:01:03 -0400 Subject: [PATCH] libevent: add UNIX domain socket support to libevent MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Matthieu Le Guellaut Signed-off-by: Alexis Laferrière --- lib/libevent/libevent.nit | 49 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/lib/libevent/libevent.nit b/lib/libevent/libevent.nit index ff10b05..c6faf22 100644 --- a/lib/libevent/libevent.nit +++ b/lib/libevent/libevent.nit @@ -2,6 +2,7 @@ # # Copyright 2013 Jean-Philippe Caissy # Copyright 2014 Alexis Laferrière +# Copyright 2018 Matthieu Le Guellaut # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -38,6 +39,8 @@ in "C" `{ #include #include #include + #include + #include // Protect callbacks for compatibility with light FFI #ifdef Connection_decr_ref @@ -421,7 +424,7 @@ extern class ConnectionListener `{ struct evconnlistener * `} private new bind_to(base: NativeEventBase, address: CString, port: Int, factory: ConnectionFactory) import ConnectionFactory.accept_connection, error_callback `{ - struct sockaddr_in sin; + struct sockaddr_in sin = {0}; struct evconnlistener *listener; ConnectionFactory_incr_ref(factory); @@ -431,7 +434,6 @@ extern class ConnectionListener `{ struct evconnlistener * `} return NULL; } - memset(&sin, 0, sizeof(sin)); sin.sin_family = hostent->h_addrtype; sin.sin_port = htons(port); memcpy( &(sin.sin_addr.s_addr), (const void*)hostent->h_addr, hostent->h_length ); @@ -448,6 +450,27 @@ extern class ConnectionListener `{ struct evconnlistener * `} return listener; `} + private new bind_unix(base: NativeEventBase, file: CString, factory: ConnectionFactory) + import ConnectionFactory.accept_connection, error_callback `{ + + ConnectionFactory_incr_ref(factory); + + struct sockaddr_un sun = {0}; + sun.sun_family = AF_UNIX; + strncpy(sun.sun_path, file, sizeof(sun.sun_path) - 1); + + struct evconnlistener *listener = evconnlistener_new_bind(base, + (evconnlistener_cb)accept_connection_cb, factory, + LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, + (struct sockaddr*)&sun, sizeof(sun)); + if (listener != NULL) { + evconnlistener_set_error_cb(listener, + (evconnlistener_errorcb)ConnectionListener_error_callback); + } + + return listener; + `} + # Get the `NativeEventBase` associated to `self` fun base: NativeEventBase `{ return evconnlistener_get_base(self); `} @@ -497,6 +520,28 @@ class ConnectionFactory if listener.address_is_null then sys.stderr.write "libevent warning: Opening {address}:{port} failed\n" end + + return listener + end + + # Listen on a UNIX domain socket for new connections + # + # On new connections, libevent callbacks `spawn_connection`. + fun bind_unix(path: String): nullable ConnectionListener + do + # Delete the socket if it already exists + var stat = path.file_stat + if stat != null and stat.is_sock then path.file_delete + + var listener = new ConnectionListener.bind_unix( + event_base, path.to_cstring, self) + + if listener.address_is_null then + print_error "libevent warning: Opening UNIX domain socket {path} failed, " + + evutil_socket_error_to_string(evutil_socket_error).to_s + return null + end + return listener end -- 1.7.9.5