AC_SUBST(FESTIVAL_CXXFLAGS)
AC_SUBST(FESTIVAL_LIBS)
+# Check if systemd socket-based activation was enabled.
+AC_ARG_ENABLE(systemd,
+ [ --enable-systemd enable systemd socket-based activation],
+ [enable_systemd=$enableval], [enable_systemd=no])
+
+if test "$enable_systemd" = "yes"; then
+ PKG_CHECK_MODULES(SYSTEMD, libsystemd-daemon)
+else
+ AC_MSG_NOTICE([systemd support is disabled.])
+fi
+
+if test "$enable_systemd" = "yes"; then
+ AC_DEFINE([SYSTEMD_ENABLED], 1, [Enable systemd socket-based activation ?])
+fi
+
+AM_CONDITIONAL(SYSTEMD_ENABLED, [test "$enable_systemd" = "yes"])
+AC_SUBST(SYSTEMD_CFLAGS)
+AC_SUBST(SYSTEMD_LIBS)
+
# Shave by default.
SHAVE_INIT([build-aux], [enable])
echo "D-Bus support: $enable_dbus"
echo "Sphinx support: $enable_sphinx"
echo "Festival support: $enable_festival"
+echo "systemd socket-based activation: $enable_systemd"
if test "$DUMP_LIB_FLAGS" = "yes"; then
echo "MURPHY_COMMON:"
$(PULSE_CFLAGS) \
$(PULSE_GLIB_CFLAGS) \
$(MURPHY_GLIB_CFLAGS) \
- $(GLIB_CFLAGS)
+ $(GLIB_CFLAGS) \
+ $(SYSTEMD_CFLAGS)
srs_daemon_LDADD = \
$(MURPHY_PULSE_LIBS) \
$(PULSE_GLIB_LIBS) \
$(MURPHY_GLIB_LIBS) \
$(GLIB_LIBS) \
+ $(SYSTEMD_LIBS) \
-ldl
srs_daemon_LDFLAGS = \
#define _GNU_SOURCE
#include <getopt.h>
+#include "srs/config.h"
+
+#ifdef SYSTEMD_ENABLED
+# include <systemd/sd-daemon.h>
+#endif
+
#include <murphy/common/mm.h>
#include <murphy/common/log.h>
" -f, --foreground don't daemonize\n"
" -h, --help show help on usage\n"
" -V, --valgrind[=VALGRIND-PATH] try to run under valgrind\n"
- " -W, --valgrind-full[=VALGRIND-PATH] try to run under valgrind\n",
+#ifdef SYSTEMD_ENABLED
+ " -S, --sockets=var1[,var2...] set sockets in by systemd\n"
+#endif
+,
argv0, cfg, plg);
if (exit_code < 0)
}
+static int set_passed_sockets(srs_context_t *srs, const char *variables)
+{
+#ifdef SYSTEMD_ENABLED
+ const char *b, *e;
+ char key[256], val[64];
+ int nfd, i, n;
+ size_t len;
+
+ nfd = sd_listen_fds(0);
+
+ if (nfd <= 0)
+ return nfd;
+
+ i = 0;
+ b = variables;
+ while (b && *b) {
+ while (*b == ',' || *b == ' ' || *b == '\t')
+ b++;
+
+ if (!*b)
+ return 0;
+
+ if (i >= nfd)
+ return 0;
+
+ if ((e = strchr(b, ',')) != NULL)
+ len = e - b;
+ else
+ len = strlen(b);
+
+ if (len >= sizeof(key)) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ strncpy(key, b, len);
+ key[len] = '\0';
+
+ n = snprintf(val, sizeof(val), "%d", SD_LISTEN_FDS_START + i);
+
+ if (n < 0 || n >= sizeof(val))
+ return -1;
+
+ srs_set_config(srs, key, val);
+
+ b = e;
+ i++;
+ }
+
+ return 0;
+#else
+ errno = EOPNOTSUPP;
+ return -1;
+#endif
+}
+
+
static void config_load_plugins(srs_context_t *srs, char *plugins)
{
char name[PATH_MAX], *p, *n;
void config_parse_cmdline(srs_context_t *srs, int argc, char **argv,
char **envp)
{
-# define OPTIONS "c:P:L:l:t:B:s:fvd:DhV"
+# define OPTIONS "c:P:L:l:t:B:s:fvd:DhS:V"
struct option options[] = {
{ "config-file" , required_argument, NULL, 'c' },
{ "plugin-dir" , required_argument, NULL, 'P' },
{ "list-debug" , no_argument , NULL, 'D' },
{ "foreground" , no_argument , NULL, 'f' },
{ "valgrind" , optional_argument, NULL, 'V' },
+ { "sockets" , required_argument, NULL, 'S' },
{ "help" , no_argument , NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
valgrind(optarg, argc, argv, optind, saved_argc, saved_argv, envp);
break;
+#ifdef SYSTEMD_ENABLED
+ case 'S':
+ SAVE_OPTARG("-S", optarg);
+ set_passed_sockets(srs, optarg);
+ break;
+#endif
+
case 'h':
SAVE_OPT("-h");
help++;
/** Configuration key for specifying the transport address. */
#define CONFIG_ADDRESS "native.address"
+#define CONFIG_SOCKET "native.socket"
/** Default transport address. */
/*#define DEFAULT_ADDRESS "unxs:@/srs/native-client"*/
#define DEFAULT_ADDRESS "tcp4:127.0.0.1:4100"
-
+#define DEFAULT_SOCKET -1
#endif /* __SRS_NATIVE_CLIENT_CONFIG_H__ */
typedef struct {
srs_plugin_t *self; /* our plugin instance */
const char *address; /* our transport address */
+ int sock; /* or existing transport socket */
mrp_transport_t *lt; /* transport we listen on */
mrp_list_hook_t clients; /* connected clients */
int next_id; /* next client id */
mrp_sockaddr_t addr;
socklen_t alen;
const char *type, *opt, *val;
- int flags;
+ int flags, state, sock;
void *typemap;
alen = mrp_transport_resolve(NULL, s->address, &addr, sizeof(addr), &type);
if (alen < 0) {
- mrp_log_error("Failed to resolve transport address '%s'.", s->address);
+ mrp_log_error("Failed to resolve transport address '%s'.",
+ s->address);
goto fail;
}
- flags = MRP_TRANSPORT_REUSEADDR | MRP_TRANSPORT_MODE_NATIVE;
- s->lt = mrp_transport_create(srs->ml, type, &evt, s, flags);
+ flags = MRP_TRANSPORT_REUSEADDR | MRP_TRANSPORT_NONBLOCK | \
+ MRP_TRANSPORT_MODE_NATIVE;
+
+ if (s->sock < 0)
+ s->lt = mrp_transport_create(srs->ml, type, &evt, s, flags);
+ else {
+ state = MRP_TRANSPORT_LISTENED;
+ sock = s->sock;
+ s->lt = mrp_transport_create_from(srs->ml, type, &sock, &evt,
+ s, flags, state);
+ }
if (s->lt == NULL) {
mrp_log_error("Failed to create transport for native clients.");
goto fail;
}
- if (mrp_transport_bind(s->lt, &addr, alen) &&
- mrp_transport_listen(s->lt, 0)) {
- mrp_log_info("Listening on transport '%s'...", s->address);
+ if (s->sock < 0) {
+ if (mrp_transport_bind(s->lt, &addr, alen) &&
+ mrp_transport_listen(s->lt, 0)) {
+ mrp_log_info("Listening on transport '%s'...", s->address);
+
+ return TRUE;
+ }
+ else
+ mrp_log_error("Failed to bind/listen transport.");
+ }
+ else {
+ mrp_log_info("Using passed in socket fd %d...", s->sock);
return TRUE;
}
- else
- mrp_log_error("Failed to bind/listen transport.");
fail:
if (s->lt) {
mrp_debug("configure native client interface plugin");
s->address = srs_get_string_config(cfg, CONFIG_ADDRESS, DEFAULT_ADDRESS);
- mrp_log_info("Using native client transport address: '%s'.", s->address);
+ s->sock = srs_get_int32_config (cfg, CONFIG_SOCKET , DEFAULT_SOCKET);
+
+ if (s->sock < 0)
+ mrp_log_info("Using native client transport: '%s'.", s->address);
+ else
+ mrp_log_info("Using native client socket: %d.", s->sock);
return TRUE;
}