TIVI-1932: Add support for systemd based socket activation. 84/11684/2 accepted/tizen/ivi accepted/tizen_ivi_panda tizen_3.0.m14.2_ivi tizen_ivi tizen_ivi_panda accepted/tizen/20131104.234709 accepted/tizen/20131111.231336 accepted/tizen/ivi/20140411.012405 accepted/tizen/ivi/panda/20140326.233657 accepted/tizen_ivi_stable/20131119.040243 submit/tizen/20131104.225404 submit/tizen_ivi/20140411.012708 submit/tizen_ivi_panda/20140326.234013 submit/tizen_ivi_stable/20131119.035945 tizen_3.0.m14.2_ivi_release
authorOssama Othman <ossama.othman@intel.com>
Sun, 3 Nov 2013 04:58:47 +0000 (21:58 -0700)
committerOssama Othman <ossama.othman@intel.com>
Sun, 3 Nov 2013 04:59:33 +0000 (21:59 -0700)
Change-Id: Ie54820778780ba858dd6445c9948b7e439c4a77c
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
CMakeLists.txt
configure.ac
lib/Makefile.am
lib/libwebsockets.c
packaging/libwebsockets.spec

index 3f9ebdc..0188cee 100644 (file)
@@ -48,6 +48,7 @@ option(WITHOUT_DEBUG "Don't compile debug related code" OFF)
 option(WITHOUT_EXTENSIONS "Don't compile with extensions" OFF)
 option(WITH_LATENCY "Build latency measuring code into the library" OFF)
 option(WITHOUT_DAEMONIZE "Don't build the daemonization api" OFF)
+option(WITH_SD_DAEMON "Build support for systemd based socket activation" OFF)
 
 if (WITHOUT_CLIENT AND WITHOUT_SERVER)
        message(FATAL_ERROR "Makes no sense to compile without both client or server.")
@@ -357,6 +358,19 @@ set(LIB_LIST)
 #
 
 #
+# SD_DAEMON (Only needed if systemd socket activation is desired.)
+#
+if (WITH_SD_DAEMON)
+       find_package(PkgConfig)
+       pkg_check_modules(SD_DAEMON REQUIRED libsystemd-daemon)
+
+       include_directories(${SD_DAEMON_INCLUDE_DIRS})
+       list(APPEND LIB_LIST ${SD_DAEMON_LIBRARIES})
+       add_definitions(${SD_DAEMON_CFLAGS_OTHER})
+       add_definitions(-DHAVE_SYSTEMD_DAEMON)
+endif()
+
+#
 # ZLIB (Only needed for deflate extensions).
 #
 if (NOT WITHOUT_EXTENSIONS)
index 667cfbf..57866ef 100644 (file)
@@ -19,6 +19,13 @@ AC_PROG_INSTALL
 AC_PROG_MAKE_SET
 AC_CONFIG_MACRO_DIR([m4])
 
