diff options
author | Corey Farrell <git@cfware.com> | 2017-06-18 20:24:04 -0400 |
---|---|---|
committer | Corey Farrell <git@cfware.com> | 2017-07-21 14:04:33 -0500 |
commit | eea9da2f42c23fae72bb5b67c51dd38ab3a92a8d (patch) | |
tree | e0e69955214e682e2e4550cb8c6298c5adc147b3 /main/io.c | |
parent | 7fcb730997a54fd58a2edf47489f464c34c6e156 (diff) |
Core: Add support for systemd socket activation.
This change adds support for socket activation of certain SOCK_STREAM
listeners in Asterisk:
* AMI / AMI over TLS
* CLI
* HTTP / HTTPS
Example systemd units are provided. This support extends to any socket
which is initialized using ast_tcptls_server_start, so any unknown
modules using this function will support socket activation.
Asterisk continues to function as normal if socket activation is not
enabled or if systemd development headers are not available during
build.
ASTERISK-27063 #close
Change-Id: Id814ee6a892f4b80d018365c8ad8d89063474f4d
Diffstat (limited to 'main/io.c')
-rw-r--r-- | main/io.c | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -36,6 +36,10 @@ #include "asterisk/utils.h" #ifdef HAVE_SYSTEMD #include <systemd/sd-daemon.h> + +#ifndef SD_LISTEN_FDS_START +#define SD_LISTEN_FDS_START 3 +#endif #endif #ifdef DEBUG_IO @@ -392,3 +396,73 @@ int ast_sd_notify(const char *state) { return 0; #endif } + +/*! + * \internal \brief Check the type and sockaddr of a file descriptor. + * \param fd File Descriptor to check. + * \param type SOCK_STREAM or SOCK_DGRAM + * \param addr The socket address to match. + * \retval 0 if matching + * \retval -1 if not matching + */ +#ifdef HAVE_SYSTEMD +static int ast_sd_is_socket_sockaddr(int fd, int type, const struct ast_sockaddr* addr) +{ + int canretry = 1; + struct ast_sockaddr fd_addr; + struct sockaddr ss; + socklen_t ss_len; + + if (sd_is_socket(fd, AF_UNSPEC, type, 1) <= 0) { + return -1; + } + +doretry: + if (getsockname(fd, &ss, &ss_len) != 0) { + return -1; + } + + if (ss.sa_family == AF_UNSPEC && canretry) { + /* An unknown bug can cause silent failure from + * the first call to getsockname. */ + canretry = 0; + goto doretry; + } + + ast_sockaddr_copy_sockaddr(&fd_addr, &ss, ss_len); + + return ast_sockaddr_cmp(addr, &fd_addr); +} +#endif + +int ast_sd_get_fd(int type, const struct ast_sockaddr *addr) +{ +#ifdef HAVE_SYSTEMD + int count = sd_listen_fds(0); + int idx; + + for (idx = 0; idx < count; idx++) { + if (!ast_sd_is_socket_sockaddr(idx + SD_LISTEN_FDS_START, type, addr)) { + return idx + SD_LISTEN_FDS_START; + } + } +#endif + + return -1; +} + +int ast_sd_get_fd_un(int type, const char *path) +{ +#ifdef HAVE_SYSTEMD + int count = sd_listen_fds(0); + int idx; + + for (idx = 0; idx < count; idx++) { + if (sd_is_socket_unix(idx + SD_LISTEN_FDS_START, type, 1, path, 0) > 0) { + return idx + SD_LISTEN_FDS_START; + } + } +#endif + + return -1; +} |