Fix to generation of Node ID based on get_node_id() utils function: if gethostid() uses the loopback address interface IPv4 we create a new ID based on the current interface IPv4

This fixes a problem on old Ubuntu distro causing the Node ID to be the same for multiple hosts.
Additional minor changes:
 - removed compilation warnings
 - some fixes to code indentation
This commit is contained in:
Andrea Bondavalli 2020-06-14 14:05:21 +02:00
parent 7c5d2a4b29
commit 7f2bd7f4f0
8 changed files with 69 additions and 52 deletions

2
daemon/json.cpp Normal file → Executable file
View File

@ -96,7 +96,7 @@ std::string config_to_json(const Config& config) {
<< ",\n \"mdns_enabled\": " << std::boolalpha << config.get_mdns_enabled()
<< ",\n \"mac_addr\": \"" << escape_json(config.get_mac_addr_str()) << "\""
<< ",\n \"ip_addr\": \"" << escape_json(config.get_ip_addr_str()) << "\""
<< ",\n \"node_id\": \"" << escape_json(get_node_id()) << "\""
<< ",\n \"node_id\": \"" << escape_json(get_node_id(config.get_ip_addr())) << "\""
<< "\n}\n";
return ss.str();
}

2
daemon/mdns_server.hpp Normal file → Executable file
View File

@ -59,7 +59,7 @@ class MDNSServer {
std::atomic_bool running_{false};
std::shared_ptr<SessionManager> session_manager_;
std::shared_ptr<Config> config_;
std::string node_id_{get_node_id()};
std::string node_id_{get_node_id(config_->get_ip_addr())};
#ifdef _USE_AVAHI_
using entry_group_bimap_t =

72
daemon/rtsp_client.cpp Normal file → Executable file
View File

@ -166,13 +166,13 @@ std::pair<bool, RtspSource> RtspClient::process(
}
if (!res.content_type.empty() &&
res.content_type.rfind("application/sdp", 0) == std::string::npos) {
res.content_type.rfind("application/sdp", 0) == std::string::npos) {
BOOST_LOG_TRIVIAL(error) << "rtsp_client:: unsupported content-type "
<< res.content_type << " from "
<< "rtsp://" << address << ":" << port << path;
if (is_describe) {
if (is_describe) {
return {false, rtsp_source};
}
}
} else {
std::stringstream ss;
ss << "rtsp:" << std::hex
@ -183,65 +183,65 @@ std::pair<bool, RtspSource> RtspClient::process(
rtsp_source.source = "mDNS";
rtsp_source.address = address;
rtsp_source.sdp = std::move(res.body);
BOOST_LOG_TRIVIAL(info) << "rtsp_client:: completed "
<< "rtsp://" << address << ":" << port << path;
BOOST_LOG_TRIVIAL(info) << "rtsp_client:: completed "
<< "rtsp://" << address << ":" << port << path;
if (is_announce || is_describe) {
if (is_announce && announced_name.empty()) {
/* if no name from URL we try from SDP file */
announced_name = sdp_get_subject(rtsp_source.sdp);
}
}
callback(announced_name.empty() ? name : announced_name, domain,
rtsp_source);
}
if (is_announce) {
if (is_announce) {
s << "RTSP/1.0 200 OK\r\n";
s << "CSeq: " << res.cseq << "\r\n";
s << "\r\n";
} else if (!is_describe) {
} else if (!is_describe) {
s << "RTSP/1.0 405 Method Not Allowed\r\n";
s << "CSeq: " << res.cseq << "\r\n";
s << "\r\n";
}
}
}
if (wait_for_updates) {
g_mutex.lock();
g_active_clients[{name, domain}] = &s;
g_mutex.unlock();
g_mutex.lock();
g_active_clients[{name, domain}] = &s;
g_mutex.unlock();
/* we start waiting for updates */
do {
do {
std::getline(s, request);
} while (request.empty() && !s.error());
if (s.error()) {
} while (request.empty() && !s.error());
if (s.error()) {
BOOST_LOG_TRIVIAL(info) << "rtsp_client:: end: "
<< s.error().message();
break;
}
BOOST_LOG_TRIVIAL(info) << "rtsp_client:: received " << request;
boost::trim(request);
is_describe = is_announce = false;
announced_name = "";
std::vector<std::string> fields;
split(fields, request, boost::is_any_of(" "));
if (fields.size() >= 2 && fields[0] == "ANNOUNCE") {
auto const [ok, protocol, host, port, path] = parse_url(fields[1]);
if (ok) {
/* if we find a valid announced source name we use it
* otherwise we try from SDP file or we use the mDNS name */
if (path.rfind("/by-name/") != std::string::npos) {
announced_name = path.substr(9);
BOOST_LOG_TRIVIAL(debug) << "rtsp_client:: found announced name "
<< announced_name;
}
}
is_announce = true;
}
BOOST_LOG_TRIVIAL(info) << "rtsp_client:: received " << request;
boost::trim(request);
is_describe = is_announce = false;
announced_name = "";
std::vector<std::string> fields;
split(fields, request, boost::is_any_of(" "));
if (fields.size() >= 2 && fields[0] == "ANNOUNCE") {
auto const res = parse_url(fields[1]);
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);
if (path.rfind("/by-name/") != std::string::npos) {
announced_name = path.substr(9);
BOOST_LOG_TRIVIAL(debug) << "rtsp_client:: found announced name "
<< announced_name;
}
}
is_announce = true;
}
} while (wait_for_updates);
}
} while (wait_for_updates);
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(warning)
<< "rtsp_client:: error with "

