Applied Clang source code formatting to daemon sources
This commit is contained in:
parent
f9a07569f9
commit
098cebd056
@ -129,7 +129,7 @@ RawStringFormats:
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
|
@ -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>()) {
|
||||
for (const auto& source : sources_.get<name_tag>()) {
|
||||
if (boost::iequals(source.source, _source) ||
|
||||
boost::iequals("all", _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();
|
||||
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,8 +135,8 @@ 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();
|
||||
}
|
||||
@ -156,20 +146,19 @@ bool Browser::worker() {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,53 +45,51 @@ 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_;
|
||||
|
@ -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()) {
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
@ -282,11 +286,11 @@ 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);
|
||||
});
|
||||
[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");
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;*/
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,8 +132,7 @@ 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 */
|
||||
@ -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 */
|
||||
|
@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
|
||||
#ifndef _MAIN_HPP_
|
||||
#define _MAIN_HPP_
|
||||
|
||||
|
@ -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 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"))) {
|
||||
(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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
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
|
||||
@ -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 */
|
||||
|
@ -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_;
|
||||
|
@ -18,15 +18,14 @@
|
||||
//
|
||||
|
||||
#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());
|
||||
@ -92,7 +91,6 @@ 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
|
||||
// no reserved, no compress, no encryption
|
||||
@ -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));
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define _SAP_HPP_
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
using namespace boost::asio;
|
||||
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -546,8 +548,8 @@ std::string SessionManager::get_source_sdp_(uint32_t id,
|
||||
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
|
||||
ptime.erase(ptime.find_last_not_of("0.") + 1, std::string::npos);
|
||||
@ -636,7 +638,7 @@ uint8_t SessionManager::get_sink_id(const std::string& name) const {
|
||||
}
|
||||
|
||||
void SessionManager::on_add_sink(const StreamSink& sink,
|
||||
const StreamInfo& info) {
|
||||
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,7 +730,7 @@ 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) {
|
||||
@ -736,10 +738,10 @@ std::error_code SessionManager::add_sink(const StreamSink& sink) {
|
||||
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()) {
|
||||
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 "
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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 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("\"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);
|
||||
@ -532,7 +534,7 @@ BOOST_AUTO_TEST_CASE(source_check_sap_browser) {
|
||||
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");
|
||||
"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");
|
||||
@ -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));
|
||||
@ -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));
|
||||
@ -801,7 +813,7 @@ BOOST_AUTO_TEST_CASE(add_remove_check_mdns_browser_all) {
|
||||
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");
|
||||
"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));
|
||||
@ -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
|
||||
|
@ -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 "";
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user