mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Parse remote device IP address from text attributes first
PiperOrigin-RevId: 490324278
This commit is contained in:
committed by
Copybara-Service
parent
defd5e03e7
commit
c499d18af6
@@ -26,6 +26,7 @@
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Third party headers
|
||||
#include "absl/strings/ascii.h"
|
||||
@@ -36,10 +37,18 @@
|
||||
#include "internal/platform/bluetooth_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/crypto.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Networking.Connectivity.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
|
||||
using ::winrt::Windows::Networking::HostNameType;
|
||||
using ::winrt::Windows::Networking::Connectivity::NetworkInformation;
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string uint64_to_mac_address_string(uint64_t bluetoothAddress) {
|
||||
std::string buffer = absl::StrFormat(
|
||||
@@ -100,6 +109,20 @@ std::string wstring_to_string(std::wstring wstr) {
|
||||
return converter.to_bytes(wstr);
|
||||
}
|
||||
|
||||
std::vector<std::string> GetIpv4Addresses() {
|
||||
std::vector<std::string> result;
|
||||
auto host_names = NetworkInformation::GetHostNames();
|
||||
for (const auto& host_name : host_names) {
|
||||
if (host_name.IPInformation() != nullptr &&
|
||||
host_name.IPInformation().NetworkAdapter() != nullptr &&
|
||||
host_name.Type() == HostNameType::Ipv4) {
|
||||
result.push_back(winrt::to_string(host_name.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ByteArray Sha256(absl::string_view input, size_t size) {
|
||||
ByteArray hash = location::nearby::Crypto::Sha256(input);
|
||||
return ByteArray{hash.data(), size};
|
||||
|
||||
@@ -44,6 +44,9 @@ std::wstring string_to_wstring(std::string str);
|
||||
std::string wstring_to_string(std::wstring wstr);
|
||||
ByteArray Sha256(absl::string_view input, size_t size);
|
||||
|
||||
// Reads the IPv4 addresses
|
||||
std::vector<std::string> GetIpv4Addresses();
|
||||
|
||||
namespace Constants {
|
||||
// The Id of the Service Name SDP attribute
|
||||
const uint16_t SdpServiceNameAttributeId = 0x100;
|
||||
|
||||
@@ -258,18 +258,6 @@ class WifiLanMedium : public api::WifiLanMedium {
|
||||
}
|
||||
|
||||
private:
|
||||
// mDNS text attributes
|
||||
static constexpr std::string_view KEY_ENDPOINT_INFO = "n";
|
||||
|
||||
// mDNS information for advertising and discovery
|
||||
static constexpr std::wstring_view MDNS_HOST_NAME = L"Windows.local";
|
||||
static constexpr std::string_view MDNS_INSTANCE_NAME_FORMAT = "%s.%slocal";
|
||||
static constexpr std::string_view MDNS_DEVICE_SELECTOR_FORMAT =
|
||||
"System.Devices.AepService.ProtocolId:=\"{4526e8c1-8aac-4153-9b16-"
|
||||
"55e86ada0e54}\" "
|
||||
"AND System.Devices.Dnssd.ServiceName:=\"%s\" AND "
|
||||
"System.Devices.Dnssd.Domain:=\"local\"";
|
||||
|
||||
// Nsd status
|
||||
static const int MEDIUM_STATUS_IDLE = 0;
|
||||
static const int MEDIUM_STATUS_ACCEPTING = (1 << 0);
|
||||
@@ -340,6 +328,9 @@ class WifiLanMedium : public api::WifiLanMedium {
|
||||
|
||||
// Keep the server socket listener pointer
|
||||
WifiLanServerSocket* server_socket_ptr_ = nullptr;
|
||||
|
||||
// Used to keep the service name is advertising.
|
||||
std::string service_name_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -22,19 +22,37 @@
|
||||
#include <cstdint>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
// ABSL headers
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
// Nearby connections headers
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/exception.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
// mDNS text attributes
|
||||
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";
|
||||
constexpr absl::string_view kMdnsInstanceNameFormat = "%s.%slocal";
|
||||
constexpr absl::string_view kMdnsDeviceSelectorFormat =
|
||||
"System.Devices.AepService.ProtocolId:=\"{4526e8c1-8aac-4153-9b16-"
|
||||
"55e86ada0e54}\" "
|
||||
"AND System.Devices.Dnssd.ServiceName:=\"%s\" AND "
|
||||
"System.Devices.Dnssd.Domain:=\"local\"";
|
||||
|
||||
} // namespace
|
||||
|
||||
bool WifiLanMedium::IsNetworkConnected() const {
|
||||
// connection_profile will be null when there's no network adapter or
|
||||
@@ -57,7 +75,7 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nsd_service_info.GetTxtRecord(KEY_ENDPOINT_INFO.data()).empty()) {
|
||||
if (nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data()).empty()) {
|
||||
NEARBY_LOGS(ERROR) << "cannot start advertising without endpoint info.";
|
||||
return false;
|
||||
}
|
||||
@@ -67,9 +85,11 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string instance_name = absl::StrFormat(
|
||||
MDNS_INSTANCE_NAME_FORMAT.data(), nsd_service_info.GetServiceName(),
|
||||
nsd_service_info.GetServiceType());
|
||||
service_name_ = nsd_service_info.GetServiceName();
|
||||
|
||||
std::string instance_name =
|
||||
absl::StrFormat(kMdnsInstanceNameFormat.data(), service_name_,
|
||||
nsd_service_info.GetServiceType());
|
||||
|
||||
NEARBY_LOGS(INFO) << "mDNS instance name is " << instance_name;
|
||||
|
||||
@@ -81,7 +101,8 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
// Add TextRecords from NsdServiceInfo
|
||||
auto text_attributes = dnssd_service_instance_.TextAttributes();
|
||||
|
||||
auto text_records = nsd_service_info.GetTxtRecords();
|
||||
absl::flat_hash_map<std::string, std::string> text_records =
|
||||
nsd_service_info.GetTxtRecords();
|
||||
auto it = text_records.begin();
|
||||
while (it != text_records.end()) {
|
||||
text_attributes.Insert(string_to_wstring(it->first),
|
||||
@@ -89,6 +110,16 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
it++;
|
||||
}
|
||||
|
||||
// Add IPv4 address in text attributes.
|
||||
std::vector<std::string> ipv4_addresses = GetIpv4Addresses();
|
||||
if (!ipv4_addresses.empty()) {
|
||||
if (ipv4_addresses.size() > 1) {
|
||||
NEARBY_LOGS(WARNING) << "The device has multiple IPv4 addresses.";
|
||||
}
|
||||
text_attributes.Insert(winrt::to_hstring(std::string(kDeviceIpv4)),
|
||||
winrt::to_hstring(ipv4_addresses[0]));
|
||||
}
|
||||
|
||||
dnssd_regirstraion_result_ = dnssd_service_instance_
|
||||
.RegisterStreamSocketListenerAsync(
|
||||
server_socket_ptr_->GetSocketListener())
|
||||
@@ -146,7 +177,7 @@ bool WifiLanMedium::StopAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
|
||||
// Init DNS service instance
|
||||
std::string instance_name = absl::StrFormat(
|
||||
MDNS_INSTANCE_NAME_FORMAT.data(), nsd_service_info.GetServiceName(),
|
||||
kMdnsInstanceNameFormat.data(), nsd_service_info.GetServiceName(),
|
||||
nsd_service_info.GetServiceType());
|
||||
int port = nsd_service_info.GetPort();
|
||||
dns_service_instance_name_ =
|
||||
@@ -154,7 +185,7 @@ bool WifiLanMedium::StopAdvertising(const NsdServiceInfo& nsd_service_info) {
|
||||
|
||||
dns_service_instance_.pszInstanceName =
|
||||
(LPWSTR)dns_service_instance_name_->c_str();
|
||||
dns_service_instance_.pszHostName = (LPWSTR)MDNS_HOST_NAME.data();
|
||||
dns_service_instance_.pszHostName = (LPWSTR)kMdnsHostName.data();
|
||||
dns_service_instance_.wPort = port;
|
||||
|
||||
// Init DNS service register request
|
||||
@@ -211,7 +242,7 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_type,
|
||||
}
|
||||
|
||||
std::string selector =
|
||||
absl::StrFormat(MDNS_DEVICE_SELECTOR_FORMAT.data(), service_type_trim);
|
||||
absl::StrFormat(kMdnsDeviceSelectorFormat.data(), service_type_trim);
|
||||
|
||||
std::vector<winrt::hstring> requestedProperties{
|
||||
L"System.Devices.IpAddress",
|
||||
@@ -361,7 +392,7 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
IMapView<winrt::hstring, IInspectable> properties, bool is_device_found) {
|
||||
NsdServiceInfo nsd_service_info{};
|
||||
|
||||
// Service name information
|
||||
// Read service name information
|
||||
IInspectable inspectable =
|
||||
properties.TryLookup(L"System.Devices.Dnssd.InstanceName");
|
||||
if (inspectable == nullptr) {
|
||||
@@ -371,7 +402,7 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
}
|
||||
nsd_service_info.SetServiceName(InspectableReader::ReadString(inspectable));
|
||||
|
||||
// Service type information
|
||||
// Read service type information
|
||||
inspectable = properties.TryLookup(L"System.Devices.Dnssd.ServiceName");
|
||||
if (inspectable == nullptr) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
@@ -386,56 +417,11 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
nsd_service_info.SetServiceType(
|
||||
(InspectableReader::ReadString(inspectable)).append("."));
|
||||
|
||||
if (is_device_found) {
|
||||
// IP Address information
|
||||
inspectable = properties.TryLookup(L"System.Devices.IPAddress");
|
||||
if (inspectable == nullptr) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "no IP address information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
auto ipaddresses = InspectableReader::ReadStringArray(inspectable);
|
||||
if (ipaddresses.size() == 0) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "no IP address information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
std::string ip_address;
|
||||
ip_address.resize(4);
|
||||
// Gets 4 bytes string
|
||||
for (std::string& address : ipaddresses) {
|
||||
uint32_t addr = inet_addr(address.data());
|
||||
if (addr == INADDR_NONE) {
|
||||
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;
|
||||
}
|
||||
|
||||
// read IP port
|
||||
inspectable = properties.TryLookup(L"System.Devices.Dnssd.PortNumber");
|
||||
if (inspectable == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << "no IP port information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
int port = InspectableReader::ReadUint16(inspectable);
|
||||
nsd_service_info.SetIPAddress(ip_address);
|
||||
nsd_service_info.SetPort(port);
|
||||
}
|
||||
// read text record
|
||||
// Read text records
|
||||
inspectable = properties.TryLookup(L"System.Devices.Dnssd.TextAttributes");
|
||||
if (inspectable == nullptr) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "no text attributes information in device information.";
|
||||
<< "No text attributes information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
@@ -453,7 +439,64 @@ ExceptionOr<NsdServiceInfo> WifiLanMedium::GetNsdServiceInformation(
|
||||
nsd_service_info.SetTxtRecord(key, value);
|
||||
}
|
||||
|
||||
return ExceptionOr(nsd_service_info);
|
||||
if (!is_device_found) {
|
||||
return ExceptionOr<NsdServiceInfo>(nsd_service_info);
|
||||
}
|
||||
|
||||
// Read IP Address information
|
||||
std::string ip_address;
|
||||
ip_address.resize(4);
|
||||
|
||||
// Find it from text first
|
||||
std::vector<std::string> ip_address_candidates;
|
||||
|
||||
std::string ipv4_address =
|
||||
nsd_service_info.GetTxtRecord(std::string(kDeviceIpv4));
|
||||
if (!ipv4_address.empty()) {
|
||||
ip_address_candidates.push_back(ipv4_address);
|
||||
} else {
|
||||
inspectable = properties.TryLookup(L"System.Devices.IPAddress");
|
||||
if (inspectable == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << "No IP address property in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
ip_address_candidates = InspectableReader::ReadStringArray(inspectable);
|
||||
}
|
||||
|
||||
if (ip_address_candidates.empty()) {
|
||||
NEARBY_LOGS(WARNING) << "No IP address information in device information.";
|
||||
return Exception{Exception::kFailed};
|
||||
}
|
||||
|
||||
// Gets 4 bytes string
|
||||
for (std::string& address : ip_address_candidates) {
|
||||
uint32_t addr = inet_addr(address.data());
|
||||
if (addr == INADDR_NONE) {
|
||||
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) {
|
||||
NEARBY_LOGS(WARNING) << "no IP port property in device information.";
|
||||
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(
|
||||
@@ -468,16 +511,28 @@ fire_and_forget WifiLanMedium::Watcher_DeviceAdded(
|
||||
"Don't add WIFI_LAN Medium";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
NEARBY_LOGS(INFO) << "device added for service name "
|
||||
<< nsd_service_info.GetServiceName();
|
||||
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
std::string endpoint =
|
||||
nsd_service_info.GetTxtRecord(KEY_ENDPOINT_INFO.data());
|
||||
nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data());
|
||||
if (endpoint.empty()) {
|
||||
NEARBY_LOGS(WARNING) << "No endpoint information! "
|
||||
"Don't add WIFI_LAN Medium";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
// Don't discover itself
|
||||
if (nsd_service_info.GetServiceName() == service_name_) {
|
||||
NEARBY_LOGS(WARNING) << "Don't add WIFI_LAN Medium for itself";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "device added for service name "
|
||||
<< nsd_service_info.GetServiceName() << ", address: "
|
||||
<< ipaddr_4bytes_to_dotdecimal_string(
|
||||
nsd_service_info.GetIPAddress())
|
||||
<< ":" << nsd_service_info.GetPort();
|
||||
|
||||
discovered_service_callback_.service_discovered_cb(nsd_service_info);
|
||||
|
||||
return fire_and_forget();
|
||||
@@ -497,8 +552,18 @@ fire_and_forget WifiLanMedium::Watcher_DeviceUpdated(
|
||||
}
|
||||
|
||||
NsdServiceInfo nsd_service_info = nsd_service_info_except.GetResult();
|
||||
NEARBY_LOGS(INFO) << "device updated for service name "
|
||||
<< nsd_service_info.GetServiceName();
|
||||
|
||||
// Don't discover itself
|
||||
if (nsd_service_info.GetServiceName() == service_name_) {
|
||||
NEARBY_LOGS(WARNING) << "Don't update WIFI_LAN Medium for itself";
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "device updated for service name: "
|
||||
<< nsd_service_info.GetServiceName() << ", address: "
|
||||
<< ipaddr_4bytes_to_dotdecimal_string(
|
||||
nsd_service_info.GetIPAddress())
|
||||
<< ":" << nsd_service_info.GetPort();
|
||||
return fire_and_forget();
|
||||
}
|
||||
|
||||
@@ -520,7 +585,7 @@ fire_and_forget WifiLanMedium::Watcher_DeviceRemoved(
|
||||
<< nsd_service_info.GetServiceName();
|
||||
|
||||
std::string endpoint =
|
||||
nsd_service_info.GetTxtRecord(KEY_ENDPOINT_INFO.data());
|
||||
nsd_service_info.GetTxtRecord(kDeviceEndpointInfo.data());
|
||||
if (endpoint.empty()) {
|
||||
return fire_and_forget{};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user