Revised Avahi client integration in mDNS client:
- aligned state handling with avahi-browse tool: browser is started in client callback - browsing is limited to IPv4 services discovered on the specific daemon network interface only Additional minor changes.
This commit is contained in:
parent
449db1c73c
commit
0f8b9e714e
@ -35,11 +35,11 @@ std::shared_ptr<Browser> Browser::create(
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<RemoteSource> Browser::get_remote_sources() {
|
std::list<RemoteSource> Browser::get_remote_sources() const {
|
||||||
std::list<RemoteSource> sources_list;
|
std::list<RemoteSource> sources_list;
|
||||||
std::shared_lock sources_lock(sources_mutex_);
|
std::shared_lock sources_lock(sources_mutex_);
|
||||||
// return list of remote sources ordered by name
|
// return list of remote sources ordered by name
|
||||||
for (auto& source: sources_.get<name_tag>()) {
|
for (const auto& source: sources_.get<name_tag>()) {
|
||||||
sources_list.push_back(source);
|
sources_list.push_back(source);
|
||||||
}
|
}
|
||||||
return sources_list;
|
return sources_list;
|
||||||
|
@ -61,12 +61,12 @@ class Browser : public MDNSClient {
|
|||||||
bool init() override;
|
bool init() override;
|
||||||
bool terminate() override;
|
bool terminate() override;
|
||||||
|
|
||||||
std::list<RemoteSource> get_remote_sources();
|
std::list<RemoteSource> get_remote_sources() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// singleton, use create() to build
|
// singleton, use create() to build
|
||||||
Browser(std::shared_ptr<Config> config):
|
Browser(std::shared_ptr<Config> config):
|
||||||
config_(config),
|
MDNSClient(config),
|
||||||
startup_(std::chrono::steady_clock::now()){};
|
startup_(std::chrono::steady_clock::now()){};
|
||||||
|
|
||||||
bool worker();
|
bool worker();
|
||||||
@ -79,7 +79,6 @@ class Browser : public MDNSClient {
|
|||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& domain) override;
|
const std::string& domain) override;
|
||||||
|
|
||||||
std::shared_ptr<Config> config_;
|
|
||||||
std::future<bool> res_;
|
std::future<bool> res_;
|
||||||
std::atomic_bool running_{false};
|
std::atomic_bool running_{false};
|
||||||
|
|
||||||
|
@ -95,6 +95,13 @@ std::shared_ptr<Config> Config::parse(const std::string& filename) {
|
|||||||
}
|
}
|
||||||
config.ip_addr_ = ip_addr;
|
config.ip_addr_ = ip_addr;
|
||||||
config.ip_str_ = ip_str;
|
config.ip_str_ = ip_str;
|
||||||
|
auto interface_idx = get_interface_index(config.interface_name_);
|
||||||
|
if (interface_idx < 0) {
|
||||||
|
std::cerr << "Cannot retrieve index for interface "
|
||||||
|
<< config.interface_name_ << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
config.interface_idx_ = interface_idx;
|
||||||
config.config_filename_ = filename;
|
config.config_filename_ = filename;
|
||||||
config.need_restart_ = false;
|
config.need_restart_ = false;
|
||||||
|
|
||||||
|
@ -57,7 +57,8 @@ class Config {
|
|||||||
uint32_t get_ip_addr() const { return ip_addr_; };
|
uint32_t get_ip_addr() const { return ip_addr_; };
|
||||||
const std::string& get_ip_addr_str() const { return ip_str_; };
|
const std::string& get_ip_addr_str() const { return ip_str_; };
|
||||||
bool get_need_restart() const { return need_restart_; };
|
bool get_need_restart() const { return need_restart_; };
|
||||||
bool get_mdns_enabled() const { return mdns_enabled; };
|
bool get_mdns_enabled() const { return mdns_enabled_; };
|
||||||
|
int get_interface_idx() { return interface_idx_; };
|
||||||
|
|
||||||
void set_http_port(uint16_t http_port) { http_port_ = http_port; };
|
void set_http_port(uint16_t http_port) { http_port_ = http_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; };
|
||||||
@ -103,8 +104,9 @@ class Config {
|
|||||||
mac_addr_ = mac_addr;
|
mac_addr_ = mac_addr;
|
||||||
};
|
};
|
||||||
void set_mdns_enabled(bool enabled) {
|
void set_mdns_enabled(bool enabled) {
|
||||||
mdns_enabled = enabled;
|
mdns_enabled_ = enabled;
|
||||||
};
|
};
|
||||||
|
void set_interface_idx(int index) { interface_idx_ = index; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* from json */
|
/* from json */
|
||||||
@ -125,13 +127,14 @@ class Config {
|
|||||||
std::string syslog_server_{""};
|
std::string syslog_server_{""};
|
||||||
std::string status_file_{"./status.json"};
|
std::string status_file_{"./status.json"};
|
||||||
std::string interface_name_{"eth0"};
|
std::string interface_name_{"eth0"};
|
||||||
bool mdns_enabled{true};
|
bool mdns_enabled_{true};
|
||||||
|
|
||||||
/* set during init */
|
/* set during init */
|
||||||
std::array<uint8_t, 6> mac_addr_{0, 0, 0, 0, 0, 0};
|
std::array<uint8_t, 6> mac_addr_{0, 0, 0, 0, 0, 0};
|
||||||
std::string mac_str_;
|
std::string mac_str_;
|
||||||
uint32_t ip_addr_{0};
|
uint32_t ip_addr_{0};
|
||||||
std::string ip_str_;
|
std::string ip_str_;
|
||||||
|
int interface_idx_;
|
||||||
std::string config_filename_;
|
std::string config_filename_;
|
||||||
|
|
||||||
/* reconfig needs daemon restart */
|
/* reconfig needs daemon restart */
|
||||||
|
@ -48,8 +48,8 @@ std::pair<uint32_t, std::string> get_interface_ip(
|
|||||||
reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_addr);
|
reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_addr);
|
||||||
uint32_t addr = ntohl(sockaddr->sin_addr.s_addr);
|
uint32_t addr = ntohl(sockaddr->sin_addr.s_addr);
|
||||||
std::string str_addr(ip::address_v4(addr).to_string());
|
std::string str_addr(ip::address_v4(addr).to_string());
|
||||||
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name << " IP address "
|
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
|
||||||
<< str_addr;*/
|
<< " IP address " << str_addr;*/
|
||||||
|
|
||||||
return std::make_pair(addr, str_addr);
|
return std::make_pair(addr, str_addr);
|
||||||
}
|
}
|
||||||
@ -81,8 +81,31 @@ std::pair<std::array<uint8_t, 6>, std::string> get_interface_mac(
|
|||||||
char str_mac[18];
|
char str_mac[18];
|
||||||
sprintf(str_mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
|
sprintf(str_mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name << " MAC address "
|
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
|
||||||
<< str_mac;*/
|
<< " MAC address " << str_mac;*/
|
||||||
|
|
||||||
return std::make_pair(mac, str_mac);
|
return std::make_pair(mac, str_mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_interface_index(const std::string& interface_name) {
|
||||||
|
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< "Cannot retrieve index for interface " << interface_name;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
struct ifreq ifr;
|
||||||
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
strncpy(ifr.ifr_name, interface_name.c_str(), IFNAMSIZ - 1);
|
||||||
|
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
|
||||||
|
close(fd);
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< "Cannot retrieve index for interface " << interface_name;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
|
||||||
|
<< " index " << ifr.ifr_ifindex;*/
|
||||||
|
|
||||||
|
return ifr.ifr_ifindex;
|
||||||
|
}
|
||||||
|
@ -24,5 +24,6 @@ std::pair<uint32_t, std::string> get_interface_ip(
|
|||||||
const std::string& interface_name);
|
const std::string& interface_name);
|
||||||
std::pair<std::array<uint8_t, 6>, std::string> get_interface_mac(
|
std::pair<std::array<uint8_t, 6>, std::string> get_interface_mac(
|
||||||
const std::string& interface_name);
|
const std::string& interface_name);
|
||||||
|
int get_interface_index(const std::string& interface_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "interface.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "rtsp_client.hpp"
|
#include "rtsp_client.hpp"
|
||||||
|
|
||||||
@ -156,16 +157,40 @@ void MDNSClient::browse_callback(AvahiServiceBrowser* b,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDNSClient::client_callback(AvahiClient* c,
|
void MDNSClient::client_callback(AvahiClient* client,
|
||||||
AvahiClientState state,
|
AvahiClientState state,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
MDNSClient& mdns = *(reinterpret_cast<MDNSClient*>(userdata));
|
MDNSClient& mdns = *(reinterpret_cast<MDNSClient*>(userdata));
|
||||||
/* Called whenever the client or server state changes */
|
/* Called whenever the client or server state changes */
|
||||||
if (state == AVAHI_CLIENT_FAILURE) {
|
|
||||||
|
switch (state) {
|
||||||
|
case AVAHI_CLIENT_FAILURE:
|
||||||
BOOST_LOG_TRIVIAL(fatal) << "avahi_client:: server connection failure: "
|
BOOST_LOG_TRIVIAL(fatal) << "avahi_client:: server connection failure: "
|
||||||
<< avahi_strerror(avahi_client_errno(c));
|
<< avahi_strerror(avahi_client_errno(client));
|
||||||
|
/* TODO reconnect if disconnected */
|
||||||
avahi_threaded_poll_quit(mdns.poll_.get());
|
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, "_rtsp._tcp", nullptr,
|
||||||
|
{}, browse_callback, &mdns));
|
||||||
|
if (mdns.sb_ == nullptr) {
|
||||||
|
BOOST_LOG_TRIVIAL(fatal)
|
||||||
|
<< "avahi_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
|
#endif
|
||||||
|
|
||||||
@ -194,17 +219,6 @@ bool MDNSClient::init() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the service browser */
|
|
||||||
sb_.reset(avahi_service_browser_new(client_.get(), AVAHI_IF_UNSPEC,
|
|
||||||
AVAHI_PROTO_UNSPEC, "_rtsp._tcp", nullptr,
|
|
||||||
{}, browse_callback, this));
|
|
||||||
if (sb_ == nullptr) {
|
|
||||||
BOOST_LOG_TRIVIAL(fatal)
|
|
||||||
<< "avahi_client:: failed to create service browser: "
|
|
||||||
<< avahi_strerror(avahi_client_errno(client_.get()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)avahi_threaded_poll_start(poll_.get());
|
(void)avahi_threaded_poll_start(poll_.get());
|
||||||
#endif
|
#endif
|
||||||
running_ = true;
|
running_ = true;
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
|
|
||||||
class MDNSClient {
|
class MDNSClient {
|
||||||
public:
|
public:
|
||||||
MDNSClient(){};
|
MDNSClient(std::shared_ptr<Config> config): config_(config){};
|
||||||
|
MDNSClient() = delete;
|
||||||
MDNSClient(const MDNSClient&) = delete;
|
MDNSClient(const MDNSClient&) = delete;
|
||||||
MDNSClient& operator=(const MDNSClient&) = delete;
|
MDNSClient& operator=(const MDNSClient&) = delete;
|
||||||
virtual ~MDNSClient() { terminate(); };
|
virtual ~MDNSClient() { terminate(); };
|
||||||
@ -93,6 +94,8 @@ class MDNSClient {
|
|||||||
static void client_callback(AvahiClient* c,
|
static void client_callback(AvahiClient* c,
|
||||||
AvahiClientState state,
|
AvahiClientState state,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
|
|
||||||
|
std::shared_ptr<Config> config_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user