diff --git a/src/libs/list.h b/src/libs/list.h new file mode 100644 index 0000000..31e6a2f --- /dev/null +++ b/src/libs/list.h @@ -0,0 +1,71 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# Copyright (C) 2018-2021 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 + + +#define LIST_STRUCT(...) \ + __VA_ARGS__ *prev; \ + __VA_ARGS__ *next; + +#define LIST_ITERATE(_first, _item, ...) { \ + for (__typeof__(_first) _item = _first; _item;) { \ + __typeof__(_first) _next = _item->next; \ + __VA_ARGS__ \ + _item = _next; \ + } \ + } + +#define LIST_APPEND(_first, _item) { \ + if (_first == NULL) { \ + _first = _item; \ + } else { \ + __typeof__(_first) _last = _first; \ + for (; _last->next; _last = _last->next); \ + _item->prev = _last; \ + _last->next = _item; \ + } \ + } + +#define LIST_APPEND_C(_first, _item, _count) { \ + LIST_APPEND(_first, _item); \ + ++(_count); \ + } + +#define LIST_REMOVE(_first, _item) { \ + if (_item->prev == NULL) { \ + _first = _item->next; \ + } else { \ + _item->prev->next = _item->next; \ + } \ + if (_item->next != NULL) { \ + _item->next->prev = _item->prev; \ + } \ + } + +#define LIST_REMOVE_C(_first, _item, _count) { \ + LIST_REMOVE(_first, _item); \ + assert((_count) >= 1); \ + --(_count); \ + } diff --git a/src/libs/tools.h b/src/libs/tools.h index 157b0d5..cf7b7fc 100644 --- a/src/libs/tools.h +++ b/src/libs/tools.h @@ -46,36 +46,6 @@ #define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0])) -#define LIST_ITERATE(_first, _item, ...) { \ - for (__typeof__(_first) _item = _first; _item;) { \ - __typeof__(_first) _next = _item->next; \ - __VA_ARGS__ \ - _item = _next; \ - } \ - } - -#define LIST_APPEND(_first, _item) { \ - if (_first == NULL) { \ - _first = _item; \ - } else { \ - __typeof__(_first) _last = _first; \ - for (; _last->next; _last = _last->next); \ - _item->prev = _last; \ - _last->next = _item; \ - } \ - } - -#define LIST_REMOVE(_first, _item) { \ - if (_item->prev == NULL) { \ - _first = _item->next; \ - } else { \ - _item->prev->next = _item->next; \ - } \ - if (_item->next != NULL) { \ - _item->next->prev = _item->prev; \ - } \ - } - INLINE const char *bool_to_string(bool flag) { return (flag ? "true" : "false"); diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index 4a594b9..ecf26c6 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -475,8 +475,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server client->hostport = _http_get_client_hostport(request); client->id = get_now_id(); - LIST_APPEND(RUN(stream_clients), client); - RUN(stream_clients_count) += 1; + LIST_APPEND_C(RUN(stream_clients), client, RUN(stream_clients_count)); if (RUN(stream_clients_count) == 1) { atomic_store(&VID(has_clients), true); @@ -643,10 +642,7 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN stream_client_s *client = (stream_client_s *)v_client; server_s *server = client->server; - char *reason = bufferevent_my_format_reason(what); - - assert(RUN(stream_clients_count) > 0); - RUN(stream_clients_count) -= 1; + LIST_REMOVE_C(RUN(stream_clients), client, RUN(stream_clients_count)); if (RUN(stream_clients_count) == 0) { atomic_store(&VID(has_clients), false); @@ -655,20 +651,19 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN # endif } + char *reason = bufferevent_my_format_reason(what); LOG_INFO("HTTP: Disconnected client: %s, id=%" PRIx64 ", %s; clients now: %u", client->hostport, client->id, reason, RUN(stream_clients_count)); + free(reason); struct evhttp_connection *conn = evhttp_request_get_connection(client->request); if (conn) { evhttp_connection_free(conn); } - LIST_REMOVE(RUN(stream_clients), client); free(client->key); free(client->hostport); free(client); - - free(reason); } static void _http_queue_send_stream(server_s *server, bool stream_updated, bool frame_updated) { diff --git a/src/ustreamer/http/server.h b/src/ustreamer/http/server.h index f667a68..10ac48a 100644 --- a/src/ustreamer/http/server.h +++ b/src/ustreamer/http/server.h @@ -58,6 +58,7 @@ #include "../../libs/process.h" #include "../../libs/frame.h" #include "../../libs/base64.h" +#include "../../libs/list.h" #include "../data/index_html.h" #include "../encoder.h" #include "../stream.h" @@ -91,8 +92,7 @@ typedef struct stream_client_sx { unsigned fps_accum; long long fps_accum_second; - struct stream_client_sx *prev; - struct stream_client_sx *next; + LIST_STRUCT(struct stream_client_sx); } stream_client_s; typedef struct {