Merge "Core: Add support for systemd socket activation." into 15

This commit is contained in:
Jenkins2
2017-07-26 08:59:58 -05:00
committed by Gerrit Code Review
13 changed files with 384 additions and 3 deletions

View File

@@ -350,6 +350,7 @@ struct ast_eid ast_eid_default;
char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
static int ast_socket_is_sd = 0; /*!< Is socket activation responsible for ast_socket? */
static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
pid_t ast_mainpid;
struct console {
@@ -1576,8 +1577,16 @@ static int ast_makesocket(void)
uid_t uid = -1;
gid_t gid = -1;
for (x = 0; x < AST_MAX_CONNECTS; x++)
for (x = 0; x < AST_MAX_CONNECTS; x++) {
consoles[x].fd = -1;
}
if (ast_socket_is_sd) {
ast_socket = ast_sd_get_fd_un(SOCK_STREAM, ast_config_AST_SOCKET);
goto start_lthread;
}
unlink(ast_config_AST_SOCKET);
ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
if (ast_socket < 0) {
@@ -1602,12 +1611,19 @@ static int ast_makesocket(void)
return -1;
}
start_lthread:
if (ast_pthread_create_background(&lthread, NULL, listener, NULL)) {
ast_log(LOG_WARNING, "Unable to create listener thread.\n");
close(ast_socket);
return -1;
}
if (ast_socket_is_sd) {
/* owner/group/permissions are set by systemd, we might not even have access
* to socket file so leave it alone */
return 0;
}
if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
struct passwd *pw;
if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
@@ -2075,7 +2091,9 @@ static void really_quit(int num, shutdown_nice_t niceness, int restart)
pthread_cancel(lthread);
close(ast_socket);
ast_socket = -1;
unlink(ast_config_AST_SOCKET);
if (!ast_socket_is_sd) {
unlink(ast_config_AST_SOCKET);
}
pthread_kill(lthread, SIGURG);
pthread_join(lthread, NULL);
}
@@ -4319,7 +4337,12 @@ int main(int argc, char *argv[])
/* Initial value of the maximum active system verbosity level. */
ast_verb_sys_level = option_verbose;
if (ast_tryconnect()) {
if (ast_sd_get_fd_un(SOCK_STREAM, ast_config_AST_SOCKET) > 0) {
ast_socket_is_sd = 1;
}
/* DO NOT perform check for existing daemon if systemd has CLI socket activation */
if (!ast_socket_is_sd && ast_tryconnect()) {
/* One is already running */
if (ast_opt_remote) {
multi_thread_safe = 1;

View File

@@ -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;
}

View File

@@ -40,6 +40,7 @@
#include "asterisk/compat.h"
#include "asterisk/tcptls.h"
#include "asterisk/io.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
@@ -618,6 +619,7 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
int flags;
int x = 1;
int tls_changed = 0;
int sd_socket;
if (desc->tls_cfg) {
char hash[41];
@@ -689,6 +691,19 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
pthread_join(desc->master, NULL);
}
sd_socket = ast_sd_get_fd(SOCK_STREAM, &desc->local_address);
if (sd_socket != -1) {
if (desc->accept_fd != sd_socket) {
if (desc->accept_fd != -1) {
close(desc->accept_fd);
}
desc->accept_fd = sd_socket;
}
goto systemd_socket_activation;
}
if (desc->accept_fd != -1) {
close(desc->accept_fd);
}
@@ -718,6 +733,8 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name);
goto error;
}
systemd_socket_activation:
flags = fcntl(desc->accept_fd, F_GETFL);
fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {