Applied Clang source code formatting to daemon sources

This commit is contained in:
Andrea Bondavalli 2020-06-16 21:14:44 +02:00
parent f9a07569f9
commit 098cebd056
37 changed files with 674 additions and 681 deletions

View File

@ -129,7 +129,7 @@ RawStringFormats:
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false

View File

@ -26,46 +26,31 @@ using namespace boost::algorithm;
using namespace std::chrono;
using second_t = duration<double, std::ratio<1> >;
std::shared_ptr<Browser> Browser::create(
std::shared_ptr<Config> config) {
std::shared_ptr<Browser> Browser::create(std::shared_ptr<Config> config) {
// no need to be thread-safe here
static std::weak_ptr<Browser> instance;
if (auto ptr = instance.lock()) {
return ptr;
}
auto ptr =
std::shared_ptr<Browser>(new Browser(config));
auto ptr = std::shared_ptr<Browser>(new Browser(config));
instance = ptr;
return ptr;
}
std::list<RemoteSource> Browser::get_remote_sources(
const std::string& _source) const {
const std::string& _source) const {
std::list<RemoteSource> sources_list;
std::shared_lock sources_lock(sources_mutex_);
// return list of remote sources ordered by name
for (const auto& source: sources_.get<name_tag>()) {
if (boost::iequals(source.source, _source) ||
boost::iequals("all", _source)) {
for (const auto& source : sources_.get<name_tag>()) {
if (boost::iequals(source.source, _source) ||
boost::iequals("all", _source)) {
sources_list.push_back(source);
}
}
return sources_list;
}
static std::string sdp_get_subject(const std::string& sdp) {
std::stringstream ssstrem(sdp);
std::string line;
while (getline(ssstrem, line, '\n')) {
if (line.substr(0, 2) == "s=") {
auto subject = line.substr(2);
trim(subject);
return subject;
}
}
return "";
}
bool Browser::worker() {
sap_.set_multicast_interface(config_->get_ip_addr_str());
// Join SAP muticast address
@ -94,49 +79,54 @@ bool Browser::worker() {
// Source is not in the map
if (is_announce) {
// annoucement, add new source
sources_.insert({
id, "SAP", ip::address_v4(ntohl(addr)).to_string(),
sdp_get_subject(sdp), {}, sdp,
static_cast<uint32_t>(duration_cast<second_t>(steady_clock::now()
- startup_).count()),
360 });
sources_.insert(
{id,
"SAP",
ip::address_v4(ntohl(addr)).to_string(),
sdp_get_subject(sdp),
{},
sdp,
static_cast<uint32_t>(
duration_cast<second_t>(steady_clock::now() - startup_)
.count()),
360});
}
} else {
// Source is already in the map
if (is_announce) {
BOOST_LOG_TRIVIAL(debug)
<< "browser:: refreshing SAP source " << it->id;
<< "browser:: refreshing SAP source " << it->id;
// annoucement, update last seen and announce period
uint32_t last_seen =
duration_cast<second_t>(steady_clock::now() - startup_).count();
uint32_t last_seen =
duration_cast<second_t>(steady_clock::now() - startup_).count();
auto upd_source{*it};
upd_source.announce_period = last_seen - upd_source.last_seen;
upd_source.last_seen = last_seen;
sources_.replace(it, upd_source);
} else {
BOOST_LOG_TRIVIAL(info)
<< "browser:: removing SAP source " << it->id
<< " name " << it->name;
sources_.replace(it, upd_source);
} else {
BOOST_LOG_TRIVIAL(info) << "browser:: removing SAP source " << it->id
<< " name " << it->name;
// deletion, remove entry
sources_.erase(it);
sources_.erase(it);
}
}
}
// check if it's time to update the SAP remote sources
if ((duration_cast<second_t>(steady_clock::now() - sap_timepoint).count())
> sap_interval) {
if ((duration_cast<second_t>(steady_clock::now() - sap_timepoint).count()) >
sap_interval) {
sap_timepoint = steady_clock::now();
// remove all sessions no longer announced
auto offset = duration_cast<second_t>(steady_clock::now() - startup_).count();
auto offset =
duration_cast<second_t>(steady_clock::now() - startup_).count();
std::unique_lock sources_lock(sources_mutex_);
for (auto it = sources_.begin(); it != sources_.end();) {
if (it->source == "SAP" &&
(offset - it->last_seen) > (it->announce_period * 10)) {
(offset - it->last_seen) > (it->announce_period * 10)) {
// remove from remote SAP sources
BOOST_LOG_TRIVIAL(info)
<< "browser:: SAP source " << it->id << " timeout";
<< "browser:: SAP source " << it->id << " timeout";
it = sources_.erase(it);
} else {
it++;
@ -145,31 +135,30 @@ bool Browser::worker() {
}
// check if it's time to process the mDNS RTSP sources
if ((duration_cast<second_t>(steady_clock::now() - mdns_timepoint).count())
> mdns_interval) {
if ((duration_cast<second_t>(steady_clock::now() - mdns_timepoint)
.count()) > mdns_interval) {
mdns_timepoint = steady_clock::now();
process_results();
}
}
return true;
}
void Browser::on_change_rtsp_source(const std::string& name,
const std::string& domain,
const RtspSource& s) {
uint32_t last_seen = duration_cast<second_t>(steady_clock::now() -
startup_).count();
const std::string& domain,
const RtspSource& s) {
uint32_t last_seen =
duration_cast<second_t>(steady_clock::now() - startup_).count();
std::unique_lock sources_lock(sources_mutex_);
/* search by name */
auto rng = sources_.get<name_tag>().equal_range(name);
while(rng.first != rng.second){
while (rng.first != rng.second) {
const auto& it = rng.first;
if (it->source == "mDNS" && it->domain == domain) {
/* mDNS source with same name and domain -> update */
BOOST_LOG_TRIVIAL(info) << "browser:: updating RTSP source " << s.id
<< " name " << name
<< " domain " << domain;
<< " name " << name << " domain " << domain;
auto upd_source{*it};
upd_source.id = s.id;
upd_source.sdp = s.sdp;
@ -181,9 +170,8 @@ void Browser::on_change_rtsp_source(const std::string& name,
++rng.first;
}
/* entry not found -> add */
BOOST_LOG_TRIVIAL(info) << "browser:: adding RTSP source " << s.id
<< " name " << name
<< " domain " << domain;
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});
}
@ -193,12 +181,12 @@ void Browser::on_remove_rtsp_source(const std::string& name,
std::unique_lock sources_lock(sources_mutex_);
auto& name_idx = sources_.get<name_tag>();
auto rng = name_idx.equal_range(name);
while(rng.first != rng.second){
while (rng.first != rng.second) {
const auto& it = rng.first;
if (it->source == "mDNS" && it->domain == domain) {
BOOST_LOG_TRIVIAL(info) << "browser:: removing RTSP source " << it->id
<< " name " << it->name
<< " domain " << it->domain;
BOOST_LOG_TRIVIAL(info)
<< "browser:: removing RTSP source " << it->id << " name " << it->name
<< " domain " << it->domain;
name_idx.erase(it);
break;
}
@ -230,4 +218,3 @@ bool Browser::terminate() {
}
return true;
}

View File

@ -20,22 +20,21 @@
#ifndef _BROWSER_HPP_
#define _BROWSER_HPP_
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <chrono>
#include <future>
#include <list>
#include <shared_mutex>
#include <thread>
#include <chrono>
#include <list>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include "config.hpp"
#include "sap.hpp"
#include "igmp.hpp"
#include "mdns_client.hpp"
#include "sap.hpp"
using namespace boost::multi_index;
@ -46,54 +45,52 @@ struct RemoteSource {
std::string name;
std::string domain; /* mDNS only */
std::string sdp;
uint32_t last_seen{0}; /* seconds from daemon startup */
uint32_t last_seen{0}; /* seconds from daemon startup */
uint32_t announce_period{0}; /* period between annoucements */
};
class Browser : public MDNSClient {
public:
static std::shared_ptr<Browser> create(
std::shared_ptr<Config> config);
static std::shared_ptr<Browser> create(std::shared_ptr<Config> config);
Browser() = delete;
Browser(const Browser&) = delete;
Browser& operator=(const Browser&) = delete;
virtual ~Browser(){ terminate(); };
virtual ~Browser() { terminate(); };
bool init() override;
bool terminate() override;
std::list<RemoteSource> get_remote_sources(
const std::string& source = "all") const;
const std::string& source = "all") const;
protected:
// singleton, use create() to build
Browser(std::shared_ptr<Config> config):
MDNSClient(config),
startup_(std::chrono::steady_clock::now()){};
Browser(std::shared_ptr<Config> config)
: MDNSClient(config), startup_(std::chrono::steady_clock::now()){};
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;
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;
std::future<bool> res_;
std::atomic_bool running_{false};
/* current sources */
struct id_tag{};
using by_id = hashed_unique<tag<id_tag>, member<RemoteSource,
std::string, &RemoteSource::id>>;
struct name_tag{};
using by_name = ordered_non_unique<tag<name_tag>, member<RemoteSource,
std::string, &RemoteSource::name>>;
using sources_t = multi_index_container<RemoteSource,
indexed_by<by_id, by_name>>;
struct id_tag {};
using by_id =
hashed_unique<tag<id_tag>,
member<RemoteSource, std::string, &RemoteSource::id>>;
struct name_tag {};
using by_name = ordered_non_unique<
tag<name_tag>,
member<RemoteSource, std::string, &RemoteSource::name>>;
using sources_t =
multi_index_container<RemoteSource, indexed_by<by_id, by_name>>;
sources_t sources_;
mutable std::shared_mutex sources_mutex_;

View File

@ -17,23 +17,22 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <exception>
#include <iostream>
#include <sstream>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "config.hpp"
#include "interface.hpp"
#include "json.hpp"
#include "config.hpp"
using namespace boost::asio;
@ -58,8 +57,7 @@ std::shared_ptr<Config> Config::parse(const std::string& filename) {
config.log_severity_ = 2;
if (config.playout_delay_ > 4000)
config.playout_delay_ = 4000;
if (config.tic_frame_size_at_1fs_ == 0 ||
config.tic_frame_size_at_1fs_ > 192)
if (config.tic_frame_size_at_1fs_ == 0 || config.tic_frame_size_at_1fs_ > 192)
config.tic_frame_size_at_1fs_ = 192;
if (config.max_tic_frame_size_ < config.tic_frame_size_at_1fs_ ||
config.max_tic_frame_size_ > 1024)
@ -76,8 +74,8 @@ std::shared_ptr<Config> 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;
if (config.ptp_domain_ > 127)
config.ptp_domain_ = 0;
auto [mac_addr, mac_str] = get_interface_mac(config.interface_name_);
if (mac_str.empty()) {

View File

@ -63,7 +63,9 @@ class Config {
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) { http_base_dir_ = http_base_dir; };
void set_http_base_dir(const std::string& http_base_dir) {
http_base_dir_ = http_base_dir;
};
void set_log_severity(int log_severity) { log_severity_ = log_severity; };
void set_playout_delay(uint32_t playout_delay) {
playout_delay_ = playout_delay;
@ -105,9 +107,7 @@ class Config {
void set_mac_addr(const std::array<uint8_t, 6>& mac_addr) {
mac_addr_ = mac_addr;
};
void set_mdns_enabled(bool enabled) {
mdns_enabled_ = enabled;
};
void set_mdns_enabled(bool enabled) { mdns_enabled_ = enabled; };
void set_interface_idx(int index) { interface_idx_ = index; };
private:

View File

@ -20,8 +20,8 @@
#include <iostream>
#include <thread>
#include "driver_handler.hpp"
#include "log.hpp"
#include "driver_handler.hpp"
/*
void dump(const void* mem, unsigned int n) {
@ -107,13 +107,13 @@ bool DriverHandler::event_receiver() {
if (palsa_msg->errCode == 0) {
size_t res_size = sizeof(int32_t);
uint8_t res[sizeof(int32_t)];
memset(res, 0, res_size);
memset(res, 0, res_size);
on_event(palsa_msg->id, res_size, res, palsa_msg->dataSize,
reinterpret_cast<const uint8_t*>(palsa_msg) + data_offset);
BOOST_LOG_TRIVIAL(debug) << "driver_handler::sending event response "
<< palsa_msg->id << " data len " << res_size;
memset(response_buffer_, 0, sizeof(response_buffer_));
memset(response_buffer_, 0, sizeof(response_buffer_));
try {
send(palsa_msg->id, client_k2u_, response_buffer_, res_size, res);
} catch (boost::system::error_code& ec) {
@ -183,8 +183,9 @@ void DriverHandler::send_command(enum MT_ALSA_msg_id id,
<< palsa_msg->errCode << " data len " << palsa_msg->dataSize;
if (id != palsa_msg->id) {
BOOST_LOG_TRIVIAL(warning) << "driver_handler:: unexpected cmd response:"
<< "sent " << id << " received " << palsa_msg->id;
BOOST_LOG_TRIVIAL(warning)
<< "driver_handler:: unexpected cmd response:"
<< "sent " << id << " received " << palsa_msg->id;
on_command_error(palsa_msg->id, DaemonErrc::invalid_driver_response);
} else {
if (palsa_msg->errCode == 0) {

View File

@ -24,9 +24,9 @@
#include "MT_ALSA_message_defs.h"
#include "config.hpp"
#include "error_code.hpp"
#include "log.hpp"
#include "netlink_client.hpp"
#include "error_code.hpp"
class DriverHandler {
public:
@ -40,7 +40,7 @@ class DriverHandler {
DriverHandler(){};
DriverHandler(const DriverHandler&) = delete;
DriverHandler& operator=(const DriverHandler&) = delete;
virtual ~DriverHandler(){ terminate(); };
virtual ~DriverHandler() { terminate(); };
virtual bool init(const Config& config);
virtual bool terminate();
@ -76,8 +76,8 @@ class DriverHandler {
uint8_t event_buffer_[buffer_size];
uint8_t response_buffer_[buffer_size];
NetlinkClient client_u2k_{"commands"}; /* u2k for commands */
NetlinkClient client_k2u_{"events"}; /* k2u for events */
std::mutex mutex_; /* one command at a time */
NetlinkClient client_k2u_{"events"}; /* k2u for events */
std::mutex mutex_; /* one command at a time */
};
#endif

View File

@ -19,50 +19,45 @@
#include <thread>
#include "driver_manager.hpp"
#include "log.hpp"
#include "driver_manager.hpp"
static const std::vector<std::string> alsa_msg_str = {
"Start",
"Stop",
"Reset",
"StartIO",
"StopIO",
"SetSampleRate",
"GetSampleRate",
"GetAudioMode",
"SetDSDAudioMode",
"SetTICFrameSizeAt1FS",
"SetMaxTICFrameSize",
"SetNumberOfInputs",
"SetNumberOfOutputs",
"GetNumberOfInputs",
"GetNumberOfOutputs",
"SetInterfaceName",
"Add_RTPStream",
"Remove_RTPStream",
"Update_RTPStream_Name",
"GetPTPInfo",
"Hello",
"Bye",
"Ping",
"SetMasterOutputVolume",
"SetMasterOutputSwitch",
"GetMasterOutputVolume",
"GetMasterOutputSwitch",
"SetPlayoutDelay",
"SetCaptureDelay",
"GetRTPStreamStatus",
"SetPTPConfig",
"GetPTPConfig",
"GetPTPStatus"
};
static const std::vector<std::string> alsa_msg_str = {"Start",
"Stop",
"Reset",
"StartIO",
"StopIO",
"SetSampleRate",
"GetSampleRate",
"GetAudioMode",
"SetDSDAudioMode",
"SetTICFrameSizeAt1FS",
"SetMaxTICFrameSize",
"SetNumberOfInputs",
"SetNumberOfOutputs",
"GetNumberOfInputs",
"GetNumberOfOutputs",
"SetInterfaceName",
"Add_RTPStream",
"Remove_RTPStream",
"Update_RTPStream_Name",
"GetPTPInfo",
"Hello",
"Bye",
"Ping",
"SetMasterOutputVolume",
"SetMasterOutputSwitch",
"GetMasterOutputVolume",
"GetMasterOutputSwitch",
"SetPlayoutDelay",
"SetCaptureDelay",
"GetRTPStreamStatus",
"SetPTPConfig",
"GetPTPConfig",
"GetPTPStatus"};
static const std::vector<std::string> ptp_status_str = {
"unlocked",
"locking",
"locked"
};
static const std::vector<std::string> ptp_status_str = {"unlocked", "locking",
"locked"};
std::shared_ptr<DriverManager> DriverManager::create() {
// no need to be thread-safe here
@ -86,9 +81,7 @@ bool DriverManager::init(const Config& config) {
ptp_config.ui8Domain = config.get_ptp_domain();
ptp_config.ui8DSCP = config.get_ptp_dscp();
bool res = hello() ||
start() ||
reset() ||
bool res = hello() || start() || reset() ||
set_interface_name(config.get_interface_name()) ||
set_ptp_config(ptp_config) ||
set_tic_frame_size_at_1fs(config.get_tic_frame_size_at_1fs()) ||
@ -288,8 +281,7 @@ void DriverManager::on_event(enum MT_ALSA_msg_id id,
if (req_size == sizeof(int32_t)) {
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;
@ -297,15 +289,15 @@ void DriverManager::on_event(enum MT_ALSA_msg_id id,
if (req_size == sizeof(int32_t)) {
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);
BOOST_LOG_TRIVIAL(info) << "driver_manager:: event SetSampleRate " << sample_rate;
BOOST_LOG_TRIVIAL(info)
<< "driver_manager:: event SetSampleRate " << sample_rate;
}
resp_size = 0;
break;

View File

@ -23,10 +23,9 @@
#include <boost/asio.hpp>
#include <mutex>
#include "driver_handler.hpp"
#include "RTP_stream_info.h"
#include "audio_streamer_clock_PTP_defs.h"
#include "driver_handler.hpp"
class DriverManager : public DriverHandler {
public:

View File

@ -102,7 +102,7 @@ std::string DaemonErrCategory::message(int ev) const {
case DaemonErrc::cannot_retrieve_sdp:
return "cannot retrieve SDP";
case DaemonErrc::cannot_parse_sdp:
return "cannot parse SDP";
return "cannot parse SDP";
case DaemonErrc::send_invalid_size:
return "send data size too big";
case DaemonErrc::send_u2k_failed:

View File

@ -45,18 +45,18 @@ std::error_code get_driver_error(int code);
// Daemon errors
enum class DaemonErrc {
invalid_stream_id = 40, // daemon invalid stream id
stream_id_in_use = 41, // daemon stream id is in use
stream_id_not_in_use = 42, // daemon stream not in use
invalid_url = 43, // daemon invalid URL
cannot_retrieve_sdp = 44, // daemon cannot retrieve SDP
cannot_parse_sdp = 45, // daemon cannot parse SDP
stream_name_in_use = 46, // daemon source or sink name in use
send_invalid_size = 50, // daemon data size too big for buffer
send_u2k_failed = 51, // daemon failed to send command to driver
send_k2u_failed = 52, // daemon failed to send event response to driver
receive_u2k_failed = 53, // daemon failed to receive response from driver
receive_k2u_failed = 54, // daemon failed to receive event from driver
invalid_stream_id = 40, // daemon invalid stream id
stream_id_in_use = 41, // daemon stream id is in use
stream_id_not_in_use = 42, // daemon stream not in use
invalid_url = 43, // daemon invalid URL
cannot_retrieve_sdp = 44, // daemon cannot retrieve SDP
cannot_parse_sdp = 45, // daemon cannot parse SDP
stream_name_in_use = 46, // daemon source or sink name in use
send_invalid_size = 50, // daemon data size too big for buffer
send_u2k_failed = 51, // daemon failed to send command to driver
send_k2u_failed = 52, // daemon failed to send event response to driver
receive_u2k_failed = 53, // daemon failed to receive response from driver
receive_k2u_failed = 54, // daemon failed to receive event from driver
invalid_driver_response = 55 // unexpected driver command response code
};

View File

@ -23,14 +23,16 @@
#include <iostream>
#include <string>
#include "http_server.hpp"
#include "log.hpp"
#include "json.hpp"
#include "log.hpp"
#include "http_server.hpp"
using namespace httplib;
static inline void set_headers(Response& res, const std::string content_type = "") {
res.set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
static inline void set_headers(Response& res,
const std::string content_type = "") {
res.set_header("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS");
res.set_header("Access-Control-Allow-Origin", "*");
res.set_header("Access-Control-Allow-Headers", "x-user-id");
if (!content_type.empty()) {
@ -52,26 +54,24 @@ static inline int get_http_error_status(const std::error_code& code) {
return 500;
}
static inline std::string get_http_error_message(
const std::error_code& code) {
std::stringstream ss;;
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();
}
static inline void set_error(
const std::error_code& code,
const std::string& message,
Response& res) {
static inline void set_error(const std::error_code& code,
const std::string& message,
Response& res) {
res.status = get_http_error_status(code);
set_headers(res, "text/plain");
res.body = message + " : " + get_http_error_message(code);
}
static inline void set_error(
int status,
const std::string& message,
Response& res) {
static inline void set_error(int status,
const std::string& message,
Response& res) {
res.status = status;
set_headers(res, "text/plain");
res.body = message;
@ -85,15 +85,16 @@ bool HttpServer::init() {
svr_.set_base_dir(config_->get_http_base_dir().c_str());
svr_.Get("(/|/Config|/PTP|/Sources|/Sinks|/Browser)", [&](const Request& req, Response& res) {
std::ifstream file(config_->get_http_base_dir() + "/index.html");
std::stringstream buffer;
buffer << file.rdbuf();
res.set_content(buffer.str(), "text/html");
});
svr_.Get("(/|/Config|/PTP|/Sources|/Sinks|/Browser)",
[&](const Request& req, Response& res) {
std::ifstream file(config_->get_http_base_dir() + "/index.html");
std::stringstream buffer;
buffer << file.rdbuf();
res.set_content(buffer.str(), "text/html");
});
/* allows cross-origin */
svr_.Options("/api/(.*?)", [&](const Request & /*req*/, Response &res) {
svr_.Options("/api/(.*?)", [&](const Request& /*req*/, Response& res) {
set_headers(res);
});
@ -178,43 +179,44 @@ bool HttpServer::init() {
});
/* get a source SDP */
svr_.Get("/api/source/sdp/([0-9]+)", [this](const Request& req, Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
svr_.Get(
"/api/source/sdp/([0-9]+)", [this](const Request& req, Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
auto ret = session_manager_->get_source_sdp(id, res.body);
if (ret) {
set_error(ret, "get source " + std::to_string(id) + " failed", res);
} else {
set_headers(res, "application/sdp");
}
});
auto ret = session_manager_->get_source_sdp(id, res.body);
if (ret) {
set_error(ret, "get source " + std::to_string(id) + " failed", res);
} else {
set_headers(res, "application/sdp");
}
});
/* get stream status */
svr_.Get("/api/sink/status/([0-9]+)", [this](const Request& req,
Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
SinkStreamStatus status;
auto ret = session_manager_->get_sink_status(id, status);
if (ret) {
set_error(ret, "failed to get sink " + std::to_string(id) +
" status", res);
} else {
set_headers(res, "application/json");
res.body = sink_status_to_json(status);
}
});
svr_.Get(
"/api/sink/status/([0-9]+)", [this](const Request& req, Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
SinkStreamStatus status;
auto ret = session_manager_->get_sink_status(id, status);
if (ret) {
set_error(ret, "failed to get sink " + std::to_string(id) + " status",
res);
} else {
set_headers(res, "application/json");
res.body = sink_status_to_json(status);
}
});
/* add a source */
svr_.Put("/api/source/([0-9]+)", [this](const Request& req, Response& res) {
@ -222,7 +224,8 @@ bool HttpServer::init() {
StreamSource source = json_to_source(req.matches[1], req.body);
auto ret = session_manager_->add_source(source);
if (ret) {
set_error(ret, "failed to add source " + std::to_string(source.id), res);
set_error(ret, "failed to add source " + std::to_string(source.id),
res);
} else {
set_headers(res);
}
@ -232,21 +235,22 @@ bool HttpServer::init() {
});
/* remove a source */
svr_.Delete("/api/source/([0-9]+)", [this](const Request& req, Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
auto ret = session_manager_->remove_source(id);
if (ret) {
set_error(ret, "failed to remove source " + std::to_string(id), res);
} else {
set_headers(res);
}
});
svr_.Delete(
"/api/source/([0-9]+)", [this](const Request& req, Response& res) {
uint32_t id;
try {
id = std::stoi(req.matches[1]);
} catch (...) {
set_error(400, "failed to convert id", res);
return;
}
auto ret = session_manager_->remove_source(id);
if (ret) {
set_error(ret, "failed to remove source " + std::to_string(id), res);
} else {
set_headers(res);
}
});
/* add a sink */
svr_.Put("/api/sink/([0-9]+)", [this](const Request& req, Response& res) {
@ -281,12 +285,12 @@ bool HttpServer::init() {
});
/* get remote sources */
svr_.Get("/api/browse/sources/(all|mdns|sap)",
[this](const Request& req, Response& res) {
auto const sources = browser_->get_remote_sources(req.matches[1]);
set_headers(res, "application/json");
res.body = remote_sources_to_json(sources);
});
svr_.Get("/api/browse/sources/(all|mdns|sap)",
[this](const Request& req, Response& res) {
auto const sources = browser_->get_remote_sources(req.matches[1]);
set_headers(res, "application/json");
res.body = remote_sources_to_json(sources);
});
svr_.set_logger([](const Request& req, const Response& res) {
if (res.status == 200) {
@ -314,7 +318,8 @@ bool HttpServer::init() {
});
/* wait for HTTP server to show up */
httplib::Client cli(config_->get_ip_addr_str().c_str(), config_->get_http_port());
httplib::Client cli(config_->get_ip_addr_str().c_str(),
config_->get_http_port());
int retry = 3;
while (retry--) {
auto res = cli.Get("/api/config");

View File

@ -22,9 +22,9 @@
#include <httplib.h>
#include "browser.hpp"
#include "config.hpp"
#include "session_manager.hpp"
#include "browser.hpp"
class HttpServer {
public:
@ -32,9 +32,7 @@ class HttpServer {
HttpServer(std::shared_ptr<SessionManager> session_manager,
std::shared_ptr<Browser> browser,
std::shared_ptr<Config> config)
: session_manager_(session_manager),
browser_(browser),
config_(config) {};
: session_manager_(session_manager), browser_(browser), config_(config){};
bool init();
bool terminate();

View File

@ -21,8 +21,9 @@
#define _IGMP_HPP_
#include <boost/asio.hpp>
#include <mutex>
#include <map>
#include <mutex>
#include "log.hpp"
using namespace boost::asio;
@ -38,7 +39,8 @@ 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();
uint32_t mcast_ip_addr =
ip::address_v4::from_string(mcast_ip.c_str()).to_ulong();
std::lock_guard<std::mutex> lock(mutex);
auto it = mcast_ref.find(mcast_ip_addr);
@ -61,18 +63,19 @@ class IGMP {
ip::multicast::enable_loopback el_option(true);
socket_.set_option(el_option, ec);
if (ec) {
BOOST_LOG_TRIVIAL(error) << "igmp:: enable loopback option "
<< ec.message();
BOOST_LOG_TRIVIAL(error)
<< "igmp:: enable loopback option " << ec.message();
}
BOOST_LOG_TRIVIAL(info) << "igmp:: joined multicast group "
<< mcast_ip << " on " << interface_ip;
BOOST_LOG_TRIVIAL(info) << "igmp:: joined multicast group " << mcast_ip
<< " on " << interface_ip;
mcast_ref[mcast_ip_addr] = 1;
return true;
}
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();
uint32_t mcast_ip_addr =
ip::address_v4::from_string(mcast_ip.c_str()).to_ulong();
std::lock_guard<std::mutex> lock(mutex);
auto it = mcast_ref.find(mcast_ip_addr);
@ -95,8 +98,8 @@ class IGMP {
return false;
}
BOOST_LOG_TRIVIAL(info) << "igmp:: left multicast group "
<< mcast_ip << " on " << interface_ip;
BOOST_LOG_TRIVIAL(info)
<< "igmp:: left multicast group " << mcast_ip << " on " << interface_ip;
return true;
}

View File

@ -18,8 +18,9 @@
// MIT License
//
#include <utility>
#include <boost/asio.hpp>
#include <utility>
#include "log.hpp"
using namespace boost::asio;
@ -79,8 +80,8 @@ std::pair<std::array<uint8_t, 6>, std::string> get_interface_mac(
std::copy(sa, sa + 8, std::begin(mac));
char str_mac[18];
sprintf(str_mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
sprintf(str_mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
<< " MAC address " << str_mac;*/

View File

@ -20,14 +20,13 @@
#include <boost/foreach.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <regex>
#include <iostream>
#include <regex>
#include <string>
#include "json.hpp"
#include "log.hpp"
#include "utils.hpp"
#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\?#-]?");
@ -83,20 +82,28 @@ std::string config_to_json(const Config& config) {
<< ",\n \"tic_frame_size_at_1fs\": " << config.get_tic_frame_size_at_1fs()
<< ",\n \"max_tic_frame_size\": " << config.get_max_tic_frame_size()
<< ",\n \"sample_rate\": " << config.get_sample_rate()
<< ",\n \"rtp_mcast_base\": \"" << escape_json(config.get_rtp_mcast_base()) << "\""
<< ",\n \"rtp_mcast_base\": \""
<< escape_json(config.get_rtp_mcast_base()) << "\""
<< ",\n \"rtp_port\": " << config.get_rtp_port()
<< ",\n \"ptp_domain\": " << unsigned(config.get_ptp_domain())
<< ",\n \"ptp_dscp\": " << unsigned(config.get_ptp_dscp())
<< ",\n \"sap_mcast_addr\": \"" << escape_json(config.get_sap_mcast_addr()) << "\""
<< ",\n \"sap_mcast_addr\": \""
<< escape_json(config.get_sap_mcast_addr()) << "\""
<< ",\n \"sap_interval\": " << config.get_sap_interval()
<< ",\n \"syslog_proto\": \"" << escape_json(config.get_syslog_proto()) << "\""
<< ",\n \"syslog_server\": \"" << escape_json(config.get_syslog_server()) << "\""
<< ",\n \"status_file\": \"" << escape_json(config.get_status_file()) << "\""
<< ",\n \"interface_name\": \"" << escape_json(config.get_interface_name()) << "\""
<< ",\n \"syslog_proto\": \"" << escape_json(config.get_syslog_proto())
<< "\""
<< ",\n \"syslog_server\": \"" << escape_json(config.get_syslog_server())
<< "\""
<< ",\n \"status_file\": \"" << escape_json(config.get_status_file())
<< "\""
<< ",\n \"interface_name\": \""
<< escape_json(config.get_interface_name()) << "\""
<< ",\n \"mdns_enabled\": " << std::boolalpha << config.get_mdns_enabled()
<< ",\n \"mac_addr\": \"" << escape_json(config.get_mac_addr_str()) << "\""
<< ",\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(config.get_ip_addr())) << "\""
<< ",\n \"node_id\": \"" << escape_json(get_node_id(config.get_ip_addr()))
<< "\""
<< "\n}\n";
return ss.str();
}
@ -185,7 +192,7 @@ std::string sources_to_json(const std::list<StreamSource>& sources) {
int count = 0;
std::stringstream ss;
ss << "{\n \"sources\": [";
for (auto const& source: sources) {
for (auto const& source : sources) {
if (count++) {
ss << ", ";
}
@ -199,7 +206,7 @@ std::string sinks_to_json(const std::list<StreamSink>& sinks) {
int count = 0;
std::stringstream ss;
ss << "{\n \"sinks\": [";
for (auto const& sink: sinks) {
for (auto const& sink : sinks) {
if (count++) {
ss << ", ";
}
@ -210,11 +217,11 @@ std::string sinks_to_json(const std::list<StreamSink>& sinks) {
}
std::string streams_to_json(const std::list<StreamSource>& sources,
const std::list<StreamSink>& sinks) {
const std::list<StreamSink>& sinks) {
int count = 0;
std::stringstream ss;
ss << "{\n \"sources\": [";
for (auto const& source: sources) {
for (auto const& source : sources) {
if (count++) {
ss << ", ";
}
@ -222,7 +229,7 @@ std::string streams_to_json(const std::list<StreamSource>& sources,
}
count = 0;
ss << " ],\n \"sinks\": [";
for (auto const& sink: sinks) {
for (auto const& sink : sinks) {
if (count++) {
ss << ", ";
}
@ -251,7 +258,7 @@ std::string remote_sources_to_json(const std::list<RemoteSource>& sources) {
int count = 0;
std::stringstream ss;
ss << "{\n \"remote_sources\": [";
for (auto const& source: sources) {
for (auto const& source : sources) {
if (count++) {
ss << ", ";
}
@ -272,11 +279,13 @@ Config json_to_config_(std::istream& js, Config& config) {
} else if (key == "rtsp_port") {
config.set_rtsp_port(val.get_value<int>());
} else if (key == "http_base_dir") {
config.set_http_base_dir(remove_undesired_chars(val.get_value<std::string>()));
config.set_http_base_dir(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "log_severity") {
config.set_log_severity(val.get_value<int>());
} else if (key == "interface_name") {
config.set_interface_name(remove_undesired_chars(val.get_value<std::string>()));
config.set_interface_name(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "playout_delay") {
config.set_playout_delay(val.get_value<uint32_t>());
} else if (key == "tic_frame_size_at_1fs") {
@ -286,7 +295,8 @@ Config json_to_config_(std::istream& js, Config& config) {
} else if (key == "sample_rate") {
config.set_sample_rate(val.get_value<uint32_t>());
} else if (key == "rtp_mcast_base") {
config.set_rtp_mcast_base(remove_undesired_chars(val.get_value<std::string>()));
config.set_rtp_mcast_base(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "rtp_port") {
config.set_rtp_port(val.get_value<uint16_t>());
} else if (key == "ptp_domain") {
@ -294,18 +304,22 @@ Config json_to_config_(std::istream& js, Config& config) {
} else if (key == "ptp_dscp") {
config.set_ptp_dscp(val.get_value<uint8_t>());
} else if (key == "sap_mcast_addr") {
config.set_sap_mcast_addr(remove_undesired_chars(val.get_value<std::string>()));
config.set_sap_mcast_addr(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "sap_interval") {
config.set_sap_interval(val.get_value<uint16_t>());
} else if (key == "mdns_enabled") {
config.set_mdns_enabled(val.get_value<bool>());
} else if (key == "status_file") {
config.set_status_file(remove_undesired_chars(val.get_value<std::string>()));
config.set_status_file(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "syslog_proto") {
config.set_syslog_proto(remove_undesired_chars(val.get_value<std::string>()));
config.set_syslog_proto(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "syslog_server") {
config.set_syslog_server(remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "mac_addr" || key == "ip_addr" || key == "node_id" ) {
config.set_syslog_server(
remove_undesired_chars(val.get_value<std::string>()));
} else if (key == "mac_addr" || key == "ip_addr" || key == "node_id") {
/* ignored */
} else {
std::cerr << "Warning: unkown configuration option " << key
@ -331,12 +345,12 @@ Config json_to_config(std::istream& js) {
return json_to_config_(js, config);
}
Config json_to_config(const std::string & json, const Config& curConfig) {
Config json_to_config(const std::string& json, const Config& curConfig) {
std::stringstream ss(json);
return json_to_config(ss, curConfig);
}
Config json_to_config(const std::string & json) {
Config json_to_config(const std::string& json) {
std::stringstream ss(json);
return json_to_config(ss);
}
@ -441,7 +455,7 @@ PTPConfig json_to_ptp_config(const std::string& json) {
return ptpConfig;
}
void json_to_sources(const std::string & json,
void json_to_sources(const std::string& json,
std::list<StreamSource>& sources) {
std::stringstream ss(json);
return json_to_sources(ss, sources);
@ -455,7 +469,8 @@ static void parse_json_sources(boost::property_tree::ptree& pt,
source.enabled = v.second.get<bool>("enabled");
source.name = v.second.get<std::string>("name");
source.io = v.second.get<std::string>("io");
source.max_samples_per_packet = v.second.get<uint32_t>("max_samples_per_packet");
source.max_samples_per_packet =
v.second.get<uint32_t>("max_samples_per_packet");
source.codec = v.second.get<std::string>("codec");
source.ttl = v.second.get<uint8_t>("ttl");
source.payload_type = v.second.get<uint8_t>("payload_type");
@ -471,8 +486,7 @@ static void parse_json_sources(boost::property_tree::ptree& pt,
}
}
void json_to_sources(std::istream& js,
std::list<StreamSource>& sources) {
void json_to_sources(std::istream& js, std::list<StreamSource>& sources) {
try {
boost::property_tree::ptree pt;
boost::property_tree::read_json(js, pt);
@ -483,8 +497,7 @@ void json_to_sources(std::istream& js,
}
}
void json_to_sinks(const std::string & json,
std::list<StreamSink>& sinks) {
void json_to_sinks(const std::string& json, std::list<StreamSink>& sinks) {
std::stringstream ss(json);
return json_to_sinks(ss, sinks);
}
@ -511,8 +524,7 @@ static void parse_json_sinks(boost::property_tree::ptree& pt,
}
}
void json_to_sinks(std::istream& js,
std::list<StreamSink>& sinks) {
void json_to_sinks(std::istream& js, std::list<StreamSink>& sinks) {
try {
boost::property_tree::ptree pt;
boost::property_tree::read_json(js, pt);
@ -523,7 +535,7 @@ void json_to_sinks(std::istream& js,
}
}
void json_to_streams(const std::string & json,
void json_to_streams(const std::string& json,
std::list<StreamSource>& sources,
std::list<StreamSink>& sinks) {
std::stringstream ss(json);
@ -543,4 +555,3 @@ void json_to_streams(std::istream& js,
std::to_string(je.line()) + " :" + je.message());
}
}

View File

@ -21,8 +21,9 @@
#define _JSON_HPP_
#include <list>
#include "session_manager.hpp"
#include "browser.hpp"
#include "session_manager.hpp"
/* JSON serializers */
std::string config_to_json(const Config& config);
@ -46,14 +47,10 @@ Config json_to_config(const std::string& json);
StreamSource json_to_source(const std::string& id, const std::string& json);
StreamSink json_to_sink(const std::string& id, const std::string& json);
PTPConfig json_to_ptp_config(const std::string& json);
void json_to_sources(std::istream& jstream,
std::list<StreamSource>& sources);
void json_to_sources(const std::string& json,
std::list<StreamSource>& sources);
void json_to_sinks(std::istream& jstream,
std::list<StreamSink>& sinks);
void json_to_sinks(const std::string& json,
std::list<StreamSink>& sinks);
void json_to_sources(std::istream& jstream, std::list<StreamSource>& sources);
void json_to_sources(const std::string& json, std::list<StreamSource>& sources);
void json_to_sinks(std::istream& jstream, std::list<StreamSink>& sinks);
void json_to_sinks(const std::string& json, std::list<StreamSink>& sinks);
void json_to_streams(std::istream& jstream,
std::list<StreamSource>& sources,
std::list<StreamSink>& sinks);

View File

@ -17,14 +17,13 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sinks/syslog_backend.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <vector>
#include "config.hpp"
#include "log.hpp"
@ -37,7 +36,6 @@ namespace keywords = boost::log::keywords;
using sink_t = sinks::synchronous_sink<sinks::syslog_backend>;
void log_init(const Config& config) {
boost::shared_ptr<logging::core> core = logging::core::get();
// remove all sink in case of re-configuration
@ -84,4 +82,3 @@ void log_init(const Config& config) {
core->add_sink(boost::make_shared<sink_t>(backend));
}
}

View File

@ -21,15 +21,15 @@
#include <iostream>
#include <thread>
#include "browser.hpp"
#include "config.hpp"
#include "driver_manager.hpp"
#include "http_server.hpp"
#include "interface.hpp"
#include "log.hpp"
#include "mdns_server.hpp"
#include "rtsp_server.hpp"
#include "log.hpp"
#include "session_manager.hpp"
#include "interface.hpp"
#include "browser.hpp"
namespace po = boost::program_options;
namespace postyle = boost::program_options::command_line_style;
@ -50,12 +50,12 @@ bool is_terminated() {
int main(int argc, char* argv[]) {
int rc = EXIT_SUCCESS;
po::options_description desc("Options");
desc.add_options()
("config,c", po::value<std::string>()->default_value("/etc/daemon.conf"),
"daemon configuration file")
("interface_name,i", po::value<std::string>(), "Network interface name")
("http_port,p", po::value<int>(), "HTTP server port")
("help,h", "Print this help message");
desc.add_options()(
"config,c", po::value<std::string>()->default_value("/etc/daemon.conf"),
"daemon configuration file")("interface_name,i", po::value<std::string>(),
"Network interface name")(
"http_port,p", po::value<int>(), "HTTP server port")(
"help,h", "Print this help message");
int unix_style = postyle::unix_style | postyle::short_allow_next;
po::variables_map vm;
@ -114,8 +114,7 @@ int main(int argc, char* argv[]) {
/* start session manager */
auto session_manager = SessionManager::create(driver, config);
if (session_manager == nullptr || !session_manager->init()) {
throw std::runtime_error(
std::string("SessionManager:: init failed"));
throw std::runtime_error(std::string("SessionManager:: init failed"));
}
/* start mDNS server */
@ -133,10 +132,9 @@ int main(int argc, char* argv[]) {
/* start browser */
auto browser = Browser::create(config);
if (browser == nullptr || !browser->init()) {
throw std::runtime_error(
std::string("Browser:: init failed"));
throw std::runtime_error(std::string("Browser:: init failed"));
}
/* start http server */
HttpServer http_server(session_manager, browser, config);
if (!http_server.init()) {
@ -150,10 +148,11 @@ int main(int argc, char* argv[]) {
while (!is_terminated()) {
auto [ip_addr, ip_str] = get_interface_ip(config->get_interface_name());
if (!ip_str.empty() && config->get_ip_addr_str() != ip_str) {
BOOST_LOG_TRIVIAL(warning) << "main:: IP address changed, restarting ...";
BOOST_LOG_TRIVIAL(warning)
<< "main:: IP address changed, restarting ...";
config->set_ip_addr_str(ip_str);
config->set_ip_addr(ip_addr);
break;
break;
}
if (config->get_need_restart()) {
@ -169,28 +168,24 @@ int main(int argc, char* argv[]) {
/* stop http server */
if (!http_server.terminate()) {
throw std::runtime_error(
std::string("HttpServer:: terminate failed"));
throw std::runtime_error(std::string("HttpServer:: terminate failed"));
}
/* stop browser */
if (!browser->terminate()) {
throw std::runtime_error(
std::string("Browser:: terminate failed"));
throw std::runtime_error(std::string("Browser:: terminate failed"));
}
/* stop rtsp server */
if (!rtsp_server.terminate()) {
throw std::runtime_error(
std::string("RtspServer:: terminate failed"));
throw std::runtime_error(std::string("RtspServer:: terminate failed"));
}
/* stop mDNS server */
if (config->get_mdns_enabled()) {
if (!mdns_server.terminate()) {
throw std::runtime_error(
std::string("MDNServer:: terminate failed"));
}
throw std::runtime_error(std::string("MDNServer:: terminate failed"));
}
}
/* stop session manager */
@ -209,7 +204,7 @@ int main(int argc, char* argv[]) {
BOOST_LOG_TRIVIAL(fatal) << "main:: fatal exception error: " << e.what();
rc = EXIT_FAILURE;
}
BOOST_LOG_TRIVIAL(info) << "main:: end ";
}

View File

@ -17,7 +17,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _MAIN_HPP_
#define _MAIN_HPP_

View File

@ -25,6 +25,7 @@
#include "rtsp_client.hpp"
#include "mdns_client.hpp"
#ifdef _USE_AVAHI_
void MDNSClient::resolve_callback(AvahiServiceResolver* r,
AvahiIfIndex interface,
@ -57,9 +58,10 @@ void MDNSClient::resolve_callback(AvahiServiceResolver* r,
char addr[AVAHI_ADDRESS_STR_MAX];
if ((flags & AVAHI_LOOKUP_RESULT_LOCAL) &&
(mdns.config_->get_interface_name() == "lo")) {
::strncpy(addr, mdns.config_->get_ip_addr_str().c_str(), sizeof addr - 1);
addr[sizeof addr - 1] = 0;
(mdns.config_->get_interface_name() == "lo")) {
::strncpy(addr, mdns.config_->get_ip_addr_str().c_str(),
sizeof addr - 1);
addr[sizeof addr - 1] = 0;
} else {
avahi_address_snprint(addr, sizeof(addr), address);
}
@ -72,36 +74,35 @@ void MDNSClient::resolve_callback(AvahiServiceResolver* r,
"wide_area: %i, "
"multicast: %i, "
"cached: %i",
host_name, port, addr,
!!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
host_name, port, addr, !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
!!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
!!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
!!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
!!(flags & AVAHI_LOOKUP_RESULT_CACHED));
BOOST_LOG_TRIVIAL(debug) << "mdns_client:: (Resolver) " << info;
/* if not on loopback interface we don't want to receive self announced sessions
* or if on loopback interface we want only local announced sessions */
if ((!(flags & AVAHI_LOOKUP_RESULT_LOCAL) &&
(mdns.config_->get_interface_name() != "lo")) ||
((flags & AVAHI_LOOKUP_RESULT_LOCAL) &&
(mdns.config_->get_interface_name() == "lo"))) {
/* if not on loopback interface we don't want to receive self announced
* sessions or if on loopback interface we want only local announced
* sessions */
if ((!(flags & AVAHI_LOOKUP_RESULT_LOCAL) &&
(mdns.config_->get_interface_name() != "lo")) ||
((flags & AVAHI_LOOKUP_RESULT_LOCAL) &&
(mdns.config_->get_interface_name() == "lo"))) {
std::lock_guard<std::mutex> lock(mdns.sources_res_mutex_);
/* process RTSP client in async task */
/* process RTSP client in async task */
mdns.sources_res_.emplace_back(std::async(
std::launch::async,
[&mdns,
name_ = std::forward<std::string>(name),
[&mdns, name_ = std::forward<std::string>(name),
domain_ = std::forward<std::string>(domain),
addr_ = std::forward<std::string>(addr),
port_ = std::forward<std::string>(std::to_string(port))] {
RtspClient::process(
std::bind(&MDNSClient::on_change_rtsp_source, &mdns,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
name_, domain_, std::string("/by-name/") + name_,
addr_, port_);
RtspClient::process(
std::bind(&MDNSClient::on_change_rtsp_source, &mdns,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3),
name_, domain_, std::string("/by-name/") + name_, addr_,
port_);
}));
}
@ -139,15 +140,14 @@ void MDNSClient::browse_callback(AvahiServiceBrowser* b,
<< " in domain " << domain;
/* check if a resolver is already running for this name and domain */
if (mdns.active_resolvers.find({name, domain}) !=
mdns.active_resolvers.end()) {
mdns.active_resolvers.end()) {
/* if already running we don't run a new resolver */
BOOST_LOG_TRIVIAL(info)
<< "mdns_client:: (Browser): resolution already ongoing ...";
}
else if (!(avahi_service_resolver_new(mdns.client_.get(), interface,
protocol, name, type, domain,
AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_NO_TXT,
resolve_callback, &mdns))) {
} else if (!(avahi_service_resolver_new(
mdns.client_.get(), interface, protocol, name, type,
domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_NO_TXT,
resolve_callback, &mdns))) {
BOOST_LOG_TRIVIAL(error)
<< "mdns_client:: "
<< "Failed to resolve service " << name << " : "
@ -183,34 +183,32 @@ void MDNSClient::client_callback(AvahiClient* client,
/* Called whenever the client or server state changes */
switch (state) {
case AVAHI_CLIENT_FAILURE:
BOOST_LOG_TRIVIAL(fatal) << "mdns_client:: server connection failure: "
<< avahi_strerror(avahi_client_errno(client));
/* TODO reconnect if disconnected */
avahi_threaded_poll_quit(mdns.poll_.get());
break;
case AVAHI_CLIENT_S_REGISTERING:
case AVAHI_CLIENT_S_RUNNING:
case AVAHI_CLIENT_S_COLLISION:
/* Create the service browser */
mdns.sb_.reset(avahi_service_browser_new(client,
mdns.config_->get_interface_idx(),
AVAHI_PROTO_INET,
"_ravenna_session._sub._rtsp._tcp",
nullptr, {}, browse_callback, &mdns));
if (mdns.sb_ == nullptr) {
BOOST_LOG_TRIVIAL(fatal)
<< "mdns_client:: failed to create service browser: "
<< avahi_strerror(avahi_client_errno(mdns.client_.get()));
case AVAHI_CLIENT_FAILURE:
BOOST_LOG_TRIVIAL(fatal) << "mdns_client:: server connection failure: "
<< avahi_strerror(avahi_client_errno(client));
/* TODO reconnect if disconnected */
avahi_threaded_poll_quit(mdns.poll_.get());
}
break;
break;
case AVAHI_CLIENT_CONNECTING:
break;
case AVAHI_CLIENT_S_REGISTERING:
case AVAHI_CLIENT_S_RUNNING:
case AVAHI_CLIENT_S_COLLISION:
/* Create the service browser */
mdns.sb_.reset(avahi_service_browser_new(
client, mdns.config_->get_interface_idx(), AVAHI_PROTO_INET,
"_ravenna_session._sub._rtsp._tcp", nullptr, {}, browse_callback,
&mdns));
if (mdns.sb_ == nullptr) {
BOOST_LOG_TRIVIAL(fatal)
<< "mdns_client:: failed to create service browser: "
<< avahi_strerror(avahi_client_errno(mdns.client_.get()));
avahi_threaded_poll_quit(mdns.poll_.get());
}
break;
case AVAHI_CLIENT_CONNECTING:
break;
}
}
#endif

View File

@ -30,16 +30,16 @@
#include <future>
#include <list>
#include <set>
#include <shared_mutex>
#include <thread>
#include <set>
#include "config.hpp"
#include "rtsp_client.hpp"
class MDNSClient {
public:
MDNSClient(std::shared_ptr<Config> config): config_(config){};
MDNSClient(std::shared_ptr<Config> config) : config_(config){};
MDNSClient() = delete;
MDNSClient(const MDNSClient&) = delete;
MDNSClient& operator=(const MDNSClient&) = delete;
@ -64,10 +64,10 @@ class MDNSClient {
#ifdef _USE_AVAHI_
/* order is important here */
std::unique_ptr<AvahiThreadedPoll, decltype(&avahi_threaded_poll_free)>
poll_{nullptr, &avahi_threaded_poll_free};
std::unique_ptr<AvahiClient, decltype(&avahi_client_free)>
client_{nullptr, &avahi_client_free};
std::unique_ptr<AvahiThreadedPoll, decltype(&avahi_threaded_poll_free)> poll_{
nullptr, &avahi_threaded_poll_free};
std::unique_ptr<AvahiClient, decltype(&avahi_client_free)> client_{
nullptr, &avahi_client_free};
std::unique_ptr<AvahiServiceBrowser, decltype(&avahi_service_browser_free)>
sb_{nullptr, &avahi_service_browser_free};
@ -98,7 +98,7 @@ class MDNSClient {
void* userdata);
std::set<std::pair<std::string /*name*/, std::string /*domain */> >
active_resolvers;
active_resolvers;
#endif
};

View File

@ -19,14 +19,14 @@
#include <boost/asio.hpp>
#include "mdns_server.hpp"
#include "config.hpp"
#include "interface.hpp"
#include "log.hpp"
#include "utils.hpp"
#include "mdns_server.hpp"
#ifdef _USE_AVAHI_
struct AvahiLockGuard {
AvahiLockGuard() = delete;
AvahiLockGuard(AvahiThreadedPoll* poll) : poll_(poll) {
@ -323,8 +323,8 @@ bool MDNSServer::init() {
session_manager_->add_source_observer(
SessionManager::ObserverType::add_source,
std::bind(&MDNSServer::add_service, this,
std::placeholders::_2, std::placeholders::_3));
std::bind(&MDNSServer::add_service, this, std::placeholders::_2,
std::placeholders::_3));
session_manager_->add_source_observer(
SessionManager::ObserverType::remove_source,

View File

@ -33,16 +33,15 @@
#include <mutex>
#include <thread>
#include "session_manager.hpp"
#include "config.hpp"
#include "session_manager.hpp"
#include "utils.hpp"
class MDNSServer {
public:
MDNSServer(std::shared_ptr<SessionManager> session_manager,
std::shared_ptr<Config> config)
: session_manager_(session_manager),
config_(config){}
: session_manager_(session_manager), config_(config) {}
MDNSServer() = delete;
MDNSServer(const MDNSServer&) = delete;

View File

@ -26,7 +26,7 @@
template <typename Protocol>
class nl_endpoint {
private:
sockaddr_nl sockaddr {.nl_family = AF_NETLINK};
sockaddr_nl sockaddr{.nl_family = AF_NETLINK};
public:
using protocol_type = Protocol;
@ -59,7 +59,8 @@ class nl_endpoint {
std::size_t size() const { return sizeof(sockaddr); }
void resize(std::size_t size) { /* nothing we can do here */ }
void resize(std::size_t size) { /* nothing we can do here */
}
std::size_t capacity() const { return sizeof(sockaddr); }
};
@ -81,7 +82,6 @@ class nl_protocol {
private:
int proto;
};
#endif

View File

@ -35,7 +35,7 @@ using boost::asio::deadline_timer;
class NetlinkClient {
public:
NetlinkClient() = delete;
NetlinkClient(const std::string & name) : name_(name) { }
NetlinkClient(const std::string& name) : name_(name) {}
void init(const nl_endpoint<nl_protocol>& listen_endpoint,
const nl_protocol& protocol) {
@ -45,9 +45,7 @@ class NetlinkClient {
check_deadline();
}
void terminate() {
socket_.close();
}
void terminate() { socket_.close(); }
std::size_t receive(const boost::asio::mutable_buffer& buffer,
boost::posix_time::time_duration timeout,
@ -79,7 +77,8 @@ class NetlinkClient {
if (deadline_.expires_at() <= deadline_timer::traits_type::now()) {
socket_.cancel();
deadline_.expires_at(boost::posix_time::pos_infin);
//BOOST_LOG_TRIVIAL(debug) << "netlink_client:: (" << name_ << ") timeout expired";
// BOOST_LOG_TRIVIAL(debug) << "netlink_client:: (" << name_ << ") timeout
// expired";
}
deadline_.async_wait(boost::bind(&NetlinkClient::check_deadline, this));

View File

@ -44,19 +44,6 @@ struct RtspResponse {
std::string body;
};
static std::string sdp_get_subject(const std::string& sdp) {
std::stringstream ssstrem(sdp);
std::string line;
while (getline(ssstrem, line, '\n')) {
if (line.substr(0, 2) == "s=") {
auto subject = line.substr(2);
trim(subject);
return subject;
}
}
return "";
}
RtspResponse read_response(tcp::iostream& s, uint16_t max_length) {
RtspResponse res;
std::string header;

View File

@ -15,12 +15,12 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "rtsp_server.hpp"
#include "utils.hpp"
#include "rtsp_server.hpp"
using boost::asio::ip::tcp;
bool RtspServer::update_source(uint8_t id,
const std::string& name,
const std::string& sdp) {
@ -28,12 +28,11 @@ bool RtspServer::update_source(uint8_t id,
BOOST_LOG_TRIVIAL(debug) << "rtsp_server:: added source " << name;
std::lock_guard<std::mutex> lock(mutex_);
for (unsigned int i = 0; i < sessions_.size(); i++) {
auto session = sessions_[i].lock();
if (session != nullptr) {
ret |= session->announce(id, name, sdp,
config_->get_ip_addr_str(),
config_->get_rtsp_port());
}
auto session = sessions_[i].lock();
if (session != nullptr) {
ret |= session->announce(id, name, sdp, config_->get_ip_addr_str(),
config_->get_rtsp_port());
}
}
return ret;
}
@ -46,8 +45,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>(config_,
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();
@ -72,24 +71,26 @@ bool RtspSession::announce(uint8_t id,
const std::string& address,
uint16_t port) {
/* if a describe request is currently not beeing process
* and the specified source id has been described on this session send update */
* 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(config_->get_ip_addr()) + " " + 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"
<< "User-Agent: aes67-daemon\r\n"
<< "connection: Keep-Alive" << "\r\n"
<< "connection: Keep-Alive"
<< "\r\n"
<< "CSeq: " << announce_cseq_++ << "\r\n"
<< "Content-Length: " << sdp.length() << "\r\n"
<< "Content-Type: application/sdp\r\n"
<< "\r\n"
<< sdp;
BOOST_LOG_TRIVIAL(info)
<< "rtsp_server:: " << "ANNOUNCE for source " << name << " sent to "
<< socket_.remote_endpoint();
BOOST_LOG_TRIVIAL(info) << "rtsp_server:: "
<< "ANNOUNCE for source " << name << " sent to "
<< socket_.remote_endpoint();
send_response(ss.str());
return true;
@ -97,7 +98,6 @@ bool RtspSession::announce(uint8_t id,
return false;
}
bool RtspSession::process_request() {
/*
DESCRIBE rtsp://127.0.0.1:8080/by-name/test RTSP/1.0
@ -142,7 +142,7 @@ bool RtspSession::process_request() {
if (!is_end) {
return false;
}
if (fields[0].substr(0, 5) == "RTSP/") {
/* we received a response, step to next request*/
return true;
@ -172,8 +172,8 @@ void RtspSession::build_response(const std::string& url) {
return;
}
auto path = std::get<4>(res);
auto base_path = std::string("/by-name/") +
get_node_id(config_->get_ip_addr()) + " ";
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 */

View File

@ -83,7 +83,8 @@ class RtspSession : public std::enable_shared_from_this<RtspSession> {
class RtspServer {
public:
constexpr static uint8_t session_num_max{(SessionManager::stream_id_max + 1) * 2};
constexpr static uint8_t session_num_max{(SessionManager::stream_id_max + 1) *
2};
RtspServer() = delete;
RtspServer(std::shared_ptr<SessionManager> session_manager,
@ -101,21 +102,17 @@ class RtspServer {
bool init() {
accept();
/* start rtsp server on a separate thread */
res_ = std::async([this](){ io_service_.run(); });
res_ = std::async([this]() { io_service_.run(); });
session_manager_->add_source_observer(
SessionManager::ObserverType::add_source,
std::bind(&RtspServer::update_source, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3));
SessionManager::ObserverType::add_source,
std::bind(&RtspServer::update_source, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
session_manager_->add_source_observer(
SessionManager::ObserverType::update_source,
std::bind(&RtspServer::update_source, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3));
SessionManager::ObserverType::update_source,
std::bind(&RtspServer::update_source, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
return true;
}
@ -129,7 +126,9 @@ class RtspServer {
private:
/* a source was updated */
bool update_source(uint8_t id, const std::string& name, const std::string& sdp);
bool update_source(uint8_t id,
const std::string& name,
const std::string& sdp);
void accept();
std::mutex mutex_;

View File

@ -18,17 +18,16 @@
//
#include <boost/bind.hpp>
#include "sap.hpp"
#include "sap.hpp"
using namespace boost::asio;
using namespace boost::asio::ip;
SAP::SAP(const std::string& sap_mcast_addr) :
addr_(sap_mcast_addr)
SAP::SAP(const std::string& sap_mcast_addr)
: addr_(sap_mcast_addr)
// remote_endpoint_(ip::address::from_string(addr_), port)
{
{
socket_.open(boost::asio::ip::udp::v4());
socket_.set_option(udp::socket::reuse_address(true));
socket_.bind(listen_endpoint_);
@ -92,9 +91,8 @@ bool SAP::receive(bool& is_announce,
io_service_.run_one();
} while (ec == boost::asio::error::would_block);
if (!ec && length > 4 && (buffer[0] == 0x20 || buffer[0] == 0x24)) {
// only accept SAP announce or delete v2 with IPv4
// only accept SAP announce or delete v2 with IPv4
// no reserved, no compress, no encryption
// and content/type = application/sdp
is_announce = (buffer[0] == 0x20);
@ -125,7 +123,7 @@ void SAP::check_deadline() {
// cancel receive operation
socket_.cancel();
deadline_.expires_at(boost::posix_time::pos_infin);
//BOOST_LOG_TRIVIAL(debug) << "SAP:: timeout expired when receiving";
// BOOST_LOG_TRIVIAL(debug) << "SAP:: timeout expired when receiving";
}
deadline_.async_wait(boost::bind(&SAP::check_deadline, this));

View File

@ -21,6 +21,7 @@
#define _SAP_HPP_
#include <boost/asio.hpp>
#include "log.hpp"
using namespace boost::asio;

View File

@ -17,25 +17,26 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH 4096 //max for SDP file
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH 4096 // max for SDP file
#define CPPHTTPLIB_READ_TIMEOUT_SECOND 10
#include <httplib.h>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/algorithm/string.hpp>
#include <chrono>
#include <experimental/map>
#include <iostream>
#include <chrono>
#include <map>
#include <set>
#include "json.hpp"
#include "log.hpp"
#include "session_manager.hpp"
#include "utils.hpp"
#include "rtsp_client.hpp"
#include "utils.hpp"
#include "session_manager.hpp"
static uint8_t get_codec_word_lenght(const std::string& codec) {
@ -222,8 +223,8 @@ bool SessionManager::parse_sdp(const std::string sdp, StreamInfo& info) const {
/* c=IN IP4 239.1.0.12/15 */
/* connection info of audio media */
if (status == sdp_parser_status::media ||
/* generic connection info */
status == sdp_parser_status::init) {
/* generic connection info */
status == sdp_parser_status::init) {
std::vector<std::string> fields;
boost::split(fields, val,
[line](char c) { return c == ' ' || c == '/'; });
@ -324,35 +325,31 @@ std::list<StreamSource> SessionManager::get_sources() const {
StreamSource SessionManager::get_source_(uint8_t id,
const StreamInfo& info) const {
return {
id,
info.enabled,
info.stream.m_cName,
info.io,
info.stream.m_ui32MaxSamplesPerPacket,
info.stream.m_cCodec,
info.stream.m_byTTL,
info.stream.m_byPayloadType,
info.stream.m_ucDSCP,
info.refclk_ptp_traceable,
{ info.stream.m_aui32Routing, info.stream.m_aui32Routing +
info.stream.m_byNbOfChannels }
};
return {id,
info.enabled,
info.stream.m_cName,
info.io,
info.stream.m_ui32MaxSamplesPerPacket,
info.stream.m_cCodec,
info.stream.m_byTTL,
info.stream.m_byPayloadType,
info.stream.m_ucDSCP,
info.refclk_ptp_traceable,
{info.stream.m_aui32Routing,
info.stream.m_aui32Routing + info.stream.m_byNbOfChannels}};
}
StreamSink SessionManager::get_sink_(uint8_t id, const StreamInfo& info) const {
return {
id,
info.stream.m_cName,
info.io,
info.sink_use_sdp,
info.sink_source,
info.sink_sdp,
info.stream.m_ui32PlayOutDelay,
info.ignore_refclk_gmid,
{ info.stream.m_aui32Routing, info.stream.m_aui32Routing +
info.stream.m_byNbOfChannels }
};
return {id,
info.stream.m_cName,
info.io,
info.sink_use_sdp,
info.sink_source,
info.sink_sdp,
info.stream.m_ui32PlayOutDelay,
info.ignore_refclk_gmid,
{info.stream.m_aui32Routing,
info.stream.m_aui32Routing + info.stream.m_byNbOfChannels}};
}
bool SessionManager::load_status() {
@ -362,8 +359,8 @@ bool SessionManager::load_status() {
std::ifstream jsonstream(config_->get_status_file());
if (!jsonstream) {
BOOST_LOG_TRIVIAL(fatal)
<< "session_manager:: cannot load status file " << config_->get_status_file();
BOOST_LOG_TRIVIAL(fatal) << "session_manager:: cannot load status file "
<< config_->get_status_file();
return false;
}
@ -409,10 +406,12 @@ static std::array<uint8_t, 6> get_mcast_mac_addr(uint32_t mcast_ip) {
// As defined by IANA, the most significant 24 bits of an IPv4 multicast
// MAC address are 0x01005E. // Bit 25 is 0, and the other 23 bits are the
// least significant 23 bits of an IPv4 multicast address.
return { 0x01, 0x00, 0x5e,
static_cast<uint8_t>((mcast_ip >> 16) & 0x7F),
static_cast<uint8_t>(mcast_ip >> 8),
static_cast<uint8_t>(mcast_ip) };
return {0x01,
0x00,
0x5e,
static_cast<uint8_t>((mcast_ip >> 16) & 0x7F),
static_cast<uint8_t>(mcast_ip >> 8),
static_cast<uint8_t>(mcast_ip)};
}
uint8_t SessionManager::get_source_id(const std::string& name) const {
@ -421,21 +420,21 @@ uint8_t SessionManager::get_source_id(const std::string& name) const {
}
void SessionManager::add_source_observer(ObserverType type, Observer cb) {
switch(type) {
case ObserverType::add_source:
add_source_observers.push_back(cb);
break;
case ObserverType::remove_source:
remove_source_observers.push_back(cb);
break;
case ObserverType::update_source:
update_source_observers.push_back(cb);
break;
switch (type) {
case ObserverType::add_source:
add_source_observers.push_back(cb);
break;
case ObserverType::remove_source:
remove_source_observers.push_back(cb);
break;
case ObserverType::update_source:
update_source_observers.push_back(cb);
break;
}
}
void SessionManager::on_add_source(const StreamSource& source,
const StreamInfo& info) {
void SessionManager::on_add_source(const StreamSource& source,
const StreamInfo& info) {
for (auto cb : add_source_observers) {
cb(source.id, source.name, get_source_sdp_(source.id, info));
}
@ -449,7 +448,7 @@ void SessionManager::on_remove_source(const StreamInfo& info) {
cb(info.stream.m_uiId, info.stream.m_cName, {});
}
igmp_.leave(config_->get_ip_addr_str(),
ip::address_v4(info.stream.m_ui32DestIP).to_string());
ip::address_v4(info.stream.m_ui32DestIP).to_string());
source_names_.erase(info.stream.m_cName);
}
@ -462,11 +461,11 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
StreamInfo info;
memset(&info.stream, 0, sizeof info.stream);
info.stream.m_bSource = 1; // source
info.stream.m_bSource = 1; // source
info.stream.m_ui32CRTP_stream_info_sizeof = sizeof(info.stream);
strncpy(info.stream.m_cName, source.name.c_str(),
sizeof(info.stream.m_cName) - 1);
info.stream.m_ucDSCP = source.dscp; // IPv4 DSCP
info.stream.m_ucDSCP = source.dscp; // IPv4 DSCP
info.stream.m_byTTL = source.ttl;
info.stream.m_byPayloadType = source.payload_type;
info.stream.m_byWordLength = get_codec_word_lenght(source.codec);
@ -474,16 +473,18 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
strncpy(info.stream.m_cCodec, source.codec.c_str(),
sizeof(info.stream.m_cCodec) - 1);
info.stream.m_ui32MaxSamplesPerPacket = source.max_samples_per_packet;
info.stream.m_ui32SamplingRate = driver_->get_current_sample_rate(); // last set from driver or config
info.stream.m_ui32SamplingRate =
driver_->get_current_sample_rate(); // last set from driver or config
info.stream.m_uiId = source.id;
info.stream.m_ui32RTCPSrcIP = config_->get_ip_addr();
info.stream.m_ui32SrcIP = config_->get_ip_addr(); // only for Source
info.stream.m_ui32DestIP =
ip::address_v4::from_string(config_->get_rtp_mcast_base().c_str()).to_ulong() +
ip::address_v4::from_string(config_->get_rtp_mcast_base().c_str())
.to_ulong() +
source.id;
info.stream.m_usSrcPort = config_->get_rtp_port();
info.stream.m_usDestPort = config_->get_rtp_port();
info.stream.m_ui32SSRC = rand() % 65536; // use random number
info.stream.m_ui32SSRC = rand() % 65536; // use random number
std::copy(source.map.begin(), source.map.end(), info.stream.m_aui32Routing);
auto mcast_mac_addr = get_mcast_mac_addr(info.stream.m_ui32DestIP);
std::copy(std::begin(mcast_mac_addr), std::end(mcast_mac_addr),
@ -497,16 +498,17 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
std::unique_lock sources_lock(sources_mutex_);
auto const it = sources_.find(source.id);
if (it != sources_.end()) {
BOOST_LOG_TRIVIAL(info) << "session_manager:: source id "
<< std::to_string(source.id) << " is in use, updating";
BOOST_LOG_TRIVIAL(info)
<< "session_manager:: source id " << std::to_string(source.id)
<< " is in use, updating";
// remove previous stream if enabled
if ((*it).second.enabled) {
(void)driver_->remove_rtp_stream((*it).second.handle);
on_remove_source((*it).second);
}
} else if (source_names_.find(source.name) != source_names_.end()) {
BOOST_LOG_TRIVIAL(error) << "session_manager:: source name "
<< source.name << " is in use";
BOOST_LOG_TRIVIAL(error)
<< "session_manager:: source name " << source.name << " is in use";
return DaemonErrc::stream_name_in_use;
}
@ -522,8 +524,8 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
}
on_add_source(source, info);
}
// update source map
// update source map
sources_[source.id] = info;
BOOST_LOG_TRIVIAL(info) << "session_manager:: added source "
<< std::to_string(source.id) << " " << info.handle;
@ -542,14 +544,14 @@ std::string SessionManager::get_source_sdp_(uint32_t id,
std::shared_lock ptp_lock(ptp_mutex_);
uint32_t sample_rate = driver_->get_current_sample_rate();
// need a 12 digit precision for ptime
// need a 12 digit precision for ptime
std::ostringstream ss_ptime;
ss_ptime.precision(12);
ss_ptime << std::fixed
<< static_cast<double>(info.stream.m_ui32MaxSamplesPerPacket) * 1000 /
static_cast<double>(sample_rate);
<< static_cast<double>(info.stream.m_ui32MaxSamplesPerPacket) *
1000 / static_cast<double>(sample_rate);
std::string ptime = ss_ptime.str();
// remove trailing zeros or dot
// remove trailing zeros or dot
ptime.erase(ptime.find_last_not_of("0.") + 1, std::string::npos);
// build SDP
@ -635,8 +637,8 @@ uint8_t SessionManager::get_sink_id(const std::string& name) const {
return it != sink_names_.end() ? it->second : (stream_id_max + 1);
}
void SessionManager::on_add_sink(const StreamSink& sink,
const StreamInfo& info) {
void SessionManager::on_add_sink(const StreamSink& sink,
const StreamInfo& info) {
igmp_.join(config_->get_ip_addr_str(),
ip::address_v4(info.stream.m_ui32DestIP).to_string());
sink_names_[sink.name] = sink.id;
@ -644,7 +646,7 @@ void SessionManager::on_add_sink(const StreamSink& sink,
void SessionManager::on_remove_sink(const StreamInfo& info) {
igmp_.leave(config_->get_ip_addr_str(),
ip::address_v4(info.stream.m_ui32DestIP).to_string());
ip::address_v4(info.stream.m_ui32DestIP).to_string());
sink_names_.erase(info.stream.m_cName);
}
@ -657,7 +659,7 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
StreamInfo info;
memset(&info.stream, 0, sizeof info.stream);
info.stream.m_bSource = 0; // sink
info.stream.m_bSource = 0; // sink
info.stream.m_ui32CRTP_stream_info_sizeof = sizeof(info.stream);
strncpy(info.stream.m_cName, sink.name.c_str(),
sizeof(info.stream.m_cName) - 1);
@ -704,9 +706,9 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
}
sdp = std::move(res.second.sdp);
} else {
BOOST_LOG_TRIVIAL(error)
<< "session_manager:: unsupported protocol in URL " << sink.source;
return DaemonErrc::invalid_url;
BOOST_LOG_TRIVIAL(error)
<< "session_manager:: unsupported protocol in URL " << sink.source;
return DaemonErrc::invalid_url;
}
BOOST_LOG_TRIVIAL(info)
@ -719,8 +721,8 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
info.sink_sdp = std::move(sdp);
} else {
BOOST_LOG_TRIVIAL(info) << "session_manager:: using SDP "
<< std::endl << sink.sdp;
BOOST_LOG_TRIVIAL(info) << "session_manager:: using SDP " << std::endl
<< sink.sdp;
if (!parse_sdp(sink.sdp, info)) {
return DaemonErrc::cannot_parse_sdp;
}
@ -728,18 +730,18 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
info.sink_sdp = std::move(sink.sdp);
}
info.sink_source = sink.source;
info.sink_use_sdp = true; // save back and use with SDP file
info.sink_use_sdp = true; // save back and use with SDP file
info.stream.m_ui32FrameSize = info.stream.m_ui32MaxSamplesPerPacket;
if (!info.stream.m_ui32FrameSize) {
// if not from SDP use config
info.stream.m_ui32FrameSize = config_->get_max_tic_frame_size();
}
BOOST_LOG_TRIVIAL(info) << "session_manager:: sink frame size " <<
info.stream.m_ui32FrameSize;
BOOST_LOG_TRIVIAL(info) << "session_manager:: playout delay " <<
info.stream.m_ui32PlayOutDelay;
BOOST_LOG_TRIVIAL(info) << "session_manager:: sink frame size "
<< info.stream.m_ui32FrameSize;
BOOST_LOG_TRIVIAL(info) << "session_manager:: playout delay "
<< info.stream.m_ui32PlayOutDelay;
auto mcast_mac_addr = get_mcast_mac_addr(info.stream.m_ui32DestIP);
std::copy(std::begin(mcast_mac_addr), std::end(mcast_mac_addr),
@ -748,14 +750,15 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
std::unique_lock sinks_lock(sinks_mutex_);
auto const it = sinks_.find(sink.id);
if (it != sinks_.end()) {
BOOST_LOG_TRIVIAL(info) << "session_manager:: sink id "
<< std::to_string(sink.id) << " is in use, updating";
BOOST_LOG_TRIVIAL(info)
<< "session_manager:: sink id " << std::to_string(sink.id)
<< " is in use, updating";
// remove previous stream
(void)driver_->remove_rtp_stream((*it).second.handle);
on_remove_sink((*it).second);
} else if (sink_names_.find(sink.name) != sink_names_.end()) {
BOOST_LOG_TRIVIAL(error) << "session_manager:: sink name "
<< sink.name << " is in use";
BOOST_LOG_TRIVIAL(error)
<< "session_manager:: sink name " << sink.name << " is in use";
return DaemonErrc::stream_name_in_use;
}
@ -892,8 +895,7 @@ size_t SessionManager::process_sap() {
// check for sources that are no longer announced and send deletion/s
for (auto const& [msg_id_hash, src_addr] : announced_sources_) {
// check if this source is no longer announced
if (active_sources.find(msg_id_hash) ==
active_sources.end()) {
if (active_sources.find(msg_id_hash) == active_sources.end()) {
// retrieve deleted source SDP
std::string sdp = get_removed_source_sdp_(msg_id_hash >> 16, src_addr);
// send deletion for this source
@ -907,7 +909,7 @@ size_t SessionManager::process_sap() {
// remove all deleted sources announced SAP::max_deletions times
std::experimental::erase_if(announced_sources_, [this](auto source) {
const auto &msg_id_hash = source.first;
const auto& msg_id_hash = source.first;
if (this->deleted_sources_count_[msg_id_hash] >= SAP::max_deletions) {
// remove from deleted sources
@ -924,7 +926,7 @@ size_t SessionManager::process_sap() {
void SessionManager::on_update_sources() {
// trigger sources SDP file update
std::shared_lock sources_lock(sources_mutex_);
for (auto const& [id, info]: sources_) {
for (auto const& [id, info] : sources_) {
for (auto cb : update_source_observers) {
cb(id, info.stream.m_cName, get_source_sdp_(id, info));
}
@ -937,7 +939,7 @@ void SessionManager::on_ptp_status_locked() {
}
using namespace std::chrono;
using second_t = duration<double, std::ratio<1> >;
using second_t = duration<double, std::ratio<1> >;
bool SessionManager::worker() {
TPTPConfig ptp_config;
@ -955,8 +957,8 @@ bool SessionManager::worker() {
while (running_) {
// check if it's time to update the PTP status
if ((duration_cast<second_t>(steady_clock::now() - ptp_timepoint).count())
> ptp_interval) {
if ((duration_cast<second_t>(steady_clock::now() - ptp_timepoint).count()) >
ptp_interval) {
ptp_timepoint = steady_clock::now();
if (driver_->get_ptp_config(ptp_config) ||
driver_->get_ptp_status(ptp_status)) {
@ -965,21 +967,21 @@ bool SessionManager::worker() {
// return false;
} else {
char ptp_clock_id[24];
uint8_t* pui64GMID = reinterpret_cast<uint8_t*>(&ptp_status.ui64GMID);
uint8_t* pui64GMID = reinterpret_cast<uint8_t*>(&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], pui64GMID[5], pui64GMID[6], pui64GMID[7]);
"%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", pui64GMID[0],
pui64GMID[1], pui64GMID[2], pui64GMID[3], pui64GMID[4],
pui64GMID[5], pui64GMID[6], pui64GMID[7]);
bool ptp_changed_gmid = false;
bool ptp_changed_to_locked = false;
bool ptp_changed_gmid = false;
bool ptp_changed_to_locked = false;
// update PTP clock status
ptp_mutex_.lock();
// update status
if (ptp_status_.gmid != ptp_clock_id) {
ptp_mutex_.lock();
// update status
if (ptp_status_.gmid != ptp_clock_id) {
ptp_status_.gmid = ptp_clock_id;
ptp_changed_gmid = true;
}
}
ptp_status_.jitter = ptp_status.i32Jitter;
std::string new_ptp_status;
switch (ptp_status.nPTPLockStatus) {
@ -999,31 +1001,30 @@ bool SessionManager::worker() {
<< "session_manager:: new PTP clock status " << new_ptp_status;
ptp_status_.status = new_ptp_status;
if (new_ptp_status == "locked") {
ptp_changed_to_locked = true;
}
}
ptp_changed_to_locked = true;
}
}
// end update PTP clock status
ptp_mutex_.unlock();
ptp_mutex_.unlock();
if (ptp_changed_to_locked) {
if (ptp_changed_to_locked) {
on_ptp_status_locked();
}
}
if (ptp_changed_gmid ||
sample_rate != driver_->get_current_sample_rate()) {
/* master clock id changed or sample rate changed
if (ptp_changed_gmid ||
sample_rate != driver_->get_current_sample_rate()) {
/* master clock id changed or sample rate changed
* we need to update all the sources */
sample_rate = driver_->get_current_sample_rate();
on_update_sources();
}
on_update_sources();
}
}
ptp_interval = 10;
}
// check if it's time to send sap announcements
if ((duration_cast<second_t>(steady_clock::now() - sap_timepoint).count())
> sap_interval) {
if ((duration_cast<second_t>(steady_clock::now() - sap_timepoint).count()) >
sap_interval) {
sap_timepoint = steady_clock::now();
auto sdp_len_sum = process_sap();
@ -1036,7 +1037,7 @@ bool SessionManager::worker() {
sap_interval = std::max(static_cast<size_t>(SAP::min_interval),
sdp_len_sum * 8 / SAP::bandwidth_limit);
sap_interval +=
(std::rand() % (sap_interval * 2 / 3)) - (sap_interval / 3);
(std::rand() % (sap_interval * 2 / 3)) - (sap_interval / 3);
}
BOOST_LOG_TRIVIAL(info) << "session_manager:: next SAP announcements in "
@ -1058,4 +1059,4 @@ bool SessionManager::worker() {
igmp_.leave(config_->get_ip_addr_str(), ptp_primary_mcast_addr);
return true;
}
}

View File

@ -21,10 +21,10 @@
#define _SESSION_MANAGER_HPP_
#include <future>
#include <list>
#include <map>
#include <shared_mutex>
#include <thread>
#include <list>
#include "config.hpp"
#include "driver_manager.hpp"
@ -102,7 +102,7 @@ class SessionManager {
SessionManager() = delete;
SessionManager(const SessionManager&) = delete;
SessionManager& operator=(const SessionManager&) = delete;
virtual ~SessionManager(){ terminate(); };
virtual ~SessionManager() { terminate(); };
// session manager interface
bool init() {
@ -135,9 +135,9 @@ class SessionManager {
std::error_code remove_source(uint32_t id);
uint8_t get_source_id(const std::string& name) const;
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)>;
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);
std::error_code add_sink(const StreamSink& sink);
@ -180,7 +180,7 @@ class SessionManager {
// singleton, use create() to build
SessionManager(std::shared_ptr<DriverManager> driver,
std::shared_ptr<Config> config)
: driver_(driver), config_(config){
: driver_(driver), config_(config) {
ptp_config_.domain = config->get_ptp_domain();
ptp_config_.dscp = config->get_ptp_dscp();
};
@ -205,7 +205,7 @@ class SessionManager {
announced_sources_;
/* number of deletions sent for a a deleted source */
std::unordered_map<uint32_t /* msg_id_hash */, int /* count */>
std::unordered_map<uint32_t /* msg_id_hash */, int /* count */>
deleted_sources_count_;
PTPConfig ptp_config_;

View File

@ -20,5 +20,5 @@
"mdns_enabled": true,
"mac_addr": "00:00:00:00:00:00",
"ip_addr": "127.0.0.1",
"node_id": "AES67 daemon d9aca383"
"node_id": "AES67 daemon 007f0100"
}

View File

@ -17,7 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH 4096 //max for SDP file
#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH 4096 // max for SDP file
#define CPPHTTPLIB_READ_TIMEOUT_SECOND 30
#include <httplib.h>
#include <boost/foreach.hpp>
@ -33,7 +33,7 @@
#define BOOST_TEST_MODULE DaemonTest
#include <boost/test/unit_test.hpp>
#if ! (defined (__arm__) || defined (__arm64__))
#if !(defined(__arm__) || defined(__arm64__))
//#define _MEMORY_CHECK_
#endif
@ -79,17 +79,12 @@ struct DaemonInstance {
static bool is_ok() { return ok; }
private:
child daemon_{
child daemon_ {
#if defined _MEMORY_CHECK_
search_path("valgrind"),
search_path("valgrind"),
#endif
"../aes67-daemon",
"-c",
"daemon.conf",
"-p",
"9999",
"-i",
"lo"};
"../aes67-daemon", "-c", "daemon.conf", "-p", "9999", "-i", "lo"
};
inline static bool ok{false};
};
@ -259,11 +254,12 @@ struct Client {
"map": [ 0, 1 ],
)";
std::string json = json1 +
std::string("\"name\": \"ALSA " + std::to_string(id) + "\",\n") +
std::string("\"source\": \"http://") +
g_daemon_address + ":" + std::to_string(g_daemon_port) +
std::string("/api/source/sdp/") + std::to_string(id) + "\"\n}";
std::string json =
json1 +
std::string("\"name\": \"ALSA " + std::to_string(id) + "\",\n") +
std::string("\"source\": \"http://") + g_daemon_address + ":" +
std::to_string(g_daemon_port) + std::string("/api/source/sdp/") +
std::to_string(id) + "\"\n}";
std::string url = std::string("/api/sink/") + std::to_string(id);
auto res = cli_.Put(url.c_str(), json, "application/json");
BOOST_REQUIRE_MESSAGE(res != nullptr, "server returned response");
@ -287,9 +283,9 @@ struct Client {
auto len = socket_.receive(boost::asio::buffer(data, g_udp_size));
if (len <= g_sap_header_len) {
continue;
}
sap_sdp.assign(data + g_sap_header_len, data + len);
} while(data[0] != 0x20 || sap_sdp != sdp);
}
sap_sdp.assign(data + g_sap_header_len, data + len);
} while (data[0] != 0x20 || sap_sdp != sdp);
BOOST_CHECK_MESSAGE(true, "SAP announcement SDP and source SDP match");
}
return true;
@ -305,10 +301,11 @@ struct Client {
}
std::string sap_sdp_(data + g_sap_header_len, data + len);
if (data[0] == 0x24 && sap_sdp_.length() > 3) {
//o=- 56 0 IN IP4 127.0.0.1
ids.insert(std::atoi(sap_sdp_.c_str() + 3));
BOOST_TEST_MESSAGE("waiting deletion for " +
std::to_string(g_stream_num_max - ids.size()) + " sources");
// o=- 56 0 IN IP4 127.0.0.1
ids.insert(std::atoi(sap_sdp_.c_str() + 3));
BOOST_TEST_MESSAGE("waiting deletion for " +
std::to_string(g_stream_num_max - ids.size()) +
" sources");
}
}
}
@ -322,9 +319,9 @@ struct Client {
auto len = socket_.receive(boost::asio::buffer(data, g_udp_size));
if (len <= g_sap_header_len) {
continue;
}
sap_sdp.assign(data + g_sap_header_len, data + len);
} while(data[0] != 0x24 || sdp.find(sap_sdp) == std::string::npos);
}
sap_sdp.assign(data + g_sap_header_len, data + len);
} while (data[0] != 0x24 || sdp.find(sap_sdp) == std::string::npos);
BOOST_CHECK_MESSAGE(true, "SAP deletion SDP matches");
}
return true;
@ -353,7 +350,7 @@ struct Client {
BOOST_REQUIRE_MESSAGE(json.first, "got remote mdns sources");
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
//BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
// BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
} while (pt.get_child("remote_sources").size() != num && retry--);
return (retry > 0);
}
@ -379,7 +376,7 @@ BOOST_AUTO_TEST_CASE(get_config) {
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
auto http_port = pt.get<int>("http_port");
//auto log_severity = pt.get<int>("log_severity");
// auto log_severity = pt.get<int>("log_severity");
auto playout_delay = pt.get<int>("playout_delay");
auto tic_frame_size_at_1fs = pt.get<int>("tic_frame_size_at_1fs");
auto max_tic_frame_size = pt.get<int>("max_tic_frame_size");
@ -396,7 +393,7 @@ BOOST_AUTO_TEST_CASE(get_config) {
auto mac_addr = pt.get<std::string>("mac_addr");
auto ip_addr = pt.get<std::string>("ip_addr");
BOOST_CHECK_MESSAGE(http_port == 9999, "config as excepcted");
//BOOST_CHECK_MESSAGE(log_severity == 5, "config as excepcted");
// BOOST_CHECK_MESSAGE(log_severity == 5, "config as excepcted");
BOOST_CHECK_MESSAGE(playout_delay == 0, "config as excepcted");
BOOST_CHECK_MESSAGE(tic_frame_size_at_1fs == 192, "config as excepcted");
BOOST_CHECK_MESSAGE(max_tic_frame_size == 1024, "config as excepcted");
@ -407,7 +404,8 @@ BOOST_AUTO_TEST_CASE(get_config) {
BOOST_CHECK_MESSAGE(ptp_dscp == 46, "config as excepcted");
BOOST_CHECK_MESSAGE(sap_interval == 1, "config as excepcted");
BOOST_CHECK_MESSAGE(syslog_proto == "none", "config as excepcted");
BOOST_CHECK_MESSAGE(syslog_server == "255.255.255.254:1234", "config as excepcted");
BOOST_CHECK_MESSAGE(syslog_server == "255.255.255.254:1234",
"config as excepcted");
BOOST_CHECK_MESSAGE(status_file == "", "config as excepcted");
BOOST_CHECK_MESSAGE(interface_name == "lo", "config as excepcted");
BOOST_CHECK_MESSAGE(mac_addr == "00:00:00:00:00:00", "config as excepcted");
@ -423,7 +421,8 @@ BOOST_AUTO_TEST_CASE(get_ptp_status) {
boost::property_tree::read_json(ss, pt);
auto status = pt.get<std::string>("status");
auto jitter = pt.get<int>("jitter");
BOOST_REQUIRE_MESSAGE(status == "unlocked" && jitter == 0, "ptp status as excepcted");
BOOST_REQUIRE_MESSAGE(status == "unlocked" && jitter == 0,
"ptp status as excepcted");
}
BOOST_AUTO_TEST_CASE(get_ptp_config) {
@ -455,7 +454,8 @@ BOOST_AUTO_TEST_CASE(set_ptp_config) {
boost::property_tree::read_json(fs, pt);
domain = pt.get<int>("ptp_domain");
dscp = pt.get<int>("ptp_dscp");
BOOST_REQUIRE_MESSAGE(domain == 1 && dscp == 48, "ptp config file as excepcted");
BOOST_REQUIRE_MESSAGE(domain == 1 && dscp == 48,
"ptp config file as excepcted");
res = cli.set_ptp_config(0, 46);
BOOST_REQUIRE_MESSAGE(res, "set default ptp config");
}
@ -463,13 +463,14 @@ BOOST_AUTO_TEST_CASE(set_ptp_config) {
BOOST_AUTO_TEST_CASE(add_invalid_source) {
Client cli;
BOOST_REQUIRE_MESSAGE(!cli.add_source(g_stream_num_max),
"not added source " + std::to_string(g_stream_num_max));
"not added source " + std::to_string(g_stream_num_max));
BOOST_REQUIRE_MESSAGE(!cli.add_source(-1), "not added source -1");
}
BOOST_AUTO_TEST_CASE(remove_invalid_source) {
Client cli;
BOOST_REQUIRE_MESSAGE(!cli.remove_source(g_stream_num_max),
BOOST_REQUIRE_MESSAGE(
!cli.remove_source(g_stream_num_max),
"not removed source " + std::to_string(g_stream_num_max));
BOOST_REQUIRE_MESSAGE(!cli.remove_source(-1), "not removed source -1");
}
@ -522,8 +523,9 @@ BOOST_AUTO_TEST_CASE(source_check_sap_browser) {
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH (auto const& v, pt.get_child("remote_sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<std::string>("sdp") == sdp.second,
"returned sap source " + v.second.get<std::string>("id"));
BOOST_REQUIRE_MESSAGE(
v.second.get<std::string>("sdp") == sdp.second,
"returned sap source " + v.second.get<std::string>("id"));
}
BOOST_REQUIRE_MESSAGE(cli.remove_source(0), "removed source 0");
cli.sap_wait_deletion(0, sdp.second, 3);
@ -531,8 +533,8 @@ BOOST_AUTO_TEST_CASE(source_check_sap_browser) {
BOOST_REQUIRE_MESSAGE(json.first, "got remote sap sources");
std::stringstream ss1(json.second);
boost::property_tree::read_json(ss1, pt);
BOOST_REQUIRE_MESSAGE(pt.get_child("remote_sources").size() == 0,
"no remote sap sources");
BOOST_REQUIRE_MESSAGE(pt.get_child("remote_sources").size() == 0,
"no remote sap sources");
}
#ifdef _USE_AVAHI_
@ -541,24 +543,28 @@ BOOST_AUTO_TEST_CASE(source_check_mdns_browser) {
BOOST_REQUIRE_MESSAGE(cli.add_source(0), "added source 0");
auto sdp = cli.get_source_sdp(0);
BOOST_REQUIRE_MESSAGE(sdp.first, "got source sdp 0");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(1), "remote mdns source found");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(1),
"remote mdns source found");
auto json = cli.get_remote_mdns_sources();
BOOST_REQUIRE_MESSAGE(json.first, "got remote mdns sources");
boost::property_tree::ptree pt;
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH (auto const& v, pt.get_child("remote_sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<std::string>("sdp") == sdp.second,
"returned mdns source " + v.second.get<std::string>("id"));
BOOST_REQUIRE_MESSAGE(
v.second.get<std::string>("sdp") == sdp.second,
"returned mdns source " + v.second.get<std::string>("id"));
}
BOOST_REQUIRE_MESSAGE(cli.remove_source(0), "removed source 0");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0), "no remote mdns sources");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0),
"no remote mdns sources");
}
BOOST_AUTO_TEST_CASE(source_check_mdns_browser_update) {
Client cli;
BOOST_REQUIRE_MESSAGE(cli.add_source(0), "added source 0");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(1), "remote mdns source found");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(1),
"remote mdns source found");
BOOST_REQUIRE_MESSAGE(cli.update_source(0), "updated source 0");
auto sdp = cli.get_source_sdp(0);
BOOST_REQUIRE_MESSAGE(sdp.first, "got source sdp 0");
@ -571,7 +577,7 @@ BOOST_AUTO_TEST_CASE(source_check_mdns_browser_update) {
std::stringstream ss(json.second);
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
//BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
// BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
BOOST_FOREACH (auto const& v, pt.get_child("remote_sources")) {
if (v.second.get<std::string>("sdp") == sdp.second) {
found = true;
@ -580,7 +586,8 @@ BOOST_AUTO_TEST_CASE(source_check_mdns_browser_update) {
} while (retry-- && !found);
BOOST_REQUIRE_MESSAGE(retry > 0, "remote mdns source updated");
BOOST_REQUIRE_MESSAGE(cli.remove_source(0), "removed source 0");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0), "no remote mdns sources");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0),
"no remote mdns sources");
}
#endif
@ -592,10 +599,10 @@ BOOST_AUTO_TEST_CASE(sink_check_status) {
boost::property_tree::ptree pt;
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
//auto is_sink_muted = pt.get<bool>("sink_flags.muted");
// auto is_sink_muted = pt.get<bool>("sink_flags.muted");
auto is_sink_some_muted = pt.get<bool>("sink_flags.some_muted");
auto is_sink_all_muted = pt.get<bool>("sink_flags.all_muted");
//BOOST_REQUIRE_MESSAGE(is_sink_muted, "sink is muted");
// BOOST_REQUIRE_MESSAGE(is_sink_muted, "sink is muted");
BOOST_REQUIRE_MESSAGE(!is_sink_all_muted, "all sinks are mutes");
BOOST_REQUIRE_MESSAGE(!is_sink_some_muted, "some sinks are muted");
BOOST_REQUIRE_MESSAGE(cli.remove_sink(0), "removed sink 0");
@ -614,7 +621,7 @@ BOOST_AUTO_TEST_CASE(add_remove_all_sources) {
boost::property_tree::read_json(ss, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned source " + std::to_string(id));
++id;
}
@ -637,7 +644,7 @@ BOOST_AUTO_TEST_CASE(add_remove_all_sinks) {
boost::property_tree::read_json(ss, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sinks")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned sink " + std::to_string(id));
++id;
}
@ -664,13 +671,13 @@ BOOST_AUTO_TEST_CASE(add_remove_check_all) {
boost::property_tree::read_json(ss, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned source " + std::to_string(id));
++id;
}
id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sinks")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned sink " + std::to_string(id));
++id;
}
@ -709,13 +716,13 @@ BOOST_AUTO_TEST_CASE(add_remove_update_check_all) {
boost::property_tree::read_json(ss, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned source " + std::to_string(id));
++id;
}
id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sinks")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned sink " + std::to_string(id));
++id;
}
@ -737,7 +744,8 @@ BOOST_AUTO_TEST_CASE(add_remove_check_sap_browser_all) {
}
for (int id = 0; id < g_stream_num_max; id++) {
auto sdp = cli.get_source_sdp(id);
BOOST_REQUIRE_MESSAGE(sdp.first, std::string("got source sdp ") + std::to_string(id));
BOOST_REQUIRE_MESSAGE(sdp.first,
std::string("got source sdp ") + std::to_string(id));
cli.sap_wait_announcement(id, sdp.second);
}
boost::property_tree::ptree pt;
@ -748,10 +756,13 @@ BOOST_AUTO_TEST_CASE(add_remove_check_sap_browser_all) {
BOOST_REQUIRE_MESSAGE(json.first, "got remote sap sources");
std::stringstream ss(json.second);
boost::property_tree::read_json(ss, pt);
//BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
} while (pt.get_child("remote_sources").size() != g_stream_num_max && retry--);
BOOST_REQUIRE_MESSAGE(pt.get_child("remote_sources").size() == g_stream_num_max,
"found " + std::to_string(pt.get_child("remote_sources").size()) + " remote sap sources");
// BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
} while (pt.get_child("remote_sources").size() != g_stream_num_max &&
retry--);
BOOST_REQUIRE_MESSAGE(
pt.get_child("remote_sources").size() == g_stream_num_max,
"found " + std::to_string(pt.get_child("remote_sources").size()) +
" remote sap sources");
for (int id = 0; id < g_stream_num_max; id++) {
BOOST_REQUIRE_MESSAGE(cli.add_sink_sdp(id),
std::string("added sink ") + std::to_string(id));
@ -762,13 +773,13 @@ BOOST_AUTO_TEST_CASE(add_remove_check_sap_browser_all) {
boost::property_tree::read_json(ss1, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned source " + std::to_string(id));
++id;
}
id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sinks")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned sink " + std::to_string(id));
++id;
}
@ -784,9 +795,10 @@ BOOST_AUTO_TEST_CASE(add_remove_check_sap_browser_all) {
BOOST_REQUIRE_MESSAGE(json.first, "got remote sap sources");
std::stringstream ss2(json.second);
boost::property_tree::read_json(ss2, pt);
//BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
// BOOST_TEST_MESSAGE(std::to_string(pt.get_child("remote_sources").size()));
} while (pt.get_child("remote_sources").size() > 0 && retry--);
BOOST_REQUIRE_MESSAGE(pt.get_child("remote_sources").size() == 0, "no remote sap sources");
BOOST_REQUIRE_MESSAGE(pt.get_child("remote_sources").size() == 0,
"no remote sap sources");
for (int id = 0; id < g_stream_num_max; id++) {
BOOST_REQUIRE_MESSAGE(cli.remove_sink(id),
std::string("removed sink ") + std::to_string(id));
@ -800,8 +812,8 @@ BOOST_AUTO_TEST_CASE(add_remove_check_mdns_browser_all) {
BOOST_REQUIRE_MESSAGE(cli.add_source(id),
std::string("added source ") + std::to_string(id));
}
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(g_stream_num_max),
"remote mdns sources found");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(g_stream_num_max),
"remote mdns sources found");
for (int id = 0; id < g_stream_num_max; id++) {
BOOST_REQUIRE_MESSAGE(cli.add_sink_sdp(id),
std::string("added sink ") + std::to_string(id));
@ -813,13 +825,13 @@ BOOST_AUTO_TEST_CASE(add_remove_check_mdns_browser_all) {
boost::property_tree::read_json(ss1, pt);
uint8_t id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sources")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned source " + std::to_string(id));
++id;
}
id = 0;
BOOST_FOREACH (auto const& v, pt.get_child("sinks")) {
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
BOOST_REQUIRE_MESSAGE(v.second.get<uint8_t>("id") == id,
"returned sink " + std::to_string(id));
++id;
}
@ -827,7 +839,8 @@ BOOST_AUTO_TEST_CASE(add_remove_check_mdns_browser_all) {
BOOST_REQUIRE_MESSAGE(cli.remove_source(id),
std::string("removed source ") + std::to_string(id));
}
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0), "no remote mdns sources found");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0),
"no remote mdns sources found");
for (int id = 0; id < g_stream_num_max; id++) {
BOOST_REQUIRE_MESSAGE(cli.remove_sink(id),
std::string("removed sink ") + std::to_string(id));
@ -872,6 +885,7 @@ BOOST_AUTO_TEST_CASE(add_remove_check_mdns_browser_update_all) {
BOOST_REQUIRE_MESSAGE(cli.remove_source(id),
std::string("removed source ") + std::to_string(id));
}
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0), "no remote mdns sources found");
BOOST_REQUIRE_MESSAGE(cli.wait_for_remote_mdns_sources(0),
"no remote mdns sources found");
}
#endif

View File

@ -18,9 +18,11 @@
//
//
#include <boost/format.hpp>
#include "utils.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
uint16_t crc16(const uint8_t* p, size_t len) {
uint8_t x;
uint16_t crc = 0xFFFF;
@ -78,7 +80,20 @@ std::string get_node_id(uint32_t ip_addr) {
std::stringstream ss;
ip_addr = htonl(ip_addr);
/* we create an host ID based on the current IP */
ss << "AES67 daemon " << boost::format("%08x") %
((ip_addr << 16) | (ip_addr >> 16));
ss << "AES67 daemon "
<< boost::format("%08x") % ((ip_addr << 16) | (ip_addr >> 16));
return ss.str();
}
std::string sdp_get_subject(const std::string& sdp) {
std::stringstream ssstrem(sdp);
std::string line;
while (getline(ssstrem, line, '\n')) {
if (line.substr(0, 2) == "s=") {
auto subject = line.substr(2);
boost::trim(subject);
return subject;
}
}
return "";
}

View File

@ -20,11 +20,11 @@
#ifndef _UTILS_HPP_
#define _UTILS_HPP_
#include <iostream>
#include <cstddef>
#include <httplib.h>
#include <cstddef>
#include <iostream>
uint16_t crc16(const uint8_t* p, size_t len);
std::tuple<bool /* res */,
@ -36,4 +36,6 @@ parse_url(const std::string& _url);
std::string get_node_id(uint32_t ip_addr);
std::string sdp_get_subject(const std::string& sdp);
#endif