diff --git a/README.md b/README.md index f73cdde..1be6524 100644 --- a/README.md +++ b/README.md @@ -62,11 +62,13 @@ The daemon can be cross-compiled for multiple platforms and implements the follo * IGMP handling for SAP, PTP and RTP sessions * Integration with systemd watchdog monitoring (from daemon release v1.6) -The directory also contains the daemon regression tests in the [tests](daemon/tests) subdirectory. -See the [README](daemon/README.md) file in this directory for additional information about the AES67 daemon configuration and the HTTP REST API. +See the [README](daemon/README.md) file in this directory for additional information about the AES67 daemon configuration and the daemon HTTP REST API. + +The directory also contains the daemon tests in the [tests](daemon/tests) subdirectory. + +Daemon tests can be executed via a Docker container by using a fake version of the daemon driver manager. +This was implemented to perfom automated execution of the tests via a GitHub workflow. -Daemon regression tests can be executed via a Docker container by using a fake version of the daemon driver manager. -This was implmented to perfom automated execution of the regression tests via a GitHub workflow. To build the Docker image for the daemon regression tests run: docker build --progress=plain -f ./Dockerfile.daemon_tests -t aes67-daemon-tests . @@ -124,16 +126,16 @@ See [ALSA RAVENNA/AES67 Driver README](https://github.com/bondagit/aes67-linux-d This directory contains systemd configuration files for the daemon. -The daemon integrates with systemd watchdog. To enable it recompile with the CMake option _-DWITH_SYSTEMD=ON_ +The daemon integrates with systemd watchdog. -You can install the daemon under systemd using the following commands: +To enable it recompile the daemon with the CMake option _-DWITH_SYSTEMD=ON_ - sudo useradd -M -l aes67-daemon -c "AES67 Linux daemon" - sudo cp daemon/aes67-daemon /usr/local/bin/aes67-daemon - sudo cp daemon/daemon.conf /etc - sudo cp systemd/aes67-daemon.service /etc/systemd/system - sudo systemctl enable aes67-daemon - sudo systemctl daemon-reexec +You can install the daemon under _systemd_ by using the script [systemd/install.sh](install.sh): + + cd systemd + sudo ./install.sh + +Before starting the daemon edit _/etc/daemon.conf_ and make sure the _interface_name_ parameter is set to your ethernet interface. To start the daemon use: @@ -154,7 +156,6 @@ You can usally install the module using the following commands: If this doesn't work because you miss kernel certificate follow the instructions at: [No OpenSSL sign-file signing_key.pem](https://superuser.com/questions/1214116/no-openssl-sign-file-signing-key-pem-leads-to-error-while-loading-kernel-modules) - Finally use the command to load the modules: sudo depmod -a @@ -320,8 +321,8 @@ and the specified buffer size cannot be used. **_Important_** Starting from Linux kernel 5.10.x onwards a change in a kernel parameter is required to fix a problem with round robin scheduler causing the latency test to fail, see [Real Time Scheduler Throttling](#notes). -## Run the daemon regression tests ## -To run daemon regression tests install the ALSA RAVENNA/AES67 kernel module with: +## Run the daemon tests ## +To run daemon tests install the ALSA RAVENNA/AES67 kernel module with: sudo insmod 3rdparty/ravenna-alsa-lkm/driver/MergingRavennaALSA.ko @@ -333,8 +334,6 @@ make sure that no instances of the aes67-daemon are running, enter the [tests](d ./daemon-test -p -**_NOTE:_** when running regression tests make sure that no other Ravenna mDNS sources are advertised on the network because this will affect the results. Regression tests run on loopback interface but Avahi ignores the interface parameter set and will forward to the daemon the sources found on all network interfaces. - ## Notes ## diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8c1a1e6..2121860 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,9 +1,9 @@ -# Docker -# Build a Docker image -# https://docs.microsoft.com/azure/devops/pipelines/languages/docker +# Azure pipeline to build and run daemon tests into Docker image trigger: -- master + branches: + include: + - '*' resources: - repo: self @@ -11,19 +11,13 @@ resources: variables: tag: '$(Build.BuildId)' -stages: -- stage: Build - displayName: Build image - jobs: - - job: Build - displayName: Build - pool: - vmImage: ubuntu-latest - steps: - - task: Docker@2 - displayName: Build an image - inputs: - command: build - dockerfile: '$(Build.SourcesDirectory)/Dockerfile.daemon_tests' - tags: | - $(tag) +pool: Default + +steps: +- task: Docker@2 + displayName: Build and run daemon tests + inputs: + command: build + dockerfile: '$(Build.SourcesDirectory)/Dockerfile.daemon_tests' + tags: | + $(tag) diff --git a/daemon/browser.cpp b/daemon/browser.cpp index 7f6ba58..a8d98bd 100644 --- a/daemon/browser.cpp +++ b/daemon/browser.cpp @@ -96,6 +96,8 @@ bool Browser::worker() { BOOST_LOG_TRIVIAL(debug) << "browser:: refreshing SAP source " << it->id; // annoucement, update last seen and announce period + last_update_ = + duration_cast(steady_clock::now() - startup_).count(); auto upd_source{*it}; if ((last_update_ - upd_source.last_seen) != 0) { upd_source.announce_period = last_update_ - upd_source.last_seen; diff --git a/daemon/browser.hpp b/daemon/browser.hpp index 716ca88..3e64a7c 100644 --- a/daemon/browser.hpp +++ b/daemon/browser.hpp @@ -57,7 +57,6 @@ class Browser : public MDNSClient { Browser() = delete; Browser(const Browser&) = delete; Browser& operator=(const Browser&) = delete; - virtual ~Browser() { terminate(); }; bool init() override; bool terminate() override; @@ -68,17 +67,17 @@ class Browser : public MDNSClient { protected: // singleton, use create() to build - Browser(std::shared_ptr config) - : MDNSClient(config), startup_(std::chrono::steady_clock::now()){}; + explicit Browser(std::shared_ptr config) : MDNSClient(config){}; bool worker(); - virtual void on_change_rtsp_source(const std::string& name, - const std::string& domain, - const RtspSource& source) override; - virtual void on_remove_rtsp_source(const std::string& name, - const std::string& domain) override; + void on_change_rtsp_source(const std::string& name, + const std::string& domain, + const RtspSource& source) override; + void on_remove_rtsp_source(const std::string& name, + const std::string& domain) override; + private: std::future res_; std::atomic_bool running_{false}; @@ -99,7 +98,7 @@ class Browser : public MDNSClient { SAP sap_{config_->get_sap_mcast_addr()}; IGMP igmp_; - std::chrono::time_point startup_; + std::chrono::time_point startup_{std::chrono::steady_clock::now()}; uint32_t last_update_{0}; /* seconds from daemon startup */ }; diff --git a/daemon/config.cpp b/daemon/config.cpp index b32199a..c1c6113 100644 --- a/daemon/config.cpp +++ b/daemon/config.cpp @@ -76,8 +76,7 @@ std::shared_ptr Config::parse(const std::string& filename, config.sap_mcast_addr_ = "224.2.127.254"; } if (config.ptp_domain_ > 127) - if (config.ptp_domain_ > 127) - config.ptp_domain_ = 0; + config.ptp_domain_ = 0; auto [mac_addr, mac_str] = get_interface_mac(config.interface_name_); if (mac_str.empty()) { diff --git a/daemon/config.hpp b/daemon/config.hpp index 7ad5344..f800b18 100644 --- a/daemon/config.hpp +++ b/daemon/config.hpp @@ -35,7 +35,7 @@ class Config { /* attributes retrieved from config json */ uint16_t get_http_port() const { return http_port_; }; uint16_t get_rtsp_port() const { return rtsp_port_; }; - const std::string get_http_base_dir() const { return http_base_dir_; }; + const std::string& get_http_base_dir() const { return http_base_dir_; }; int get_log_severity() const { return log_severity_; }; uint32_t get_playout_delay() const { return playout_delay_; }; uint32_t get_tic_frame_size_at_1fs() const { return tic_frame_size_at_1fs_; }; @@ -64,14 +64,14 @@ class Config { bool get_daemon_restart() const { return daemon_restart_; }; bool get_driver_restart() const { return driver_restart_; }; bool get_mdns_enabled() const { return mdns_enabled_; }; - int get_interface_idx() { return interface_idx_; }; + int get_interface_idx() const { return interface_idx_; }; const std::string& get_ptp_status_script() const { return ptp_status_script_; } void set_http_port(uint16_t http_port) { http_port_ = http_port; }; void set_rtsp_port(uint16_t rtsp_port) { rtsp_port_ = rtsp_port; }; - void set_http_base_dir(const std::string& http_base_dir) { + void set_http_base_dir(std::string_view http_base_dir) { http_base_dir_ = http_base_dir; }; void set_log_severity(int log_severity) { log_severity_ = log_severity; }; @@ -85,10 +85,10 @@ class Config { max_tic_frame_size_ = max_tic_frame_size; }; void set_sample_rate(uint32_t sample_rate) { sample_rate_ = sample_rate; }; - void set_rtp_mcast_base(const std::string& rtp_mcast_base) { + void set_rtp_mcast_base(std::string_view rtp_mcast_base) { rtp_mcast_base_ = rtp_mcast_base; }; - void set_sap_mcast_addr(const std::string& sap_mcast_addr) { + void set_sap_mcast_addr(std::string_view sap_mcast_addr) { sap_mcast_addr_ = sap_mcast_addr; }; void set_rtp_port(uint16_t rtp_port) { rtp_port_ = rtp_port; }; @@ -97,30 +97,30 @@ class Config { void set_sap_interval(uint16_t sap_interval) { sap_interval_ = sap_interval; }; - void set_syslog_proto(const std::string& syslog_proto) { + void set_syslog_proto(std::string_view syslog_proto) { syslog_proto_ = syslog_proto; }; - void set_syslog_server(const std::string& syslog_server) { + void set_syslog_server(std::string_view syslog_server) { syslog_server_ = syslog_server; }; - void set_status_file(const std::string& status_file) { + void set_status_file(std::string_view status_file) { status_file_ = status_file; }; - void set_interface_name(const std::string& interface_name) { + void set_interface_name(std::string_view interface_name) { interface_name_ = interface_name; }; - void set_ip_addr_str(const std::string& ip_str) { ip_str_ = ip_str; }; + void set_ip_addr_str(std::string_view ip_str) { ip_str_ = ip_str; }; void set_ip_addr(uint32_t ip_addr) { ip_addr_ = ip_addr; }; - void set_mac_addr_str(const std::string& mac_str) { mac_str_ = mac_str; }; + void set_mac_addr_str(std::string_view mac_str) { mac_str_ = mac_str; }; void set_mac_addr(const std::array& mac_addr) { mac_addr_ = mac_addr; }; void set_mdns_enabled(bool enabled) { mdns_enabled_ = enabled; }; void set_interface_idx(int index) { interface_idx_ = index; }; - void set_ptp_status_script(const std::string& script) { + void set_ptp_status_script(std::string_view script) { ptp_status_script_ = script; }; - void set_custom_node_id(const std::string& node_id) { + void set_custom_node_id(std::string_view node_id) { custom_node_id_ = node_id; }; void set_auto_sinks_update(bool auto_sinks_update) { diff --git a/daemon/driver_handler.cpp b/daemon/driver_handler.cpp index 0ba8690..78241bf 100644 --- a/daemon/driver_handler.cpp +++ b/daemon/driver_handler.cpp @@ -54,7 +54,7 @@ void DriverHandler::send(enum MT_ALSA_msg_id id, NetlinkClient& client, uint8_t* buffer, size_t data_size, - const uint8_t* data) { + const uint8_t* data) const { struct MT_ALSA_msg alsa_msg; memset(&alsa_msg, 0, sizeof(alsa_msg)); alsa_msg.id = id; @@ -143,7 +143,7 @@ bool DriverHandler::terminate(const Config& /* config */) { void DriverHandler::send_command(enum MT_ALSA_msg_id id, size_t data_size, const uint8_t* data) { - std::lock_guard lock(mutex_); + std::scoped_lock lock{mutex_}; if (data_size > max_payload) { on_command_error(id, DaemonErrc::send_invalid_size); return; diff --git a/daemon/driver_handler.hpp b/daemon/driver_handler.hpp index 501ab05..a27e2d0 100644 --- a/daemon/driver_handler.hpp +++ b/daemon/driver_handler.hpp @@ -37,7 +37,7 @@ class DriverHandler { static constexpr size_t buffer_size = NLMSG_SPACE(max_payload) + sizeof(struct MT_ALSA_msg); - DriverHandler(){}; + DriverHandler() = default; DriverHandler(const DriverHandler&) = delete; DriverHandler& operator=(const DriverHandler&) = delete; virtual ~DriverHandler(){}; @@ -67,7 +67,7 @@ class DriverHandler { NetlinkClient& client, uint8_t* buffer, size_t data_size, - const uint8_t* data); + const uint8_t* data) const; bool event_receiver(); std::future res_; diff --git a/daemon/driver_manager.cpp b/daemon/driver_manager.cpp index 9715db0..f1fe34c 100644 --- a/daemon/driver_manager.cpp +++ b/daemon/driver_manager.cpp @@ -75,7 +75,7 @@ bool DriverManager::init(const Config& config) { return false; } - sample_rate = config.get_sample_rate(); + sample_rate_ = config.get_sample_rate(); TPTPConfig ptp_config; ptp_config.ui8Domain = config.get_ptp_domain(); @@ -287,39 +287,41 @@ void DriverManager::on_event(enum MT_ALSA_msg_id id, break; case MT_ALSA_Msg_SetMasterOutputVolume: if (req_size == sizeof(int32_t)) { - memcpy(&output_volume, req, req_size); + memcpy(&output_volume_, req, req_size); BOOST_LOG_TRIVIAL(info) - << "driver_manager:: event SetMasterOutputVolume " << output_volume; + << "driver_manager:: event SetMasterOutputVolume " + << output_volume_; } resp_size = 0; break; case MT_ALSA_Msg_SetMasterOutputSwitch: if (req_size == sizeof(int32_t)) { - memcpy(&output_switch, req, req_size); + memcpy(&output_switch_, req, req_size); BOOST_LOG_TRIVIAL(info) - << "driver_manager:: event SetMasterOutputSwitch " << output_switch; + << "driver_manager:: event SetMasterOutputSwitch " + << output_switch_; } resp_size = 0; break; case MT_ALSA_Msg_SetSampleRate: if (req_size == sizeof(uint32_t)) { - memcpy(&sample_rate, req, req_size); + memcpy(&sample_rate_, req, req_size); BOOST_LOG_TRIVIAL(info) - << "driver_manager:: event SetSampleRate " << sample_rate; + << "driver_manager:: event SetSampleRate " << sample_rate_; } resp_size = 0; break; case MT_ALSA_Msg_GetMasterOutputVolume: resp_size = sizeof(int32_t); - memcpy(resp, &output_volume, resp_size); + memcpy(resp, &output_volume_, resp_size); BOOST_LOG_TRIVIAL(info) - << "driver_manager:: event GetMasterOutputVolume " << output_volume; + << "driver_manager:: event GetMasterOutputVolume " << output_volume_; break; case MT_ALSA_Msg_GetMasterOutputSwitch: resp_size = sizeof(int32_t); - memcpy(resp, &output_switch, resp_size); + memcpy(resp, &output_switch_, resp_size); BOOST_LOG_TRIVIAL(info) - << "driver_manager:: event GetMasterOutputSwitch " << output_switch; + << "driver_manager:: event GetMasterOutputSwitch " << output_switch_; break; default: BOOST_LOG_TRIVIAL(error) << "driver_manager:: unknown event " diff --git a/daemon/driver_manager.hpp b/daemon/driver_manager.hpp index fda9c8d..bfb5c1c 100644 --- a/daemon/driver_manager.hpp +++ b/daemon/driver_manager.hpp @@ -53,13 +53,13 @@ class DriverManager : public DriverHandler { std::error_code get_number_of_inputs(int32_t& inputs); std::error_code get_number_of_outputs(int32_t& outputs); - int32_t get_current_output_volume() { return output_volume; }; - int32_t get_current_output_switch() { return output_switch; }; - uint32_t get_current_sample_rate() { return sample_rate; }; + int32_t get_current_output_volume() const { return output_volume_; }; + int32_t get_current_output_switch() const { return output_switch_; }; + uint32_t get_current_sample_rate() const { return sample_rate_; }; protected: // singleton, use create to build - DriverManager(){}; + DriverManager() = default; // these are used in init/terminate std::error_code hello(); @@ -79,12 +79,13 @@ class DriverManager : public DriverHandler { const uint8_t* req = nullptr) override; void on_event_error(enum MT_ALSA_msg_id id, std::error_code error) override; + private: std::error_code retcode_; uint8_t recv_data_[NLMSG_SPACE(max_payload)]{0}; - int32_t output_volume{-20}; - int32_t output_switch{0}; - uint32_t sample_rate{0}; + int32_t output_volume_{-20}; + int32_t output_switch_{0}; + uint32_t sample_rate_{0}; }; #endif diff --git a/daemon/fake_driver_manager.cpp b/daemon/fake_driver_manager.cpp index 40983e0..da5b342 100644 --- a/daemon/fake_driver_manager.cpp +++ b/daemon/fake_driver_manager.cpp @@ -120,8 +120,9 @@ std::error_code DriverManager::add_rtp_stream( uint64_t& stream_handle) { stream_handle = ++g_handle; handles_.insert(stream_handle); - BOOST_LOG_TRIVIAL(info) << "fake_driver_manager:: add RTP stream success handle " - << stream_handle; + BOOST_LOG_TRIVIAL(info) + << "fake_driver_manager:: add RTP stream success handle " + << stream_handle; return std::error_code{}; } @@ -170,7 +171,8 @@ std::error_code DriverManager::set_playout_delay(int32_t delay) { std::error_code DriverManager::get_sample_rate(uint32_t& sample_rate) { sample_rate = sample_rate_; - BOOST_LOG_TRIVIAL(info) << "fake_driver_manager:: sample rate " << sample_rate; + BOOST_LOG_TRIVIAL(info) << "fake_driver_manager:: sample rate " + << sample_rate; return std::error_code{}; } diff --git a/daemon/fake_driver_manager.hpp b/daemon/fake_driver_manager.hpp index f6c6708..4c12d3b 100644 --- a/daemon/fake_driver_manager.hpp +++ b/daemon/fake_driver_manager.hpp @@ -52,13 +52,13 @@ class DriverManager { std::error_code get_number_of_inputs(int32_t& inputs); std::error_code get_number_of_outputs(int32_t& outputs); - int32_t get_current_output_volume() { return output_volume_; }; - int32_t get_current_output_switch() { return output_switch_; }; - uint32_t get_current_sample_rate() { return sample_rate_; }; + int32_t get_current_output_volume() const { return output_volume_; }; + int32_t get_current_output_switch() const { return output_switch_; }; + uint32_t get_current_sample_rate() const { return sample_rate_; }; protected: // singleton, use create to build - DriverManager(){}; + DriverManager() = default; // these are used in init/terminate std::error_code hello(); diff --git a/daemon/http_server.cpp b/daemon/http_server.cpp index 2a9e005..9aff992 100644 --- a/daemon/http_server.cpp +++ b/daemon/http_server.cpp @@ -31,7 +31,7 @@ using namespace httplib; static inline void set_headers(Response& res, - const std::string content_type = "") { + const std::string& content_type = "") { res.set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); res.set_header("Access-Control-Allow-Origin", "*"); @@ -57,7 +57,6 @@ static inline int get_http_error_status(const std::error_code& code) { static inline std::string get_http_error_message(const std::error_code& code) { std::stringstream ss; - ; ss << "(" << code.category().name() << ") " << code.message(); return ss.str(); } @@ -352,11 +351,12 @@ bool HttpServer::init() { httplib::Client cli(config_->get_ip_addr_str().c_str(), config_->get_http_port()); int retry = 3; - while (retry--) { + while (retry) { auto res = cli.Get("/api/config"); if (res && res->status == 200) { break; } + --retry; std::this_thread::sleep_for(std::chrono::seconds(1)); } return retry; diff --git a/daemon/http_server.hpp b/daemon/http_server.hpp index 4741046..1b561f5 100644 --- a/daemon/http_server.hpp +++ b/daemon/http_server.hpp @@ -29,9 +29,9 @@ class HttpServer { public: HttpServer() = delete; - HttpServer(std::shared_ptr session_manager, - std::shared_ptr browser, - std::shared_ptr config) + explicit HttpServer(std::shared_ptr session_manager, + std::shared_ptr browser, + std::shared_ptr config) : session_manager_(session_manager), browser_(browser), config_(config){}; bool init(); bool terminate(); diff --git a/daemon/igmp.hpp b/daemon/igmp.hpp index e5c35d0..58b350b 100644 --- a/daemon/igmp.hpp +++ b/daemon/igmp.hpp @@ -41,11 +41,11 @@ class IGMP { bool join(const std::string& interface_ip, const std::string& mcast_ip) { uint32_t mcast_ip_addr = ip::address_v4::from_string(mcast_ip.c_str()).to_ulong(); - std::lock_guard lock(mutex); + std::scoped_lock lock{mutex}; auto it = mcast_ref.find(mcast_ip_addr); if (it != mcast_ref.end() && (*it).second > 0) { - mcast_ref[mcast_ip_addr]++; + (*it).second++; return true; } @@ -76,14 +76,14 @@ class IGMP { bool leave(const std::string& interface_ip, const std::string& mcast_ip) { uint32_t mcast_ip_addr = ip::address_v4::from_string(mcast_ip.c_str()).to_ulong(); - std::lock_guard lock(mutex); + std::scoped_lock lock{mutex}; auto it = mcast_ref.find(mcast_ip_addr); if (it == mcast_ref.end() || (*it).second == 0) { return false; } - if (--mcast_ref[mcast_ip_addr] > 0) { + if (--(*it).second > 0) { return true; } diff --git a/daemon/interface.cpp b/daemon/interface.cpp index f5f9fb5..ce89621 100644 --- a/daemon/interface.cpp +++ b/daemon/interface.cpp @@ -127,7 +127,7 @@ std::pair, std::string> get_mac_from_arp_cache( std::vector tokens; std::getline(stream, line); - if (line.find(ip)) { + if (line.find(ip) == std::string::npos) { continue; } boost::split(tokens, line, boost::is_any_of(" "), boost::token_compress_on); @@ -139,8 +139,8 @@ std::pair, std::string> get_mac_from_arp_cache( int j = 0; bool check = false; for (auto const& item : vec) { - mac[j] = strtol(item.c_str(), NULL, 16); - check |= mac[j]; + mac[j] = strtol(item.c_str(), nullptr, 16); + check = check | (mac[j] != 0); j++; } if (check) { diff --git a/daemon/json.cpp b/daemon/json.cpp index a395976..c39c3ec 100644 --- a/daemon/json.cpp +++ b/daemon/json.cpp @@ -29,7 +29,7 @@ #include "json.hpp" static inline std::string remove_undesired_chars(const std::string& s) { - std::regex html_regex("[^ A-Za-z0-9:~.,_/=%\()\\r\\n\\t\?#-]?"); + std::regex html_regex("[^ A-Za-z0-9:~.,_/=%()\\r\\n\\t\?#-]?"); return std::regex_replace(s, html_regex, ""); } diff --git a/daemon/main.cpp b/daemon/main.cpp index 98039ec..8706fbe 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -39,7 +39,7 @@ namespace po = boost::program_options; namespace postyle = boost::program_options::command_line_style; namespace logging = boost::log; -static std::string version("bondagit-1.6.1"); +static const std::string version("bondagit-1.6.2"); static std::atomic terminate = false; void termination_handler(int signum) { diff --git a/daemon/mdns_client.cpp b/daemon/mdns_client.cpp index 224e7f4..7dd746b 100644 --- a/daemon/mdns_client.cpp +++ b/daemon/mdns_client.cpp @@ -87,7 +87,7 @@ void MDNSClient::resolve_callback(AvahiServiceResolver* r, (mdns.config_->get_interface_name() != "lo")) || ((flags & AVAHI_LOOKUP_RESULT_LOCAL) && (mdns.config_->get_interface_name() == "lo"))) { - std::lock_guard lock(mdns.sources_res_mutex_); + std::scoped_lock lock{mdns.sources_res_mutex_}; /* process RTSP client in async task */ mdns.sources_res_.emplace_back(std::async( @@ -153,7 +153,7 @@ void MDNSClient::browse_callback(AvahiServiceBrowser* b, << avahi_strerror(avahi_client_errno(mdns.client_.get())); } else { /* add the resolver to the active pool */ - mdns.active_resolvers.insert({name, domain}); + mdns.active_resolvers.emplace(name, domain); } break; @@ -244,7 +244,7 @@ bool MDNSClient::init() { void MDNSClient::process_results() { #ifdef _USE_AVAHI_ - std::lock_guard lock(sources_res_mutex_); + std::scoped_lock lock{sources_res_mutex_}; /* remove all completed results and populate remote sources list */ sources_res_.remove_if([](auto& result) { if (!result.valid()) { @@ -269,7 +269,7 @@ bool MDNSClient::terminate() { RtspClient::stop_all(); #ifdef _USE_AVAHI_ /* wait for all pending results and remove from list */ - std::lock_guard lock(sources_res_mutex_); + std::scoped_lock lock{sources_res_mutex_}; BOOST_LOG_TRIVIAL(info) << "mdns_client:: waiting for " << sources_res_.size() << " RTSP clients"; sources_res_.remove_if([](auto& result) { diff --git a/daemon/mdns_client.hpp b/daemon/mdns_client.hpp index 2525ec8..fd15117 100644 --- a/daemon/mdns_client.hpp +++ b/daemon/mdns_client.hpp @@ -39,11 +39,11 @@ class MDNSClient { public: - MDNSClient(std::shared_ptr config) : config_(config){}; + explicit MDNSClient(std::shared_ptr config) : config_(config){}; MDNSClient() = delete; MDNSClient(const MDNSClient&) = delete; MDNSClient& operator=(const MDNSClient&) = delete; - virtual ~MDNSClient() { terminate(); }; + virtual ~MDNSClient() = default; virtual bool init(); virtual bool terminate(); @@ -55,22 +55,7 @@ class MDNSClient { virtual void on_remove_rtsp_source(const std::string& name, const std::string& domain){}; - void process_results(); - std::list > sources_res_; - std::mutex sources_res_mutex_; - - std::atomic_bool running_{false}; - std::shared_ptr config_; - #ifdef _USE_AVAHI_ - /* order is important here */ - std::unique_ptr poll_{ - nullptr, &avahi_threaded_poll_free}; - std::unique_ptr client_{ - nullptr, &avahi_client_free}; - std::unique_ptr - sb_{nullptr, &avahi_service_browser_free}; - static void resolve_callback(AvahiServiceResolver* r, AvahiIfIndex interface, AvahiProtocol protocol, @@ -96,10 +81,28 @@ class MDNSClient { static void client_callback(AvahiClient* c, AvahiClientState state, void* userdata); +#endif + void process_results(); + + std::shared_ptr config_; + + private: + std::list > sources_res_; + std::mutex sources_res_mutex_; + + std::atomic_bool running_{false}; + +#ifdef _USE_AVAHI_ + /* order is important here */ + std::unique_ptr poll_{ + nullptr, &avahi_threaded_poll_free}; + std::unique_ptr client_{ + nullptr, &avahi_client_free}; + std::unique_ptr + sb_{nullptr, &avahi_service_browser_free}; std::set > active_resolvers; - #endif }; diff --git a/daemon/mdns_server.cpp b/daemon/mdns_server.cpp index 9611d3d..6626e6d 100644 --- a/daemon/mdns_server.cpp +++ b/daemon/mdns_server.cpp @@ -28,7 +28,7 @@ #ifdef _USE_AVAHI_ struct AvahiLockGuard { AvahiLockGuard() = delete; - AvahiLockGuard(AvahiThreadedPoll* poll) : poll_(poll) { + explicit AvahiLockGuard(AvahiThreadedPoll* poll) : poll_(poll) { if (poll_ != nullptr) { avahi_threaded_poll_lock(poll_); } @@ -38,6 +38,8 @@ struct AvahiLockGuard { avahi_threaded_poll_unlock(poll_); } } + AvahiLockGuard(const AvahiLockGuard&) = delete; + AvahiLockGuard& operator=(const AvahiLockGuard&) = delete; private: AvahiThreadedPoll* poll_{nullptr}; diff --git a/daemon/mdns_server.hpp b/daemon/mdns_server.hpp index 178b3ce..a2aa875 100644 --- a/daemon/mdns_server.hpp +++ b/daemon/mdns_server.hpp @@ -46,15 +46,27 @@ class MDNSServer { MDNSServer() = delete; MDNSServer(const MDNSServer&) = delete; MDNSServer& operator=(const MDNSServer&) = delete; - virtual ~MDNSServer() { terminate(); }; + virtual ~MDNSServer() = default; virtual bool init(); virtual bool terminate(); - bool add_service(const std::string& name, const std::string& sdp); + bool add_service(const std::string& name, const std::string &sdp); bool remove_service(const std::string& name); protected: +#ifdef _USE_AVAHI_ + static void entry_group_callback(AvahiEntryGroup* g, + AvahiEntryGroupState state, + void* userdata); + static void client_callback(AvahiClient* c, + AvahiClientState state, + void* userdata); + + bool create_services(AvahiClient* client); +#endif + + private: std::atomic_bool running_{false}; std::shared_ptr session_manager_; std::shared_ptr config_; @@ -72,14 +84,6 @@ class MDNSServer { std::unique_ptr client_{ nullptr, &avahi_client_free}; - static void entry_group_callback(AvahiEntryGroup* g, - AvahiEntryGroupState state, - void* userdata); - static void client_callback(AvahiClient* c, - AvahiClientState state, - void* userdata); - - bool create_services(AvahiClient* client); #endif }; diff --git a/daemon/netlink.hpp b/daemon/netlink.hpp index cfc0fe1..7635f04 100644 --- a/daemon/netlink.hpp +++ b/daemon/netlink.hpp @@ -26,62 +26,55 @@ template class nl_endpoint { private: - sockaddr_nl sockaddr{.nl_family = AF_NETLINK}; + sockaddr_nl sockaddr_{.nl_family = AF_NETLINK}; public: using protocol_type = Protocol; using data_type = boost::asio::detail::socket_addr_type; nl_endpoint() { - sockaddr.nl_groups = 0; - sockaddr.nl_pid = getpid(); + sockaddr_.nl_groups = 0; + sockaddr_.nl_pid = getpid(); } nl_endpoint(int group, int pid = getpid()) { - sockaddr.nl_groups = group; - sockaddr.nl_pid = pid; - } - - nl_endpoint(const nl_endpoint& other) { sockaddr = other.sockaddr; } - - nl_endpoint& operator=(const nl_endpoint& other) { - sockaddr = other.sockaddr; - return *this; + sockaddr_.nl_groups = group; + sockaddr_.nl_pid = pid; } protocol_type protocol() const { return protocol_type(); } - data_type* data() { return reinterpret_cast(&sockaddr); } + data_type* data() { return reinterpret_cast(&sockaddr_); } const data_type* data() const { - return reinterpret_cast(&sockaddr); + return reinterpret_cast(&sockaddr_); } - std::size_t size() const { return sizeof(sockaddr); } + std::size_t size() const { return sizeof(sockaddr_); } void resize(std::size_t size) { /* nothing we can do here */ } - std::size_t capacity() const { return sizeof(sockaddr); } + std::size_t capacity() const { return sizeof(sockaddr_); } }; class nl_protocol { public: - nl_protocol() { proto = 0; } + nl_protocol() : proto_(0) {} - explicit nl_protocol(int proto) { this->proto = proto; } + explicit nl_protocol(int proto) : proto_(proto) {} int type() const { return SOCK_RAW; } - int protocol() const { return proto; } + int protocol() const { return proto_; } int family() const { return PF_NETLINK; } - typedef nl_endpoint endpoint; - typedef boost::asio::basic_raw_socket socket; + using endpoint = nl_endpoint; + using socket = boost::asio::basic_raw_socket; private: - int proto; + int proto_; }; #endif diff --git a/daemon/netlink_client.hpp b/daemon/netlink_client.hpp index a085bc2..f8ce5e8 100644 --- a/daemon/netlink_client.hpp +++ b/daemon/netlink_client.hpp @@ -35,7 +35,7 @@ using boost::asio::deadline_timer; class NetlinkClient { public: NetlinkClient() = delete; - NetlinkClient(const std::string& name) : name_(name) {} + explicit NetlinkClient(const std::string& name) : name_(name) {} void init(const nl_endpoint& listen_endpoint, const nl_protocol& protocol) { diff --git a/daemon/rtsp_client.cpp b/daemon/rtsp_client.cpp index e1dea27..ff085e2 100644 --- a/daemon/rtsp_client.cpp +++ b/daemon/rtsp_client.cpp @@ -98,14 +98,13 @@ struct RtspActiveClientRemover { domain_(domain), wait_for_updates_(wait_for_updates) { if (stream_ != nullptr && wait_for_updates_) { - RtspClient::g_mutex.lock(); + std::scoped_lock lock{RtspClient::g_mutex}; RtspClient::g_active_clients[{name_, domain_}] = stream_; - RtspClient::g_mutex.unlock(); } } ~RtspActiveClientRemover() { if (stream_ != nullptr && wait_for_updates_) { - std::lock_guard lock(RtspClient::g_mutex); + std::scoped_lock lock{RtspClient::g_mutex}; auto it = RtspClient::g_active_clients.find({name_, domain_}); if (it != RtspClient::g_active_clients.end() && it->second == stream_) { RtspClient::g_active_clients.erase(it); @@ -113,6 +112,9 @@ struct RtspActiveClientRemover { } } + RtspActiveClientRemover(const RtspActiveClientRemover&) = delete; + RtspActiveClientRemover& operator=(const RtspActiveClientRemover&) = delete; + private: ip::tcp::iostream* stream_{nullptr}; const std::string& name_; @@ -120,13 +122,14 @@ struct RtspActiveClientRemover { bool wait_for_updates_{false}; }; -std::pair RtspClient::process(RtspClient::Observer callback, - const std::string& name, - const std::string& domain, - const std::string& path, - const std::string& address, - const std::string& port, - bool wait_for_updates) { +std::pair RtspClient::process( + const RtspClient::Observer& callback, + const std::string& name, + const std::string& domain, + const std::string& path, + const std::string& address, + const std::string& port, + bool wait_for_updates) { RtspSource rtsp_source; ip::tcp::iostream s; RtspActiveClientRemover clientRemover(&s, name, domain, wait_for_updates); @@ -258,9 +261,9 @@ std::pair RtspClient::process(RtspClient::Observer callback, if (std::get<0>(res)) { /* if we find a valid announced source name we use it * otherwise we try from SDP file or we use the mDNS name */ - auto path = std::get<4>(res); + const auto& lpath = std::get<4>(res); if (path.rfind("/by-name/") != std::string::npos) { - announced_name = path.substr(9); + announced_name = lpath.substr(9); BOOST_LOG_TRIVIAL(debug) << "rtsp_client:: found announced name " << announced_name; } @@ -279,7 +282,7 @@ std::pair RtspClient::process(RtspClient::Observer callback, } void RtspClient::stop(const std::string& name, const std::string& domain) { - std::lock_guard lock(g_mutex); + std::scoped_lock lock{g_mutex}; auto it = g_active_clients.find({name, domain}); if (it != g_active_clients.end()) { BOOST_LOG_TRIVIAL(info) @@ -294,12 +297,12 @@ void RtspClient::stop(const std::string& name, const std::string& domain) { } bool RtspClient::is_active(const std::string& name, const std::string& domain) { - std::lock_guard lock(g_mutex); + std::scoped_lock lock{g_mutex}; return g_active_clients.find({name, domain}) != g_active_clients.end(); } void RtspClient::stop_all() { - std::lock_guard lock(g_mutex); + std::scoped_lock lock{g_mutex}; auto it = g_active_clients.begin(); while (it != g_active_clients.end()) { BOOST_LOG_TRIVIAL(info) << "rtsp_client:: stopping client " diff --git a/daemon/rtsp_client.hpp b/daemon/rtsp_client.hpp index 7c8623e..502f959 100644 --- a/daemon/rtsp_client.hpp +++ b/daemon/rtsp_client.hpp @@ -41,7 +41,7 @@ class RtspClient { const std::string& domain, const RtspSource& source)>; - static std::pair process(Observer callback, + static std::pair process(const Observer& callback, const std::string& name, const std::string& domain, const std::string& path, @@ -57,11 +57,11 @@ class RtspClient { const std::string& address, const std::string& port = dft_port); - inline static std::atomic g_seq_number{0}; inline static std::map< std::pair, boost::asio::ip::tcp::iostream* /*stream*/> g_active_clients; + inline static std::atomic g_seq_number{0}; inline static std::mutex g_mutex; }; diff --git a/daemon/rtsp_server.cpp b/daemon/rtsp_server.cpp index 55b482e..c495890 100644 --- a/daemon/rtsp_server.cpp +++ b/daemon/rtsp_server.cpp @@ -25,7 +25,7 @@ bool RtspServer::update_source(uint8_t id, const std::string& sdp) { bool ret = false; BOOST_LOG_TRIVIAL(debug) << "rtsp_server:: added source " << name; - std::lock_guard lock(mutex_); + std::scoped_lock lock{mutex_}; for (unsigned int i = 0; i < sessions_.size(); i++) { auto session = sessions_[i].lock(); if (session != nullptr) { @@ -39,7 +39,7 @@ bool RtspServer::update_source(uint8_t id, void RtspServer::accept() { acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { if (!ec) { - std::lock_guard lock(mutex_); + std::scoped_lock lock{mutex_}; /* check for free sessions */ unsigned int i = 0; for (; i < sessions_.size(); i++) { @@ -73,8 +73,8 @@ bool RtspSession::announce(uint8_t id, * and the specified source id has been described on this session send update */ if (cseq_ < 0 && source_ids_.find(id) != source_ids_.end()) { - std::string path(std::string("/by-name/") + - config_->get_node_id() + " " + name); + std::string path(std::string("/by-name/") + config_->get_node_id() + " " + + name); std::stringstream ss; ss << "ANNOUNCE rtsp://" << address << ":" << std::to_string(port) << httplib::detail::encode_url(path) << " RTSP/1.0\r\n" @@ -170,17 +170,18 @@ void RtspSession::build_response(const std::string& url) { send_error(400, "Bad Request"); return; } - auto path = std::get<4>(res); - auto base_path = - std::string("/by-name/") + config_->get_node_id() + " "; + const auto& path = std::get<4>(res); + auto base_path = std::string("/by-name/") + config_->get_node_id() + " "; uint8_t id = SessionManager::stream_id_max + 1; if (path.rfind(base_path) != std::string::npos) { /* extract the source name from path and retrive the id */ id = session_manager_->get_source_id(path.substr(base_path.length())); } else if (path.rfind("/by-id/") != std::string::npos) { try { - id = stoi(path.substr(7)); + id = (uint8_t)stoi(path.substr(7)); } catch (...) { + id = SessionManager::stream_id_max + 1; + ; } } if (id != (SessionManager::stream_id_max + 1)) { diff --git a/daemon/rtsp_server.hpp b/daemon/rtsp_server.hpp index 52fb232..b170edc 100644 --- a/daemon/rtsp_server.hpp +++ b/daemon/rtsp_server.hpp @@ -44,10 +44,7 @@ class RtspSession : public std::enable_shared_from_this { tcp::socket socket) : config_(config), session_manager_(session_manager), - socket_(std::move(socket)), - length_{0}, - cseq_{-1}, - consumed_{0} {} + socket_(std::move(socket)) {} virtual ~RtspSession() { BOOST_LOG_TRIVIAL(debug) << "rtsp_server:: session end"; @@ -87,18 +84,14 @@ class RtspServer { 2}; RtspServer() = delete; - RtspServer(std::shared_ptr session_manager, - std::shared_ptr config) + explicit RtspServer(std::shared_ptr session_manager, + std::shared_ptr config) : session_manager_(session_manager), config_(config), - sessions_(session_num_max), - sessions_start_point_(session_num_max), acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string( config_->get_ip_addr_str()), - config_->get_rtsp_port())), - socket_(io_service_) {} - + config_->get_rtsp_port())) {} bool init() { accept(); /* start rtsp server on a separate thread */ @@ -135,8 +128,8 @@ class RtspServer { boost::asio::io_service io_service_; std::shared_ptr session_manager_; std::shared_ptr config_; - std::vector > sessions_; - std::vector > sessions_start_point_; + std::vector > sessions_{session_num_max}; + std::vector > sessions_start_point_{session_num_max}; tcp::acceptor acceptor_; tcp::socket socket_{io_service_}; std::future res_; diff --git a/daemon/sap.cpp b/daemon/sap.cpp index 3149ef5..03232d7 100644 --- a/daemon/sap.cpp +++ b/daemon/sap.cpp @@ -106,7 +106,7 @@ bool SAP::receive(bool& is_announce, is_announce = (buffer[0] == 0x20); memcpy(&msg_id_hash, buffer + 2, sizeof(msg_id_hash)); memcpy(&addr, buffer + 4, sizeof(addr)); - for (int i = 8; buffer[i] != 0 && i < static_cast(length); i++) { + for (int i = 8; i < static_cast(length) && buffer[i] != 0; i++) { buffer[i] = std::tolower(buffer[i]); } if (!memcmp(buffer + 8, "application/sdp", 16)) { diff --git a/daemon/sap.hpp b/daemon/sap.hpp index 934d738..fbe8e52 100644 --- a/daemon/sap.hpp +++ b/daemon/sap.hpp @@ -37,7 +37,7 @@ class SAP { constexpr static uint16_t max_length = 4096; SAP() = delete; - SAP(const std::string& sap_mcast_addr); + explicit SAP(const std::string& sap_mcast_addr); bool set_multicast_interface(const std::string& interface_ip); bool announcement(uint16_t msg_id_hash, diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index c84a484..7c1a18d 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -38,7 +38,7 @@ #include "session_manager.hpp" #include "interface.hpp" -static uint8_t get_codec_word_length(const std::string& codec) { +static uint8_t get_codec_word_length(std::string_view codec) { if (codec == "L16") { return 2; } @@ -60,7 +60,7 @@ static uint8_t get_codec_word_length(const std::string& codec) { return 0; } -bool SessionManager::parse_sdp(const std::string sdp, StreamInfo& info) const { +bool SessionManager::parse_sdp(const std::string& sdp, StreamInfo& info) const { /* v=0 o=- 4 0 IN IP4 10.0.0.12 @@ -409,7 +409,7 @@ bool SessionManager::load_status() { return true; } -bool SessionManager::save_status() { +bool SessionManager::save_status() const { if (config_->get_status_file().empty()) { return true; } @@ -443,7 +443,8 @@ uint8_t SessionManager::get_source_id(const std::string& name) const { return it != source_names_.end() ? it->second : (stream_id_max + 1); } -void SessionManager::add_source_observer(ObserverType type, Observer cb) { +void SessionManager::add_source_observer(ObserverType type, + const Observer& cb) { switch (type) { case ObserverType::add_source: add_source_observers.push_back(cb); @@ -459,7 +460,7 @@ void SessionManager::add_source_observer(ObserverType type, Observer cb) { void SessionManager::on_add_source(const StreamSource& source, const StreamInfo& info) { - for (auto cb : add_source_observers) { + for (const auto& cb : add_source_observers) { cb(source.id, source.name, get_source_sdp_(source.id, info)); } if (IN_MULTICAST(info.stream.m_ui32DestIP)) { @@ -470,8 +471,8 @@ void SessionManager::on_add_source(const StreamSource& source, } void SessionManager::on_remove_source(const StreamInfo& info) { - for (auto cb : remove_source_observers) { - cb(info.stream.m_uiId, info.stream.m_cName, {}); + for (const auto& cb : remove_source_observers) { + cb((uint8_t)info.stream.m_uiId, info.stream.m_cName, {}); } if (IN_MULTICAST(info.stream.m_ui32DestIP)) { igmp_.leave(config_->get_ip_addr_str(), @@ -531,13 +532,14 @@ std::error_code SessionManager::add_source(const StreamSource& source) { config_->get_interface_name(), ip::address_v4(info.stream.m_ui32DestIP).to_string()); int retry = 3; - while (!mac_addr.second.length() && retry--) { + while (!mac_addr.second.length() && retry > 0) { // if not in cache already try to populate the MAC cache (void)echo_try_connect( ip::address_v4(info.stream.m_ui32DestIP).to_string()); mac_addr = get_mac_from_arp_cache( config_->get_interface_name(), ip::address_v4(info.stream.m_ui32DestIP).to_string()); + retry--; } if (!mac_addr.second.length()) { BOOST_LOG_TRIVIAL(error) @@ -693,8 +695,7 @@ std::error_code SessionManager::remove_source(uint32_t id) { } std::error_code ret; - const auto& info = (*it).second; - if (info.enabled) { + if (const auto& info = (*it).second; info.enabled) { ret = driver_->remove_rtp_stream(info.handle); if (!ret) { on_remove_source(info); @@ -808,7 +809,7 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) { return DaemonErrc::cannot_parse_sdp; } - info.sink_sdp = std::move(sink.sdp); + info.sink_sdp = sink.sdp; } info.sink_source = sink.source; info.sink_use_sdp = true; // save back and use with SDP file @@ -922,7 +923,7 @@ std::error_code SessionManager::get_sink_status( return ret; } -std::error_code SessionManager::set_driver_config(const std::string& name, +std::error_code SessionManager::set_driver_config(std::string_view name, uint32_t value) const { if (name == "sample_rate") return driver_->set_sample_rate(value); @@ -1076,7 +1077,7 @@ void SessionManager::on_update_sources() { // trigger sources SDP file update sources_mutex_.lock(); for (auto& [id, info] : sources_) { - for (auto cb : update_source_observers) { + for (const auto& cb : update_source_observers) { info.session_version++; cb(id, info.stream.m_cName, get_source_sdp_(id, info)); } @@ -1104,7 +1105,7 @@ void SessionManager::on_ptp_status_changed(const std::string& status) const { char* argv_list[] = { const_cast(config_->get_ptp_status_script().c_str()), - const_cast(status.c_str()), NULL}; + const_cast(status.c_str()), nullptr}; execv(config_->get_ptp_status_script().c_str(), argv_list); exit(0); @@ -1142,7 +1143,8 @@ bool SessionManager::worker() { // return false; } else { char ptp_clock_id[24]; - uint8_t* pui64GMID = reinterpret_cast(&ptp_status.ui64GMID); + const uint8_t* pui64GMID = + reinterpret_cast(&ptp_status.ui64GMID); snprintf(ptp_clock_id, sizeof(ptp_clock_id), "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", pui64GMID[0], pui64GMID[1], pui64GMID[2], pui64GMID[3], pui64GMID[4], diff --git a/daemon/session_manager.hpp b/daemon/session_manager.hpp index d7d4d66..8ead203 100644 --- a/daemon/session_manager.hpp +++ b/daemon/session_manager.hpp @@ -86,7 +86,7 @@ struct PTPStatus { struct StreamInfo { TRTP_stream_info stream; uint64_t handle{0}; - bool enabled{0}; + bool enabled{false}; bool refclk_ptp_traceable{false}; bool ignore_refclk_gmid{false}; std::string io; @@ -109,7 +109,7 @@ class SessionManager { SessionManager() = delete; SessionManager(const SessionManager&) = delete; SessionManager& operator=(const SessionManager&) = delete; - virtual ~SessionManager() { terminate(); }; + virtual ~SessionManager() = default; // session manager interface bool init() { @@ -127,10 +127,10 @@ class SessionManager { if (running_) { running_ = false; auto ret = res_.get(); - for (auto source : get_sources()) { + for (const auto& source : get_sources()) { remove_source(source.id); } - for (auto sink : get_sinks()) { + for (const auto& sink : get_sinks()) { remove_sink(sink.id); } return ret; @@ -148,7 +148,7 @@ class SessionManager { enum class ObserverType { add_source, remove_source, update_source }; using Observer = std::function< bool(uint8_t id, const std::string& name, const std::string& sdp)>; - void add_source_observer(ObserverType type, Observer cb); + void add_source_observer(ObserverType type, const Observer& cb); std::error_code add_sink(const StreamSink& sink); std::error_code get_sink(uint8_t id, StreamSink& sink) const; @@ -158,13 +158,13 @@ class SessionManager { uint8_t get_sink_id(const std::string& name) const; std::error_code set_ptp_config(const PTPConfig& config); - std::error_code set_driver_config(const std::string& name, + std::error_code set_driver_config(std::string_view name, uint32_t value) const; void get_ptp_config(PTPConfig& config) const; void get_ptp_status(PTPStatus& status) const; bool load_status(); - bool save_status(); + bool save_status() const; size_t process_sap(); @@ -197,17 +197,18 @@ class SessionManager { bool sink_is_still_valid(const std::string sdp, const std::list sources_list) const; - bool parse_sdp(const std::string sdp, StreamInfo& info) const; + bool parse_sdp(const std::string& sdp, StreamInfo& info) const; bool worker(); // singleton, use create() to build - SessionManager(std::shared_ptr driver, - std::shared_ptr browser, - std::shared_ptr config) + explicit SessionManager(std::shared_ptr driver, + std::shared_ptr browser, + std::shared_ptr config) : browser_(browser), driver_(driver), config_(config) { ptp_config_.domain = config->get_ptp_domain(); ptp_config_.dscp = config->get_ptp_dscp(); }; + private: std::shared_ptr browser_; std::shared_ptr driver_; std::shared_ptr config_; diff --git a/daemon/tests/daemon_test.cpp b/daemon/tests/daemon_test.cpp index 1b6ddad..2bac33b 100644 --- a/daemon/tests/daemon_test.cpp +++ b/daemon/tests/daemon_test.cpp @@ -70,7 +70,8 @@ struct DaemonInstance { auto pid = daemon_.native_handle(); /* trigger normal daemon termination */ kill(pid, SIGTERM); - daemon_.wait(); + std::error_code ec; + daemon_.wait(ec); BOOST_REQUIRE_MESSAGE(!daemon_.exit_code(), "daemon exited normally"); ok = false; } diff --git a/daemon/utils.cpp b/daemon/utils.cpp index 9533a1c..30fc8c2 100644 --- a/daemon/utils.cpp +++ b/daemon/utils.cpp @@ -99,7 +99,7 @@ std::string sdp_get_subject(const std::string& sdp) { return ""; } -SDPOrigin sdp_get_origin(const std::string sdp) { +SDPOrigin sdp_get_origin(const std::string& sdp) { SDPOrigin origin; try { std::stringstream sstream(sdp); diff --git a/daemon/utils.hpp b/daemon/utils.hpp index c0757db..2085f11 100644 --- a/daemon/utils.hpp +++ b/daemon/utils.hpp @@ -55,6 +55,6 @@ struct SDPOrigin { } }; -SDPOrigin sdp_get_origin(const std::string sdp); +SDPOrigin sdp_get_origin(const std::string& sdp); #endif diff --git a/systemd/daemon.conf b/systemd/daemon.conf new file mode 100644 index 0000000..d942a77 --- /dev/null +++ b/systemd/daemon.conf @@ -0,0 +1,24 @@ +{ + "http_port": 8080, + "rtsp_port": 8854, + "http_base_dir": "/usr/local/share/aes67-daemon/webui/", + "log_severity": 2, + "playout_delay": 0, + "tic_frame_size_at_1fs": 64, + "max_tic_frame_size": 1024, + "sample_rate": 48000, + "rtp_mcast_base": "239.1.0.1", + "rtp_port": 5004, + "ptp_domain": 0, + "ptp_dscp": 48, + "sap_mcast_addr": "239.255.255.255", + "sap_interval": 30, + "syslog_proto": "none", + "syslog_server": "255.255.255.254:1234", + "status_file": "/etc/status.json", + "interface_name": "eth0", + "mdns_enabled": true, + "custom_node_id": "", + "ptp_status_script": "/usr/local/share/aes67-daemon/scripts/ptp_status.sh", + "auto_sinks_update": true +} diff --git a/systemd/install.sh b/systemd/install.sh new file mode 100755 index 0000000..dadee42 --- /dev/null +++ b/systemd/install.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# Tested on Ubuntu 21.04 +# + +#create a user for the daemon +sudo useradd -M -l aes67-daemon -c "AES67 Linux daemon" +#copy the daemon binary +sudo cp ../daemon/aes67-daemon /usr/local/bin/aes67-daemon +#create the daemon webui and scripts directories +sudo install -d -o aes67-daemon /var/lib/aes67-daemon /usr/local/share/aes67-daemon/scripts/ /usr/local/share/aes67-daemon/webui/ +#copy the ptp script +sudo install -o aes67-daemon ../daemon/scripts/ptp_status.sh /usr/local/share/aes67-daemon/scripts/ +#copy the webui +sudo cp -r ../webui/dist/* /usr/local/share/aes67-daemon/webui/ +#copy daemon configuration and status files +sudo install -o aes67-daemon status.json daemon.conf /etc +#copy the daemon systemd service definition +sudo cp aes67-daemon.service /etc/systemd/system +#enable the daemon service +sudo systemctl enable aes67-daemon +sudo systemctl daemon-reexec + + diff --git a/systemd/status.json b/systemd/status.json new file mode 100644 index 0000000..d524933 --- /dev/null +++ b/systemd/status.json @@ -0,0 +1,4 @@ +{ + "sources": [ ], + "sinks": [ ] +} diff --git a/ubuntu-packages.sh b/ubuntu-packages.sh index 64c8d7d..b32bf72 100755 --- a/ubuntu-packages.sh +++ b/ubuntu-packages.sh @@ -19,4 +19,5 @@ sudo apt-get install -y libasound2-dev sudo apt-get install -y linuxptp sudo apt-get install -y libavahi-client-dev sudo apt install -y linux-headers-$(uname -r) +sudo apt-get install -y libsystemd-dev