From 6bc8ceed0b5bd6385991bd1dea65f36bffeea782 Mon Sep 17 00:00:00 2001 From: Sun Dro Date: Wed, 9 Jun 2021 02:27:16 +0400 Subject: [PATCH 1/7] Fixed buffer append crash --- server/BCMK | 2 +- server/hls.cpp | 209 ++++++++++++++++++++++++++++++------------------- server/hls.h | 23 +++++- 3 files changed, 149 insertions(+), 85 deletions(-) diff --git a/server/BCMK b/server/BCMK index c757e9f8..b651bad3 100644 --- a/server/BCMK +++ b/server/BCMK @@ -16,7 +16,7 @@ BC_VERSION := $(shell sed 's/.*([^:]*://;s/-[^()]*//;s/).*//;q' $(TOPDIR)/debian CFLAGS += -DBC_VERSION='"$(BC_VERSION)"' # Enable SSL/TLS support for HLS -CFLAGS += -DBC_HLS_WITH_SSL=y +#CFLAGS += -DBC_HLS_WITH_SSL=y TARGETS = bc-server SERVER_OBJS = bc-server.o bc-thread.o media_writer.o g723-dec.o \ diff --git a/server/hls.cpp b/server/hls.cpp index 1a2369b0..b94e6047 100644 --- a/server/hls.cpp +++ b/server/hls.cpp @@ -647,30 +647,22 @@ std::string hls_session::get_request() void hls_session::tx_buffer_append(uint8_t *data, size_t size) { - size_t old_size = _tx_buffer.size(); - _tx_buffer.resize(old_size + size); - memcpy(_tx_buffer.data() + old_size, data, size); -} - -size_t hls_session::tx_buffer_advance(size_t size) -{ - _tx_buffer.erase(_tx_buffer.begin(), _tx_buffer.begin() + size); - return _tx_buffer.size(); + _tx_buffer.append(data, size); } ssize_t hls_session::tx_buffer_flush() { - if (!_tx_buffer.size()) return 0; + if (!_tx_buffer.used()) return 0; - ssize_t sent = send(_fd, _tx_buffer.data(), _tx_buffer.size(), MSG_NOSIGNAL); + ssize_t sent = send(_fd, _tx_buffer.data(), _tx_buffer.used(), MSG_NOSIGNAL); if (sent < 0) { bc_log(Error, "Can not send data to HLS client: %s (%s)", get_addr(), strerror(errno)); return sent; } - tx_buffer_advance(sent); - return _tx_buffer.size(); + _tx_buffer.advance(sent); + return _tx_buffer.used(); } bool hls_session::create_response() @@ -684,8 +676,7 @@ bool hls_session::create_response() std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } else if (_type == hls_session::request_type::invalid) @@ -695,8 +686,7 @@ bool hls_session::create_response() std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } else if (_type == hls_session::request_type::index) @@ -718,9 +708,7 @@ bool hls_session::create_response() std_string_append(response, "Content-Length: %zu\r\n\r\n", body.length()); response.append(body); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); - + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } else if (_type == hls_session::request_type::playlist) @@ -733,8 +721,7 @@ bool hls_session::create_response() std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -789,9 +776,7 @@ bool hls_session::create_response() std_string_append(response, "Content-Length: %zu\r\n\r\n", body.length()); response.append(body); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); - + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } else if (_type == hls_session::request_type::rec_playlist) @@ -804,8 +789,7 @@ bool hls_session::create_response() std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -817,8 +801,7 @@ bool hls_session::create_response() std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -829,9 +812,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 500 Internal server error\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); avformat_free_context(pFormatCtx); return true; @@ -844,9 +825,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 500 Internal server error\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); avformat_close_input(&pFormatCtx); avformat_free_context(pFormatCtx); @@ -878,8 +857,7 @@ bool hls_session::create_response() std_string_append(response, "Content-Length: %zu\r\n\r\n", body.length()); response.append(body); - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } else if (_type == hls_session::request_type::initial) @@ -891,9 +869,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 404 Not Fount\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -918,9 +894,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 404 Not Fount\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -934,11 +908,8 @@ bool hls_session::create_response() std_string_append(response, "Server: bluechery\r\n"); std_string_append(response, "Content-Length: %zu\r\n\r\n", segment->size()); - size_t response_size = response.length() + segment->size(); - _tx_buffer.resize(response_size); - - memcpy(_tx_buffer.data(), response.c_str(), response.length()); - memcpy(_tx_buffer.data() + response.length(), segment->data(), segment->size()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); + _tx_buffer.append(segment->data(), segment->size()); delete segment; return true; @@ -952,9 +923,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 404 Not Fount\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -965,9 +934,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 404 Not Fount\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -982,11 +949,8 @@ bool hls_session::create_response() std_string_append(response, "Server: bluechery\r\n"); std_string_append(response, "Content-Length: %zu\r\n\r\n", segment->size()); - size_t response_size = response.length() + segment->size(); - _tx_buffer.resize(response_size); - - memcpy(_tx_buffer.data(), response.c_str(), response.length()); - memcpy(_tx_buffer.data() + response.length(), segment->data(), segment->size()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); + _tx_buffer.append(segment->data(), segment->size()); delete segment; return true; @@ -1000,9 +964,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 404 Not Fount\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); return true; } @@ -1013,9 +975,7 @@ bool hls_session::create_response() std::string response = std::string("HTTP/1.1 500 Internal server error\r\n"); std_string_append(response, "User-Agent: bluechery/%s\r\n", __VERSION__); std_string_append(response, "Content-Length: 0\r\n\r\n"); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); delete fstream; return true; @@ -1030,9 +990,7 @@ bool hls_session::create_response() std_string_append(response, "Connection: close\r\n"); std_string_append(response, "Server: bluechery\r\n"); std_string_append(response, "Content-Length: %ld\r\n\r\n", fstream->get_size()); - - _tx_buffer.resize(response.length()); - memcpy(_tx_buffer.data(), response.c_str(), response.length()); + _tx_buffer.append((uint8_t*)response.c_str(), response.length()); set_fstream(fstream); return true; @@ -1233,8 +1191,8 @@ static void* hls_session_thread(void *ctx) else bc_log(Debug, "Received HLS request from: client(%s)[%d]: %s", session->get_addr(), ssl->get_fd(), request.c_str()); /* Send response */ - const hls_byte_buffer &tx_buffer = session->tx_buffer_get(); - if (tx_buffer.size() && ssl->ssl_write(tx_buffer.data(), tx_buffer.size()) <= 0) + hls_byte_buffer &tx_buffer = session->tx_buffer_get(); + if (tx_buffer.used() && ssl->ssl_write(tx_buffer.data(), tx_buffer.used()) <= 0) { bc_log(Error, "%s", ssl->get_last_error().c_str()); delete session; @@ -1303,6 +1261,97 @@ void hls_filestream::finish() } } +////////////////////////////////////////////////// +// BYTE BUFFER +////////////////////////////////////////////////// + +void hls_byte_buffer::clear() +{ + if (_data != NULL) + { + free(_data); + _data = NULL; + _size = 0; + _used = 0; + } +} + +size_t hls_byte_buffer::advance(size_t size) +{ + this->erase(0, size); + return _size; +} + +size_t hls_byte_buffer::erase(size_t posit, size_t size) +{ + if (!size || posit >= _used) return 0; + size = ((posit + size) > _used) ? + _used - posit : size; + + size_t tail_offset = posit + size; + if (tail_offset >= _used) + { + _used = posit; + return _used; + } + + size_t tail_size = _used - tail_offset; + const uint8_t *tail = &_data[tail_offset]; + memmove(&_data[posit], tail, tail_size); + + _used -= size; + return size; +} + +size_t hls_byte_buffer::resize(size_t size) +{ + if (_data == NULL && size) + { + _data = (uint8_t*)malloc(size); + if (_data == NULL) + { + bc_log(Error, "Failed to allocate memory for HLS byte buffer: %s", strerror(errno)); + return 0; + } + + _size = size; + _used = 0; + return size; + } + else if (_data != NULL && !size) + { + this->clear(); + return 0; + } + + if (!_size || _data == NULL) return 0; + _used = (size < _used) ? size : _used; + _data = (uint8_t*)realloc(_data, size); + + if (size && _data == NULL) + { + bc_log(Error, "Failed to reallocate memory for HLS byte buffer: %s", strerror(errno)); + _size = 0; + _used = 0; + return 0; + } + + _size = size; + return _size; +} + +size_t hls_byte_buffer::append(uint8_t *data, size_t size) +{ + if (data == NULL || !size) return 0; + + if (_used + size > _size) + this->resize(_used + size + 1); + + memcpy(&_data[_used], data, size); + _used += size; + return _used; +} + ////////////////////////////////////////////////// // HLS CONTENT ////////////////////////////////////////////////// @@ -1321,10 +1370,10 @@ hls_content::hls_content() } /* - using only 4 segments in playlist is enough since we are using sliding window + using only 3 segments in playlist is enough since we are using sliding window also it will decrease usage of RAM (less segments in window = less RAM usage) */ - set_window_size(4); + set_window_size(3); _init = true; } @@ -1423,22 +1472,18 @@ hls_segment* hls_content::get_initial_segment() bool hls_content::add_data(uint8_t *data, size_t size, int64_t pts, hls_segment::type type, int flags) { + if (!_in_buffer.append(data, size)) return false; + bool is_key = flags & AV_PKT_FLAG_KEY; int64_t pts_diff = (pts - get_last_pts()); double duration = (double)pts_diff / (double)90000; - size_t buff_size = _in_buffer.size(); - _in_buffer.resize(buff_size + size); - uint8_t *offset = _in_buffer.data(); - memcpy(offset + buff_size, data, size); - - if (duration >= HLS_SEGMENT_DURATION && - (_in_buffer.size() >= HLS_SEGMENT_SIZE || is_key)) + if (duration >= HLS_SEGMENT_DURATION && (_in_buffer.used() >= HLS_SEGMENT_SIZE || is_key)) { hls_segment *segment = new hls_segment; if (segment == NULL) return false; - if (!segment->add_data(_in_buffer.data(), _in_buffer.size())) + if (!segment->add_data(_in_buffer.data(), _in_buffer.used())) { delete segment; return false; @@ -1639,7 +1684,7 @@ int hls_write_event(hls_events *events, hls_events::event_data *ev_data) uint8_t buffer[HLS_SERVER_CHUNK_MAX]; ssize_t size = fstream->read_data(buffer, sizeof(buffer)); - if (size > 0) session->tx_buffer_append(buffer, size); + session->tx_buffer_append(buffer, size); if (fstream->eof_reached() || size <= 0) { @@ -1647,7 +1692,7 @@ int hls_write_event(hls_events *events, hls_events::event_data *ev_data) session->set_fstream(NULL); } - return session->tx_buffer_get().size() ? 1 : -1; + return session->tx_buffer_get().used() ? 1 : -1; } int hls_event_callback(void *events, void* data, int reason) diff --git a/server/hls.h b/server/hls.h index 43df8647..8ea6dc1b 100644 --- a/server/hls.h +++ b/server/hls.h @@ -129,7 +129,26 @@ class hls_events int event_fd = -1; /* EPOLL File decriptor */ }; -typedef std::vector hls_byte_buffer; +class hls_byte_buffer +{ +public: + ~hls_byte_buffer() { this->clear(); } + + size_t append(uint8_t *data, size_t size); + size_t erase(size_t posit, size_t size); + size_t advance(size_t size); + size_t resize(size_t size); + void clear(); + + uint8_t* data() { return _data; } + size_t size() { return _size; } + size_t used() { return _used; } + +private: + uint8_t *_data = NULL; + size_t _size = 0; + size_t _used = 0; +}; class hls_filestream { @@ -180,7 +199,7 @@ class hls_session bool handle_request(const std::string &request); bool create_response(); - const hls_byte_buffer& tx_buffer_get() { return _tx_buffer; } + hls_byte_buffer& tx_buffer_get() { return _tx_buffer; } void tx_buffer_append(uint8_t *data, size_t size); size_t tx_buffer_advance(size_t size); ssize_t tx_buffer_flush(); From 941dda43bc41f518bb7e5ad7e7393938a3087997 Mon Sep 17 00:00:00 2001 From: Sun Dro Date: Wed, 9 Jun 2021 18:59:49 -0400 Subject: [PATCH 2/7] Fixed build, installation and upgrade on bullseye and buster distrinutions --- debian/bluecherry.preinst.template | 12 ++++++++++++ lib/BCMK | 9 ++++++++- lib/bc-db-mysql.cpp | 6 ++++++ nginx-configs/php/bullseye.conf | 11 +++++++---- nginx-configs/php/buster.conf | 14 +++++++++----- scripts/build_helper/post_make_install.sh | 8 +++++++- scripts/build_pkg_native.sh | 7 +++++++ server/BCMK | 3 --- utils/BCMK | 12 ++++++------ utils/onvif_tool | 1 - 10 files changed, 62 insertions(+), 21 deletions(-) delete mode 160000 utils/onvif_tool diff --git a/debian/bluecherry.preinst.template b/debian/bluecherry.preinst.template index 1f79a435..0da44acd 100644 --- a/debian/bluecherry.preinst.template +++ b/debian/bluecherry.preinst.template @@ -3,6 +3,18 @@ # Note: this template file is prepended with misc/sql/load_db_creds.sh at packaging stage. # So "$dbname", "$user", "$password" variables are available. +if [[ $(cat /etc/os-release | grep "^ID=" | grep centos) ]] +then + systemctl stop httpd.service +else + if [ ! -z `which service` ] + then + service apache2 stop || true + else + invoke-rc.d apache2 stop || true + fi +fi + if [ "$1" = upgrade ] && dpkg --compare-versions "$2" lt "1:2.0.3"; then echo "UPGRADES WILL NOT WORK!!" echo "Please 'dpkg -P bluecherry' before installing this new package" diff --git a/lib/BCMK b/lib/BCMK index 5b548904..a409f819 100644 --- a/lib/BCMK +++ b/lib/BCMK @@ -1,4 +1,11 @@ -LDFLAGS += -L/usr/lib64/mysql -lmysqlclient -lconfig -lm -lrt -lbsd +ifeq ($(BC_DEBIAN_BULLSEYE),y) + CFLAGS += -DBC_USE_MARIADB=y + LDFLAGS += -L/usr/lib64/mariadb -lmariadbclient +else + LDFLAGS += -L/usr/lib64/mysql -lmysqlclient +endif + +LDFLAGS += -lconfig -lm -lrt -lbsd LDFLAGS += -lavutil -lavformat -lavcodec -lpugixml CFLAGS += -fPIC -DETCDIR="\"$(etc_dir)\"" diff --git a/lib/bc-db-mysql.cpp b/lib/bc-db-mysql.cpp index 52fdbd82..49b1e2d1 100755 --- a/lib/bc-db-mysql.cpp +++ b/lib/bc-db-mysql.cpp @@ -20,9 +20,15 @@ #include "bc-db.h" +#ifdef BC_USE_MARIADB +#include +#include +#include +#else #include #include #include +#endif struct bc_db_mysql_res { MYSQL_RES *res; diff --git a/nginx-configs/php/bullseye.conf b/nginx-configs/php/bullseye.conf index 8098d71d..581a8205 100644 --- a/nginx-configs/php/bullseye.conf +++ b/nginx-configs/php/bullseye.conf @@ -1,6 +1,9 @@ - location ~ \.php$ { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/var/run/php7.4-fpm.sock; - fastcgi_index index.php; + location ~ \.php$ { + fastcgi_pass unix:/run/php/php7.4-fpm.sock; + fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi.conf; + set $path_info $fastcgi_path_info; + fastcgi_param PATH_INFO $path_info; + fastcgi_param SCRIPT_FILENAME $document_root/index.php; + fastcgi_index index.php; } diff --git a/nginx-configs/php/buster.conf b/nginx-configs/php/buster.conf index f57bf0c6..b53afa09 100644 --- a/nginx-configs/php/buster.conf +++ b/nginx-configs/php/buster.conf @@ -1,6 +1,10 @@ - location ~ \.php$ { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/var/run/php7.3-fpm.sock; - fastcgi_index index.php; + location ~ \.php$ { + fastcgi_pass unix:/run/php/php7.3-fpm.sock; + fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi.conf; - } + set $path_info $fastcgi_path_info; + fastcgi_param PATH_INFO $path_info; + fastcgi_param SCRIPT_FILENAME $document_root/index.php; + fastcgi_index index.php; + } + diff --git a/scripts/build_helper/post_make_install.sh b/scripts/build_helper/post_make_install.sh index e3001091..236a48f3 100755 --- a/scripts/build_helper/post_make_install.sh +++ b/scripts/build_helper/post_make_install.sh @@ -43,7 +43,13 @@ then mkdir -p ${DST_DIR}/usr/share/bluecherry/nginx-includes/ cp ${SRC_PATH}/nginx-configs/php/* ${DST_DIR}/usr/share/bluecherry/nginx-includes/ - _CODENAME_=`cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2` + + if [[ $(cat /etc/os-release | grep "^ID=" | grep debian) ]] + then + _CODENAME_=`cat /etc/os-release | grep VERSION_CODENAME | cut -d = -f 2` + else + _CODENAME_=`cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2` + fi mkdir -p ${DST_DIR}/etc/nginx/sites-enabled/ cat ${SRC_PATH}/nginx-configs/bluecherry.conf | sed \ diff --git a/scripts/build_pkg_native.sh b/scripts/build_pkg_native.sh index d69ba62c..78fd15d3 100755 --- a/scripts/build_pkg_native.sh +++ b/scripts/build_pkg_native.sh @@ -12,6 +12,13 @@ else sudo `dirname $0`/install_prereqs_native.sh fi +if [[ $(cat /etc/os-release | grep "^ID=" | grep debian) && \ + $(cat /etc/os-release | grep "^VERSION=" | grep 11) ]] +then + apt-get install -y libmariadb-dev + export BC_DEBIAN_BULLSEYE=y +fi + # TODO Implement building outside of sources tree # Safety measures. TODO quick compilation without spare rebuilds diff --git a/server/BCMK b/server/BCMK index c757e9f8..96b139e4 100644 --- a/server/BCMK +++ b/server/BCMK @@ -15,9 +15,6 @@ LDFLAGS += -lopencv_core -lopencv_imgproc -lopencv_imgcodecs BC_VERSION := $(shell sed 's/.*([^:]*://;s/-[^()]*//;s/).*//;q' $(TOPDIR)/debian/changelog) CFLAGS += -DBC_VERSION='"$(BC_VERSION)"' -# Enable SSL/TLS support for HLS -CFLAGS += -DBC_HLS_WITH_SSL=y - TARGETS = bc-server SERVER_OBJS = bc-server.o bc-thread.o media_writer.o g723-dec.o \ bc-detect.o streaming.o rtsp.o signals.o motion_processor.o trigger_processor.o \ diff --git a/utils/BCMK b/utils/BCMK index 3bfd962f..915f7580 100644 --- a/utils/BCMK +++ b/utils/BCMK @@ -19,13 +19,13 @@ $(TOPDIR)/server/g723-dec.o: %.o:%.c %.h clean: rm -f $(TARGETS) *.o -onvif_tool/onvif_tool: - cd onvif_tool/ && autoreconf -i \ - && ./configure \ - && $(MAKE) $(MAKEARGS) \ - && $(STRIP) onvif_tool +#onvif_tool/onvif_tool: +# cd onvif_tool/ && autoreconf -i \ +# && ./configure \ +# && $(MAKE) $(MAKEARGS) \ +# && $(STRIP) onvif_tool install: licensecmd ptzcmd $(INSTALL_PROG) -D licensecmd $(DESTDIR)$(libexec_dir)/licensecmd $(INSTALL_PROG) -D ptzcmd $(DESTDIR)$(libexec_dir)/ptzcmd - $(INSTALL_PROG) -D onvif_tool/onvif_tool $(DESTDIR)$(libexec_dir)/onvif_tool + $(INSTALL_PROG) -D onvif_tool $(DESTDIR)$(libexec_dir)/onvif_tool diff --git a/utils/onvif_tool b/utils/onvif_tool deleted file mode 160000 index 7f16d21b..00000000 --- a/utils/onvif_tool +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7f16d21b525e569f8fb238ea8e72de66bf039609 From 2811a4d11f01f097c44a6688aeb4e68444f76eee Mon Sep 17 00:00:00 2001 From: Sun Dro Date: Fri, 11 Jun 2021 00:20:26 +0400 Subject: [PATCH 3/7] Added php-mysql and php-sqlite3 packages in dependencies --- debian/control.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/control.in b/debian/control.in index 65f90bea..06b37403 100644 --- a/debian/control.in +++ b/debian/control.in @@ -21,6 +21,8 @@ Depends: ${shlibs:Depends}, ssl-cert, ucf, curl, sysstat, mkvtoolnix, php-mail, php-mail-mime, php-net-smtp, sqlite3, nmap, nginx, php-fpm, + php-mysql, + php-sqlite3, v4l-utils, vainfo, i965-va-driver, From fd9a2ae4e6b19cefb79c16a91f62c1f8ccd31a55 Mon Sep 17 00:00:00 2001 From: Sun Dro Date: Fri, 11 Jun 2021 01:39:50 +0400 Subject: [PATCH 4/7] Destroy session on disconnect --- server/bc-server.cpp | 5 ++++- server/hls.cpp | 5 +++-- utils/BCMK | 12 ++++++------ utils/onvif_tool | 1 - 4 files changed, 13 insertions(+), 10 deletions(-) delete mode 160000 utils/onvif_tool diff --git a/server/bc-server.cpp b/server/bc-server.cpp index ea25ae3c..e7d8a8be 100644 --- a/server/bc-server.cpp +++ b/server/bc-server.cpp @@ -858,10 +858,10 @@ static int bc_initial_cleanup_untracked_media() } const char *filepath = bc_db_get_val(dbres, "filepath", NULL); - bc_db_free_table(dbres); if (!filepath || !*filepath) { bc_log(Warning, "Failed to read oldest file path"); + bc_db_free_table(dbres); return -1; } @@ -879,6 +879,7 @@ static int bc_initial_cleanup_untracked_media() if (count != 7) { bc_log(Warning, "Failed determine oldest media time"); + bc_db_free_table(dbres); return -1; } @@ -887,6 +888,7 @@ static int bc_initial_cleanup_untracked_media() if (!bc_get_media_locations(locations)) { bc_log(Warning, "No media locations available for cleanup"); + bc_db_free_table(dbres); return -1; } @@ -896,6 +898,7 @@ static int bc_initial_cleanup_untracked_media() bc_log(Info, "Initial media cleanup finished: removed(%d), archived(%d), errors(%d), others(%d)", ctx.removed, ctx.archived, ctx.errors, ctx.others); + bc_db_free_table(dbres); return 0; } diff --git a/server/hls.cpp b/server/hls.cpp index b94e6047..5d0551d6 100644 --- a/server/hls.cpp +++ b/server/hls.cpp @@ -438,9 +438,10 @@ bool hls_events::modify(hls_events::event_data *data, int events) bool hls_events::remove(hls_events::event_data *data) { - if (epoll_ctl(event_fd, EPOLL_CTL_DEL, data->fd, NULL) < 0) return false; + bool status = true; + if (data->fd >= 0 && epoll_ctl(event_fd, EPOLL_CTL_DEL, data->fd, NULL) < 0) status = false; clear_callback(data); - return true; + return status; } bool hls_events::service(int timeout_ms) diff --git a/utils/BCMK b/utils/BCMK index 3bfd962f..915f7580 100644 --- a/utils/BCMK +++ b/utils/BCMK @@ -19,13 +19,13 @@ $(TOPDIR)/server/g723-dec.o: %.o:%.c %.h clean: rm -f $(TARGETS) *.o -onvif_tool/onvif_tool: - cd onvif_tool/ && autoreconf -i \ - && ./configure \ - && $(MAKE) $(MAKEARGS) \ - && $(STRIP) onvif_tool +#onvif_tool/onvif_tool: +# cd onvif_tool/ && autoreconf -i \ +# && ./configure \ +# && $(MAKE) $(MAKEARGS) \ +# && $(STRIP) onvif_tool install: licensecmd ptzcmd $(INSTALL_PROG) -D licensecmd $(DESTDIR)$(libexec_dir)/licensecmd $(INSTALL_PROG) -D ptzcmd $(DESTDIR)$(libexec_dir)/ptzcmd - $(INSTALL_PROG) -D onvif_tool/onvif_tool $(DESTDIR)$(libexec_dir)/onvif_tool + $(INSTALL_PROG) -D onvif_tool $(DESTDIR)$(libexec_dir)/onvif_tool diff --git a/utils/onvif_tool b/utils/onvif_tool deleted file mode 160000 index 7f16d21b..00000000 --- a/utils/onvif_tool +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7f16d21b525e569f8fb238ea8e72de66bf039609 From 01328270cba757fd853c84826402d44dc0d3eb61 Mon Sep 17 00:00:00 2001 From: Sun Dro Date: Sat, 12 Jun 2021 03:52:32 +0400 Subject: [PATCH 5/7] Fixes memory related issues and invalid read of uninitialized variables --- lib/input_device.cpp | 8 ++++++-- server/bc-thread.cpp | 6 ++++++ server/hls.cpp | 34 +++++++++++++++++++++++++++------- server/rtsp.cpp | 2 +- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/lib/input_device.cpp b/lib/input_device.cpp index b386fd36..77af5f60 100644 --- a/lib/input_device.cpp +++ b/lib/input_device.cpp @@ -194,8 +194,10 @@ void stream_properties::video_properties::apply(AVCodecContext *cc) const cc->profile = profile; if (!extradata.empty()) { cc->extradata_size = extradata.size(); - cc->extradata = (uint8_t*)av_malloc(extradata.size() + AV_INPUT_BUFFER_PADDING_SIZE); + size_t size = extradata.size() + AV_INPUT_BUFFER_PADDING_SIZE; + cc->extradata = (uint8_t*)av_malloc(size); memcpy(cc->extradata, &extradata.front(), extradata.size()); + memset(cc->extradata + extradata.size(), 0, AV_INPUT_BUFFER_PADDING_SIZE); } else { cc->extradata_size = 0; cc->extradata = 0; @@ -221,8 +223,10 @@ void stream_properties::audio_properties::apply(AVCodecContext *cc) const cc->bits_per_coded_sample = bits_per_coded_sample; if (!extradata.empty()) { cc->extradata_size = extradata.size(); - cc->extradata = (uint8_t*)av_malloc(extradata.size() + AV_INPUT_BUFFER_PADDING_SIZE); + size_t size = extradata.size() + AV_INPUT_BUFFER_PADDING_SIZE; + cc->extradata = (uint8_t*)av_malloc(size); memcpy(cc->extradata, &extradata.front(), extradata.size()); + memset(cc->extradata + extradata.size(), 0, AV_INPUT_BUFFER_PADDING_SIZE); } else { cc->extradata_size = 0; cc->extradata = 0; diff --git a/server/bc-thread.cpp b/server/bc-thread.cpp index 974442dd..bd477161 100644 --- a/server/bc-thread.cpp +++ b/server/bc-thread.cpp @@ -64,6 +64,12 @@ void stop_handle_properly(struct bc_record *bc_rec) bc_streaming_destroy_hls(bc_rec); + if (bc_rec->hls_stream) + { + hls_content *content = bc_rec->hls_stream->get_hls_content(bc_rec->id); + if (content) content->clear_window(); + } + if (bc_rec->liveview_substream) { bc_rec->liveview_substream->stop(); diff --git a/server/hls.cpp b/server/hls.cpp index 5d0551d6..05a205f8 100644 --- a/server/hls.cpp +++ b/server/hls.cpp @@ -53,9 +53,11 @@ extern "C" { #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP #endif -#define HLS_SEGMENT_SIZE (188 * 7 * 1024) -#define HLS_SEGMENT_DURATION 3.0 // Most accepted HLS segment duration -#define HLS_SERVER_CHUNK_MAX 65535 +#define HLS_SEGMENT_SIZE (188 * 7 * 1024) // Most accepted HLS segment size +#define HLS_SEGMENT_SIZE_MAX (188 * 7 * 1024 * 5) // Maximal HLS segment duration +#define HLS_SEGMENT_DURATION 3.0 // Most accepted HLS segment duration +#define HLS_SEGMENT_DURATION_MAX 6.0 // Maximal HLS segment duration +#define HLS_SERVER_CHUNK_MAX 65535 // RX chunk size to send per one call static void std_string_append(std::string &source, const char *data, ...) { @@ -1280,6 +1282,7 @@ void hls_byte_buffer::clear() size_t hls_byte_buffer::advance(size_t size) { this->erase(0, size); + this->resize(_used); return _size; } @@ -1407,6 +1410,10 @@ bool hls_content::clear_window() _init_segment = NULL; } + _in_buffer.clear(); + _pts = 0; + _cc = 0; + if (pthread_mutex_unlock(&_mutex)) { bc_log(Error, "Can not unlock pthread mutex: %s", strerror(errno)); @@ -1476,16 +1483,29 @@ bool hls_content::add_data(uint8_t *data, size_t size, int64_t pts, hls_segment: if (!_in_buffer.append(data, size)) return false; bool is_key = flags & AV_PKT_FLAG_KEY; - int64_t pts_diff = (pts - get_last_pts()); - double duration = (double)pts_diff / (double)90000; + int64_t last_pts = get_last_pts(); + if (last_pts <= 0) update_pts(pts); + + int64_t pts_diff = pts - get_last_pts(); + double duration = pts_diff > 0 ? (double)pts_diff / (double)90000 : 0; - if (duration >= HLS_SEGMENT_DURATION && (_in_buffer.used() >= HLS_SEGMENT_SIZE || is_key)) + if ((is_key && duration >= HLS_SEGMENT_DURATION) || + (_in_buffer.used() > HLS_SEGMENT_SIZE_MAX || + duration > HLS_SEGMENT_DURATION_MAX)) { hls_segment *segment = new hls_segment; - if (segment == NULL) return false; + if (segment == NULL) + { + bc_log(Error, "Can not allocate data for HLS segment obj"); + clear_window(); + update_pts(pts); + return false; + } if (!segment->add_data(_in_buffer.data(), _in_buffer.used())) { + clear_window(); + update_pts(pts); delete segment; return false; } diff --git a/server/rtsp.cpp b/server/rtsp.cpp index 05cae70a..e40d0f19 100644 --- a/server/rtsp.cpp +++ b/server/rtsp.cpp @@ -227,7 +227,7 @@ void rtsp_server::wake() { pthread_mutex_lock(&wake_lock); if (!awakening) { - uint8_t v; + uint8_t v = 1; if (write(wakeupfd[1], &v, 1) < 0) bc_log(Error, "Error writing to wakeup fd: %s", strerror(errno)); awakening = true; From 794c15b2108da923265be79713c5e843a013a8cb Mon Sep 17 00:00:00 2001 From: Curtis Hall Date: Sat, 12 Jun 2021 15:54:21 -0500 Subject: [PATCH 6/7] Update RC2 changelog --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 6e712908..9024f7eb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +bluecherry (3:3.1.0-rc2) focal bionic buster groovy hirsute bullseye; urgency=low + + * FIX: Resolve large memory leak, causing OOM failure sometimes as soon as 1 hour. (https://github.com/bluecherrydvr/bluecherry-apps/commit/01328270cba757fd853c84826402d44dc0d3eb61) / #01328270cba757fd853c84826402d44dc0d3eb61 + * FIX: Resolve buffer append crash (#6bc8ceed0b5bd6385991bd1dea65f36bffeea782) + + -- Curtis Hall Wed, 12 Jun 2021 15:52:04 -0600 + bluecherry (3:3.1.0-rc1) focal bionic buster groovy; urgency=low * FEATURE: Migrate completely to nginx instead of Apache (#436) From 91906b3a76a20f3f22d6e195278d05a65d39bb5d Mon Sep 17 00:00:00 2001 From: Curtis Hall Date: Sat, 12 Jun 2021 15:55:55 -0500 Subject: [PATCH 7/7] Update license to reflect RC2 --- server/v3license_processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/v3license_processor.h b/server/v3license_processor.h index 3766acd1..c54f94f5 100644 --- a/server/v3license_processor.h +++ b/server/v3license_processor.h @@ -8,7 +8,7 @@ #define LICENSE_KEY "36E898-AC0FD0-46D28E-F4D165-8E9743-07934E" #define PRODUCT_ID "9c5dcb22-b7a8-4f0c-9deb-c5426bfe6ae6" -#define PRODUCT_VERSION "3.1.0-rc1" +#define PRODUCT_VERSION "3.1.0-rc2" #define METADATA_KEY "streams"