refactoring

This commit is contained in:
Maxim Devaev
2024-03-03 03:24:40 +02:00
parent a9dfff84e6
commit 8cb6fc4e78
17 changed files with 242 additions and 210 deletions

View File

@@ -54,7 +54,7 @@ int us_unjpeg(const us_frame_s *src, us_frame_s *dest, bool decode) {
// https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg // https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg
_jpeg_error_manager_s jpeg_error; _jpeg_error_manager_s jpeg_error;
jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error); jpeg.err = jpeg_std_error((struct jpeg_error_mgr*)&jpeg_error);
jpeg_error.mgr.error_exit = _jpeg_error_handler; jpeg_error.mgr.error_exit = _jpeg_error_handler;
jpeg_error.frame = src; jpeg_error.frame = src;
if (setjmp(jpeg_error.jmp) < 0) { if (setjmp(jpeg_error.jmp) < 0) {
@@ -94,7 +94,7 @@ done:
} }
static void _jpeg_error_handler(j_common_ptr jpeg) { static void _jpeg_error_handler(j_common_ptr jpeg) {
_jpeg_error_manager_s *jpeg_error = (_jpeg_error_manager_s *)jpeg->err; _jpeg_error_manager_s *jpeg_error = (_jpeg_error_manager_s*)jpeg->err;
char msg[JMSG_LENGTH_MAX]; char msg[JMSG_LENGTH_MAX];
(*jpeg_error->mgr.format_message)(jpeg, msg); (*jpeg_error->mgr.format_message)(jpeg, msg);

View File

@@ -22,6 +22,14 @@
#include "bev.h" #include "bev.h"
#include <string.h>
#include <errno.h>
#include <event2/util.h>
#include <event2/bufferevent.h>
#include "../../libs/tools.h"
char *us_bufferevent_format_reason(short what) { char *us_bufferevent_format_reason(short what) {
char *reason; char *reason;
@@ -34,6 +42,7 @@ char *us_bufferevent_format_reason(short what) {
strncat(reason, perror_str, 1023); strncat(reason, perror_str, 1023);
free(perror_str); free(perror_str);
strcat(reason, " ("); strcat(reason, " (");
# define FILL_REASON(x_bev, x_name) { \ # define FILL_REASON(x_bev, x_name) { \
if (what & x_bev) { \ if (what & x_bev) { \
if (first) { \ if (first) { \
@@ -44,7 +53,6 @@ char *us_bufferevent_format_reason(short what) {
strcat(reason, x_name); \ strcat(reason, x_name); \
} \ } \
} }
FILL_REASON(BEV_EVENT_READING, "reading"); FILL_REASON(BEV_EVENT_READING, "reading");
FILL_REASON(BEV_EVENT_WRITING, "writing"); FILL_REASON(BEV_EVENT_WRITING, "writing");
FILL_REASON(BEV_EVENT_ERROR, "error"); FILL_REASON(BEV_EVENT_ERROR, "error");

View File

@@ -22,14 +22,5 @@
#pragma once #pragma once
#include <string.h>
#include <errno.h>
#include <event2/util.h>
#include <event2/bufferevent.h>
#include "../../libs/tools.h"
#include "../../libs/logging.h"
char *us_bufferevent_format_reason(short what); char *us_bufferevent_format_reason(short what);

View File

@@ -22,6 +22,13 @@
#include "mime.h" #include "mime.h"
#include <string.h>
#include <event2/util.h>
#include "../../libs/tools.h"
#include "../../libs/array.h"
static const struct { static const struct {
const char *ext; // cppcheck-suppress unusedStructMember const char *ext; // cppcheck-suppress unusedStructMember

View File

@@ -22,12 +22,5 @@
#pragma once #pragma once
#include <string.h>
#include <event2/util.h>
#include "../../libs/tools.h"
#include "../../libs/array.h"
const char *us_guess_mime_type(const char *str); const char *us_guess_mime_type(const char *str);

View File

@@ -22,6 +22,14 @@
#include "path.h" #include "path.h"
#ifdef TEST_HTTP_PATH
# include <stdio.h>
# include <stdlib.h>
#endif
#include <string.h>
#include "../../libs/tools.h"
char *us_simplify_request_path(const char *str) { char *us_simplify_request_path(const char *str) {
// Based on Lighttpd sources: // Based on Lighttpd sources:

View File

@@ -22,13 +22,5 @@
#pragma once #pragma once
#ifdef TEST_HTTP_PATH
# include <stdio.h>
# include <stdlib.h>
#endif
#include <string.h>
#include "../../libs/tools.h"
char *us_simplify_request_path(const char *str); char *us_simplify_request_path(const char *str);

View File

@@ -22,6 +22,61 @@
#include "server.h" #include "server.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <event2/util.h>
#include <event2/event.h>
#include <event2/thread.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/keyvalq_struct.h>
#ifndef EVTHREAD_USE_PTHREADS_IMPLEMENTED
# error Required libevent-pthreads support
#endif
#include "../../libs/types.h"
#include "../../libs/tools.h"
#include "../../libs/threading.h"
#include "../../libs/logging.h"
#include "../../libs/process.h"
#include "../../libs/frame.h"
#include "../../libs/base64.h"
#include "../../libs/list.h"
#include "../data/index_html.h"
#include "../data/favicon_ico.h"
#include "../encoder.h"
#include "../stream.h"
#ifdef WITH_GPIO
# include "../gpio/gpio.h"
#endif
#include "bev.h"
#include "unix.h"
#include "uri.h"
#include "mime.h"
#include "static.h"
#ifdef WITH_SYSTEMD
# include "systemd/systemd.h"
#endif
static int _http_preprocess_request(struct evhttp_request *request, us_server_s *server); static int _http_preprocess_request(struct evhttp_request *request, us_server_s *server);
@@ -46,6 +101,12 @@ static const char *_http_get_header(struct evhttp_request *request, const char *
static char *_http_get_client_hostport(struct evhttp_request *request); static char *_http_get_client_hostport(struct evhttp_request *request);
#define _S_LOG_ERROR(x_msg, ...) US_LOG_ERROR("HTTP: " x_msg, ##__VA_ARGS__)
#define _S_LOG_PERROR(x_msg, ...) US_LOG_PERROR("HTTP: " x_msg, ##__VA_ARGS__)
#define _S_LOG_INFO(x_msg, ...) US_LOG_INFO("HTTP: " x_msg, ##__VA_ARGS__)
#define _S_LOG_VERBOSE(x_msg, ...) US_LOG_VERBOSE("HTTP: " x_msg, ##__VA_ARGS__)
#define _S_LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("HTTP: " x_msg, ##__VA_ARGS__)
#define _A_EVBUFFER_NEW(x_buf) assert((x_buf = evbuffer_new()) != NULL) #define _A_EVBUFFER_NEW(x_buf) assert((x_buf = evbuffer_new()) != NULL)
#define _A_EVBUFFER_ADD(x_buf, x_data, x_size) assert(!evbuffer_add(x_buf, x_data, x_size)) #define _A_EVBUFFER_ADD(x_buf, x_data, x_size) assert(!evbuffer_add(x_buf, x_data, x_size))
#define _A_EVBUFFER_ADD_PRINTF(x_buf, x_fmt, ...) assert(evbuffer_add_printf(x_buf, x_fmt, ##__VA_ARGS__) >= 0) #define _A_EVBUFFER_ADD_PRINTF(x_buf, x_fmt, ...) assert(evbuffer_add_printf(x_buf, x_fmt, ##__VA_ARGS__) >= 0)
@@ -119,15 +180,15 @@ int us_server_listen(us_server_s *server) {
{ {
if (server->static_path[0] != '\0') { if (server->static_path[0] != '\0') {
US_LOG_INFO("Enabling HTTP file server: %s", server->static_path); _S_LOG_INFO("Enabling the file server: %s", server->static_path);
evhttp_set_gencb(run->http, _http_callback_static, (void *)server); evhttp_set_gencb(run->http, _http_callback_static, (void*)server);
} else { } else {
assert(!evhttp_set_cb(run->http, "/", _http_callback_root, (void *)server)); assert(!evhttp_set_cb(run->http, "/", _http_callback_root, (void*)server));
assert(!evhttp_set_cb(run->http, "/favicon.ico", _http_callback_favicon, (void *)server)); assert(!evhttp_set_cb(run->http, "/favicon.ico", _http_callback_favicon, (void*)server));
} }
assert(!evhttp_set_cb(run->http, "/state", _http_callback_state, (void *)server)); assert(!evhttp_set_cb(run->http, "/state", _http_callback_state, (void*)server));
assert(!evhttp_set_cb(run->http, "/snapshot", _http_callback_snapshot, (void *)server)); assert(!evhttp_set_cb(run->http, "/snapshot", _http_callback_snapshot, (void*)server));
assert(!evhttp_set_cb(run->http, "/stream", _http_callback_stream, (void *)server)); assert(!evhttp_set_cb(run->http, "/stream", _http_callback_stream, (void*)server));
} }
us_frame_copy(stream->run->blank->jpeg, ex->frame); us_frame_copy(stream->run->blank->jpeg, ex->frame);
@@ -152,17 +213,17 @@ int us_server_listen(us_server_s *server) {
char *raw_token; char *raw_token;
US_ASPRINTF(raw_token, "%s:%s", server->user, server->passwd); US_ASPRINTF(raw_token, "%s:%s", server->user, server->passwd);
us_base64_encode((uint8_t *)raw_token, strlen(raw_token), &encoded_token, NULL); us_base64_encode((u8*)raw_token, strlen(raw_token), &encoded_token, NULL);
free(raw_token); free(raw_token);
US_ASPRINTF(run->auth_token, "Basic %s", encoded_token); US_ASPRINTF(run->auth_token, "Basic %s", encoded_token);
free(encoded_token); free(encoded_token);
US_LOG_INFO("Using HTTP basic auth"); _S_LOG_INFO("Using HTTP basic auth");
} }
if (server->unix_path[0] != '\0') { if (server->unix_path[0] != '\0') {
US_LOG_DEBUG("Binding HTTP to UNIX socket '%s' ...", server->unix_path); _S_LOG_DEBUG("Binding server to UNIX socket '%s' ...", server->unix_path);
if ((run->ext_fd = us_evhttp_bind_unix( if ((run->ext_fd = us_evhttp_bind_unix(
run->http, run->http,
server->unix_path, server->unix_path,
@@ -171,33 +232,33 @@ int us_server_listen(us_server_s *server) {
) { ) {
return -1; return -1;
} }
US_LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path); _S_LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path);
# ifdef WITH_SYSTEMD # ifdef WITH_SYSTEMD
} else if (server->systemd) { } else if (server->systemd) {
US_LOG_DEBUG("Binding HTTP to systemd socket ..."); _S_LOG_DEBUG("Binding HTTP to systemd socket ...");
if ((run->ext_fd = us_evhttp_bind_systemd(run->http)) < 0) { if ((run->ext_fd = us_evhttp_bind_systemd(run->http)) < 0) {
return -1; return -1;
} }
US_LOG_INFO("Listening systemd socket ..."); _S_LOG_INFO("Listening systemd socket ...");
# endif # endif
} else { } else {
US_LOG_DEBUG("Binding HTTP to [%s]:%u ...", server->host, server->port); _S_LOG_DEBUG("Binding HTTP to [%s]:%u ...", server->host, server->port);
if (evhttp_bind_socket(run->http, server->host, server->port) < 0) { if (evhttp_bind_socket(run->http, server->host, server->port) < 0) {
US_LOG_PERROR("Can't bind HTTP on [%s]:%u", server->host, server->port) _S_LOG_PERROR("Can't bind HTTP on [%s]:%u", server->host, server->port)
return -1; return -1;
} }
US_LOG_INFO("Listening HTTP on [%s]:%u", server->host, server->port); _S_LOG_INFO("Listening HTTP on [%s]:%u", server->host, server->port);
} }
return 0; return 0;
} }
void us_server_loop(us_server_s *server) { void us_server_loop(us_server_s *server) {
US_LOG_INFO("Starting HTTP eventloop ..."); _S_LOG_INFO("Starting eventloop ...");
event_base_dispatch(server->run->base); event_base_dispatch(server->run->base);
US_LOG_INFO("HTTP eventloop stopped"); _S_LOG_INFO("Eventloop stopped");
} }
void us_server_loop_break(us_server_s *server) { void us_server_loop_break(us_server_s *server) {
@@ -282,7 +343,7 @@ static int _http_check_run_compat_action(struct evhttp_request *request, void *v
} }
static void _http_callback_root(struct evhttp_request *request, void *v_server) { static void _http_callback_root(struct evhttp_request *request, void *v_server) {
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
COMPAT_REQUEST; COMPAT_REQUEST;
@@ -297,13 +358,13 @@ static void _http_callback_root(struct evhttp_request *request, void *v_server)
} }
static void _http_callback_favicon(struct evhttp_request *request, void *v_server) { static void _http_callback_favicon(struct evhttp_request *request, void *v_server) {
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
struct evbuffer *buf; struct evbuffer *buf;
_A_EVBUFFER_NEW(buf); _A_EVBUFFER_NEW(buf);
_A_EVBUFFER_ADD(buf, (const void *)US_FAVICON_ICO_DATA, US_FAVICON_ICO_DATA_SIZE); _A_EVBUFFER_ADD(buf, (const void*)US_FAVICON_ICO_DATA, US_FAVICON_ICO_DATA_SIZE);
ADD_HEADER("Content-Type", "image/x-icon"); ADD_HEADER("Content-Type", "image/x-icon");
evhttp_send_reply(request, HTTP_OK, "OK", buf); evhttp_send_reply(request, HTTP_OK, "OK", buf);
@@ -311,7 +372,7 @@ static void _http_callback_favicon(struct evhttp_request *request, void *v_serve
} }
static void _http_callback_static(struct evhttp_request *request, void *v_server) { static void _http_callback_static(struct evhttp_request *request, void *v_server) {
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
COMPAT_REQUEST; COMPAT_REQUEST;
@@ -327,7 +388,7 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
if ((uri = evhttp_uri_parse(evhttp_request_get_uri(request))) == NULL) { if ((uri = evhttp_uri_parse(evhttp_request_get_uri(request))) == NULL) {
goto bad_request; goto bad_request;
} }
if ((uri_path = (char *)evhttp_uri_get_path(uri)) == NULL) { if ((uri_path = (char*)evhttp_uri_get_path(uri)) == NULL) {
uri_path = "/"; uri_path = "/";
} }
if ((decoded_path = evhttp_uridecode(uri_path, 0, NULL)) == NULL) { if ((decoded_path = evhttp_uridecode(uri_path, 0, NULL)) == NULL) {
@@ -342,7 +403,7 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
} }
if ((fd = open(static_path, O_RDONLY)) < 0) { if ((fd = open(static_path, O_RDONLY)) < 0) {
US_LOG_PERROR("HTTP: Can't open found static file %s", static_path); _S_LOG_PERROR("Can't open found static file %s", static_path);
goto not_found; goto not_found;
} }
@@ -350,11 +411,11 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
struct stat st; struct stat st;
if (fstat(fd, &st) < 0) { if (fstat(fd, &st) < 0) {
US_LOG_PERROR("HTTP: Can't stat() found static file %s", static_path); _S_LOG_PERROR("Can't stat() found static file %s", static_path);
goto not_found; goto not_found;
} }
if (st.st_size > 0 && evbuffer_add_file(buf, fd, 0, st.st_size) < 0) { if (st.st_size > 0 && evbuffer_add_file(buf, fd, 0, st.st_size) < 0) {
US_LOG_ERROR("HTTP: Can't serve static file %s", static_path); _S_LOG_ERROR("Can't serve static file %s", static_path);
goto not_found; goto not_found;
} }
@@ -386,7 +447,7 @@ cleanup:
#undef COMPAT_REQUEST #undef COMPAT_REQUEST
static void _http_callback_state(struct evhttp_request *request, void *v_server) { static void _http_callback_state(struct evhttp_request *request, void *v_server) {
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
us_server_runtime_s *const run = server->run; us_server_runtime_s *const run = server->run;
us_server_exposed_s *const ex = run->exposed; us_server_exposed_s *const ex = run->exposed;
us_stream_s *const stream = server->stream; us_stream_s *const stream = server->stream;
@@ -394,7 +455,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
us_encoder_type_e enc_type; us_encoder_type_e enc_type;
unsigned enc_quality; uint enc_quality;
us_encoder_get_runtime_params(stream->enc, &enc_type, &enc_quality); us_encoder_get_runtime_params(stream->enc, &enc_type, &enc_quality);
struct evbuffer *buf; struct evbuffer *buf;
@@ -472,7 +533,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
} }
static void _http_callback_snapshot(struct evhttp_request *request, void *v_server) { static void _http_callback_snapshot(struct evhttp_request *request, void *v_server) {
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
us_server_exposed_s *const ex = server->run->exposed; us_server_exposed_s *const ex = server->run->exposed;
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
@@ -529,7 +590,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
// https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L791 // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L791
// https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L1458 // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L1458
us_server_s *const server = (us_server_s *)v_server; us_server_s *const server = v_server;
us_server_runtime_s *const run = server->run; us_server_runtime_s *const run = server->run;
PREPROCESS_REQUEST; PREPROCESS_REQUEST;
@@ -566,20 +627,20 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
# endif # endif
} }
US_LOG_INFO("HTTP: NEW client (now=%u): %s, id=%" PRIx64, _S_LOG_INFO("NEW client (now=%u): %s, id=%" PRIx64,
run->stream_clients_count, client->hostport, client->id); run->stream_clients_count, client->hostport, client->id);
struct bufferevent *const buf_event = evhttp_connection_get_bufferevent(conn); struct bufferevent *const buf_event = evhttp_connection_get_bufferevent(conn);
if (server->tcp_nodelay && run->ext_fd >= 0) { if (server->tcp_nodelay && run->ext_fd >= 0) {
US_LOG_DEBUG("HTTP: Setting up TCP_NODELAY to the client %s ...", client->hostport); _S_LOG_DEBUG("Setting up TCP_NODELAY to the client %s ...", client->hostport);
const evutil_socket_t fd = bufferevent_getfd(buf_event); const evutil_socket_t fd = bufferevent_getfd(buf_event);
assert(fd >= 0); assert(fd >= 0);
int on = 1; int on = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) != 0) { if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) != 0) {
US_LOG_PERROR("HTTP: Can't set TCP_NODELAY to the client %s", client->hostport); _S_LOG_PERROR("Can't set TCP_NODELAY to the client %s", client->hostport);
} }
} }
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client); bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void*)client);
bufferevent_enable(buf_event, EV_READ); bufferevent_enable(buf_event, EV_READ);
} else { } else {
evhttp_request_free(request); evhttp_request_free(request);
@@ -589,12 +650,12 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
#undef PREPROCESS_REQUEST #undef PREPROCESS_REQUEST
static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_client) { static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_client) {
us_stream_client_s *const client = (us_stream_client_s *)v_client; us_stream_client_s *const client = v_client;
us_server_s *const server = client->server; us_server_s *const server = client->server;
us_server_exposed_s *const ex = server->run->exposed; us_server_exposed_s *const ex = server->run->exposed;
const long double now = us_get_now_monotonic(); const ldf now = us_get_now_monotonic();
const long long now_second = us_floor_ms(now); const sll now_second = us_floor_ms(now);
if (now_second != client->fps_accum_second) { if (now_second != client->fps_accum_second) {
client->fps = client->fps_accum; client->fps = client->fps_accum;
@@ -728,7 +789,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
assert(!bufferevent_write_buffer(buf_event, buf)); assert(!bufferevent_write_buffer(buf_event, buf));
evbuffer_free(buf); evbuffer_free(buf);
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client); bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void*)client);
bufferevent_enable(buf_event, EV_READ); bufferevent_enable(buf_event, EV_READ);
# undef ADD_ADVANCE_HEADERS # undef ADD_ADVANCE_HEADERS
@@ -739,7 +800,7 @@ static void _http_callback_stream_error(struct bufferevent *buf_event, short wha
(void)buf_event; (void)buf_event;
(void)what; (void)what;
us_stream_client_s *const client = (us_stream_client_s *)v_client; us_stream_client_s *const client = v_client;
us_server_s *const server = client->server; us_server_s *const server = client->server;
us_server_runtime_s *const run = server->run; us_server_runtime_s *const run = server->run;
@@ -753,7 +814,7 @@ static void _http_callback_stream_error(struct bufferevent *buf_event, short wha
} }
char *const reason = us_bufferevent_format_reason(what); char *const reason = us_bufferevent_format_reason(what);
US_LOG_INFO("HTTP: DEL client (now=%u): %s, id=%" PRIx64 ", %s", _S_LOG_INFO("DEL client (now=%u): %s, id=%" PRIx64 ", %s",
run->stream_clients_count, client->hostport, client->id, reason); run->stream_clients_count, client->hostport, client->id, reason);
free(reason); free(reason);
@@ -791,7 +852,7 @@ static void _http_queue_send_stream(us_server_s *server, bool stream_updated, bo
if (dual_update || frame_updated || client->need_first_frame) { if (dual_update || frame_updated || client->need_first_frame) {
struct bufferevent *const buf_event = evhttp_connection_get_bufferevent(conn); struct bufferevent *const buf_event = evhttp_connection_get_bufferevent(conn);
bufferevent_setcb(buf_event, NULL, _http_callback_stream_write, _http_callback_stream_error, (void *)client); bufferevent_setcb(buf_event, NULL, _http_callback_stream_write, _http_callback_stream_error, (void*)client);
bufferevent_enable(buf_event, EV_READ|EV_WRITE); bufferevent_enable(buf_event, EV_READ|EV_WRITE);
client->need_first_frame = false; client->need_first_frame = false;
@@ -806,9 +867,9 @@ static void _http_queue_send_stream(us_server_s *server, bool stream_updated, bo
}); });
if (queued) { if (queued) {
static unsigned queued_fps_accum = 0; static uint queued_fps_accum = 0;
static long long queued_fps_second = 0; static sll queued_fps_second = 0;
const long long now = us_floor_ms(us_get_now_monotonic()); const sll now = us_floor_ms(us_get_now_monotonic());
if (now != queued_fps_second) { if (now != queued_fps_second) {
ex->queued_fps = queued_fps_accum; ex->queued_fps = queued_fps_accum;
queued_fps_accum = 0; queued_fps_accum = 0;
@@ -824,7 +885,7 @@ static void _http_refresher(int fd, short what, void *v_server) {
(void)fd; (void)fd;
(void)what; (void)what;
us_server_s *server = (us_server_s *)v_server; us_server_s *server = v_server;
us_server_exposed_s *ex = server->run->exposed; us_server_exposed_s *ex = server->run->exposed;
us_ring_s *const ring = server->stream->run->http_jpeg_ring; us_ring_s *const ring = server->stream->run->http_jpeg_ring;
@@ -838,7 +899,7 @@ static void _http_refresher(int fd, short what, void *v_server) {
stream_updated = true; stream_updated = true;
us_ring_consumer_release(ring, ri); us_ring_consumer_release(ring, ri);
} else if (ex->expose_end_ts + 1 < us_get_now_monotonic()) { } else if (ex->expose_end_ts + 1 < us_get_now_monotonic()) {
US_LOG_DEBUG("HTTP: Repeating exposed ..."); _S_LOG_DEBUG("Repeating exposed ...");
ex->expose_begin_ts = us_get_now_monotonic(); ex->expose_begin_ts = us_get_now_monotonic();
ex->expose_cmp_ts = ex->expose_begin_ts; ex->expose_cmp_ts = ex->expose_begin_ts;
ex->expose_end_ts = ex->expose_begin_ts; ex->expose_end_ts = ex->expose_begin_ts;
@@ -867,7 +928,7 @@ static void _http_refresher(int fd, short what, void *v_server) {
static bool _expose_frame(us_server_s *server, const us_frame_s *frame) { static bool _expose_frame(us_server_s *server, const us_frame_s *frame) {
us_server_exposed_s *const ex = server->run->exposed; us_server_exposed_s *const ex = server->run->exposed;
US_LOG_DEBUG("HTTP: Updating exposed frame (online=%d) ...", frame->online); _S_LOG_DEBUG("Updating exposed frame (online=%d) ...", frame->online);
ex->expose_begin_ts = us_get_now_monotonic(); ex->expose_begin_ts = us_get_now_monotonic();
if (server->drop_same_frames && frame->online) { if (server->drop_same_frames && frame->online) {
@@ -879,13 +940,13 @@ static bool _expose_frame(us_server_s *server, const us_frame_s *frame) {
) { ) {
ex->expose_cmp_ts = us_get_now_monotonic(); ex->expose_cmp_ts = us_get_now_monotonic();
ex->expose_end_ts = ex->expose_cmp_ts; ex->expose_end_ts = ex->expose_cmp_ts;
US_LOG_VERBOSE("HTTP: Dropped same frame number %u; cmp_time=%.06Lf", _S_LOG_VERBOSE("Dropped same frame number %u; cmp_time=%.06Lf",
ex->dropped, (ex->expose_cmp_ts - ex->expose_begin_ts)); ex->dropped, (ex->expose_cmp_ts - ex->expose_begin_ts));
ex->dropped += 1; ex->dropped += 1;
return false; // Not updated return false; // Not updated
} else { } else {
ex->expose_cmp_ts = us_get_now_monotonic(); ex->expose_cmp_ts = us_get_now_monotonic();
US_LOG_VERBOSE("HTTP: Passed same frame check (need_drop=%d, maybe_same=%d); cmp_time=%.06Lf", _S_LOG_VERBOSE("Passed same frame check (need_drop=%d, maybe_same=%d); cmp_time=%.06Lf",
need_drop, maybe_same, (ex->expose_cmp_ts - ex->expose_begin_ts)); need_drop, maybe_same, (ex->expose_cmp_ts - ex->expose_begin_ts));
} }
} }
@@ -902,7 +963,7 @@ static bool _expose_frame(us_server_s *server, const us_frame_s *frame) {
ex->expose_cmp_ts = ex->expose_begin_ts; ex->expose_cmp_ts = ex->expose_begin_ts;
ex->expose_end_ts = us_get_now_monotonic(); ex->expose_end_ts = us_get_now_monotonic();
US_LOG_VERBOSE("HTTP: Exposed frame: online=%d, exp_time=%.06Lf", _S_LOG_VERBOSE("Exposed frame: online=%d, exp_time=%.06Lf",
ex->frame->online, (ex->expose_end_ts - ex->expose_begin_ts)); ex->frame->online, (ex->expose_end_ts - ex->expose_begin_ts));
return true; // Updated return true; // Updated
} }
@@ -925,7 +986,7 @@ static char *_http_get_client_hostport(struct evhttp_request *request) {
if (xff != NULL) { if (xff != NULL) {
US_DELETE(addr, free); US_DELETE(addr, free);
assert((addr = strndup(xff, 1024)) != NULL); assert((addr = strndup(xff, 1024)) != NULL);
for (unsigned index = 0; addr[index]; ++index) { for (uint index = 0; addr[index]; ++index) {
if (addr[index] == ',') { if (addr[index] == ',') {
addr[index] = '\0'; addr[index] = '\0';
break; break;

View File

@@ -22,95 +22,53 @@
#pragma once #pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <event2/util.h> #include <event2/util.h>
#include <event2/event.h> #include <event2/event.h>
#include <event2/thread.h>
#include <event2/http.h> #include <event2/http.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/keyvalq_struct.h>
#ifndef EVTHREAD_USE_PTHREADS_IMPLEMENTED #include "../../libs/types.h"
# error Required libevent-pthreads support
#endif
#include "../../libs/tools.h"
#include "../../libs/threading.h"
#include "../../libs/logging.h"
#include "../../libs/process.h"
#include "../../libs/frame.h" #include "../../libs/frame.h"
#include "../../libs/base64.h"
#include "../../libs/list.h" #include "../../libs/list.h"
#include "../data/index_html.h"
#include "../data/favicon_ico.h"
#include "../encoder.h" #include "../encoder.h"
#include "../stream.h" #include "../stream.h"
#ifdef WITH_GPIO
# include "../gpio/gpio.h"
#endif
#include "bev.h"
#include "unix.h"
#include "uri.h"
#include "mime.h"
#include "static.h"
#ifdef WITH_SYSTEMD
# include "systemd/systemd.h"
#endif
typedef struct us_stream_client_sx { typedef struct us_stream_client_sx {
struct us_server_sx *server; struct us_server_sx *server;
struct evhttp_request *request; struct evhttp_request *request;
char *key; char *key;
bool extra_headers; bool extra_headers;
bool advance_headers; bool advance_headers;
bool dual_final_frames; bool dual_final_frames;
bool zero_data; bool zero_data;
char *hostport; char *hostport;
uint64_t id; u64 id;
bool need_initial; bool need_initial;
bool need_first_frame; bool need_first_frame;
bool updated_prev; bool updated_prev;
unsigned fps; uint fps;
unsigned fps_accum; uint fps_accum;
long long fps_accum_second; sll fps_accum_second;
US_LIST_STRUCT(struct us_stream_client_sx); US_LIST_STRUCT(struct us_stream_client_sx);
} us_stream_client_s; } us_stream_client_s;
typedef struct { typedef struct {
us_frame_s *frame; us_frame_s *frame;
unsigned captured_fps; uint captured_fps;
unsigned queued_fps; uint queued_fps;
unsigned dropped; uint dropped;
long double expose_begin_ts; ldf expose_begin_ts;
long double expose_cmp_ts; ldf expose_cmp_ts;
long double expose_end_ts; ldf expose_end_ts;
bool notify_last_online; bool notify_last_online;
unsigned notify_last_width; uint notify_last_width;
unsigned notify_last_height; uint notify_last_height;
} us_server_exposed_s; } us_server_exposed_s;
typedef struct { typedef struct {
@@ -124,37 +82,37 @@ typedef struct {
us_server_exposed_s *exposed; us_server_exposed_s *exposed;
us_stream_client_s *stream_clients; us_stream_client_s *stream_clients;
unsigned stream_clients_count; uint stream_clients_count;
} us_server_runtime_s; } us_server_runtime_s;
typedef struct us_server_sx { typedef struct us_server_sx {
char *host; us_stream_s *stream;
unsigned port;
char *unix_path; char *host;
bool unix_rm; uint port;
mode_t unix_mode;
char *unix_path;
bool unix_rm;
mode_t unix_mode;
# ifdef WITH_SYSTEMD # ifdef WITH_SYSTEMD
bool systemd; bool systemd;
# endif # endif
bool tcp_nodelay; bool tcp_nodelay;
unsigned timeout; uint timeout;
char *user; char *user;
char *passwd; char *passwd;
char *static_path; char *static_path;
char *allow_origin; char *allow_origin;
char *instance_id; char *instance_id;
unsigned drop_same_frames; uint drop_same_frames;
unsigned fake_width; uint fake_width;
unsigned fake_height; uint fake_height;
bool notify_parent; bool notify_parent;
us_stream_s *stream;
us_server_runtime_s *run; us_server_runtime_s *run;
} us_server_s; } us_server_s;

View File

@@ -22,6 +22,19 @@
#include "static.h" #include "static.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include "../../libs/tools.h"
#include "../../libs/logging.h"
#include "path.h"
char *us_find_static_file_path(const char *root_path, const char *request_path) { char *us_find_static_file_path(const char *root_path, const char *request_path) {
char *path = NULL; char *path = NULL;

View File

@@ -22,18 +22,5 @@
#pragma once #pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include "../../libs/tools.h"
#include "../../libs/logging.h"
#include "path.h"
char *us_find_static_file_path(const char *root_path, const char *request_path); char *us_find_static_file_path(const char *root_path, const char *request_path);

View File

@@ -22,11 +22,22 @@
#include "systemd.h" #include "systemd.h"
#include <unistd.h>
#include <assert.h>
#include <event2/http.h>
#include <event2/util.h>
#include <systemd/sd-daemon.h>
#include "../../../libs/tools.h"
#include "../../../libs/logging.h"
evutil_socket_t us_evhttp_bind_systemd(struct evhttp *http) { evutil_socket_t us_evhttp_bind_systemd(struct evhttp *http) {
const int fds = sd_listen_fds(1); const int fds = sd_listen_fds(1);
if (fds < 1) { if (fds < 1) {
US_LOG_ERROR("No available systemd sockets"); US_LOG_ERROR("HTTP: No available systemd sockets");
return -1; return -1;
} }
@@ -39,7 +50,7 @@ evutil_socket_t us_evhttp_bind_systemd(struct evhttp *http) {
assert(!evutil_make_socket_nonblocking(fd)); assert(!evutil_make_socket_nonblocking(fd));
if (evhttp_accept_socket(http, fd) < 0) { if (evhttp_accept_socket(http, fd) < 0) {
US_LOG_PERROR("Can't evhttp_accept_socket() systemd socket"); US_LOG_PERROR("HTTP: Can't evhttp_accept_socket() systemd socket");
return -1; return -1;
} }
return fd; return fd;

View File

@@ -22,16 +22,8 @@
#pragma once #pragma once
#include <unistd.h>
#include <assert.h>
#include <event2/http.h> #include <event2/http.h>
#include <event2/util.h> #include <event2/util.h>
#include <systemd/sd-daemon.h>
#include "../../../libs/tools.h"
#include "../../../libs/logging.h"
evutil_socket_t us_evhttp_bind_systemd(struct evhttp *http); evutil_socket_t us_evhttp_bind_systemd(struct evhttp *http);

View File

@@ -22,13 +22,29 @@
#include "unix.h" #include "unix.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <event2/http.h>
#include <event2/util.h>
#include "../../libs/types.h"
#include "../../libs/tools.h"
#include "../../libs/logging.h"
evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode) { evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode) {
struct sockaddr_un addr = {0}; struct sockaddr_un addr = {0};
const size_t max_sun_path = sizeof(addr.sun_path) - 1; const uz max_sun_path = sizeof(addr.sun_path) - 1;
if (strlen(path) > max_sun_path) { if (strlen(path) > max_sun_path) {
US_LOG_ERROR("UNIX socket path is too long; max=%zu", max_sun_path); US_LOG_ERROR("HTTP: UNIX socket path is too long; max=%zu", max_sun_path);
return -1; return -1;
} }
@@ -41,24 +57,24 @@ evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool
if (rm && unlink(path) < 0) { if (rm && unlink(path) < 0) {
if (errno != ENOENT) { if (errno != ENOENT) {
US_LOG_PERROR("Can't remove old UNIX socket '%s'", path); US_LOG_PERROR("HTTP: Can't remove old UNIX socket '%s'", path);
return -1; return -1;
} }
} }
if (bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { if (bind(fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0) {
US_LOG_PERROR("Can't bind HTTP to UNIX socket '%s'", path); US_LOG_PERROR("HTTP: Can't bind HTTP to UNIX socket '%s'", path);
return -1; return -1;
} }
if (mode && chmod(path, mode) < 0) { if (mode && chmod(path, mode) < 0) {
US_LOG_PERROR("Can't set permissions %o to UNIX socket '%s'", mode, path); US_LOG_PERROR("HTTP: Can't set permissions %o to UNIX socket '%s'", mode, path);
return -1; return -1;
} }
if (listen(fd, 128) < 0) { if (listen(fd, 128) < 0) {
US_LOG_PERROR("Can't listen UNIX socket '%s'", path); US_LOG_PERROR("HTTP: Can't listen UNIX socket '%s'", path);
return -1; return -1;
} }
if (evhttp_accept_socket(http, fd) < 0) { if (evhttp_accept_socket(http, fd) < 0) {
US_LOG_PERROR("Can't evhttp_accept_socket() UNIX socket '%s'", path); US_LOG_PERROR("HTTP: Can't evhttp_accept_socket() UNIX socket '%s'", path);
return -1; return -1;
} }
return fd; return fd;

View File

@@ -22,21 +22,12 @@
#pragma once #pragma once
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <event2/http.h> #include <event2/http.h>
#include <event2/util.h> #include <event2/util.h>
#include "../../libs/tools.h" #include "../../libs/types.h"
#include "../../libs/logging.h"
evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode); evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode);

View File

@@ -22,6 +22,12 @@
#include "uri.h" #include "uri.h"
#include <event2/util.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h>
#include "../../libs/types.h"
bool us_uri_get_true(struct evkeyvalq *params, const char *key) { bool us_uri_get_true(struct evkeyvalq *params, const char *key) {
const char *value_str = evhttp_find_header(params, key); const char *value_str = evhttp_find_header(params, key);

View File

@@ -22,12 +22,10 @@
#pragma once #pragma once
#include <stdbool.h>
#include <event2/util.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h> #include <event2/keyvalq_struct.h>
#include "../../libs/types.h"
bool us_uri_get_true(struct evkeyvalq *params, const char *key); bool us_uri_get_true(struct evkeyvalq *params, const char *key);
char *us_uri_get_string(struct evkeyvalq *params, const char *key); char *us_uri_get_string(struct evkeyvalq *params, const char *key);