17
daemon/rtsp_server.cpp Normal file → Executable file
View File

@ -46,9 +46,8 @@ void RtspServer::accept() {
unsigned int i = 0;
for (; i < sessions_.size(); i++) {
if (sessions_[i].use_count() == 0) {
auto session = std::make_shared<RtspSession>(session_manager_,
std::move(socket_));
auto session = std::make_shared<RtspSession>(config_,
session_manager_, std::move(socket_));
sessions_[i] = session;
sessions_start_point_[i] = steady_clock::now();
session->start();
@ -75,7 +74,8 @@ bool RtspSession::announce(uint8_t id,
/* if a describe request is currently not beeing process
* 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/") + get_node_id() + " " + name);
std::string path(std::string("/by-name/") +
get_node_id(config_->get_ip_addr()) + " " + name);
std::stringstream ss;
ss << "ANNOUNCE rtsp://" << address << ":" << std::to_string(port)
<< httplib::detail::encode_url(path) << " RTSP/1.0\r\n"
@ -164,15 +164,16 @@ bool RtspSession::process_request() {
}
void RtspSession::build_response(const std::string& url) {
auto const [ok, protocol, host, port, path] = parse_url(url);
if (!ok) {
auto const res = parse_url(url);
if (!std::get<0>(res)) {
BOOST_LOG_TRIVIAL(error) << "rtsp_server:: cannot parse URL " << url
<< " from " << socket_.remote_endpoint();
send_error(400, "Bad Request");
return;
}
auto base_path = std::string("/by-name/") + get_node_id() + " ";
auto path = std::get<4>(res);
auto base_path = std::string("/by-name/") +
get_node_id(config_->get_ip_addr()) + " ";
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 */

7
daemon/rtsp_server.hpp Normal file → Executable file
View File

@ -39,9 +39,11 @@ class RtspSession : public std::enable_shared_from_this<RtspSession> {
constexpr static uint16_t max_length = 4096; // byte
constexpr static uint16_t session_tout_secs = 10; // sec
RtspSession(std::shared_ptr<SessionManager> session_manager,
RtspSession(std::shared_ptr<Config> config,
std::shared_ptr<SessionManager> session_manager,
tcp::socket socket)
: session_manager_(session_manager),
: config_(config),
session_manager_(session_manager),
socket_(std::move(socket)),
length_{0},
cseq_{-1},
@ -66,6 +68,7 @@ class RtspSession : public std::enable_shared_from_this<RtspSession> {
void read_request();
void send_error(int status_code, const std::string& description);
void send_response(const std::string& response);
std::shared_ptr<Config> config_;
std::shared_ptr<SessionManager> session_manager_;
tcp::socket socket_;
char data_[max_length + 1];

3
daemon/session_manager.cpp Normal file → Executable file
View File

@ -557,7 +557,8 @@ std::string SessionManager::get_source_sdp_(uint32_t id,
ss << "v=0\n"
<< "o=- " << static_cast<unsigned>(id) << " 0 IN IP4 "
<< ip::address_v4(info.stream.m_ui32SrcIP).to_string() << "\n"
<< "s=" << get_node_id() << " " << info.stream.m_cName << "\n"
<< "s=" << get_node_id(config_->get_ip_addr()) << " "
<< info.stream.m_cName << "\n"
<< "c=IN IP4 " << ip::address_v4(info.stream.m_ui32DestIP).to_string()
<< "/" << static_cast<unsigned>(info.stream.m_byTTL) << "\n"
<< "t=0 0\n"

16
daemon/utils.cpp Normal file → Executable file
View File

@ -18,6 +18,7 @@
//
//
#include <boost/format.hpp>
#include "utils.hpp"
uint16_t crc16(const uint8_t* p, size_t len) {
@ -73,8 +74,19 @@ parse_url(const std::string& _url) {
return {host.length() > 0, protocol, host, port, path};
}
std::string get_node_id() {
std::string get_node_id(uint32_t ip_addr) {
std::stringstream ss;
ss << "AES67 daemon " << std::hex << (uint32_t)gethostid();
if (gethostid() == 0x7f0101) {
/* hostid is using lo interface ip
we create an host ID based on the current IP */
ss << "AES67 daemon "
<< boost::format("%02x%02x%02x%02x")
% ((ip_addr >> 8) & 0xff)
% ((ip_addr >> 24) & 0xff)
% (ip_addr & 0xff)
% ((ip_addr >> 16) & 0xff);
} else {
ss << "AES67 daemon " << std::hex << (uint32_t)gethostid();
}
return ss.str();
}

2
daemon/utils.hpp Normal file → Executable file
View File

@ -34,6 +34,6 @@ std::tuple<bool /* res */,
std::string /* path */>
parse_url(const std::string& _url);
std::string get_node_id();
std::string get_node_id(uint32_t ip_addr);
#endif