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:
Andrea Bondavalli 2020-04-03 09:55:01 -07:00
parent 449db1c73c
commit 0f8b9e714e
8 changed files with 77 additions and 27 deletions

View File

@ -35,11 +35,11 @@ std::shared_ptr<Browser> Browser::create(
return ptr;
}
std::list<RemoteSource> Browser::get_remote_sources() {
std::list<RemoteSource> Browser::get_remote_sources() const {
std::list<RemoteSource> sources_list;
std::shared_lock sources_lock(sources_mutex_);
// 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);
}
return sources_list;

View File

@ -61,12 +61,12 @@ class Browser : public MDNSClient {
bool init() override;
bool terminate() override;
std::list<RemoteSource> get_remote_sources();
std::list<RemoteSource> get_remote_sources() const;
protected:
// singleton, use create() to build
Browser(std::shared_ptr<Config> config):
config_(config),
MDNSClient(config),
startup_(std::chrono::steady_clock::now()){};
bool worker();
@ -79,7 +79,6 @@ class Browser : public MDNSClient {
const std::string& name,
const std::string& domain) override;
std::shared_ptr<Config> config_;
std::future<bool> res_;
std::atomic_bool running_{false};

View File

@ -95,6 +95,13 @@ std::shared_ptr<Config> Config::parse(const std::string& filename) {
}
config.ip_addr_ = ip_addr;
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.need_restart_ = false;

View File

@ -57,7 +57,8 @@ class Config {
uint32_t get_ip_addr() const { return ip_addr_; };
const std::string& get_ip_addr_str() const { return ip_str_; };
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_base_dir(const std::string& http_base_dir) { http_base_dir_ = http_base_dir; };
@ -103,8 +104,9 @@ class Config {
mac_addr_ = mac_addr;
};
void set_mdns_enabled(bool enabled) {
mdns_enabled = enabled;
mdns_enabled_ = enabled;
};
void set_interface_idx(int index) { interface_idx_ = index; };
private:
/* from json */
@ -125,13 +127,14 @@ class Config {
std::string syslog_server_{""};
std::string status_file_{"./status.json"};
std::string interface_name_{"eth0"};
bool mdns_enabled{true};
bool mdns_enabled_{true};
/* set during init */
std::array<uint8_t, 6> mac_addr_{0, 0, 0, 0, 0, 0};
std::string mac_str_;
uint32_t ip_addr_{0};
std::string ip_str_;
int interface_idx_;
std::string config_filename_;
/* reconfig needs daemon restart */

View File

@ -48,8 +48,8 @@ std::pair<uint32_t, std::string> get_interface_ip(
reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_addr);
uint32_t addr = ntohl(sockaddr->sin_addr.s_addr);
std::string str_addr(ip::address_v4(addr).to_string());
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name << " IP address "
<< str_addr;*/
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
<< " IP address " << 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];
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;*/
/*BOOST_LOG_TRIVIAL(debug) << "interface " << interface_name
<< " MAC address " << 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;
}

View File

@ -24,5 +24,6 @@ std::pair<uint32_t, std::string> get_interface_ip(
const std::string& interface_name);
std::pair<std::array<uint8_t, 6>, std::string> get_interface_mac(
const std::string& interface_name);
int get_interface_index(const std::string& interface_name);
#endif

View File

@ -22,6 +22,7 @@
#include <boost/asio.hpp>
#include "config.hpp"
#include "interface.hpp"
#include "log.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,
void* userdata) {
MDNSClient& mdns = *(reinterpret_cast<MDNSClient*>(userdata));
/* 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: "
<< avahi_strerror(avahi_client_errno(c));
<< 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, "_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
@ -194,17 +219,6 @@ bool MDNSClient::init() {
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());
#endif
running_ = true;

View File

@ -38,7 +38,8 @@
class MDNSClient {
public:
MDNSClient(){};
MDNSClient(std::shared_ptr<Config> config): config_(config){};
MDNSClient() = delete;
MDNSClient(const MDNSClient&) = delete;
MDNSClient& operator=(const MDNSClient&) = delete;
virtual ~MDNSClient() { terminate(); };
@ -93,6 +94,8 @@ class MDNSClient {
static void client_callback(AvahiClient* c,
AvahiClientState state,
void* userdata);
std::shared_ptr<Config> config_;
#endif
};