Add Wifi Medium to query WIFI interface capability and information

PiperOrigin-RevId: 451233512
This commit is contained in:
hai007
2022-05-26 13:40:14 -07:00
committed by Copybara-Service
parent ea939b70d3
commit 500f67c85e
25 changed files with 882 additions and 26 deletions
+3
View File
@@ -437,6 +437,7 @@ let package = Package(
"connections/implementation/mediums/lost_entity_tracker_test.cc",
"connections/implementation/mediums/bluetooth_radio_test.cc",
"connections/implementation/mediums/wifi_hotspot_test.cc",
"connections/implementation/mediums/wifi_test.cc",
"connections/implementation/endpoint_channel_manager_test.cc",
"connections/implementation/bwu_manager_test.cc",
"connections/implementation/base_bwu_handler_test.cc",
@@ -462,6 +463,8 @@ let package = Package(
"internal/platform/uuid_test.cc",
"internal/platform/wifi_hotspot_test.cc",
"internal/platform/wifi_lan_test.cc",
"internal/platform/wifi_test.cc",
"internal/platform/wifi_utils_test.cc",
"internal/platform/condition_variable_test.cc",
"internal/platform/thread_check_nocompile_test.py",
"internal/platform/bluetooth_classic_test.cc",
+25 -3
View File
@@ -548,11 +548,31 @@ Status BasePcpHandler::RequestConnection(
// Generate the nonce to use for this connection.
std::int32_t nonce = prng_.NextInt32();
bool is_supports_5_ghz = false;
std::string bssid = "";
std::int32_t ap_frequency = -1;
std::string ip_address = "";
if (mediums_->GetWifi().IsAvailable()) {
is_supports_5_ghz =
mediums_->GetWifi().GetCapability().supports_5_ghz;
api::WifiInformation& wifi_info =
mediums_->GetWifi().GetInformation();
bssid = wifi_info.bssid;
ap_frequency = wifi_info.ap_frequency;
ip_address = wifi_info.ip_address_4_bytes;
NEARBY_LOGS(INFO) << "Query for WIFI information: is_supports_5_ghz="
<< is_supports_5_ghz << "; bssid=" << bssid
<< "; ap_frequency=" << ap_frequency
<< "Mhz; ip_address in bytes format=" << ip_address;
}
// The first message we have to send, after connecting, is to tell the
// endpoint about ourselves.
Exception write_exception = WriteConnectionRequestFrame(
channel.get(), client->GetLocalEndpointId(), info.endpoint_info,
nonce, GetSupportedConnectionMediumsByPriority(connection_options),
nonce, is_supports_5_ghz, bssid, ap_frequency, ip_address,
GetSupportedConnectionMediumsByPriority(connection_options),
connection_options.keep_alive_interval_millis,
connection_options.keep_alive_timeout_millis);
if (!write_exception.Ok()) {
@@ -710,12 +730,14 @@ bool BasePcpHandler::CanReceiveIncomingConnection(ClientProxy* client) const {
Exception BasePcpHandler::WriteConnectionRequestFrame(
EndpointChannel* endpoint_channel, const std::string& local_endpoint_id,
const ByteArray& local_endpoint_info, std::int32_t nonce,
bool supports_5_ghz, const std::string& bssid, std::int32_t ap_frequency,
const std::string& ip_address,
const std::vector<proto::connections::Medium>& supported_mediums,
std::int32_t keep_alive_interval_millis,
std::int32_t keep_alive_timeout_millis) {
return endpoint_channel->Write(parser::ForConnectionRequest(
local_endpoint_id, local_endpoint_info, nonce, /*supports_5_ghz =*/false,
/*bssid=*/std::string{}, supported_mediums, keep_alive_interval_millis,
local_endpoint_id, local_endpoint_info, nonce, supports_5_ghz, bssid,
ap_frequency, ip_address, supported_mediums, keep_alive_interval_millis,
keep_alive_timeout_millis));
}
@@ -387,6 +387,8 @@ class BasePcpHandler : public PcpHandler,
static Exception WriteConnectionRequestFrame(
EndpointChannel* endpoint_channel, const std::string& local_endpoint_id,
const ByteArray& local_endpoint_info, std::int32_t nonce,
bool supports_5_ghz, const std::string& bssid, std::int32_t ap_frequency,
const std::string& ip_address,
const std::vector<proto::connections::Medium>& supported_mediums,
std::int32_t keep_alive_interval_millis,
std::int32_t keep_alive_timeout_millis);
@@ -195,9 +195,10 @@ TEST_F(EndpointManagerTest, RegisterFrameProcessorWorks) {
auto endpoint_channel = std::make_unique<MockEndpointChannel>();
auto connect_request = std::make_unique<MockFrameProcessor>();
ByteArray endpoint_info{"endpoint_name"};
auto read_data =
parser::ForConnectionRequest("endpoint_id", endpoint_info, 1234, false,
"", std::vector{Medium::BLE}, 0, 0);
auto read_data = parser::ForConnectionRequest(
"endpoint_id", endpoint_info, 1234, false, "", 2412, "8xqT",
std::vector<Medium>{Medium::BLE}, 0,
0);
EXPECT_CALL(*connect_request, OnIncomingFrame);
EXPECT_CALL(*connect_request, OnEndpointDisconnect);
EXPECT_CALL(*endpoint_channel, Read())
+2
View File
@@ -32,6 +32,7 @@ cc_library(
"bluetooth_radio.h",
"mediums.h",
"webrtc_stub.h",
"wifi.h",
"wifi_hotspot.h",
"wifi_lan.h",
],
@@ -101,6 +102,7 @@ cc_test(
"lost_entity_tracker_test.cc",
"wifi_hotspot_test.cc",
"wifi_lan_test.cc",
"wifi_test.cc",
],
defines = ["NO_WEBRTC"],
shard_count = 16,
@@ -26,6 +26,8 @@ Ble& Mediums::GetBle() { return ble_; }
BleV2& Mediums::GetBleV2() { return ble_v2_; }
Wifi& Mediums::GetWifi() { return wifi_; }
WifiLan& Mediums::GetWifiLan() { return wifi_lan_; }
WifiHotspot& Mediums::GetWifiHotspot() { return wifi_hotspot_; }
@@ -24,6 +24,7 @@
#else
#include "connections/implementation/mediums/webrtc.h"
#endif
#include "connections/implementation/mediums/wifi.h"
#include "connections/implementation/mediums/wifi_hotspot.h"
#include "connections/implementation/mediums/wifi_lan.h"
@@ -49,6 +50,9 @@ class Mediums {
// Returns a handle to the Ble medium.
BleV2& GetBleV2();
// Returns a handle to the Wifi medium.
Wifi& GetWifi();
// Returns a handle to the Wifi-Lan medium.
WifiLan& GetWifiLan();
@@ -71,6 +75,7 @@ class Mediums {
BluetoothClassic bluetooth_classic_{bluetooth_radio_};
Ble ble_{bluetooth_radio_};
BleV2 ble_v2_{bluetooth_radio_};
Wifi wifi_;
WifiLan wifi_lan_;
WifiHotspot wifi_hotspot_;
mediums::WebRtc webrtc_;
+80
View File
@@ -0,0 +1,80 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CORE_INTERNAL_MEDIUMS_WIFI_H_
#define CORE_INTERNAL_MEDIUMS_WIFI_H_
// #include "internal/platform/mutex.h"
#include <string>
#include "internal/platform/mutex_lock.h"
#include "internal/platform/wifi.h"
namespace location {
namespace nearby {
namespace connections {
class Wifi {
public:
Wifi() = default;
~Wifi() = default;
// Not copyable or movable
Wifi(const Wifi&) = delete;
Wifi& operator=(const Wifi&) = delete;
Wifi(Wifi&&) = delete;
Wifi& operator=(Wifi&&) = delete;
// Returns true, if Wifi Medium are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return IsAvailableLocked();
}
api::WifiCapability& GetCapability() {
MutexLock lock(&mutex_);
return medium_.GetCapability();
}
api::WifiInformation& GetInformation() {
MutexLock lock(&mutex_);
return medium_.GetInformation();
}
bool VerifyInternetConnectivity() {
MutexLock lock(&mutex_);
return medium_.VerifyInternetConnectivity();
}
std::string GetIpAddress() const {
MutexLock lock(&mutex_);
return medium_.GetIpAddress();
}
private:
mutable Mutex mutex_;
WifiMedium medium_ ABSL_GUARDED_BY(mutex_);
// Same as IsAvailable(), but must be called with mutex_ held.
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
if (medium_.IsValid()) return medium_.IsInterfaceValid();
return false;
}
};
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_MEDIUMS_WIFI_H_
@@ -0,0 +1,49 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "connections/implementation/mediums/wifi.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
namespace connections {
namespace {
TEST(WifiTest, ConstructorDestructorWorks) {
Wifi wifi_a;
Wifi wifi_b;
if (wifi_a.IsAvailable() && wifi_b.IsAvailable()) {
// Make sure we can create 2 distinct mediums.
EXPECT_NE(&wifi_a, &wifi_b);
}
// TODO(b/233324423): Add test coverage for wifi.h
}
TEST(WifiTest, CanGetCapability) {
// TODO(b/233324423): Add test coverage for wifi.h
}
TEST(WifiTest, CanInformation) {
// TODO(b/233324423): Add test coverage for wifi.h
}
} // namespace
} // namespace connections
} // namespace nearby
} // namespace location
@@ -66,6 +66,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id,
const ByteArray& endpoint_info,
std::int32_t nonce, bool supports_5_ghz,
const std::string& bssid,
std::int32_t ap_frequency,
const std::string& ip_address,
const std::vector<Medium>& mediums,
std::int32_t keep_alive_interval_millis,
std::int32_t keep_alive_timeout_millis) {
@@ -84,6 +86,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id,
auto* medium_metadata = connection_request->mutable_medium_metadata();
medium_metadata->set_supports_5_ghz(supports_5_ghz);
if (!bssid.empty()) medium_metadata->set_bssid(bssid);
medium_metadata->set_ap_frequency(ap_frequency);
if (!ip_address.empty()) medium_metadata->set_ip_address(ip_address);
if (!mediums.empty()) {
for (const auto& medium : mediums) {
connection_request->add_mediums(MediumToConnectionRequestMedium(medium));
@@ -46,6 +46,8 @@ ByteArray ForConnectionRequest(const std::string& endpoint_id,
const ByteArray& endpoint_info,
std::int32_t nonce, bool supports_5_ghz,
const std::string& bssid,
std::int32_t ap_frequency,
const std::string& ip_address,
const std::vector<Medium>& mediums,
std::int32_t keep_alive_interval_millis,
std::int32_t keep_alive_timeout_millis);
@@ -40,6 +40,8 @@ constexpr absl::string_view kEndpointName{"XYZ"};
constexpr int kNonce = 1234;
constexpr bool kSupports5ghz = true;
constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"};
constexpr int kApFrequency = 2412;
constexpr absl::string_view kIp4Bytes = {"8xqT"};
constexpr std::array<Medium, 9> kMediums = {
Medium::MDNS, Medium::BLUETOOTH, Medium::WIFI_HOTSPOT,
Medium::BLE, Medium::WIFI_LAN, Medium::WIFI_AWARE,
@@ -95,7 +97,7 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) {
endpoint_name: "XYZ"
endpoint_info: "XYZ"
nonce: 1234
medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" >
medium_metadata: < supports_5_ghz: true bssid: "FF:FF:FF:FF:FF:FF" ip_address: "8xqT" ap_frequency: 2412 >
mediums: MDNS
mediums: BLUETOOTH
mediums: WIFI_HOTSPOT
@@ -111,9 +113,10 @@ TEST(OfflineFramesTest, CanGenerateConnectionRequest) {
>)pb";
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis);
kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
auto response = FromBytes(bytes);
ASSERT_TRUE(response.ok());
OfflineFrame message = FromBytes(bytes).result();
@@ -35,6 +35,8 @@ constexpr absl::string_view kEndpointName{"XYZ"};
constexpr int kNonce = 1234;
constexpr bool kSupports5ghz = true;
constexpr absl::string_view kBssid{"FF:FF:FF:FF:FF:FF"};
constexpr int kApFrequency = 2412;
constexpr absl::string_view kIp4Bytes = {"8xqT"};
constexpr int kStatusAccepted = 0;
constexpr absl::string_view kSsid = "ssid";
constexpr absl::string_view kPassword = "password";
@@ -57,9 +59,10 @@ TEST(OfflineFramesValidatorTest, ValidatesAsOkWithValidConnectionRequestFrame) {
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis);
kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
@@ -73,9 +76,10 @@ TEST(OfflineFramesValidatorTest,
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis);
kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
auto* v1_frame = offline_frame.mutable_v1();
@@ -93,9 +97,10 @@ TEST(OfflineFramesValidatorTest,
std::string empty_enpoint_id;
ByteArray bytes = ForConnectionRequest(
empty_enpoint_id, ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid),
std::vector(kMediums.begin(), kMediums.end()), kKeepAliveIntervalMillis,
kKeepAliveTimeoutMillis);
kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
@@ -110,7 +115,9 @@ TEST(OfflineFramesValidatorTest,
ByteArray empty_endpoint_info;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), empty_endpoint_info, kNonce, kSupports5ghz,
std::string(kBssid), std::vector(kMediums.begin(), kMediums.end()),
std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
@@ -126,7 +133,9 @@ TEST(OfflineFramesValidatorTest,
std::string empty_bssid;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, empty_bssid, std::vector(kMediums.begin(), kMediums.end()),
kSupports5ghz, empty_bssid, kApFrequency, std::string(kIp4Bytes),
std::vector<Medium, std::allocator<Medium>>(kMediums.begin(),
kMediums.end()),
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
@@ -142,8 +151,8 @@ TEST(OfflineFramesValidatorTest,
std::vector<Medium> empty_mediums;
ByteArray bytes = ForConnectionRequest(
std::string(kEndpointId), ByteArray{std::string(kEndpointName)}, kNonce,
kSupports5ghz, std::string(kBssid), empty_mediums,
kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
kSupports5ghz, std::string(kBssid), kApFrequency, std::string(kIp4Bytes),
empty_mediums, kKeepAliveIntervalMillis, kKeepAliveTimeoutMillis);
offline_frame.ParseFromString(std::string(bytes));
auto ret_value = EnsureValidOfflineFrame(offline_frame);
+6
View File
@@ -334,14 +334,17 @@ cc_library(
"file.cc",
"wifi_hotspot.cc",
"wifi_lan.cc",
"wifi_utils.cc",
],
hdrs = [
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
"wifi.h",
"wifi_hotspot.h",
"wifi_lan.h",
"wifi_utils.h",
],
copts = ["-DCORE_ADAPTER_DLL"],
defines = ["NO_WEBRTC"],
@@ -350,6 +353,7 @@ cc_library(
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
"//internal/analytics:__subpackages__",
"//internal/platform:__pkg__",
"//internal/platform/implementation:__subpackages__",
],
deps = [
":logging",
@@ -390,6 +394,8 @@ cc_test(
"uuid_test.cc",
"wifi_hotspot_test.cc",
"wifi_lan_test.cc",
"wifi_test.cc",
"wifi_utils_test.cc",
],
copts = ["-DCORE_ADAPTER_DLL"],
defines = ["NO_WEBRTC"],
+39
View File
@@ -46,6 +46,39 @@ enum class WifiConnectionStatus {
kAuthFailure = 3,
};
// WIFI Band type.
enum class WifiBandType {
kUnknown = 0,
kBand24Ghz = 1,
kBand5Ghz = 2,
kBand6Ghz = 3,
kBand60Ghz = 4,
};
// Native WIFI's capablity parameters
struct WifiCapability {
bool supports_5_ghz = false;
bool supports_6_ghz = false;
};
// Native WIFI's information parameters
struct WifiInformation {
// Is this WIFI interface connected to AP or not
bool is_connected;
// AP's SSID if connected
std::string ssid;
// WiFi LAN BSSID, in the form of a six-byte MAC address: XX:XX:XX:XX:XX:XX
std::string bssid;
// The frequency of the WiFi LAN AP(in MHz, or -1 is not associated with an AP
// over WiFi).
std::int32_t ap_frequency;
// The interface's IP address in the form of "xx.xx.xx.xx"
std::string ip_address_dot_decimal;
// IP address, in network byte order: the highest order byte of the address is
// in byte[0].
std::string ip_address_4_bytes;
};
// Represents a WiFi network found during a call to WifiMedium#scan().
class WifiScanResult {
public:
@@ -66,6 +99,12 @@ class WifiMedium {
public:
virtual ~WifiMedium() {}
virtual bool IsInterfaceValid() const = 0;
virtual WifiCapability& GetCapability() = 0;
virtual WifiInformation& GetInformation() = 0;
class ScanResultCallback {
public:
virtual ~ScanResultCallback() = default;
@@ -73,6 +73,7 @@ cc_library(
visibility = ["//visibility:private"],
deps = [
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:types",
"//internal/platform/implementation:comm",
"//internal/platform/implementation:types",
@@ -124,6 +125,7 @@ cc_library(
"wifi_lan_medium.cc",
"wifi_lan_server_socket.cc",
"wifi_lan_socket.cc",
"wifi_medium.cc",
],
copts = ["-Ithird_party/nearby/internal/platform/implementation/windows/generated"],
defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"],
@@ -32,6 +32,7 @@ cc_library(
"comsuppwd.lib",
"setupapi.lib",
"dnsapi.lib",
"wlanapi.lib",
],
textual_hdrs = glob(["**/*.h"]),
visibility = [
@@ -227,7 +227,7 @@ ImplementationPlatform::CreateServerSyncMedium() {
// TODO(b/184975123): replace with real implementation.
std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() {
return std::unique_ptr<WifiMedium>();
return std::make_unique<windows::WifiMedium>();
}
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
@@ -15,12 +15,29 @@
#ifndef PLATFORM_IMPL_WINDOWS_WIFI_H_
#define PLATFORM_IMPL_WINDOWS_WIFI_H_
#include <windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
// Nearby connections headers
#include "internal/platform/implementation/wifi.h"
#include "internal/platform/wifi_utils.h"
// WinRT headers
#include "internal/platform/implementation/windows/generated/winrt/Windows.Foundation.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 {
using ::winrt::Windows::Networking::HostName;
using ::winrt::Windows::Networking::HostNameType;
using ::winrt::Windows::Networking::Connectivity::ConnectionProfile;
using ::winrt::Windows::Networking::Connectivity::NetworkInformation;
// Represents a WiFi network found during a call to WifiMedium#scan().
class WifiScanResult : public api::WifiScanResult {
public:
@@ -46,9 +63,15 @@ class WifiScanResult : public api::WifiScanResult {
// Container of operations that can be performed over the WiFi medium.
class WifiMedium : public api::WifiMedium {
public:
// TODO(b/184975123): replace with real implementation.
WifiMedium();
~WifiMedium() override = default;
bool IsInterfaceValid() const override;
api::WifiCapability& GetCapability() override { return wifi_capability_; }
api::WifiInformation& GetInformation() override;
class ScanResultCallback : public api::WifiMedium::ScanResultCallback {
public:
// TODO(b/184975123): replace with real implementation.
@@ -88,7 +111,16 @@ class WifiMedium : public api::WifiMedium {
// Returns the local device's IP address in the IPv4 dotted-quad format.
// TODO(b/184975123): replace with real implementation.
std::string GetIpAddress() override { return "Un-implemented"; }
std::string GetIpAddress() override;
private:
// Since the WIFI interface capability won't change in the connection session,
// we only need to querry it once at the beginning
void InitCapability();
bool wifi_interface_valid_;
api::WifiCapability wifi_capability_;
api::WifiInformation wifi_information_;
};
} // namespace windows
@@ -0,0 +1,228 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/strings/str_format.h"
#include "internal/platform/implementation/windows/wifi.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/logging.h"
namespace location {
namespace nearby {
namespace windows {
namespace {
constexpr int kMacAddrLen = 6;
constexpr int kDefaultApFreq = -1;
} // namespace
WifiMedium::WifiMedium() {
InitCapability();
}
PWLAN_INTERFACE_INFO_LIST EnumInterface(PHANDLE client_handle) {
DWORD client_version = 2;
DWORD negotiated_version = 0;
DWORD result = 0;
/* variables used for WlanEnumInterfaces */
PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL;
result =
WlanOpenHandle(client_version, NULL, &negotiated_version, client_handle);
if (result != ERROR_SUCCESS) {
NEARBY_LOGS(INFO) << "WlanOpenHandle failed with error: " << result;
return p_intf_list;
}
result = WlanEnumInterfaces(*client_handle, NULL, &p_intf_list);
if (result != ERROR_SUCCESS) {
NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: " << result;
}
return p_intf_list;
}
bool WifiMedium::IsInterfaceValid() const {
return wifi_interface_valid_;
}
void WifiMedium::InitCapability() {
HANDLE client_handle = NULL;
/* variables used for WlanEnumInterfaces */
PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL;
PWLAN_INTERFACE_INFO p_intf_info = NULL;
PWLAN_INTERFACE_CAPABILITY p_intf_capability = NULL;
wifi_capability_.supports_5_ghz = false;
wifi_capability_.supports_6_ghz = false;
wifi_interface_valid_ = false;
p_intf_list = EnumInterface(&client_handle);
if (!client_handle) {
NEARBY_LOGS(INFO) << "Client Handle is NULL";
return;
}
if (!p_intf_list) {
NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: ";
return;
}
wifi_interface_valid_ = true;
for (int i = 0; i < (int)p_intf_list->dwNumberOfItems; i++) {
p_intf_info = (WLAN_INTERFACE_INFO*)&p_intf_list->InterfaceInfo[i];
if (WlanGetInterfaceCapability(client_handle, &p_intf_info->InterfaceGuid,
NULL, &p_intf_capability) != ERROR_SUCCESS) {
NEARBY_LOGS(INFO) << "Get Capability failed";
WlanFreeMemory(p_intf_list);
p_intf_list = NULL;
return;
}
for (int j = 0; j < p_intf_capability->dwNumberOfSupportedPhys; j++) {
if (p_intf_capability->dot11PhyTypes[j] == dot11_phy_type_ofdm)
wifi_capability_.supports_5_ghz = true;
}
}
WlanFreeMemory(p_intf_capability);
p_intf_capability = NULL;
WlanFreeMemory(p_intf_list);
p_intf_list = NULL;
}
api::WifiInformation& WifiMedium::GetInformation() {
HANDLE client_handle = NULL;
PWLAN_AVAILABLE_NETWORK_LIST pWLAN_AVAILABLE_NETWORK_LIST = NULL;
DWORD result = 0;
DWORD connect_info_size = sizeof(WLAN_CONNECTION_ATTRIBUTES);
WLAN_OPCODE_VALUE_TYPE op_code_value_type = wlan_opcode_value_type_invalid;
/* variables used for WlanEnumInterfaces */
PWLAN_INTERFACE_INFO_LIST p_intf_list = NULL;
PWLAN_INTERFACE_INFO p_intf_info = NULL;
PWLAN_CONNECTION_ATTRIBUTES p_connect_info = NULL;
ULONG* channel = NULL;
wifi_information_.is_connected = false;
wifi_information_.ap_frequency = kDefaultApFreq;
p_intf_list = EnumInterface(&client_handle);
if (!client_handle) {
NEARBY_LOGS(INFO) << "Client Handle is NULL";
return wifi_information_;
}
if (!p_intf_list) {
NEARBY_LOGS(INFO) << "WlanEnumInterfaces failed with error: ";
return wifi_information_;
}
for (int i = 0; i < (int)p_intf_list->dwNumberOfItems; i++) {
p_intf_info = (WLAN_INTERFACE_INFO*)&p_intf_list->InterfaceInfo[i];
if (p_intf_info->isState == wlan_interface_state_connected) {
NEARBY_LOGS(INFO) << "Found connected WIFI interface No: " << i;
wifi_information_.is_connected = true;
DWORD channel_size;
result = WlanQueryInterface(client_handle, &p_intf_info->InterfaceGuid,
wlan_intf_opcode_channel_number, NULL,
&channel_size, (PVOID*)&channel,
&op_code_value_type);
if (result != ERROR_SUCCESS) {
NEARBY_LOGS(INFO) << "WlanQueryInterface error = " << result;
} else {
wifi_information_.ap_frequency =
WifiUtils::ConvertChannelToFrequencyMhz(
*channel, api::WifiBandType::kUnknown);
NEARBY_LOGS(INFO) << "Frequency: " << *channel << "; ap_frequency: "
<< wifi_information_.ap_frequency;
WlanFreeMemory(channel);
channel = NULL;
}
result = WlanQueryInterface(client_handle, &p_intf_info->InterfaceGuid,
wlan_intf_opcode_current_connection, NULL,
&connect_info_size, (PVOID*)&p_connect_info,
&op_code_value_type);
if (result != ERROR_SUCCESS) {
NEARBY_LOGS(INFO) << "WlanQueryInterface error = " << result;
WlanFreeMemory(p_intf_list);
p_intf_list = NULL;
return wifi_information_;
}
wifi_information_.ssid.resize(
p_connect_info->wlanAssociationAttributes.dot11Ssid.uSSIDLength);
std::memcpy(
wifi_information_.ssid.data(),
reinterpret_cast<const char*>(
p_connect_info->wlanAssociationAttributes.dot11Ssid.ucSSID),
wifi_information_.ssid.size());
NEARBY_LOGS(INFO) << "wifi ssid is: " << wifi_information_.ssid
<< "; length is:" << wifi_information_.ssid.length();
char str_tmp[kMacAddrLen];
strncpy(str_tmp,
reinterpret_cast<const char*>(
p_connect_info->wlanAssociationAttributes.dot11Bssid),
kMacAddrLen);
wifi_information_.bssid = absl::StrFormat(
"%2llx:%2llx:%2llx:%2llx:%2llx:%2llx", str_tmp[0], str_tmp[1],
str_tmp[2], str_tmp[3], str_tmp[4], str_tmp[5]);
NEARBY_LOGS(INFO) << "wifi bssid is: " << wifi_information_.bssid;
}
}
WlanFreeMemory(p_connect_info);
p_connect_info = NULL;
WlanFreeMemory(p_intf_list);
p_intf_list = NULL;
wifi_information_.ip_address_dot_decimal = GetIpAddress();
wifi_information_.ip_address_4_bytes = ipaddr_dotdecimal_to_4bytes_string(
wifi_information_.ip_address_dot_decimal);
return wifi_information_;
}
std::string WifiMedium::GetIpAddress() {
auto host_names = NetworkInformation::GetHostNames();
for (auto host_name : host_names) {
if (host_name.IPInformation() != nullptr &&
host_name.IPInformation().NetworkAdapter() != nullptr &&
host_name.Type() == HostNameType::Ipv4) {
std::string ipv4_s = winrt::to_string(host_name.ToString());
NEARBY_LOGS(INFO) << "Found IP: " << ipv4_s;
auto profile = host_name.IPInformation()
.NetworkAdapter()
.GetConnectedProfileAsync()
.get();
if (profile.IsWlanConnectionProfile()) {
if ( wifi_information_.ssid == winrt::to_string(
profile.WlanConnectionProfileDetails().GetConnectedSsid())) {
NEARBY_LOGS(INFO)
<< "SSID of this IP matches with this WIFI interface's SSID:"
<< wifi_information_.ssid << ", return this IP";
return ipv4_s;
}
}
}
}
return {};
}
} // namespace windows
} // namespace nearby
} // namespace location
+76
View File
@@ -0,0 +1,76 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/wifi.h"
#ifndef PLATFORM_PUBLIC_WIFI_H_
#define PLATFORM_PUBLIC_WIFI_H_
namespace location {
namespace nearby {
class WifiMedium {
public:
using Platform = api::ImplementationPlatform;
WifiMedium() : impl_(Platform::CreateWifiMedium()) {}
~WifiMedium() = default;
api::WifiCapability& GetCapability() {
CHECK(impl_);
return impl_->GetCapability();
}
api::WifiInformation& GetInformation() {
CHECK(impl_);
return impl_->GetInformation();
}
bool IsInterfaceValid() const {
CHECK(impl_);
return impl_->IsInterfaceValid();
}
bool VerifyInternetConnectivity() {
CHECK(impl_);
return impl_->VerifyInternetConnectivity();
}
std::string GetIpAddress() const {
CHECK(impl_);
return impl_->GetIpAddress();
}
bool IsValid() const { return impl_ != nullptr; }
api::WifiMedium& GetImpl() {
CHECK(impl_);
return *impl_;
}
private:
// Mutex mutex_;
std::unique_ptr<api::WifiMedium> impl_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_PUBLIC_WIFI_H_
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/wifi.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
namespace {
TEST(WifiMediumTest, ConstructorDestructorWorks) {
WifiMedium wifi_a;
WifiMedium wifi_b;
if (wifi_a.IsValid() && wifi_b.IsValid()) {
// Make sure we can create 2 distinct mediums.
EXPECT_NE(&wifi_a.GetImpl(), &wifi_a.GetImpl());
}
// TODO(b/233324423): Add test coverage for wifi.h
}
TEST(WifiMediumTest, CanGetCapability) {
// TODO(b/233324423): Add test coverage for wifi.h
}
TEST(WifiMediumTest, CanInformation) {
// TODO(b/233324423): Add test coverage for wifi.h
}
} // namespace
} // namespace nearby
} // namespace location
+96
View File
@@ -0,0 +1,96 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/wifi_utils.h"
namespace location {
namespace nearby {
// Utility function to convert channel number to frequency in MHz
// @param channel to convert
// @return center frequency in Mhz of the channel, return "kUnspecified" if no
// match
// Add band support later
int WifiUtils::ConvertChannelToFrequencyMhz(int channel, WifiBandType band) {
if (band == WifiBandType::kUnknown || band == WifiBandType::kBand24Ghz ||
band == WifiBandType::kBand5Ghz) {
if (channel == 14) {
return 2484;
} else if (channel >= kBand24GhzFirstChNum &&
channel <= kBand24GhzLastChNum) {
return ((channel - kBand24GhzFirstChNum) * 5) + kBand24GhzStartFreqMhz;
} else if (channel >= kBand5GhzFirstChNum &&
channel <= kBand5GhzLastChNum) {
return ((channel - kBand5GhzFirstChNum) * 5) + kBand5GhzStartFreqMhz;
} else {
return kUnspecified;
}
}
if (band == WifiBandType::kBand6Ghz) {
if (channel >= kBand6GhzFirstChNum &&
channel <= kBand6GhzLastChNum) {
if (channel == 2) {
return kBand6GhzOpClass136Ch2FreqMhz;
}
return ((channel - kBand6GhzFirstChNum) * 5) +
kBand6GhzStartFreqMhz;
} else {
return kUnspecified;
}
}
if (band == WifiBandType::kBand60Ghz) {
if (channel >= kBand60GhzFirstChNum &&
channel <= kBand60GhzLastChNum) {
return ((channel - kBand60GhzFirstChNum) * 2160) +
kBand60GhzStartFreqMhz;
} else {
return kUnspecified;
}
}
return kUnspecified;
}
// Utility function to convert frequency in MHz to channel number
// @param freqMhz frequency in MHz
// @return channel number associated with given frequency, return "kUnspecified"
// if no match
int WifiUtils::ConvertFrequencyMhzToChannel(int freq_mhz) {
// Special case
if (freq_mhz == kBand24GhzEndFreqMhz) {
return 14;
} else if (freq_mhz >= kBand24GhzStartFreqMhz &&
freq_mhz <= kBand24GhzEndFreqMhz) {
return (freq_mhz - kBand24GhzStartFreqMhz) / 5 + kBand24GhzFirstChNum;
} else if (freq_mhz >= kBand5GhzStartFreqMhz &&
freq_mhz <= kBand5GhzEndFreqMhz) {
return (freq_mhz - kBand5GhzStartFreqMhz) / 5 + kBand5GhzFirstChNum;
} else if (freq_mhz >= kBand6GhzStartFreqMhz &&
freq_mhz <= kBand6GhzEndFreqMhz) {
if (freq_mhz == kBand6GhzOpClass136Ch2FreqMhz) {
return 2;
}
return (freq_mhz - kBand6GhzStartFreqMhz) / 5 + kBand6GhzFirstChNum;
} else if (freq_mhz >= kBand60GhzStartFreqMhz &&
freq_mhz <= kBand60GhzEndFreqMhz) {
return (freq_mhz - kBand60GhzStartFreqMhz) / 2160 + kBand60GhzFirstChNum;
}
return kUnspecified;
}
} // namespace nearby
} // namespace location
+55
View File
@@ -0,0 +1,55 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_BASE_WIFI_UTILS_H_
#define PLATFORM_BASE_WIFI_UTILS_H_
#include "internal/platform/implementation/wifi.h"
namespace location {
namespace nearby {
using location::nearby::api::WifiBandType;
class WifiUtils {
public:
static constexpr int kUnspecified = -1;
static constexpr int kBand24GhzFirstChNum = 1;
static constexpr int kBand24GhzLastChNum = 14;
static constexpr int kBand24GhzStartFreqMhz = 2412;
static constexpr int kBand24GhzEndFreqMhz = 2484;
static constexpr int kBand5GhzFirstChNum = 32;
static constexpr int kBand5GhzLastChNum = 177;
static constexpr int kBand5GhzStartFreqMhz = 5160;
static constexpr int kBand5GhzEndFreqMhz = 5885;
static constexpr int kBand6GhzFirstChNum = 1;
static constexpr int kBand6GhzLastChNum = 233;
static constexpr int kBand6GhzStartFreqMhz = 5955;
static constexpr int kBand6GhzEndFreqMhz = 7115;
static constexpr int kBand6GhzPscStartMhz = 5975;
static constexpr int kBand6GhzPscStepSizeMhz = 80;
static constexpr int kBand6GhzOpClass136Ch2FreqMhz = 5935;
static constexpr int kBand60GhzFirstChNum = 1;
static constexpr int kBand60GhzLastChNum = 6;
static constexpr int kBand60GhzStartFreqMhz = 58320;
static constexpr int kBand60GhzEndFreqMhz = 70200;
static int ConvertChannelToFrequencyMhz(int channel, WifiBandType band_type);
static int ConvertFrequencyMhzToChannel(int freq_mhz);
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_WIFI_UTILS_H_
+91
View File
@@ -0,0 +1,91 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/wifi_utils.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
namespace {
constexpr int kChan6Num_2G = 9;
constexpr int kChan6NumFreq_2G = 2452;
constexpr int kChan48Num_5G = 48;
constexpr int kChan48NumFreq_5G = 5240;
constexpr int kChan69Num_6G = 69;
constexpr int kChan69NumFreq_6G = 6295;
constexpr int kChan4Num_60G = 4;
constexpr int kChan4NumFreq_60G = 64800;
constexpr int kChan20Num_2G_NotExist = 20;
constexpr int kChan180Num_5G_NotExist = 180;
constexpr int kChan0Num_6G_NotExist = 0;
constexpr int kChan30Num_60G_NotExist = 30;
constexpr int kFreqNotExist = 1002;
TEST(WifiUtilsTest, ConvertChannelToFrequency) {
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G,
WifiBandType::kUnknown),
kChan6NumFreq_2G);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan6Num_2G,
WifiBandType::kBand24Ghz),
kChan6NumFreq_2G);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan48Num_5G,
WifiBandType::kBand5Ghz),
kChan48NumFreq_5G);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan69Num_6G,
WifiBandType::kBand6Ghz),
kChan69NumFreq_6G);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan4Num_60G,
WifiBandType::kBand60Ghz),
kChan4NumFreq_60G);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan20Num_2G_NotExist,
WifiBandType::kBand24Ghz),
WifiUtils::kUnspecified);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan180Num_5G_NotExist,
WifiBandType::kBand5Ghz),
WifiUtils::kUnspecified);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan0Num_6G_NotExist,
WifiBandType::kBand6Ghz),
WifiUtils::kUnspecified);
EXPECT_EQ(WifiUtils::ConvertChannelToFrequencyMhz(kChan30Num_60G_NotExist,
WifiBandType::kBand60Ghz),
WifiUtils::kUnspecified);}
TEST(WifiUtilsTest, ConvertFrequencyToChannel) {
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan6NumFreq_2G),
kChan6Num_2G);
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan48NumFreq_5G),
kChan48Num_5G);
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan69NumFreq_6G),
kChan69Num_6G);
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kChan4NumFreq_60G),
kChan4Num_60G);
EXPECT_EQ(WifiUtils::ConvertFrequencyMhzToChannel(kFreqNotExist),
WifiUtils::kUnspecified);
}
} // namespace
} // namespace nearby
} // namespace location