diff options
author | Alex Vakulenko <avakulenko@google.com> | 2015-12-17 11:21:09 -0800 |
---|---|---|
committer | Alex Vakulenko <avakulenko@google.com> | 2015-12-17 12:03:49 -0800 |
commit | 3dae2c9f756721a220f8b59c70306031568a3ff2 (patch) | |
tree | f48420d91da97121035d9736ce17d9b82e095570 | |
parent | f1a77fcb460c16e690306ea1e296d26ba7b90da2 (diff) | |
download | weaved-3dae2c9f756721a220f8b59c70306031568a3ff2.tar.gz |
Fix avahi host name resolution scenarios
When host name collision is detected, avahi picks a new host name,
however it fails to update any published services with the new name
which leads to wrong IP address resolution for the service.
As a work-around, when we detect an avahi-client restart, we just
re-publish our service, so it picks up the new host name.
BUG: 26237307
Change-Id: I980735890c62957e1bc433a07c319eff646c358c
-rw-r--r-- | buffet/avahi_mdns_client.cc | 44 | ||||
-rw-r--r-- | buffet/avahi_mdns_client.h | 8 |
2 files changed, 45 insertions, 7 deletions
diff --git a/buffet/avahi_mdns_client.cc b/buffet/avahi_mdns_client.cc index 852f59a..c60b727 100644 --- a/buffet/avahi_mdns_client.cc +++ b/buffet/avahi_mdns_client.cc @@ -54,8 +54,9 @@ AvahiMdnsClient::AvahiMdnsClient() int ret = 0; - client_.reset(avahi_client_new(avahi_threaded_poll_get(thread_pool_.get()), - {}, nullptr, this, &ret)); + client_.reset(avahi_client_new( + avahi_threaded_poll_get(thread_pool_.get()), {}, + &AvahiMdnsClient::OnAvahiClientStateUpdate, this, &ret)); CHECK(client_) << avahi_strerror(ret); avahi_threaded_poll_start(thread_pool_.get()); @@ -71,14 +72,17 @@ AvahiMdnsClient::~AvahiMdnsClient() { avahi_threaded_poll_stop(thread_pool_.get()); } -// TODO(rginda): Report errors back to the caller. -// TODO(rginda): Support publishing more than one service. void AvahiMdnsClient::PublishService(const std::string& service_type, uint16_t port, const std::vector<std::string>& txt) { CHECK(group_); CHECK_EQ("_privet._tcp", service_type); + if (prev_port_ == port && prev_service_type_ == service_type && + txt_records_ == txt) { + return; + } + // Create txt record. std::unique_ptr<AvahiStringList, decltype(&avahi_string_list_free)> txt_list{ nullptr, &avahi_string_list_free}; @@ -95,8 +99,9 @@ void AvahiMdnsClient::PublishService(const std::string& service_type, } int ret = 0; + txt_records_ = txt; - if (prev_port_ == port && prev_type_ == service_type) { + if (prev_port_ == port && prev_service_type_ == service_type) { ret = avahi_entry_group_update_service_txt_strlst( group_.get(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, {}, service_name_.c_str(), service_type.c_str(), nullptr, txt_list.get()); @@ -104,7 +109,7 @@ void AvahiMdnsClient::PublishService(const std::string& service_type, CHECK_GE(ret, 0) << avahi_strerror(ret); } else { prev_port_ = port; - prev_type_ = service_type; + prev_service_type_ = service_type; avahi_entry_group_reset(group_.get()); CHECK(avahi_entry_group_is_empty(group_.get())); @@ -123,6 +128,33 @@ void AvahiMdnsClient::PublishService(const std::string& service_type, void AvahiMdnsClient::StopPublishing(const std::string& service_type) { CHECK(group_); avahi_entry_group_reset(group_.get()); + prev_service_type_.clear(); + prev_port_ = 0; + txt_records_.clear(); +} + +void AvahiMdnsClient::OnAvahiClientStateUpdate(AvahiClient* s, + AvahiClientState state, + void* userdata) { + // Avahi service has been re-initialized (probably due to host name conflict), + // so we need to republish the service if it has been previously published. + if (state == AVAHI_CLIENT_S_RUNNING) { + AvahiMdnsClient* self = static_cast<AvahiMdnsClient*>(userdata); + self->RepublishService(); + } +} + +void AvahiMdnsClient::RepublishService() { + // If we don't have a service to publish, there is nothing else to do here. + if (prev_service_type_.empty()) + return; + + LOG(INFO) << "Republishing mDNS service"; + std::string service_type = std::move(prev_service_type_); + uint16_t port = prev_port_; + std::vector<std::string> txt = std::move(txt_records_); + StopPublishing(service_type); + PublishService(service_type, port, txt); } } // namespace buffet diff --git a/buffet/avahi_mdns_client.h b/buffet/avahi_mdns_client.h index 405180d..6bc896e 100644 --- a/buffet/avahi_mdns_client.h +++ b/buffet/avahi_mdns_client.h @@ -40,9 +40,15 @@ class AvahiMdnsClient : public MdnsClient { void StopPublishing(const std::string& service_type) override; private: + static void OnAvahiClientStateUpdate(AvahiClient* s, + AvahiClientState state, + void* userdata); + void RepublishService(); + uint16_t prev_port_{0}; - std::string prev_type_; + std::string prev_service_type_; std::string service_name_; + std::vector<std::string> txt_records_; std::unique_ptr<AvahiThreadedPoll, decltype(&avahi_threaded_poll_free)> thread_pool_{nullptr, &avahi_threaded_poll_free}; std::unique_ptr< ::AvahiClient, decltype(&avahi_client_free)> client_{ |