mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Read IPv6 address from mDNS record.
PiperOrigin-RevId: 822743670
This commit is contained in:
committed by
Copybara-Service
parent
7e8cbfc140
commit
bd21843464
@@ -70,7 +70,6 @@ cc_library(
|
||||
"//connections:partners",
|
||||
],
|
||||
deps = [
|
||||
":mac_address",
|
||||
"//proto:connections_enums_cc_proto",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
@@ -83,7 +82,6 @@ cc_library(
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:span",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
@@ -201,4 +202,22 @@ std::string SocketAddress::ToString() const {
|
||||
return address_string;
|
||||
}
|
||||
|
||||
bool SocketAddress::IsV6LinkLocal() const {
|
||||
if (address_.ss_family != AF_INET6) {
|
||||
return false;
|
||||
}
|
||||
const sockaddr_in6* v6_address =
|
||||
reinterpret_cast<const sockaddr_in6*>(&address_);
|
||||
return IN6_IS_ADDR_LINKLOCAL(&v6_address->sin6_addr);
|
||||
}
|
||||
|
||||
bool SocketAddress::SetScopeId(uint32_t scope_id) {
|
||||
if (address_.ss_family != AF_INET6) {
|
||||
return false;
|
||||
}
|
||||
sockaddr_in6* v6_address = reinterpret_cast<sockaddr_in6*>(&address_);
|
||||
v6_address->sin6_scope_id = scope_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nearby::windows
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
@@ -72,6 +73,14 @@ class SocketAddress {
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
// Returns true if the address is a link local IPv6 address, ie. FE80::XXXX.
|
||||
// Returns false if the address is not IPv6 or is not link local.
|
||||
bool IsV6LinkLocal() const;
|
||||
|
||||
// Sets the scope id of the address.
|
||||
// Returns false if the address is not IPv6.
|
||||
bool SetScopeId(uint32_t scope_id);
|
||||
|
||||
// Returns a pointer to the internal sockaddr_storage.
|
||||
// This can be used to modify the address directly. However, the dual_stack
|
||||
// state is not honored, ie. it will not convert IPv4 addresses to mapped IPv6
|
||||
@@ -86,6 +95,13 @@ class SocketAddress {
|
||||
return const_cast<sockaddr*>(reinterpret_cast<const sockaddr*>(&address_));
|
||||
}
|
||||
|
||||
const sockaddr_in* ipv4_address() const {
|
||||
return reinterpret_cast<const sockaddr_in*>(&address_);
|
||||
}
|
||||
const sockaddr_in6* ipv6_address() const {
|
||||
return reinterpret_cast<const sockaddr_in6*>(&address_);
|
||||
}
|
||||
|
||||
private:
|
||||
// If `address_` is AF_INET, then rewrite into mapped ipv6 address, e.g.
|
||||
// [::ffff:192.0.2.1].
|
||||
|
||||
@@ -185,5 +185,21 @@ TEST(SocketAddressTest, DualStack) {
|
||||
EXPECT_FALSE(address2.dual_stack());
|
||||
}
|
||||
|
||||
TEST(SocketAddressTest, IPv6LinkLocalSuccess) {
|
||||
SocketAddress address(/*dual_stack=*/true);
|
||||
char bytes[16] = {0xfe, 0x80, 0, 0, 0, 0, 0, 0,
|
||||
0x4d, 0xb2, 0xb3, 0x5c, 0x22, 0x03, 0x98, 0xa1};
|
||||
EXPECT_TRUE(SocketAddress::FromBytes(address, bytes, 8080));
|
||||
EXPECT_TRUE(address.IsV6LinkLocal());
|
||||
}
|
||||
|
||||
TEST(SocketAddressTest, IPv6LinkLocalFail) {
|
||||
SocketAddress address(/*dual_stack=*/true);
|
||||
char bytes[16] = {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0x4d, 0xb2, 0xb3, 0x5c, 0x22, 0x03, 0x98, 0xa1};
|
||||
EXPECT_TRUE(SocketAddress::FromBytes(address, bytes, 8080));
|
||||
EXPECT_FALSE(address.IsV6LinkLocal());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby::windows
|
||||
|
||||
@@ -310,6 +310,23 @@ std::vector<std::string> InspectableReader::ReadStringArray(
|
||||
return result;
|
||||
}
|
||||
|
||||
GUID InspectableReader::ReadGuid(IInspectable inspectable) {
|
||||
if (inspectable == nullptr) {
|
||||
return GUID{};
|
||||
}
|
||||
auto property_value =
|
||||
inspectable.try_as<winrt::Windows::Foundation::IPropertyValue>();
|
||||
if (property_value == nullptr) {
|
||||
throw std::invalid_argument("no property value interface.");
|
||||
}
|
||||
if (property_value.Type() !=
|
||||
winrt::Windows::Foundation::PropertyType::Guid) {
|
||||
throw std::invalid_argument("not guid data type.");
|
||||
}
|
||||
|
||||
return property_value.GetGuid();
|
||||
}
|
||||
|
||||
std::optional<std::wstring> GetDnsHostName() {
|
||||
DWORD size = 0;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ class InspectableReader {
|
||||
static uint32_t ReadUint32(IInspectable inspectable);
|
||||
static std::string ReadString(IInspectable inspectable);
|
||||
static std::vector<std::string> ReadStringArray(IInspectable inspectable);
|
||||
static GUID ReadGuid(IInspectable inspectable);
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -269,13 +269,9 @@ class WifiLanMedium : public api::WifiLanMedium {
|
||||
return (medium_status_ & kMediumStatusDiscovering) != 0;
|
||||
}
|
||||
|
||||
// Checks whether the IP address is connectable in the given timeout.
|
||||
// Parameters:
|
||||
// ip - IP string in format as 192.168.1.1
|
||||
// port - The IP port to connect.
|
||||
// timeout - IP is not connectable if cannot connect in the duration.
|
||||
// Result - return true if the IP is connectable, otherwise return false.
|
||||
bool IsConnectableIpAddress(absl::string_view ip, int port,
|
||||
// Checks whether the service in the given timeout.
|
||||
// Returns true if the IP is connectable, otherwise return false.
|
||||
bool IsConnectableIpAddress(const NsdServiceInfo& nsd_service_info,
|
||||
absl::Duration timeout = absl::Seconds(1));
|
||||
|
||||
// Methods to manage discovred services.
|
||||
@@ -311,9 +307,6 @@ class WifiLanMedium : public api::WifiLanMedium {
|
||||
winrt::Windows::Devices::Enumeration::DeviceInformationUpdate
|
||||
deviceInfoUpdate);
|
||||
|
||||
// Gets error message from exception pointer
|
||||
std::string GetErrorMessage(std::exception_ptr eptr);
|
||||
|
||||
void RestartScanning();
|
||||
|
||||
//
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
// Windows headers
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
// Standard C/C++ headers
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -68,8 +70,6 @@ constexpr absl::string_view kDeviceEndpointInfo = "n";
|
||||
constexpr absl::string_view kDeviceIpv4 = "IPv4";
|
||||
|
||||
// mDNS information for advertising and discovery
|
||||
constexpr std::wstring_view kMdnsHostName = L"Windows.local";
|
||||
const char kMdnsInstanceNameFormat[] = "%s.%slocal";
|
||||
constexpr absl::string_view kMdnsDeviceSelectorFormat =
|
||||
"System.Devices.AepService.ProtocolId:=\"{4526e8c1-8aac-4153-9b16-"
|
||||
"55e86ada0e54}\" "
|
||||
@@ -79,6 +79,85 @@ constexpr absl::string_view kMdnsDeviceSelectorFormat =
|
||||
constexpr absl::Duration kConnectTimeout = absl::Seconds(2);
|
||||
constexpr absl::Duration kConnectServiceTimeout = absl::Seconds(3);
|
||||
|
||||
bool IsSelfInstance(IMapView<winrt::hstring, IInspectable> properties,
|
||||
absl::string_view self_instance_name) {
|
||||
IInspectable inspectable =
|
||||
properties.TryLookup(L"System.Devices.Dnssd.InstanceName");
|
||||
if (inspectable == nullptr) {
|
||||
VLOG(1) << "no service name information in device information.";
|
||||
// Unable to find instance name, so treat it as a self instance.
|
||||
return true;
|
||||
}
|
||||
// Don't discover itself
|
||||
if (InspectableReader::ReadString(inspectable) == self_instance_name) {
|
||||
VLOG(1) << "Don't update WIFI_LAN device for itself.";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetMdnsIpv4Address(const std::string& address_str,
|
||||
NsdServiceInfo& nsd_service_info) {
|
||||
SocketAddress ipv4_address(/*dual_stack=*/false);
|
||||
if (!SocketAddress::FromString(ipv4_address, address_str)) {
|
||||
return false;
|
||||
}
|
||||
DCHECK_EQ(ipv4_address.address()->sa_family, AF_INET);
|
||||
if (ipv4_address.address()->sa_family == AF_INET) {
|
||||
std::string ip_address_bytes;
|
||||
ip_address_bytes.resize(4);
|
||||
const sockaddr_in* ipv4_addr = ipv4_address.ipv4_address();
|
||||
std::memcpy(ip_address_bytes.data(), &ipv4_addr->sin_addr.s_addr, 4);
|
||||
nsd_service_info.SetIPAddress(ip_address_bytes);
|
||||
VLOG(1) << "Found ipv4 address: " <<ipv4_address.ToString();
|
||||
return true;
|
||||
}
|
||||
// Should not reach here.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetMdnsIpv6Address(const std::string& address_str,
|
||||
IMapView<winrt::hstring, IInspectable> properties,
|
||||
NsdServiceInfo& nsd_service_info) {
|
||||
SocketAddress ipv6_address(/*dual_stack=*/true);
|
||||
if (!SocketAddress::FromString(ipv6_address, address_str)) {
|
||||
return false;
|
||||
}
|
||||
DCHECK_EQ(ipv6_address.address()->sa_family, AF_INET6);
|
||||
if (ipv6_address.address()->sa_family == AF_INET6) {
|
||||
if (ipv6_address.IsV6LinkLocal()) {
|
||||
// Skip link local addresses if the interface index is not available.
|
||||
NET_IFINDEX interface_index = 0;
|
||||
IInspectable inspectable =
|
||||
properties.TryLookup(L"System.Devices.Dnssd.NetworkAdapterId");
|
||||
if (inspectable == nullptr) {
|
||||
return false;
|
||||
}
|
||||
GUID network_adapter_id = InspectableReader::ReadGuid(inspectable);
|
||||
NET_LUID luid;
|
||||
if (ConvertInterfaceGuidToLuid(&network_adapter_id, &luid) !=
|
||||
NO_ERROR) {
|
||||
VLOG(1) << "Failed to get interface luid";
|
||||
return false;
|
||||
}
|
||||
if (ConvertInterfaceLuidToIndex(&luid, &interface_index) !=
|
||||
NO_ERROR) {
|
||||
VLOG(1) << "Failed to get interface index";
|
||||
return false;
|
||||
}
|
||||
VLOG(1) << "network adapter luid: " << luid.Value
|
||||
<< ", interface index: " << interface_index;
|
||||
ipv6_address.SetScopeId(interface_index);
|
||||
}
|
||||
nsd_service_info.SetIPv6Address(ipv6_address.ToString());
|
||||
VLOG(1) << "Found ipv6 address: " <<ipv6_address.ToString();
|
||||
return true;
|
||||
}
|
||||
// Should not reach here.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
bool WifiLanMedium::IsNetworkConnected() const {
|
||||
@@ -167,6 +246,7 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_type,
|
||||
|
||||
std::vector<winrt::hstring> requestedProperties{
|
||||
L"System.Devices.IpAddress",
|
||||
L"System.Devices.Dnssd.NetworkAdapterId",
|
||||
L"System.Devices.Dnssd.HostName",
|
||||
L"System.Devices.Dnssd.InstanceName",
|
||||
L"System.Devices.Dnssd.PortNumber",
|
||||
@@ -284,10 +364,7 @@ std::unique_ptr<api::WifiLanServerSocket> WifiLanMedium::ListenForService(
|
||||
kEnableIpv6DualStack);
|
||||
if (server_socket->Listen(dual_stack)) {
|
||||
int port = server_socket_ptr->GetPort();
|
||||
LOG(INFO) << "started to listen serive on IP:port "
|
||||
<< ipaddr_4bytes_to_dotdecimal_string(
|
||||
server_socket_ptr->GetIPAddress())
|
||||
<< ":" << port;
|
||||
LOG(INFO) << "started to listen serive on port: " << port;
|
||||
port_to_server_socket_map_.insert({port, server_socket_ptr});
|
||||
|
||||
server_socket->SetCloseNotifier([this, server_socket_ptr, port]() {
|
||||
@@ -358,11 +435,25 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
std::string value = text_attribute.substr(pos + 1);
|
||||
nsd_service_info.SetTxtRecord(key, value);
|
||||
}
|
||||
|
||||
// mDNS record must have device endpoint info.
|
||||
if (nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data()).empty()) {
|
||||
LOG(ERROR) << "No device endpoint info found.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
if (!is_device_found) {
|
||||
return ExceptionOr<NsdServiceInfo>(nsd_service_info);
|
||||
}
|
||||
|
||||
// Read IP port
|
||||
inspectable = properties.TryLookup(L"System.Devices.Dnssd.PortNumber");
|
||||
if (inspectable == nullptr) {
|
||||
VLOG(1) << "no IP port property in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
int port = InspectableReader::ReadUint16(inspectable);
|
||||
nsd_service_info.SetPort(port);
|
||||
|
||||
// Read IP Address information
|
||||
// Use the mDNS resolved IP addresses first. If not available, use the IP
|
||||
// addresses from TXT record.
|
||||
@@ -378,46 +469,39 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
ip_address_candidates.push_back(ipv4_address);
|
||||
}
|
||||
|
||||
if (ip_address_candidates.empty()) {
|
||||
VLOG(1) << "No IP address information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
// Gets 4 bytes string
|
||||
std::string ip_address;
|
||||
ip_address.resize(4);
|
||||
bool has_ipv4_address = false;
|
||||
bool has_ipv6_address = false;
|
||||
for (std::string& address : ip_address_candidates) {
|
||||
uint32_t addr = inet_addr(address.data());
|
||||
if (addr == INADDR_NONE) {
|
||||
continue;
|
||||
if (has_ipv4_address && has_ipv6_address) {
|
||||
// Windows only provide 1 of each of IPv4 and IPv6 addresses.
|
||||
break;
|
||||
}
|
||||
if (!has_ipv4_address) {
|
||||
if (GetMdnsIpv4Address(address, nsd_service_info)) {
|
||||
has_ipv4_address = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!has_ipv6_address) {
|
||||
if (GetMdnsIpv6Address(address, properties, nsd_service_info)) {
|
||||
has_ipv6_address = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
in_addr ipv4_addr;
|
||||
ipv4_addr.S_un.S_addr = addr;
|
||||
ip_address[0] = static_cast<char>(ipv4_addr.S_un.S_un_b.s_b1);
|
||||
ip_address[1] = static_cast<char>(ipv4_addr.S_un.S_un_b.s_b2);
|
||||
ip_address[2] = static_cast<char>(ipv4_addr.S_un.S_un_b.s_b3);
|
||||
ip_address[3] = static_cast<char>(ipv4_addr.S_un.S_un_b.s_b4);
|
||||
break;
|
||||
}
|
||||
|
||||
nsd_service_info.SetIPAddress(ip_address);
|
||||
|
||||
// Read IP port
|
||||
inspectable = properties.TryLookup(L"System.Devices.Dnssd.PortNumber");
|
||||
if (inspectable == nullptr) {
|
||||
VLOG(1) << "no IP port property in device information.";
|
||||
if (!has_ipv4_address && !has_ipv6_address) {
|
||||
VLOG(1) << "no IP addresses in mDNS record.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
int port = InspectableReader::ReadUint16(inspectable);
|
||||
nsd_service_info.SetPort(port);
|
||||
|
||||
return ExceptionOr<NsdServiceInfo>(nsd_service_info);
|
||||
}
|
||||
|
||||
fire_and_forget WifiLanMedium::Watcher_DeviceAdded(
|
||||
DeviceWatcher sender, DeviceInformation deviceInfo) {
|
||||
VLOG(1) << "WifiLanMedium::Watcher_DeviceAdded";
|
||||
if (IsSelfInstance(deviceInfo.Properties(), service_name_)) {
|
||||
return fire_and_forget{};
|
||||
}
|
||||
// need to read IP address and port information from deviceInfo
|
||||
ExceptionOr<NsdServiceInfo> nsd_service_info_except =
|
||||
GetNsdServiceInformation(deviceInfo.Properties(),
|
||||
@@ -430,29 +514,13 @@ fire_and_forget WifiLanMedium::Watcher_DeviceAdded(
|
||||
}
|
||||
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
std::string endpoint =
|
||||
nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data());
|
||||
if (endpoint.empty()) {
|
||||
VLOG(1) << "No endpoint information! Don't add WIFI_LAN device.";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
// Don't discover itself
|
||||
if (nsd_service_info.GetServiceName() == service_name_) {
|
||||
VLOG(1) << "Don't add WIFI_LAN device for itself";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
LOG(INFO) << "device found for service name "
|
||||
<< nsd_service_info.GetServiceName() << ", address: "
|
||||
<< ipaddr_4bytes_to_dotdecimal_string(
|
||||
nsd_service_info.GetIPAddress())
|
||||
<< ":" << nsd_service_info.GetPort();
|
||||
<< nsd_service_info.GetServiceName()
|
||||
<< " on port " << nsd_service_info.GetPort();
|
||||
|
||||
if (!IsConnectableIpAddress(
|
||||
ipaddr_4bytes_to_dotdecimal_string(nsd_service_info.GetIPAddress()),
|
||||
nsd_service_info.GetPort(), kConnectTimeout)) {
|
||||
LOG(WARNING) << "Don't add WIFI_LAN device since it is not reachable.";
|
||||
if (!IsConnectableIpAddress(nsd_service_info, kConnectTimeout)) {
|
||||
VLOG(1) << "mDNS service " << nsd_service_info.GetServiceName()
|
||||
<< " is not reachable.";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
@@ -464,6 +532,10 @@ fire_and_forget WifiLanMedium::Watcher_DeviceAdded(
|
||||
|
||||
fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
VLOG(1) << "WifiLanMedium::Watcher_DeviceUpdated";
|
||||
if (IsSelfInstance(deviceInfoUpdate.Properties(), service_name_)) {
|
||||
return fire_and_forget{};
|
||||
}
|
||||
ExceptionOr<NsdServiceInfo> nsd_service_info_except =
|
||||
GetNsdServiceInformation(deviceInfoUpdate.Properties(),
|
||||
/*is_device_found*/ true);
|
||||
@@ -475,24 +547,14 @@ fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
|
||||
// Don't discover itself
|
||||
if (nsd_service_info.GetServiceName() == service_name_) {
|
||||
VLOG(1) << "Don't update WIFI_LAN device for itself.";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
// check having any changes
|
||||
std::optional<NsdServiceInfo> last_nsd_service_info =
|
||||
GetDiscoveredService(winrt::to_string(deviceInfoUpdate.Id()));
|
||||
if (!last_nsd_service_info.has_value()) {
|
||||
LOG(INFO) << "device updated for service name "
|
||||
<< nsd_service_info.GetServiceName() << ", address: "
|
||||
<< ipaddr_4bytes_to_dotdecimal_string(
|
||||
nsd_service_info.GetIPAddress())
|
||||
<< ":" << nsd_service_info.GetPort();
|
||||
if (IsConnectableIpAddress(
|
||||
ipaddr_4bytes_to_dotdecimal_string(nsd_service_info.GetIPAddress()),
|
||||
nsd_service_info.GetPort(), kConnectTimeout)) {
|
||||
<< nsd_service_info.GetServiceName()
|
||||
<< " on port " << nsd_service_info.GetPort();
|
||||
if (IsConnectableIpAddress(nsd_service_info, kConnectTimeout)) {
|
||||
// If the device is not in the discovered service list, but it is
|
||||
// connectable during update, we add it to the discovered service list.
|
||||
UpdateDiscoveredService(winrt::to_string(deviceInfoUpdate.Id()),
|
||||
@@ -501,7 +563,8 @@ fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
LOG(WARNING) << "Don't update WIFI_LAN device since it is not reachable.";
|
||||
VLOG(1) << "mDNS service " << nsd_service_info.GetServiceName()
|
||||
<< " is not reachable.";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
@@ -511,6 +574,8 @@ fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
nsd_service_info.GetServiceName()) &&
|
||||
(last_nsd_service_info->GetIPAddress() ==
|
||||
nsd_service_info.GetIPAddress()) &&
|
||||
(last_nsd_service_info->GetIPv6Address() ==
|
||||
nsd_service_info.GetIPv6Address()) &&
|
||||
(last_nsd_service_info->GetPort() == nsd_service_info.GetPort())) {
|
||||
VLOG(1) << "Don't update WIFI_LAN device since there is no change.";
|
||||
return fire_and_forget{};
|
||||
@@ -542,6 +607,10 @@ fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
|
||||
fire_and_forget WifiLanMedium::Watcher_DeviceRemoved(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
VLOG(1) << "WifiLanMedium::Watcher_DeviceRemoved";
|
||||
if (IsSelfInstance(deviceInfoUpdate.Properties(), service_name_)) {
|
||||
return fire_and_forget{};
|
||||
}
|
||||
// need to read IP address and port information from deviceInfo
|
||||
ExceptionOr<NsdServiceInfo> nsd_service_info_except =
|
||||
GetNsdServiceInformation(deviceInfoUpdate.Properties(),
|
||||
@@ -555,13 +624,6 @@ fire_and_forget WifiLanMedium::Watcher_DeviceRemoved(
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
LOG(INFO) << "device removed for service name "
|
||||
<< nsd_service_info.GetServiceName();
|
||||
|
||||
std::string endpoint =
|
||||
nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data());
|
||||
if (endpoint.empty()) {
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
RemoveDiscoveredService(winrt::to_string(deviceInfoUpdate.Id()));
|
||||
discovered_service_callback_.service_lost_cb(nsd_service_info);
|
||||
|
||||
@@ -598,22 +660,28 @@ void WifiLanMedium::RemoveDiscoveredService(absl::string_view id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WifiLanMedium::IsConnectableIpAddress(absl::string_view ip, int port,
|
||||
absl::Duration timeout) {
|
||||
bool WifiLanMedium::IsConnectableIpAddress(
|
||||
const NsdServiceInfo& nsd_service_info, absl::Duration timeout) {
|
||||
bool result = false;
|
||||
int error = -1;
|
||||
int size = sizeof(int);
|
||||
timeval tm;
|
||||
fd_set set;
|
||||
unsigned long non_blocking = 1; // NOLINT
|
||||
struct sockaddr_in serv_addr;
|
||||
if (nsd_service_info.GetIPAddress().empty()) {
|
||||
return false;
|
||||
}
|
||||
SocketAddress service_address(/*dual_stack=*/false);
|
||||
if (!SocketAddress::FromBytes(service_address,
|
||||
nsd_service_info.GetIPAddress(),
|
||||
nsd_service_info.GetPort())) {
|
||||
LOG(ERROR) << "no valid service address and port to connect.";
|
||||
return false;
|
||||
}
|
||||
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(port);
|
||||
serv_addr.sin_addr.S_un.S_addr = inet_addr(std::string(ip).c_str());
|
||||
|
||||
ioctlsocket(sock, /*cmd=*/FIONBIO, /*argp=*/&non_blocking);
|
||||
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) ==
|
||||
if (connect(sock, service_address.address(), sizeof(sockaddr_storage)) ==
|
||||
SOCKET_ERROR) {
|
||||
tm.tv_sec = timeout / absl::Seconds(1);
|
||||
tm.tv_usec = 0;
|
||||
@@ -641,16 +709,4 @@ bool WifiLanMedium::IsConnectableIpAddress(absl::string_view ip, int port,
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string WifiLanMedium::GetErrorMessage(std::exception_ptr eptr) {
|
||||
try {
|
||||
if (eptr) {
|
||||
std::rethrow_exception(eptr);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
return e.what();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nearby::windows
|
||||
|
||||
@@ -69,13 +69,22 @@ class NsdServiceInfo {
|
||||
txt_records_ = txt_records;
|
||||
}
|
||||
|
||||
// Gets IP Address, which is in byte sequence, in network order.
|
||||
std::string GetIPAddress() const { return ip_address_; }
|
||||
// Gets IPv4 Address, which is in byte sequence, in network order.
|
||||
std::string GetIPAddress() const { return ipv4_address_; }
|
||||
|
||||
// Sets IP Address. Not used in advertising.
|
||||
// Sets IPv4 Address. Not used in advertising.
|
||||
// mDNS system should advertise IP address based on the interface used to
|
||||
// start advertising.
|
||||
void SetIPAddress(const std::string& ip_address) { ip_address_ = ip_address; }
|
||||
void SetIPAddress(const std::string& ip_address) {
|
||||
ipv4_address_ = ip_address;
|
||||
}
|
||||
|
||||
// IPv6 address is in string format. The address can include a scope ID which
|
||||
// cannot be represented in byte sequence without some hackery.
|
||||
std::string GetIPv6Address() const { return ipv6_address_; }
|
||||
void SetIPv6Address(const std::string& ipv6_address) {
|
||||
ipv6_address_ = ipv6_address;
|
||||
}
|
||||
|
||||
// Gets the port number
|
||||
int GetPort() const { return port_; }
|
||||
@@ -96,7 +105,8 @@ class NsdServiceInfo {
|
||||
private:
|
||||
std::string service_name_;
|
||||
absl::flat_hash_map<std::string, std::string> txt_records_;
|
||||
std::string ip_address_;
|
||||
std::string ipv4_address_;
|
||||
std::string ipv6_address_;
|
||||
int port_;
|
||||
std::string service_type_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user