+PKG_CHECK_MODULES([SD_DAEMON],
+                  [libsystemd-daemon],
+                  [AC_DEFINE([HAVE_SYSTEMD_DAEMON])],
+                 [AC_MSG_NOTICE([Systemd socket activation won't be enabled])])
+AC_SUBST([SD_DAEMON_LIBS])
+AC_SUBST([SD_DAEMON_CFLAGS])
+
 applyhash='CFLAGS+= -DLWS_LIBRARY_VERSION=\"$(PACKAGE_VERSION)\" -DLWS_BUILD_HASH=\"${shell git log -n 1 --pretty=%h}\"'
 AC_SUBST([applyhash])
 AM_SUBST_NOTMAKE([applyhash])
index e4f9ce0..bd2cb81 100644 (file)
@@ -44,8 +44,9 @@ else
 dist_libwebsockets_la_SOURCES += sha-1.c
 endif
 
-libwebsockets_la_CFLAGS=-Wall -std=gnu99 -pedantic
+libwebsockets_la_CFLAGS=-Wall -std=gnu99 -pedantic $(SD_DAEMON_CFLAGS)
 libwebsockets_la_LDFLAGS=
+libwebsockets_la_LIBADD=$(SD_DAEMON_LIBS)
 
 # uncomment below and use cat ./lib/.libs/*.su | sort -k2g | tac
 # to get a worst-first list of static stack usage if you have gcc 4.6+
index 0c85f0a..796ddcc 100644 (file)
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_SYSTEMD_DAEMON
+#include <systemd/sd-daemon.h>
+#endif  /* HAVE_SYSTEMD_DAEMON */
+
 #ifdef LWS_OPENSSL_SUPPORT
 int openssl_websocket_private_data_index;
 #endif
@@ -2020,55 +2024,89 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
        /* set up our external listening socket we serve on */
 
        if (info->port) {
-               int sockfd;
+               int sockfd = -1;
 
-               sockfd = socket(AF_INET, SOCK_STREAM, 0);
-               if (sockfd < 0) {
-                       lwsl_err("ERROR opening socket\n");
-                       goto bail;
-               }
+#ifdef HAVE_SYSTEMD_DAEMON
+               int const begin = SD_LISTEN_FDS_START;
+               int const end   = begin + sd_listen_fds(0);
+               int fd;
 
-#ifndef WIN32
                /*
-                * allow us to restart even if old sockets in TIME_WAIT
-                * (REUSEADDR on Unix means, "don't hang on to this
-                * address after the listener is closed."  On Windows, though,
-                * it means "don't keep other processes from binding to
-                * this address while we're using it)
+                * Check if we have a systemd activated socket we can
+                * use.  Otherwise explicitly create the socket.
                 */
-               setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+               for (fd = begin; fd < end; ++fd) {
+                       if (sd_is_socket_inet(fd,
+                                       AF_INET,
+                                       SOCK_STREAM,
+                                       1,  // check if in accepting mode
+                                       info->port)) {
+                               sockfd = fd;
+                               lwsl_notice("Systemd socket activation "
+                                           "succeeded.\n");
+                               break;
+                       }
+               }
+
+               if (sockfd == -1) {
+                       if (end > begin) {
+                               lwsl_warn("Systemd socket activation "
+                                         "failed.\n"
+                                         "Creating new socket instead.\n");
+                       }
+#endif /* HAVE_SYSTEMD_DAEMON */
+                       sockfd = socket(AF_INET, SOCK_STREAM, 0);
+                       if (sockfd < 0) {
+                               lwsl_err("ERROR opening socket\n");
+                               goto bail;
+                       }
+
+#ifndef WIN32
+                       /*
+                        * allow us to restart even if old sockets in TIME_WAIT
+                        * (REUSEADDR on Unix means, "don't hang on to this
+                        * address after the listener is closed."  On Windows, though,
+                        * it means "don't keep other processes from binding to
+                        * this address while we're using it)
+                        */
+                       setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
                                              (const void *)&opt, sizeof(opt));
 #endif
 
-               /* Disable Nagle */
-               opt = 1;
-               setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
+                       /* Disable Nagle */
+                       opt = 1;
+                       setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
                                              (const void *)&opt, sizeof(opt));
 
-               #ifdef WIN32
-               opt = 0;
-               ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
-               #else
-               fcntl(sockfd, F_SETFL, O_NONBLOCK);
-               #endif
-
-               bzero((char *) &serv_addr, sizeof(serv_addr));
-               serv_addr.sin_family = AF_INET;
-               if (info->iface == NULL)
-                       serv_addr.sin_addr.s_addr = INADDR_ANY;
-               else
-                       interface_to_sa(info->iface, &serv_addr,
+                       #ifdef WIN32
+                       opt = 0;
+                       ioctlsocket(sockfd, FIONBIO, (unsigned long *)&opt);
+                       #else
+                       fcntl(sockfd, F_SETFL, O_NONBLOCK);
+                       #endif
+
+                       bzero((char *) &serv_addr, sizeof(serv_addr));
+                       serv_addr.sin_family = AF_INET;
+                       if (info->iface == NULL)
+                               serv_addr.sin_addr.s_addr = INADDR_ANY;
+                       else
+                               interface_to_sa(info->iface, &serv_addr,
                                                sizeof(serv_addr));
-               serv_addr.sin_port = htons(info->port);
+                       serv_addr.sin_port = htons(info->port);
 
-               n = bind(sockfd, (struct sockaddr *) &serv_addr,
+                       n = bind(sockfd, (struct sockaddr *) &serv_addr,
                                                             sizeof(serv_addr));
-               if (n < 0) {
-                       lwsl_err("ERROR on binding to port %d (%d %d)\n",
+                       if (n < 0) {
+                               lwsl_err("ERROR on binding to port %d (%d %d)\n",
                                                        info->port, n, errno);
-                       close(sockfd);
-                       goto bail;
+                               close(sockfd);
+                               goto bail;
+                       }
+
+                       listen(sockfd, LWS_SOMAXCONN);
+#ifdef HAVE_SYSTEMD_DAEMON
                }
+#endif /* HAVE_SYSTEMD_DAEMON */
 
                wsi = (struct libwebsocket *)malloc(
                                        sizeof(struct libwebsocket));
@@ -2090,9 +2128,9 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
                context->listen_service_count = 0;
                context->listen_service_fd = sockfd;
 
-               listen(sockfd, LWS_SOMAXCONN);
                lwsl_notice(" Listening on port %d\n", info->port);
        }
+
 #endif
 
        /*
index 8f90a0a..fbfbe26 100644 (file)
@@ -11,6 +11,7 @@ Requires(postun): /sbin/ldconfig
 BuildRequires: zlib-devel
 BuildRequires: openssl-devel
 BuildRequires: cmake
+BuildRequires: pkgconfig(libsystemd-daemon)
 
 %description
 C Websockets Server Library
@@ -28,7 +29,7 @@ Development files needed for building websocket clients and servers
 
 %build
 
-%cmake -DWITH_SSL=On
+%cmake -DWITH_SSL=On -DWITH_SD_DAEMON=ON
 
 make %{?jobs:-j%jobs}