diff --git a/daemon/browser.cpp b/daemon/browser.cpp index 24d525d..c27b5c4 100644 --- a/daemon/browser.cpp +++ b/daemon/browser.cpp @@ -35,11 +35,11 @@ std::shared_ptr Browser::create( return ptr; } -std::list Browser::get_remote_sources() { +std::list Browser::get_remote_sources() const { std::list sources_list; std::shared_lock sources_lock(sources_mutex_); // return list of remote sources ordered by name - for (auto& source: sources_.get()) { + for (const auto& source: sources_.get()) { sources_list.push_back(source); } return sources_list; diff --git a/daemon/browser.hpp b/daemon/browser.hpp index c593604..5707d43 100644 --- a/daemon/browser.hpp +++ b/daemon/browser.hpp @@ -61,12 +61,12 @@ class Browser : public MDNSClient { bool init() override; bool terminate() override; - std::list get_remote_sources(); + std::list get_remote_sources() const; protected: // singleton, use create() to build Browser(std::shared_ptr 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_; std::future res_; std::atomic_bool running_{false}; diff --git a/daemon/config.cpp b/daemon/config.cpp index a954408..d8f3af1 100644 --- a/daemon/config.cpp +++ b/daemon/config.cpp @@ -95,6 +95,13 @@ std::shared_ptr 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; diff --git a/daemon/config.hpp b/daemon/config.hpp index fbe7c41..a88e21d 100644 --- a/daemon/config.hpp +++ b/daemon/config.hpp @@ -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 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 */ diff --git a/daemon/interface.cpp b/daemon/interface.cpp index c393cd2..f2793c2 100644 --- a/daemon/interface.cpp +++ b/daemon/interface.cpp @@ -48,8 +48,8 @@ std::pair get_interface_ip( reinterpret_cast(&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::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; +} diff --git a/daemon/interface.hpp b/daemon/interface.hpp index 21b9059..2a7fdb0 100644 --- a/daemon/interface.hpp +++ b/daemon/interface.hpp @@ -24,5 +24,6 @@ std::pair get_interface_ip( const std::string& interface_name); std::pair, std::string> get_interface_mac( const std::string& interface_name); +int get_interface_index(const std::string& interface_name); #endif diff --git a/daemon/mdns_client.cpp b/daemon/mdns_client.cpp index cd577c6..742465f 100644 --- a/daemon/mdns_client.cpp +++ b/daemon/mdns_client.cpp @@ -22,6 +22,7 @@ #include #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(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; diff --git a/daemon/mdns_client.hpp b/daemon/mdns_client.hpp index 28de978..acff811 100644 --- a/daemon/mdns_client.hpp +++ b/daemon/mdns_client.hpp @@ -38,7 +38,8 @@ class MDNSClient { public: - MDNSClient(){}; + MDNSClient(std::shared_ptr 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_; #endif };