cedric pushed a commit to branch master.
commit 9176271492a7e46305ab95e5e9cf87687c38956c
Author: Cedric Bail <[email protected]>
Date: Sun Mar 10 15:49:54 2013 +0900
ecore_con: add systemd socket activation.
Be careful, systemd socket activation require you to always order
server socket creation in the same order as defined in the unit file.
This means ecore_con_server_add should always been in the same order
for those of them using systemd socket activation.
---
ChangeLog | 1 +
NEWS | 1 +
configure.ac | 8 ++++
src/lib/ecore_con/Ecore_Con.h | 3 +-
src/lib/ecore_con/ecore_con.c | 82 +++++++++++++++++++++++++++++++++--
src/lib/ecore_con/ecore_con_local.c | 69 ++++++++++++++++++++++-------
src/lib/ecore_con/ecore_con_private.h | 5 +++
7 files changed, 149 insertions(+), 20 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 129e551..719dfc9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
2013-03-10 Cedric Bail
* Eeze: add a dummy implementation of libmount when it is not available.
+ * Ecore_Con: add systemd socket activation support
(ECORE_CON_SOCKET_ACTIVATE).
2013-03-08 Igor Murzov
diff --git a/NEWS b/NEWS
index 08ce5de..2729d5c 100644
--- a/NEWS
+++ b/NEWS
@@ -72,6 +72,7 @@ Additions:
* Ecore_x: Add atom related with indicator type.
* Ecore_x: Add manual render code before deiconify
* Eeze: Add a dummy libmount replacement for when libmount is not there.
+ * Ecore_Con: Add systemd socket activation support
(ECORE_CON_SOCKET_ACTIVATE).
Deprecations:
* ecore_x:
diff --git a/configure.ac b/configure.ac
index 79d562b..d43be7b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1883,21 +1883,26 @@ want_ecore_con_local_sockets="yes"
want_ecore_con_abstract_sockets="yes"
if test "${have_wince}" = "yes"; then
+ want_systemd="no"
want_curl="no"
want_cares="no"
want_ecore_con_local_sockets="no"
want_ecore_con_abstract_sockets="no"
elif test "${have_win32}" = "yes"; then
+ want_systemd="no"
want_cares="yes"
want_ecore_con_abstract_sockets="no"
elif test "${have_darwin}" = "yes"; then
+ want_systemd="no"
want_cares="no"
want_ecore_con_abstract_sockets="no"
elif test "${have_ps3}" = "yes"; then
+ want_systemd="no"
want_cares="no"
want_ecore_con_local_sockets="no"
want_ecore_con_abstract_sockets="no"
else
+ want_systemd="yes"
want_cares="no"
fi
@@ -1934,11 +1939,14 @@ else
ecore_con_resolver="fork"
fi
+EFL_OPTIONAL_DEPEND_PKG([ECORE_CON], [${want_systemd}], [SYSTEMD],
[libsystemd-daemon])
+
EFL_ADD_FEATURE([ECORE_CON], [curl])
EFL_ADD_FEATURE([ECORE_CON], [cares])
EFL_ADD_FEATURE([ECORE_CON], [local-sockets],
[${want_ecore_con_local_sockets}])
EFL_ADD_FEATURE([ECORE_CON], [abstract-sockets],
[${want_ecore_con_abstract_sockets}])
EFL_ADD_FEATURE([ECORE_CON], [resolver], [${ecore_con_resolver}])
+EFL_ADD_FEATURE([ECORE_CON], [systemd-daemon], [${want_systemd}])
EFL_EVAL_PKGS([ECORE_CON])
diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h
index 78225a3..3eec770 100644
--- a/src/lib/ecore_con/Ecore_Con.h
+++ b/src/lib/ecore_con/Ecore_Con.h
@@ -662,7 +662,8 @@ typedef enum _Ecore_Con_Type
* @note Only functional for clients
* @since 1.2
*/
- ECORE_CON_NO_PROXY = (1 << 8)
+ ECORE_CON_NO_PROXY = (1 << 8),
+ ECORE_CON_SOCKET_ACTIVATE = (1 << 9)
} Ecore_Con_Type;
/**
diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
index eac019e..b4da457 100644
--- a/src/lib/ecore_con/ecore_con.c
+++ b/src/lib/ecore_con/ecore_con.c
@@ -15,6 +15,10 @@
#include <arpa/inet.h>
#include <sys/un.h>
+#ifdef HAVE_SYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+
#ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
#endif
@@ -88,6 +92,10 @@ static void _ecore_con_lookup_done(void *data,
static const char * _ecore_con_pretty_ip(struct sockaddr *client_addr);
+#ifdef HAVE_SYSTEMD
+int sd_fd_index = 0;
+int sd_fd_max = 0;
+#endif
void
_ecore_con_client_kill(Ecore_Con_Client *cl)
@@ -158,7 +166,6 @@ ecore_con_init(void)
#ifdef HAVE_EVIL
if (!evil_init())
return --_ecore_con_init_count;
-
#endif
if (!ecore_init())
@@ -197,6 +204,10 @@ ecore_con_init(void)
ecore_con_ssl_init();
ecore_con_info_init();
+#ifdef HAVE_SYSTEMD
+ sd_fd_max = sd_listen_fds(0);
+#endif
+
return _ecore_con_init_count;
}
@@ -1425,6 +1436,45 @@ _ecore_con_cb_tcp_listen(void *data,
goto error;
}
+#ifdef HAVE_SYSTEMD
+ if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
+ {
+ if (sd_is_socket_inet(SD_LISTEN_FDS_START + sd_fd_index,
+ net_info->info.ai_family,
+ net_info->info.ai_socktype,
+ 1,
+ svr->port) <= 0)
+ {
+ ERR("Your systemd unit seems to provide fd in the wrong order for
Socket activation.");
+ goto error;
+ }
+
+ svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
+
+ /* I am wondering if that's really going to work as the bind is already
done */
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+
+ lin.l_onoff = 1;
+ lin.l_linger = 0;
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
+ sizeof(struct linger)) < 0)
+ goto error;
+
+ if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
+ {
+ int flag = 1;
+
+ if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
+ sizeof(int)) < 0)
+ {
+ goto error;
+ }
+ }
+
+ goto fd_ready;
+ }
+#endif
+
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
net_info->info.ai_protocol);
if (svr->fd < 0) goto error;
@@ -1439,7 +1489,7 @@ _ecore_con_cb_tcp_listen(void *data,
if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
{
- int flag = 1;
+ int flag = 1;
if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
sizeof(int)) < 0)
@@ -1453,8 +1503,11 @@ _ecore_con_cb_tcp_listen(void *data,
if (listen(svr->fd, 4096) < 0) goto error;
+#ifdef HAVE_SYSTEMD
+ fd_ready:
+#endif
svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_svr_tcp_handler,
svr, NULL, NULL);
+ _ecore_con_svr_tcp_handler, svr,
NULL, NULL);
if (!svr->fd_handler)
{
memerr = "Memory allocation failure";
@@ -1492,7 +1545,27 @@ _ecore_con_cb_udp_listen(void *data,
svr->delete_me = EINA_TRUE;
goto error;
}
+#ifdef HAVE_SYSTEMD
+ if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
+ {
+ if (sd_is_socket_inet(SD_LISTEN_FDS_START + sd_fd_index,
+ net_info->info.ai_family,
+ net_info->info.ai_socktype,
+ -1,
+ svr->port) <= 0)
+ {
+ ERR("Your systemd unit seems to provide fd in the wrong order for
Socket activation.");
+ goto error;
+ }
+ svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
+
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on,
sizeof(on)) != 0)
+ goto error;
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+ goto fd_ready;
+ }
+#endif
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
net_info->info.ai_protocol);
if (svr->fd < 0) goto error;
@@ -1532,6 +1605,9 @@ _ecore_con_cb_udp_listen(void *data,
if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
goto error;
+#ifdef HAVE_SYSTEMD
+ fd_ready:
+#endif
svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
_ecore_con_svr_udp_handler, svr, NULL, NULL);
diff --git a/src/lib/ecore_con/ecore_con_local.c
b/src/lib/ecore_con/ecore_con_local.c
index 2ca00d0..fc2063a 100644
--- a/src/lib/ecore_con/ecore_con_local.c
+++ b/src/lib/ecore_con/ecore_con_local.c
@@ -13,6 +13,10 @@
#include <sys/socket.h>
#include <sys/un.h>
+#ifdef HAVE_SYSTEMD
+# include <systemd/sd-daemon.h>
+#endif
+
#ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
#endif
@@ -186,6 +190,7 @@ ecore_con_local_listen(
struct stat st;
mode_t mask;
int socket_unix_len;
+ Eina_Bool abstract_socket;
mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
@@ -249,25 +254,10 @@ ecore_con_local_listen(
pmode = umask(mask);
start:
- svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (svr->fd < 0)
- goto error_umask;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
- goto error_umask;
-
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
- goto error_umask;
-
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
- sizeof(struct linger)) < 0)
- goto error_umask;
-
socket_unix.sun_family = AF_UNIX;
if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
{
+ abstract_socket = EINA_TRUE;
#ifdef HAVE_ABSTRACT_SOCKETS
/* . is a placeholder */
snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s",
@@ -283,10 +273,54 @@ start:
}
else
{
+ abstract_socket = EINA_FALSE;
strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
}
+#ifdef HAVE_SYSTEMD
+ if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
+ {
+ if (sd_is_socket_unix(SD_LISTEN_FDS_START + sd_fd_index,
+ SOCK_STREAM, 1,
+ socket_unix.sun_path,
+ abstract_socket ? socket_unix_len : 0) <= 0)
+ {
+ ERR("Your systemd unit seems to provide fd in the wrong order for
Socket activation.");
+ goto error_umask;
+ }
+ svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
+
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
+ goto error_umask;
+
+ lin.l_onoff = 1;
+ lin.l_linger = 0;
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
+ sizeof(struct linger)) < 0)
+ goto error_umask;
+
+ goto fd_ready;
+ }
+#else
+ (void) abstract_socket;
+#endif
+ svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (svr->fd < 0)
+ goto error_umask;
+
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
+ goto error_umask;
+
+ if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
+ goto error_umask;
+
+ lin.l_onoff = 1;
+ lin.l_linger = 0;
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
+ sizeof(struct linger)) < 0)
+ goto error_umask;
+
if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
{
if ((((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) ||
@@ -302,6 +336,9 @@ start:
if (listen(svr->fd, 4096) < 0)
goto error_umask;
+#ifdef HAVE_SYSTEMD
+ fd_ready:
+#endif
svr->path = strdup(buf);
if (!svr->path)
goto error_umask;
diff --git a/src/lib/ecore_con/ecore_con_private.h
b/src/lib/ecore_con/ecore_con_private.h
index 2c988d8..bdd7d96 100644
--- a/src/lib/ecore_con/ecore_con_private.h
+++ b/src/lib/ecore_con/ecore_con_private.h
@@ -270,6 +270,11 @@ struct Ecore_Con_Socks_v5
unsigned int plen;
};
+#ifdef HAVE_SYSTEMD
+extern int sd_fd_index;
+extern int sd_fd_max;
+#endif
+
extern Ecore_Con_Socks *_ecore_con_proxy_once;
extern Ecore_Con_Socks *_ecore_con_proxy_global;
void ecore_con_socks_init(void);
--
------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the
endpoint security space. For insight on selecting the right partner to
tackle endpoint security challenges, access the full report.
http://p.sf.net/sfu/symantec-dev2dev