From 9176271492a7e46305ab95e5e9cf87687c38956c Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Sun, 10 Mar 2013 15:49:54 +0900 Subject: [PATCH] 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 | 81 +++++++++++++++++++------- src/lib/ecore_con/ecore_con_private.h | 5 ++ 7 files changed, 155 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 129e551a20..719dfc99dc 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 08ce5debe2..2729d5c34b 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 79d562b4f1..d43be7bed3 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 78225a32ba..3eec770667 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 eac019edc3..b4da4578f6 100644 --- a/src/lib/ecore_con/ecore_con.c +++ b/src/lib/ecore_con/ecore_con.c @@ -15,6 +15,10 @@ #include #include +#ifdef HAVE_SYSTEMD +# include +#endif + #ifdef HAVE_WS2TCPIP_H # include #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 2ca00d0529..fc2063aa3b 100644 --- a/src/lib/ecore_con/ecore_con_local.c +++ b/src/lib/ecore_con/ecore_con_local.c @@ -13,6 +13,10 @@ #include #include +#ifdef HAVE_SYSTEMD +# include +#endif + #ifdef HAVE_WS2TCPIP_H # include #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,6 +254,57 @@ ecore_con_local_listen( pmode = umask(mask); start: + 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", + svr->name); + /* first char null indicates abstract namespace */ + socket_unix.sun_path[0] = '\0'; + socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, + svr->name); +#else + ERR("Your system does not support abstract sockets!"); + goto error_umask; +#endif + } + 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; @@ -265,28 +321,6 @@ start: sizeof(struct linger)) < 0) goto error_umask; - socket_unix.sun_family = AF_UNIX; - if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT) - { -#ifdef HAVE_ABSTRACT_SOCKETS - /* . is a placeholder */ - snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s", - svr->name); - /* first char null indicates abstract namespace */ - socket_unix.sun_path[0] = '\0'; - socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, - svr->name); -#else - ERR("Your system does not support abstract sockets!"); - goto error_umask; -#endif - } - else - { - strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path)); - socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix); - } - 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 2c988d88f2..bdd7d961d6 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);