diff --git a/src/http/server.c b/src/http/server.c index 20c696e..a1fa097 100644 --- a/src/http/server.c +++ b/src/http/server.c @@ -31,9 +31,6 @@ #include #include -#include -#include -#include #include #include @@ -59,11 +56,12 @@ # include "../gpio.h" #endif -#include "blank.h" +#include "unix.h" #include "uri.h" #include "base64.h" #include "mime.h" #include "static.h" +#include "blank.h" #include "data/index_html.h" @@ -215,51 +213,16 @@ int http_server_listen(struct http_server_t *server) { } if (server->unix_path[0] != '\0') { - struct sockaddr_un unix_addr; - LOG_DEBUG("Binding HTTP to UNIX socket '%s' ...", server->unix_path); - -# define MAX_SUN_PATH (sizeof(unix_addr.sun_path) - 1) - - if (strlen(server->unix_path) > MAX_SUN_PATH) { - LOG_ERROR("UNIX socket path is too long; max=%zu", MAX_SUN_PATH); + if ((server->run->unix_fd = evhttp_my_bind_unix( + server->run->http, + server->unix_path, + server->unix_rm, + server->unix_mode)) < 0 + ) { return -1; } - - MEMSET_ZERO(unix_addr); - strncpy(unix_addr.sun_path, server->unix_path, MAX_SUN_PATH); - unix_addr.sun_family = AF_UNIX; - -# undef MAX_SUN_PATH - - assert((server->run->unix_fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); - assert(!evutil_make_socket_nonblocking(server->run->unix_fd)); - - if (server->unix_rm && unlink(server->unix_path) < 0) { - if (errno != ENOENT) { - LOG_PERROR("Can't remove old UNIX socket '%s'", server->unix_path); - return -1; - } - } - if (bind(server->run->unix_fd, (struct sockaddr *)&unix_addr, sizeof(struct sockaddr_un)) < 0) { - LOG_PERROR("Can't bind HTTP to UNIX socket '%s'", server->unix_path); - return -1; - } - if (server->unix_mode && chmod(server->unix_path, server->unix_mode) < 0) { - LOG_PERROR("Can't set permissions %o to UNIX socket '%s'", server->unix_mode, server->unix_path); - return -1; - } - if (listen(server->run->unix_fd, 128) < 0) { - LOG_PERROR("Can't listen UNIX socket '%s'", server->unix_path); - return -1; - } - if (evhttp_accept_socket(server->run->http, server->run->unix_fd) < 0) { - LOG_PERROR("Can't evhttp_accept_socket() UNIX socket '%s'", server->unix_path); - return -1; - } - LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path); - } else { LOG_DEBUG("Binding HTTP to [%s]:%u ...", server->host, server->port); if (evhttp_bind_socket(server->run->http, server->host, server->port) < 0) { diff --git a/src/http/unix.c b/src/http/unix.c new file mode 100644 index 0000000..421338c --- /dev/null +++ b/src/http/unix.c @@ -0,0 +1,86 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# Copyright (C) 2018 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#include "unix.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "../tools.h" +#include "../logging.h" + + +evutil_socket_t evhttp_my_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode) { + evutil_socket_t fd = -1; + struct sockaddr_un addr; + +# define MAX_SUN_PATH (sizeof(addr.sun_path) - 1) + + if (strlen(path) > MAX_SUN_PATH) { + LOG_ERROR("UNIX socket path is too long; max=%zu", MAX_SUN_PATH); + return -1; + } + + MEMSET_ZERO(addr); + strncpy(addr.sun_path, path, MAX_SUN_PATH); + addr.sun_family = AF_UNIX; + +# undef MAX_SUN_PATH + + assert((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); + assert(!evutil_make_socket_nonblocking(fd)); + + if (rm && unlink(path) < 0) { + if (errno != ENOENT) { + LOG_PERROR("Can't remove old UNIX socket '%s'", path); + return -1; + } + } + if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { + LOG_PERROR("Can't bind HTTP to UNIX socket '%s'", path); + return -1; + } + if (mode && chmod(path, mode) < 0) { + LOG_PERROR("Can't set permissions %o to UNIX socket '%s'", mode, path); + return -1; + } + if (listen(fd, 128) < 0) { + LOG_PERROR("Can't listen UNIX socket '%s'", path); + return -1; + } + if (evhttp_accept_socket(http, fd) < 0) { + LOG_PERROR("Can't evhttp_accept_socket() UNIX socket '%s'", path); + return -1; + } + return fd; +} diff --git a/src/http/unix.h b/src/http/unix.h new file mode 100644 index 0000000..792442d --- /dev/null +++ b/src/http/unix.h @@ -0,0 +1,33 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# Copyright (C) 2018 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#pragma once + +#include + +#include + +#include +#include + + +evutil_socket_t evhttp_my_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode);