From 6ed3a9ef541188082c404fba7eb17925e1463d4e Mon Sep 17 00:00:00 2001 From: Andrea Bondavalli Date: Sat, 14 Jan 2023 18:22:24 +0100 Subject: [PATCH] Remote source origin is parsed and extracted from SDP when the source is discovered or updated. This way we avoid parsing the SDP multiple times. --- daemon/browser.cpp | 9 +++--- daemon/browser.hpp | 2 ++ daemon/session_manager.cpp | 56 ++++++-------------------------------- daemon/session_manager.hpp | 18 ------------ daemon/utils.cpp | 42 ++++++++++++++++++++++++++-- daemon/utils.hpp | 19 +++++++++++++ 6 files changed, 75 insertions(+), 71 deletions(-) diff --git a/daemon/browser.cpp b/daemon/browser.cpp index 420e01d..efd0a69 100644 --- a/daemon/browser.cpp +++ b/daemon/browser.cpp @@ -19,7 +19,6 @@ #include -#include "utils.hpp" #include "browser.hpp" using namespace boost::algorithm; @@ -85,6 +84,7 @@ bool Browser::worker() { ip::address_v4(ntohl(addr)).to_string(), sdp_get_subject(sdp), {}, + sdp_get_origin(sdp), sdp, static_cast( duration_cast(steady_clock::now() - startup_) @@ -163,8 +163,9 @@ void Browser::on_change_rtsp_source(const std::string& name, << " name " << name << " domain " << domain; auto upd_source{*it}; upd_source.id = s.id; - upd_source.sdp = s.sdp; upd_source.address = s.address; + upd_source.origin = sdp_get_origin(s.sdp); + upd_source.sdp = s.sdp; upd_source.last_seen = last_seen; sources_.get().replace(it, upd_source); return; @@ -174,8 +175,8 @@ void Browser::on_change_rtsp_source(const std::string& name, /* entry not found -> add */ BOOST_LOG_TRIVIAL(info) << "browser:: adding RTSP source " << s.id << " name " << name << " domain " << domain; - sources_.insert( - {s.id, s.source, s.address, name, domain, s.sdp, last_seen, 0}); + sources_.insert({s.id, s.source, s.address, name, domain, + sdp_get_origin(s.sdp), s.sdp, last_seen, 0}); } void Browser::on_remove_rtsp_source(const std::string& name, diff --git a/daemon/browser.hpp b/daemon/browser.hpp index c76d467..381bec9 100644 --- a/daemon/browser.hpp +++ b/daemon/browser.hpp @@ -35,6 +35,7 @@ #include "igmp.hpp" #include "mdns_client.hpp" #include "sap.hpp" +#include "utils.hpp" using namespace boost::multi_index; @@ -44,6 +45,7 @@ struct RemoteSource { std::string address; std::string name; std::string domain; /* mDNS only */ + SDPOrigin origin; std::string sdp; uint32_t last_seen{0}; /* seconds from daemon startup */ uint32_t announce_period{0}; /* period between annoucements */ diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index 2bcad4a..706f273 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -607,44 +607,6 @@ std::string SessionManager::get_removed_source_sdp_( return sdp; } -bool SessionManager::parse_sdp_origin(const std::string sdp, - SDPOrigin& origin) const { - try { - std::stringstream sdp_string_stream(sdp); - std::string line; - while (getline(sdp_string_stream, line, '\n')) { - boost::trim(line); - if (line[1] != '=') { - BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid SDP file"; - return false; - } - std::string val = line.substr(2); - switch (line[0]) { - case 'o': - std::vector fields; - boost::split(fields, val, [line](char c) { return c == ' '; }); - if (fields.size() < 6) { - BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid origin"; - return false; - } - - origin.username = fields[0]; - origin.session_id = fields[1]; - origin.session_version = std::stoull(fields[2]); - origin.network_type = fields[3]; - origin.address_type = fields[4]; - origin.unicast_address = fields[5]; - return true; - } - } - } catch (...) { - BOOST_LOG_TRIVIAL(fatal) << "session_manager:: invalid SDP" - << ", cannot extract SDP identifier"; - } - - return false; -} - std::string SessionManager::get_source_sdp_(uint32_t id, const StreamInfo& info) const { std::shared_lock ptp_lock(ptp_mutex_); @@ -1068,23 +1030,21 @@ std::list SessionManager::get_updated_sinks( uint64_t newVersion{0}; StreamSink sink{get_sink_(id, info)}; for (auto& source : sources_list) { - SDPOrigin source_sdp_origin; - if (!parse_sdp_origin(source.sdp, source_sdp_origin)) + // if no remote source origin specified, skip + if (source.origin.session_id == "") continue; - if (sinks_[sink.id].origin == source_sdp_origin && - sink.sdp != source.sdp && + // search for the largest corresponding remote source version + if (sinks_[sink.id].origin == source.origin && sink.sdp != source.sdp && sinks_[sink.id].origin.session_version < - source_sdp_origin.session_version && - newVersion < source_sdp_origin.session_version) { - newVersion = source_sdp_origin.session_version; + source.origin.session_version && + newVersion < source.origin.session_version) { + newVersion = source.origin.session_version; sink.sdp = source.sdp; } } if (newVersion) { - // Re-add sink with new SDP, since the sink.id is the same there will be - // an update BOOST_LOG_TRIVIAL(info) << "session_manager:: sink " << std::to_string(sink.id) << " SDP change detected version " << newVersion << " updating"; @@ -1097,6 +1057,8 @@ std::list SessionManager::get_updated_sinks( void SessionManager::update_sinks(const std::list& sources_list) { auto sinks_list = get_updated_sinks(sources_list); for (auto& sink : sinks_list) { + // Re-add sink with new SDP, since the sink.id is the same there will be + // an update add_sink(sink); } } diff --git a/daemon/session_manager.hpp b/daemon/session_manager.hpp index ffc21c7..5b9dda0 100644 --- a/daemon/session_manager.hpp +++ b/daemon/session_manager.hpp @@ -32,23 +32,6 @@ #include "igmp.hpp" #include "sap.hpp" -struct SDPOrigin { - std::string username; - std::string session_id; - uint64_t session_version{0}; - std::string network_type; - std::string address_type; - std::string unicast_address; - - bool operator==(const SDPOrigin& rhs) const { - // session_version is not part of comparison, see RFC 4566 - return username == rhs.username && session_id == rhs.session_id && - network_type == rhs.network_type && - address_type == rhs.address_type && - unicast_address == rhs.unicast_address; - } -}; - struct StreamSource { uint8_t id{0}; bool enabled{false}; @@ -211,7 +194,6 @@ class SessionManager { const std::list sources_list) const; bool parse_sdp(const std::string sdp, StreamInfo& info) const; - bool parse_sdp_origin(const std::string sdp, SDPOrigin& origin) const; bool worker(); // singleton, use create() to build SessionManager(std::shared_ptr driver, diff --git a/daemon/utils.cpp b/daemon/utils.cpp index 1f3c753..9533a1c 100644 --- a/daemon/utils.cpp +++ b/daemon/utils.cpp @@ -19,6 +19,7 @@ // #include "utils.hpp" +#include "log.hpp" #include #include @@ -86,9 +87,9 @@ std::string get_host_node_id(uint32_t ip_addr) { } std::string sdp_get_subject(const std::string& sdp) { - std::stringstream ssstrem(sdp); + std::stringstream sstrem(sdp); std::string line; - while (getline(ssstrem, line, '\n')) { + while (getline(sstrem, line, '\n')) { if (line.substr(0, 2) == "s=") { auto subject = line.substr(2); boost::trim(subject); @@ -97,3 +98,40 @@ std::string sdp_get_subject(const std::string& sdp) { } return ""; } + +SDPOrigin sdp_get_origin(const std::string sdp) { + SDPOrigin origin; + try { + std::stringstream sstream(sdp); + std::string line; + while (getline(sstream, line, '\n')) { + boost::trim(line); + if (line[1] != '=') { + BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid SDP file"; + break; + } + std::string val = line.substr(2); + if (line[0] == 'o') { + std::vector fields; + boost::split(fields, val, [line](char c) { return c == ' '; }); + if (fields.size() < 6) { + BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid origin"; + break; + } + + origin.username = fields[0]; + origin.session_id = fields[1]; + origin.session_version = std::stoull(fields[2]); + origin.network_type = fields[3]; + origin.address_type = fields[4]; + origin.unicast_address = fields[5]; + break; + } + } + } catch (...) { + BOOST_LOG_TRIVIAL(fatal) << "session_manager:: invalid SDP" + << ", cannot extract SDP identifier"; + } + + return origin; +} diff --git a/daemon/utils.hpp b/daemon/utils.hpp index 343f75d..c0757db 100644 --- a/daemon/utils.hpp +++ b/daemon/utils.hpp @@ -38,4 +38,23 @@ std::string get_host_node_id(uint32_t ip_addr); std::string sdp_get_subject(const std::string& sdp); +struct SDPOrigin { + std::string username; + std::string session_id; + uint64_t session_version{0}; + std::string network_type; + std::string address_type; + std::string unicast_address; + + bool operator==(const SDPOrigin& rhs) const { + // session_version is not part of comparison, see RFC 4566 + return username == rhs.username && session_id == rhs.session_id && + network_type == rhs.network_type && + address_type == rhs.address_type && + unicast_address == rhs.unicast_address; + } +}; + +SDPOrigin sdp_get_origin(const std::string sdp); + #endif