blob: 6816df34f4b411e6f6d59875b52a5e98d48e9eca [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/mdns/cpp/service_subscriber.h"
#include "lib/fxl/logging.h"
namespace mdns {
ServiceSubscriber::ServiceSubscriber() {}
ServiceSubscriber::~ServiceSubscriber() { Reset(); }
void ServiceSubscriber::Init(fuchsia::mdns::ServiceSubscriptionPtr subscription,
UpdateCallback callback) {
subscription_ = std::move(subscription);
callback_ = std::move(callback);
HandleInstanceUpdates();
}
fuchsia::mdns::ServiceSubscriptionPtr ServiceSubscriber::Reset() {
callback_ = nullptr;
instances_.reset();
return std::move(subscription_);
}
void ServiceSubscriber::HandleInstanceUpdates(
uint64_t version,
fidl::VectorPtr<fuchsia::mdns::ServiceInstance> instances) {
FXL_DCHECK(subscription_);
if (instances) {
if (callback_) {
IssueCallbacks(instances);
}
instances_ = std::move(instances);
}
subscription_->GetInstances(
version, [this](uint64_t version,
std::vector<fuchsia::mdns::ServiceInstance> instances) {
HandleInstanceUpdates(version, fidl::VectorPtr(std::move(instances)));
});
}
void ServiceSubscriber::IssueCallbacks(
const std::vector<fuchsia::mdns::ServiceInstance>& instances) {
// For each instance in the update, see if it represents a new instance or
// a change with respect to an old instance.
for (auto& new_instance : instances) {
bool found = false;
// Search the old instances to see if there's a match.
for (auto& old_instance : *instances_) {
if (new_instance.service_name == old_instance.service_name &&
new_instance.instance_name == old_instance.instance_name) {
// Found a match. If there's been a change, issue a callback to
// indicate that.
if (new_instance.v4_address != old_instance.v4_address ||
new_instance.v6_address != old_instance.v6_address ||
*new_instance.text != *old_instance.text) {
callback_(&old_instance, &new_instance);
}
found = true;
break;
}
}
if (!found) {
// No match was found. Issue a callback indicating a new instance.
callback_(nullptr, &new_instance);
}
}
// For each old instance, determine whether it has been removed.
for (auto& old_instance : *instances_) {
bool found = false;
// Search the new instances to see if there's a match.
for (auto& new_instance : instances) {
if (new_instance.service_name == old_instance.service_name &&
new_instance.instance_name == old_instance.instance_name) {
found = true;
break;
}
}
if (!found) {
// No match was found. Issue a callback indicating a removed instance.
callback_(&old_instance, nullptr);
}
}
}
} // namespace mdns