blob: 3d6d66750d0ae46fcef4edb1c50a5a8e142e5bac [file] [log] [blame]
// Copyright 2017 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 "garnet/bin/netconnector/mdns/mdns_fidl_util.h"
#include "lib/fxl/logging.h"
namespace netconnector {
namespace mdns {
// static
const std::string MdnsFidlUtil::kFuchsiaServiceName = "_fuchsia._tcp.";
// static
MdnsServiceInstancePtr MdnsFidlUtil::CreateServiceInstance(
const std::string& service_name,
const std::string& instance_name,
const SocketAddress& v4_address,
const SocketAddress& v6_address,
const std::vector<std::string>& text) {
MdnsServiceInstancePtr service_instance = MdnsServiceInstance::New();
service_instance->service_name = service_name;
service_instance->instance_name = instance_name;
service_instance->text = fidl::Array<fidl::String>::From(text);
if (v4_address.is_valid()) {
service_instance->v4_address = CreateSocketAddressIPv4(v4_address);
}
if (v6_address.is_valid()) {
service_instance->v6_address = CreateSocketAddressIPv6(v6_address);
}
return service_instance;
}
// static
bool MdnsFidlUtil::UpdateServiceInstance(
const MdnsServiceInstancePtr& service_instance,
const SocketAddress& v4_address,
const SocketAddress& v6_address,
const std::vector<std::string>& text) {
bool changed = false;
if (v4_address.is_valid()) {
if (!service_instance->v4_address) {
service_instance->v4_address = CreateSocketAddressIPv4(v4_address);
} else if (UpdateSocketAddressIPv4(service_instance->v4_address,
v4_address)) {
changed = true;
}
} else if (service_instance->v4_address) {
service_instance->v4_address.reset();
changed = true;
}
if (v6_address.is_valid()) {
if (!service_instance->v6_address) {
service_instance->v6_address = CreateSocketAddressIPv6(v6_address);
} else if (UpdateSocketAddressIPv6(service_instance->v6_address,
v6_address)) {
changed = true;
}
} else if (service_instance->v6_address) {
service_instance->v6_address.reset();
changed = true;
}
if (service_instance->text.size() != text.size()) {
service_instance->text.resize(text.size());
changed = true;
}
for (size_t i = 0; i < text.size(); ++i) {
if (service_instance->text[i] != text[i]) {
service_instance->text[i] = text[i];
changed = true;
}
}
return changed;
}
// static
netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
const IpAddress& ip_address) {
if (!ip_address) {
return nullptr;
}
FXL_DCHECK(ip_address.is_v4());
netstack::SocketAddressPtr result = netstack::SocketAddress::New();
result->addr = netstack::NetAddress::New();
result->addr->family = netstack::NetAddressFamily::IPV4;
result->addr->ipv4 = fidl::Array<uint8_t>::New(4);
result->port = 0;
FXL_DCHECK(result->addr->ipv4.size() == ip_address.byte_count());
std::memcpy(result->addr->ipv4.data(), ip_address.as_bytes(),
result->addr->ipv4.size());
return result;
}
// static
netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
const IpAddress& ip_address) {
if (!ip_address) {
return nullptr;
}
FXL_DCHECK(ip_address.is_v6());
netstack::SocketAddressPtr result = netstack::SocketAddress::New();
result->addr = netstack::NetAddress::New();
result->addr->family = netstack::NetAddressFamily::IPV6;
result->addr->ipv6 = fidl::Array<uint8_t>::New(16);
result->port = 0;
FXL_DCHECK(result->addr->ipv6.size() == ip_address.byte_count());
std::memcpy(result->addr->ipv6.data(), ip_address.as_bytes(),
result->addr->ipv6.size());
return result;
}
// static
netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
const SocketAddress& socket_address) {
if (!socket_address) {
return nullptr;
}
FXL_DCHECK(socket_address.is_v4());
netstack::SocketAddressPtr result =
CreateSocketAddressIPv4(socket_address.address());
result->port = socket_address.port().as_uint16_t();
return result;
}
// static
netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
const SocketAddress& socket_address) {
if (!socket_address) {
return nullptr;
}
FXL_DCHECK(socket_address.is_v6());
netstack::SocketAddressPtr result =
CreateSocketAddressIPv6(socket_address.address());
result->port = socket_address.port().as_uint16_t();
return result;
}
// static
bool MdnsFidlUtil::UpdateSocketAddressIPv4(
const netstack::SocketAddressPtr& net_address,
const SocketAddress& socket_address) {
FXL_DCHECK(net_address);
FXL_DCHECK(socket_address.is_v4());
bool changed = false;
if (net_address->port != socket_address.port().as_uint16_t()) {
net_address->port = socket_address.port().as_uint16_t();
changed = true;
}
FXL_DCHECK(net_address->addr->ipv4.size() ==
socket_address.address().byte_count());
if (std::memcmp(net_address->addr->ipv4.data(),
socket_address.address().as_bytes(),
net_address->addr->ipv4.size()) != 0) {
std::memcpy(net_address->addr->ipv4.data(),
socket_address.address().as_bytes(),
net_address->addr->ipv4.size());
changed = true;
}
return changed;
}
// static
bool MdnsFidlUtil::UpdateSocketAddressIPv6(
const netstack::SocketAddressPtr& net_address,
const SocketAddress& socket_address) {
FXL_DCHECK(net_address);
FXL_DCHECK(socket_address.is_v4());
bool changed = false;
if (net_address->port != socket_address.port().as_uint16_t()) {
net_address->port = socket_address.port().as_uint16_t();
changed = true;
}
FXL_DCHECK(net_address->addr->ipv6.size() ==
socket_address.address().byte_count());
if (std::memcmp(net_address->addr->ipv6.data(),
socket_address.address().as_bytes(),
net_address->addr->ipv6.size()) != 0) {
std::memcpy(net_address->addr->ipv6.data(),
socket_address.address().as_bytes(),
net_address->addr->ipv6.size());
changed = true;
}
return changed;
}
} // namespace mdns
} // namespace netconnector