journal-remote.c revision cc64d0175a3c2c974709e9962c00fbe04d74c43f
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen/***
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen This file is part of systemd.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Copyright 2012 Zbigniew Jędrzejewski-Szmek
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen systemd is free software; you can redistribute it and/or modify it
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen under the terms of the GNU Lesser General Public License as published by
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen (at your option) any later version.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen systemd is distributed in the hope that it will be useful, but
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Lesser General Public License for more details.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen You should have received a copy of the GNU Lesser General Public License
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen***/
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <errno.h>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <fcntl.h>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <inttypes.h>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <stdio.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <stdlib.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <string.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <sys/prctl.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <sys/socket.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <sys/stat.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <sys/types.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <unistd.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <getopt.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "sd-daemon.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "sd-event.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "journal-file.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "journald-native.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "socket-util.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "mkdir.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "build.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "macro.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "strv.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "fileio.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "socket-util.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "microhttpd-util.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#ifdef HAVE_GNUTLS
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <gnutls/gnutls.h>
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#endif
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "journal-remote-parse.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include "journal-remote-write.h"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#define REMOTE_JOURNAL_PATH "/var/log/journal/" SD_ID128_FORMAT_STR "/remote-%s.journal"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_output = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_url = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_getter = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic bool arg_stdin = false;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_listen_raw = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_listen_http = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char* arg_listen_https = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int arg_compress = true;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int arg_seal = false;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersenstatic char *key_pem = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char *cert_pem = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic char *trust_pem = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen/**********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************/
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int spawn_child(const char* child, char** argv) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int fd[2];
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen pid_t parent_pid, child_pid;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen if (pipe(fd) < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to create pager pipe: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return -errno;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek parent_pid = getpid();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek child_pid = fork();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (child_pid < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = -errno;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to fork: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek close_pipe(fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
a22e1850c36e52cb9d593b99be59b6ba7639d80aLennart Poettering
a22e1850c36e52cb9d593b99be59b6ba7639d80aLennart Poettering /* In the child */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (child_pid == 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = dup2(fd[1], STDOUT_FILENO);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to dup pipe to stdout: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _exit(EXIT_FAILURE);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = close_pipe(fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_warning("Failed to close pipe fds: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Make sure the child goes away when the parent dies */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _exit(EXIT_FAILURE);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen /* Check whether our parent died before we were able
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen * to set the death signal */
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen if (getppid() != parent_pid)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _exit(EXIT_SUCCESS);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek execvp(child, argv);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to exec child %s: %m", child);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek _exit(EXIT_FAILURE);
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen }
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = close(fd[1]);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_warning("Failed to close write end of pipe: %m");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return fd[0];
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int spawn_curl(char* url) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek char **argv = STRV_MAKE("curl",
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen "-HAccept: application/vnd.fdo.journal",
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen "--silent",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "--show-error",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = spawn_child("curl", argv);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen log_error("Failed to spawn curl: %m");
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen return r;
5256e00e8b9015dd1a976d647fc71dc7efbd8cf8Tom Gundersen}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int spawn_getter(char *getter, char *url) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek char _cleanup_strv_free_ **words = NULL, **words2 = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(getter);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek words = strv_split_quoted(getter);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!words)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = spawn_child(words[0], words);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to spawn getter %s: %m", getter);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int open_output(Writer *s, const char* url) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek char _cleanup_free_ *name, *output = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek char *c;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek name = strdup(url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!name)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for(c = name; *c; c++) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (*c == '/' || *c == ':' || *c == ' ')
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *c = '~';
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else if (*c == '?') {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *c = '\0';
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek break;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!arg_output) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sd_id128_t machine;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_id128_get_machine(&machine);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("failed to determine machine ID128: %s", strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = asprintf(&output, REMOTE_JOURNAL_PATH,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek SD_ID128_FORMAT_VAL(machine), name);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = is_dir(arg_output);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r > 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = asprintf(&output,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "%s/remote-%s.journal", arg_output, name);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek output = strdup(arg_output);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!output)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = journal_file_open_reliably(output,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek O_RDWR|O_CREAT, 0640,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek arg_compress, arg_seal,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek &s->metrics,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek s->mmap,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek NULL, &s->journal);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to open output journal %s: %s",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek arg_output, strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_info("Opened output file %s", s->journal->path);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/**********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************/
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmektypedef struct MHDDaemonWrapper {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek uint64_t fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek struct MHD_Daemon *daemon;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sd_event_source *event;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek} MHDDaemonWrapper;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmektypedef struct RemoteServer {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek RemoteSource **sources;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ssize_t sources_size;
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek ssize_t active;
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek sd_event *events;
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek sd_event_source *sigterm_event, *sigint_event, *listen_event;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek Writer writer;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek Hashmap *daemons;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek} RemoteServer;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* This should go away as soon as µhttpd allows state to be passed around. */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic RemoteServer *server;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dispatch_raw_source_event(sd_event_source *event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int fd,
56fd6bf795926409b087bce406ea851ad89f9fe8Tom Gundersen uint32_t revents,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void *userdata);
d0d6a4cd70477970812bff0a37e70f66208d7c14Tom Gundersenstatic int dispatch_raw_connection_event(sd_event_source *event,
d0d6a4cd70477970812bff0a37e70f66208d7c14Tom Gundersen int fd,
d0d6a4cd70477970812bff0a37e70f66208d7c14Tom Gundersen uint32_t revents,
d0d6a4cd70477970812bff0a37e70f66208d7c14Tom Gundersen void *userdata);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dispatch_http_event(sd_event_source *event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int fd,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek uint32_t revents,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void *userdata);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int get_source_for_fd(RemoteServer *s, int fd, RemoteSource **source) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(fd >= 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(source);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!GREEDY_REALLOC0_T(s->sources, s->sources_size, fd + 1))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen if (s->sources[fd] == NULL) {
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen s->sources[fd] = new0(RemoteSource, 1);
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen if (!s->sources[fd])
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen return log_oom();
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen s->sources[fd]->fd = -1;
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen s->active++;
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen }
113bfde15f9393fa8bc22cbd839c0bc64e733ee2Tom Gundersen
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *source = s->sources[fd];
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int remove_source(RemoteServer *s, int fd) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek RemoteSource *source;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(fd >= 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(fd < s->sources_size);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek source = s->sources[fd];
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (source) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek source_free(source);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek s->sources[fd] = NULL;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta s->active--;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta }
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta close(fd);
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta return 0;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta}
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rautastatic int add_source(RemoteServer *s, int fd, const char* name) {
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta RemoteSource *source = NULL;
0d4ad91dd4fc831c31a9775b0eadf97fea6cd7f6Alin Rauta char *realname;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(fd >= 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (name) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek realname = strdup(name);
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek if (!realname)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = asprintf(&realname, "fd:%d", fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_debug("Creating source for fd:%d (%s)", fd, name);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = get_source_for_fd(s, fd, &source);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to create source for fd:%d (%s)", fd, name);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(source);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(source->fd < 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek source->fd = fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_event_add_io(s->events, &source->event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek fd, EPOLLIN, dispatch_raw_source_event, s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to register event source for fd:%d: %s",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek fd, strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return 1; /* work to do */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek error:
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek remove_source(s, fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int setup_raw_socket(RemoteServer *s, const char *address) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int fd, r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (fd < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_event_add_io(s->events, &s->listen_event, fd, EPOLLIN,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek dispatch_raw_connection_event, s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek close(fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek s->active ++;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/**********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************/
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic RemoteSource *request_meta(void **connection_cls) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek RemoteSource *source;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(connection_cls);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (*connection_cls)
2972cba11712c3bfbe9fa07d1f3c3c4330127733Nick Owens return *connection_cls;
2972cba11712c3bfbe9fa07d1f3c3c4330127733Nick Owens
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering source = new0(RemoteSource, 1);
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering if (!source)
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering return NULL;
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering source->fd = -1;
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering log_debug("Added RemoteSource as connection metadata %p", source);
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering *connection_cls = source;
2972cba11712c3bfbe9fa07d1f3c3c4330127733Nick Owens return source;
2972cba11712c3bfbe9fa07d1f3c3c4330127733Nick Owens}
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering
e2bccc9d9974eb1290653ecfa3ccfd03c313842bDavid Herrmannstatic void request_meta_free(void *cls,
e2bccc9d9974eb1290653ecfa3ccfd03c313842bDavid Herrmann struct MHD_Connection *connection,
e2bccc9d9974eb1290653ecfa3ccfd03c313842bDavid Herrmann void **connection_cls,
505c5f6de1a5c0afb238a46db94fe3571902cc9dBenedikt Morbach enum MHD_RequestTerminationCode toe) {
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering RemoteSource *s;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(connection_cls);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek s = *connection_cls;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_debug("Cleaning up connection metadata %p", s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek source_free(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *connection_cls = NULL;
5c82dd13e1eef502afcef209a3b14a2100966909Benedikt Morbach}
4046d8361c55c80ab8577aea52523b9e6eab0d0cLennart Poettering
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int process_http_upload(
a46e37cb1225a36a33e8728005693e825cdbc01aSusant Sahani struct MHD_Connection *connection,
a46e37cb1225a36a33e8728005693e825cdbc01aSusant Sahani const char *upload_data,
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering size_t *upload_data_size,
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering RemoteSource *source) {
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering bool finished = false;
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering int r;
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering assert(source);
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering log_debug("request_handler_upload: connection %p, %zu bytes",
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering connection, *upload_data_size);
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering if (*upload_data_size) {
1f0d9695125bf8e66d0e53e37d454755a84899bbLennart Poettering log_info("Received %zu bytes", *upload_data_size);
a46e37cb1225a36a33e8728005693e825cdbc01aSusant Sahani
a46e37cb1225a36a33e8728005693e825cdbc01aSusant Sahani r = push_data(source, upload_data, *upload_data_size);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to store received data of size %zu: %s",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *upload_data_size, strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_oom_internal(connection);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *upload_data_size = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek finished = true;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek while (true) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = process_source(source, &server->writer, arg_compress, arg_seal);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r == -E2BIG)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_warning("Entry too big, skipped");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else if (r == -EAGAIN || r == -EWOULDBLOCK)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek break;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_warning("Failed to process data for connection %p", connection);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_UNPROCESSABLE_ENTITY,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "Processing failed: %s", strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!finished)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return MHD_YES;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* The upload is finished */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (source_non_empty(source)) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_warning("EOF reached with incomplete data");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_EXPECTATION_FAILED,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "Trailing data not processed.");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_ACCEPTED, "OK.\n");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek};
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int request_handler(
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void *cls,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek struct MHD_Connection *connection,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *url,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *method,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *version,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *upload_data,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek size_t *upload_data_size,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void **connection_cls) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *header;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r ,code;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(connection);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(connection_cls);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(method);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_debug("Handling a connection %s %s %s", method, url, version);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (*connection_cls)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return process_http_upload(connection,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek upload_data, upload_data_size,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *connection_cls);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!streq(method, "POST"))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "Unsupported method.\n");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!streq(url, "/upload"))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_NOT_FOUND,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "Not found.\n");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek header = MHD_lookup_connection_value(connection,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_HEADER_KIND, "Content-Type");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!header || !streq(header, "application/vnd.fdo.journal"))
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek return respond_error(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "Content-Type: application/vnd.fdo.journal"
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek " is required.\n");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (trust_pem) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = check_permissions(connection, &code);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return code;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!request_meta(connection_cls))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return respond_oom(connection);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return MHD_YES;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int setup_microhttpd_server(RemoteServer *s, int fd, bool https) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek struct MHD_OptionItem opts[] = {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_LISTEN_SOCKET, fd},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_END},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_END},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_END},
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek { MHD_OPTION_END}};
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int opts_pos = 3;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int flags =
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_USE_DEBUG |
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_USE_PEDANTIC_CHECKS |
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_USE_EPOLL_LINUX_ONLY |
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_USE_DUAL_STACK;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const union MHD_DaemonInfo *info;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r, epoll_fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHDDaemonWrapper *d;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(fd >= 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = fd_nonblock(fd, true);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to make fd:%d nonblocking: %s", fd, strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (https) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek opts[opts_pos++] = (struct MHD_OptionItem)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek {MHD_OPTION_HTTPS_MEM_KEY, 0, key_pem};
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek opts[opts_pos++] = (struct MHD_OptionItem)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek {MHD_OPTION_HTTPS_MEM_CERT, 0, cert_pem};
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek flags |= MHD_USE_SSL;
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen if (trust_pem)
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen opts[opts_pos++] = (struct MHD_OptionItem)
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen {MHD_OPTION_HTTPS_MEM_TRUST, 0, trust_pem};
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen }
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen d = new(MHDDaemonWrapper, 1);
769b56a308c3f3d3952eda87fd4fb004207f4f49Tom Gundersen if (!d)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek d->fd = (uint64_t) fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek d->daemon = MHD_start_daemon(flags, 0,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek NULL, NULL,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek request_handler, NULL,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_OPTION_ARRAY, opts,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_OPTION_END);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!d->daemon) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to start µhttp daemon");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = -EINVAL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek https ? "HTTPS" : "HTTP", fd, d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau if (!info) {
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau log_error("µhttp returned NULL daemon info");
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau r = -ENOTSUP;
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau goto error;
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau }
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau
301f4073fe1c2757e602aef24cee9ccf5f81a3a3Michael Marineau epoll_fd = info->listen_fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (epoll_fd < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("µhttp epoll fd is invalid");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = -EUCLEAN;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_event_add_io(s->events, &d->event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek epoll_fd, EPOLLIN, dispatch_http_event, d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to add event callback: %s", strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = hashmap_ensure_allocated(&s->daemons, uint64_hash_func, uint64_compare_func);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_oom();
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = hashmap_put(s->daemons, &d->fd, d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to add daemon to hashmap: %s", strerror(-r));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek goto error;
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahani }
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahani
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahani s->active ++;
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahani return 0;
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahani
1adc5d0bcd17fc8a8cd22fcd03174bfd75306dcdSusant Sahanierror:
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_stop_daemon(d->daemon);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek free(d->daemon);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek free(d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmekstatic int setup_microhttpd_socket(RemoteServer *s,
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek const char *address,
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek bool https) {
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek int fd;
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek
e88d8021ba34be32ef5ace32e7243da798b0d1c5Zbigniew Jędrzejewski-Szmek fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM | SOCK_CLOEXEC);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (fd < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return setup_microhttpd_server(s, fd, https);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dispatch_http_event(sd_event_source *event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int fd,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek uint32_t revents,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void *userdata) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHDDaemonWrapper *d = userdata;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_info("%s", __func__);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = MHD_run(d->daemon);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r == MHD_NO) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("MHD_run failed!");
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen // XXX: unregister daemon
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen return -EINVAL;
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen }
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen return 1; /* work to do */
4a6970c5354cd367b1fa62114057d8e084a20403Torstein Husebø}
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen
3e43b2cd97bd82efe6a09e8b9b2e6b5f33f578a0Jan Janssen/**********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek **********************************************************************/
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int dispatch_sigterm(sd_event_source *event,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const struct signalfd_siginfo *si,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek void *userdata) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek RemoteServer *s = userdata;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_received_signal(LOG_INFO, si);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sd_event_exit(s->events, 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int setup_signals(RemoteServer *s) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sigset_t mask;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert_se(sigemptyset(&mask) == 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sigset_add_many(&mask, SIGINT, SIGTERM, -1);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, dispatch_sigterm, s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, dispatch_sigterm, s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek}
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int remoteserver_init(RemoteServer *s) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek int r, n, fd;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek const char *output_name = NULL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sd_event_default(&s->events);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek setup_signals(s);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(server == NULL);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek server = s;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek n = sd_listen_fds(true);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (n < 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Failed to read listening file descriptors from environment: %s",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek strerror(-n));
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return n;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_info("Received %d descriptors", n);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (sd_is_socket(fd, AF_UNSPEC, 0, false)) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert_not_reached("not implemented");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else if (sd_is_socket(fd, AF_UNSPEC, 0, true)) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_info("Received a connection socket (fd:%d)", fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = add_source(s, fd, NULL);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek output_name = "socket";
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Unknown socket passed on fd:%d", fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return -EINVAL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (arg_url) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek char _cleanup_free_ *url = NULL;
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen char _cleanup_strv_free_ **urlv = strv_new(arg_url, "/entries", NULL);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!urlv)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return log_oom();
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen url = strv_join(urlv, "");
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (!url)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return log_oom();
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (arg_getter) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_info("Spawning getter %s...", url);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen fd = spawn_getter(arg_getter, url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek } else {
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen log_info("Spawning curl %s...", url);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen fd = spawn_curl(url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (fd < 0)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return fd;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
9c8ca3f7a69f82ca181b3cd2d5e1d3e621938abbZbigniew Jędrzejewski-Szmek r = add_source(s, fd, arg_url);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen output_name = arg_url;
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma if (arg_listen_raw) {
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma log_info("Listening on a socket...");
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma r = setup_raw_socket(s, arg_listen_raw);
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma if (r < 0)
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma return r;
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek output_name = arg_listen_raw;
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen if (arg_listen_http) {
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma r = setup_microhttpd_socket(s, arg_listen_http, false);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (r < 0)
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma return r;
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma output_name = arg_listen_http;
f47c5c47d1a7bcfa1842ff7cc52b1f7fc1d86bcfpoma }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (arg_listen_https) {
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen r = setup_microhttpd_socket(s, arg_listen_https, true);
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen if (r < 0)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen output_name = arg_listen_https;
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen }
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (arg_stdin) {
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen log_info("Reading standard input...");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = add_source(s, STDIN_FILENO, "stdin");
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen if (r < 0)
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen output_name = "stdin";
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen }
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen if (s->active == 0) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek log_error("Zarro sources specified");
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen return -EINVAL;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen if (!!n + !!arg_url + !!arg_listen_raw + !!arg_stdin > 1)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek output_name = "multiple";
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen r = writer_init(&s->writer);
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen if (r < 0)
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen return r;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen r = open_output(&s->writer, output_name);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return r;
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen}
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int server_destroy(RemoteServer *s) {
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen int r;
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen ssize_t i;
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen MHDDaemonWrapper *d;
0a8a0fad010018be0f46d1c2e077ade0eb27c7dbTom Gundersen
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek r = writer_close(&s->writer);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek while ((d = hashmap_steal_first(s->daemons))) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek MHD_stop_daemon(d->daemon);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek sd_event_source_unref(d->event);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek free(d);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek }
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek hashmap_free(s->daemons);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(s->sources_size == 0 || s->sources);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for (i = 0; i < s->sources_size; i++)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen remove_source(s, i);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
free(s->sources);
sd_event_source_unref(s->sigterm_event);
sd_event_source_unref(s->sigint_event);
sd_event_source_unref(s->listen_event);
sd_event_unref(s->events);
/* fds that we're listening on remain open... */
return r;
}
/**********************************************************************
**********************************************************************
**********************************************************************/
static int dispatch_raw_source_event(sd_event_source *event,
int fd,
uint32_t revents,
void *userdata) {
RemoteServer *s = userdata;
RemoteSource *source;
int r;
assert(fd < s->sources_size);
source = s->sources[fd];
assert(source->fd == fd);
r = process_source(source, &s->writer, arg_compress, arg_seal);
if (source->state == STATE_EOF) {
log_info("EOF reached with source fd:%d (%s)",
source->fd, source->name);
if (source_non_empty(source))
log_warning("EOF reached with incomplete data");
remove_source(s, source->fd);
log_info("%zd active source remaining", s->active);
} else if (r == -E2BIG) {
log_error("Entry too big, skipped");
r = 1;
}
return r;
}
static int accept_connection(const char* type, int fd, SocketAddress *addr) {
int fd2, r;
log_debug("Accepting new %s connection on fd:%d", type, fd);
fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (fd2 < 0) {
log_error("accept() on fd:%d failed: %m", fd);
return -errno;
}
switch(socket_address_family(addr)) {
case AF_INET:
case AF_INET6: {
char* _cleanup_free_ a = NULL;
r = socket_address_print(addr, &a);
if (r < 0) {
log_error("socket_address_print(): %s", strerror(-r));
close(fd2);
return r;
}
log_info("Accepted %s %s connection from %s",
type,
socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
a);
return fd2;
};
default:
log_error("Rejected %s connection with unsupported family %d",
type, socket_address_family(addr));
close(fd2);
return -EINVAL;
}
}
static int dispatch_raw_connection_event(sd_event_source *event,
int fd,
uint32_t revents,
void *userdata) {
RemoteServer *s = userdata;
int fd2;
SocketAddress addr = {
.size = sizeof(union sockaddr_union),
.type = SOCK_STREAM,
};
fd2 = accept_connection("raw", fd, &addr);
if (fd2 < 0)
return fd2;
return add_source(s, fd2, NULL);
}
/**********************************************************************
**********************************************************************
**********************************************************************/
static int help(void) {
printf("%s [OPTIONS...]\n\n"
"Write external journal events to a journal file.\n\n"
"Options:\n"
" --url=URL Read events from systemd-journal-gatewayd at URL\n"
" --getter=COMMAND Read events from the output of COMMAND\n"
" --listen-raw=ADDR Listen for connections at ADDR\n"
" --listen-http=ADDR Listen for HTTP connections at ADDR\n"
" --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
" --stdin Read events from standard input\n"
" -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
" --[no-]compress Use XZ-compression in the output journal (default: yes)\n"
" --[no-]seal Use Event sealing in the output journal (default: no)\n"
" -h --help Show this help and exit\n"
" --version Print version string and exit\n"
"\n"
"Note: file descriptors from sd_listen_fds() will be consumed, too.\n"
, program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_URL,
ARG_LISTEN_RAW,
ARG_LISTEN_HTTP,
ARG_LISTEN_HTTPS,
ARG_STDIN,
ARG_GETTER,
ARG_COMPRESS,
ARG_NO_COMPRESS,
ARG_SEAL,
ARG_NO_SEAL,
ARG_KEY,
ARG_CERT,
ARG_TRUST,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "url", required_argument, NULL, ARG_URL },
{ "getter", required_argument, NULL, ARG_GETTER },
{ "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
{ "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
{ "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
{ "stdin", no_argument, NULL, ARG_STDIN },
{ "output", required_argument, NULL, 'o' },
{ "compress", no_argument, NULL, ARG_COMPRESS },
{ "no-compress", no_argument, NULL, ARG_NO_COMPRESS },
{ "seal", no_argument, NULL, ARG_SEAL },
{ "no-seal", no_argument, NULL, ARG_NO_SEAL },
{ "key", required_argument, NULL, ARG_KEY },
{ "cert", required_argument, NULL, ARG_CERT },
{ "trust", required_argument, NULL, ARG_TRUST },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
switch(c) {
case 'h':
help();
return 0 /* done */;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0 /* done */;
case ARG_URL:
if (arg_url) {
log_error("cannot currently set more than one --url");
return -EINVAL;
}
arg_url = optarg;
break;
case ARG_GETTER:
if (arg_getter) {
log_error("cannot currently use --getter more than once");
return -EINVAL;
}
arg_getter = optarg;
break;
case ARG_LISTEN_RAW:
if (arg_listen_raw) {
log_error("cannot currently use --listen-raw more than once");
return -EINVAL;
}
arg_listen_raw = optarg;
break;
case ARG_LISTEN_HTTP:
if (arg_listen_http) {
log_error("cannot currently use --listen-http more than once");
return -EINVAL;
}
arg_listen_http = optarg;
break;
case ARG_LISTEN_HTTPS:
if (arg_listen_https) {
log_error("cannot currently use --listen-https more than once");
return -EINVAL;
}
arg_listen_https = optarg;
break;
case ARG_KEY:
if (key_pem) {
log_error("Key file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &key_pem, NULL);
if (r < 0) {
log_error("Failed to read key file: %s", strerror(-r));
return r;
}
assert(key_pem);
break;
case ARG_CERT:
if (cert_pem) {
log_error("Certificate file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &cert_pem, NULL);
if (r < 0) {
log_error("Failed to read certificate file: %s", strerror(-r));
return r;
}
assert(cert_pem);
break;
case ARG_TRUST:
#ifdef HAVE_GNUTLS
if (trust_pem) {
log_error("CA certificate file specified twice");
return -EINVAL;
}
r = read_full_file(optarg, &trust_pem, NULL);
if (r < 0) {
log_error("Failed to read CA certificate file: %s", strerror(-r));
return r;
}
assert(trust_pem);
break;
#else
log_error("Option --trust is not available.");
#endif
case ARG_STDIN:
arg_stdin = true;
break;
case 'o':
if (arg_output) {
log_error("cannot use --output/-o more than once");
return -EINVAL;
}
arg_output = optarg;
break;
case ARG_COMPRESS:
arg_compress = true;
break;
case ARG_NO_COMPRESS:
arg_compress = false;
break;
case ARG_SEAL:
arg_seal = true;
break;
case ARG_NO_SEAL:
arg_seal = false;
break;
case '?':
return -EINVAL;
default:
log_error("Unknown option code %c", c);
return -EINVAL;
}
if (arg_listen_https && !(key_pem && cert_pem)) {
log_error("Options --key and --cert must be used when https sources are specified");
return -EINVAL;
}
if (optind < argc) {
log_error("This program takes no positional arguments");
return -EINVAL;
}
return 1 /* work to do */;
}
static int setup_gnutls_logger(void) {
if (!arg_listen_http && !arg_listen_https)
return 0;
#ifdef HAVE_GNUTLS
gnutls_global_set_log_function(log_func_gnutls);
gnutls_global_set_log_level(GNUTLS_LOG_LEVEL);
#endif
return 0;
}
int main(int argc, char **argv) {
RemoteServer s = {};
int r, r2;
log_set_max_level(LOG_DEBUG);
log_show_color(true);
log_parse_environment();
r = parse_argv(argc, argv);
if (r <= 0)
return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
r = setup_gnutls_logger();
if (r < 0)
return EXIT_FAILURE;
if (remoteserver_init(&s) < 0)
return EXIT_FAILURE;
log_debug("%s running as pid %lu",
program_invocation_short_name, (unsigned long) getpid());
sd_notify(false,
"READY=1\n"
"STATUS=Processing requests...");
while (s.active) {
r = sd_event_get_state(s.events);
if (r < 0)
break;
if (r == SD_EVENT_FINISHED)
break;
r = sd_event_run(s.events, -1);
if (r < 0) {
log_error("Failed to run event loop: %s", strerror(-r));
break;
}
}
log_info("Finishing after writing %" PRIu64 " entries", s.writer.seqnum);
r2 = server_destroy(&s);
sd_notify(false, "STATUS=Shutting down...");
return r >= 0 && r2 >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}