WIFI Hotspot implementation (1)

Part 1: Internal common code

PiperOrigin-RevId: 440437253
This commit is contained in:
hai007
2022-04-08 13:18:47 -07:00
committed by Copybara-Service
parent 59ea8e8005
commit 43a165e418
11 changed files with 539 additions and 0 deletions
+5
View File
@@ -42,6 +42,7 @@ cc_library(
"runnable.h",
"socket.h",
"types.h",
"wifi_hotspot_credential.h",
],
copts = ["-DCORE_ADAPTER_DLL"],
defines = ["NO_WEBRTC"],
@@ -56,6 +57,7 @@ cc_library(
"//third_party/nearby/presence:__subpackages__",
],
deps = [
"//proto:connections_enums_cc_proto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/meta:type_traits",
"@com_google_absl//absl/strings",
@@ -310,6 +312,7 @@ cc_library(
"ble_v2.cc",
"bluetooth_classic.cc",
"file.cc",
"wifi_hotspot.cc",
"wifi_lan.cc",
],
hdrs = [
@@ -317,6 +320,7 @@ cc_library(
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
"wifi_hotspot.h",
"wifi_lan.h",
],
copts = ["-DCORE_ADAPTER_DLL"],
@@ -361,6 +365,7 @@ cc_test(
"pipe_test.cc",
"scheduled_executor_test.cc",
"single_thread_executor_test.cc",
"wifi_hotspot_test.cc",
"wifi_lan_test.cc",
],
copts = ["-DCORE_ADAPTER_DLL"],
+1
View File
@@ -57,6 +57,7 @@ cc_library(
"bluetooth_classic.h",
"server_sync.h",
"wifi.h",
"wifi_hotspot.h",
"wifi_lan.h",
],
defines = ["NO_WEBRTC"],
@@ -210,6 +210,11 @@ std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
return std::make_unique<g3::WifiLanMedium>();
}
std::unique_ptr<WifiHotspotMedium>
ImplementationPlatform::CreateWifiHotspotMedium() {
return nullptr;
}
#ifndef NO_WEBRTC
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
if (MediumEnvironment::Instance().GetEnvironmentConfig().webrtc_enabled) {
@@ -163,6 +163,10 @@ std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
return std::make_unique<ios::WifiLanMedium>();
}
std::unique_ptr<WifiHotspotMedium> ImplementationPlatform::CreateWifiHotspotMedium() {
return nullptr;
}
#ifndef NO_WEBRTC
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() { return nullptr; }
#endif
@@ -42,6 +42,7 @@
#include "internal/platform/implementation/webrtc.h"
#endif
#include "internal/platform/implementation/wifi.h"
#include "internal/platform/implementation/wifi_hotspot.h"
#include "internal/platform/implementation/wifi_lan.h"
#include "internal/platform/os_name.h"
#include "internal/platform/payload_id.h"
@@ -114,6 +115,7 @@ class ImplementationPlatform {
static std::unique_ptr<ServerSyncMedium> CreateServerSyncMedium();
static std::unique_ptr<WifiMedium> CreateWifiMedium();
static std::unique_ptr<WifiLanMedium> CreateWifiLanMedium();
static std::unique_ptr<WifiHotspotMedium> CreateWifiHotspotMedium();
#ifndef NO_WEBRTC
static std::unique_ptr<WebRtcMedium> CreateWebRtcMedium();
#endif
@@ -0,0 +1,114 @@
// Copyright 2020 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_API_WIFI_HOTSPOT_H_
#define PLATFORM_API_WIFI_HOTSPOT_H_
#include <string>
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/listeners.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_hotspot_credential.h"
namespace location {
namespace nearby {
namespace api {
class WifiHotspotSocket {
public:
virtual ~WifiHotspotSocket() = default;
// Returns the InputStream of the WifiHotspotSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiHotspotSocket object is destroyed.
virtual InputStream& GetInputStream() = 0;
// Returns the OutputStream of the WifiHotspotSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiHotspotSocket object is destroyed.
virtual OutputStream& GetOutputStream() = 0;
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
};
class WifiHotspotServerSocket {
public:
virtual ~WifiHotspotServerSocket() = default;
virtual std::string GetIPAddress() const = 0;
virtual int GetPort() const = 0;
// Blocks until either:
// - at least one incoming connection request is available, or
// - ServerSocket is closed.
// On success, returns connected socket, ready to exchange data.
// Returns nullptr on error.
// Once error is reported, it is permanent, and ServerSocket has to be closed.
virtual std::unique_ptr<WifiHotspotSocket> Accept() = 0;
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
};
// Container of operations that can be performed over the WifiHotspot medium.
class WifiHotspotMedium {
public:
virtual ~WifiHotspotMedium() = default;
// Connects to a WifiHotspot service by ip address and port.
// On success, returns a new WifiHotspotSocket.
// On error, returns nullptr.
virtual std::unique_ptr<WifiHotspotSocket> ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag) = 0;
// Listens for incoming connection.
//
// port - A port number.
// 0 : use a random port.
// 1~65536 : open a server socket on that exact port.
// On success, returns a new WifiHotspotServerSocket.
// On error, returns nullptr.
virtual std::unique_ptr<WifiHotspotServerSocket> ListenForService(
int port) = 0;
// Start a softAP as Hotspot with platform dependent APIs and set the
// SSID/password pair back to the credentials. BWU module will retieve these
// credentials and send to the client device through established channel and
// then client may connect to this Hotspot with these credentials.
virtual bool StartWifiHotspot(HotspotCredentials* hotspot_credentials) = 0;
virtual bool StopWifiHotspot() = 0;
// Client device connect to a softAP with specified credential.
virtual bool ConnectWifiHotspot(HotspotCredentials* hotspot_credentials) = 0;
virtual bool DisconnectWifiHotspot() = 0;
// Returns the port range as a pair of min and max port.
virtual absl::optional<std::pair<std::int32_t, std::int32_t>>
GetDynamicPortRange() = 0;
};
} // namespace api
} // namespace nearby
} // namespace location
#endif // PLATFORM_API_WIFI_HOTSPOT_H_
@@ -232,6 +232,11 @@ std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
return absl::make_unique<windows::WifiLanMedium>();
}
std::unique_ptr<WifiHotspotMedium>
ImplementationPlatform::CreateWifiHotspotMedium() {
return nullptr;
}
// TODO(b/184975123): replace with real implementation.
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
return absl::make_unique<windows::WebRtcMedium>();
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2020 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_hotspot.h"
#include "internal/platform/mutex_lock.h"
namespace location {
namespace nearby {
WifiHotspotSocket WifiHotspotMedium::ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag) {
NEARBY_LOGS(INFO) << "WifiHotspotMedium::ConnectToService: ip address="
<< ip_address << ", port=" << port;
return WifiHotspotSocket(
impl_->ConnectToService(ip_address, port, cancellation_flag));
}
} // namespace nearby
} // namespace location
+210
View File
@@ -0,0 +1,210 @@
// Copyright 2020 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_PUBLIC_WIFI_HOTSPOT_H_
#define PLATFORM_PUBLIC_WIFI_HOTSPOT_H_
#include <memory>
#include <string>
#include <utility>
#include "absl/container/flat_hash_map.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/wifi_hotspot.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/wifi_hotspot_credential.h"
namespace location {
namespace nearby {
// Socket class for both SoftAP ( created through accept connection from STA)
// and STA side (created through connect request to SoftAP side)
// Class WifiHotspotSocket is copyable & movable
class WifiHotspotSocket final {
public:
WifiHotspotSocket() = default;
WifiHotspotSocket(const WifiHotspotSocket&) = default;
WifiHotspotSocket& operator=(const WifiHotspotSocket&) = default;
WifiHotspotSocket(WifiHotspotSocket&&) = default;
WifiHotspotSocket& operator=(WifiHotspotSocket&&) = default;
explicit WifiHotspotSocket(std::unique_ptr<api::WifiHotspotSocket> socket)
: impl_(std::move(socket)) {}
// Returns the InputStream of the WifiHotspotSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiHotspotSocket object is destroyed.
InputStream& GetInputStream() {
CHECK(impl_);
return impl_->GetInputStream();
}
// Returns the OutputStream of the WifiHotspotSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the WifiHotspotSocket object is destroyed.
OutputStream& GetOutputStream() {
CHECK(impl_);
return impl_->GetOutputStream();
}
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() {
CHECK(impl_);
return impl_->Close();
}
// Returns true if a socket is usable. If this method returns false,
// it is not safe to call any other method.
// NOTE(socket validity):
// Socket created by a default public constructor is not valid, because
// it is missing platform implementation.
// The only way to obtain a valid socket is through connection, such as
// an object returned by WifiHotspotMedium::Connect
// These methods may also return an invalid socket if connection failed for
// any reason.
bool IsValid() const { return impl_ != nullptr; }
// Returns reference to platform implementation.
// This is used to communicate with platform code, and for debugging purposes.
// Returned reference will remain valid for while WifiHotspotSocket object is
// itself valid. Typically WifiHotspotSocket lifetime matches duration of the
// connection, and is controlled by end user, since they hold the instance.
api::WifiHotspotSocket& GetImpl() { return *impl_; }
private:
std::shared_ptr<api::WifiHotspotSocket> impl_;
};
// Server socket class for SoftAP when it listen to connection request
class WifiHotspotServerSocket final {
public:
WifiHotspotServerSocket() = default;
WifiHotspotServerSocket(const WifiHotspotServerSocket&) = default;
WifiHotspotServerSocket& operator=(const WifiHotspotServerSocket&) = default;
explicit WifiHotspotServerSocket(
std::unique_ptr<api::WifiHotspotServerSocket> socket)
: impl_(std::move(socket)) {}
// Returns ip address.
std::string GetIPAddress() const {
CHECK(impl_);
return impl_->GetIPAddress();
}
// Returns port.
int GetPort() const {
CHECK(impl_);
return impl_->GetPort();
}
// Blocks until either:
// - at least one incoming connection request is available, or
// - ServerSocket is closed.
// On success, returns connected socket, ready to exchange data.
// On error, "impl_" will be nullptr and the caller will check it by calling
// member function "IsValid()"
// Once error is reported, it is permanent, and
// ServerSocket has to be closed by caller.
WifiHotspotSocket Accept() {
std::unique_ptr<api::WifiHotspotSocket> socket = impl_->Accept();
if (!socket) {
NEARBY_LOGS(INFO)
<< "WifiHotspotServerSocket Accept() failed on server socket: ";
}
return WifiHotspotSocket(std::move(socket));
}
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() {
NEARBY_LOGS(INFO) << "WifiHotspotServerSocket Closing:: " << this;
return impl_->Close();
}
bool IsValid() const { return impl_ != nullptr; }
api::WifiHotspotServerSocket& GetImpl() {
CHECK(impl_);
return *impl_;
}
private:
std::shared_ptr<api::WifiHotspotServerSocket> impl_;
};
// Container of operations that can be performed over the WifiHotspot medium.
class WifiHotspotMedium {
public:
using Platform = api::ImplementationPlatform;
WifiHotspotMedium() : impl_(Platform::CreateWifiHotspotMedium()) {}
// Returns a new WifiHotspotSocket by ip address and port.
// On Success, WifiHotspotSocket::IsValid()returns true.
WifiHotspotSocket ConnectToService(absl::string_view ip_address, int port,
CancellationFlag* cancellation_flag);
// Returns a new WifiHotspotServerSocket.
// On Success, WifiHotspotServerSocket::IsValid() returns true.
WifiHotspotServerSocket ListenForService(int port = 0) {
return WifiHotspotServerSocket(impl_->ListenForService(port));
}
// Returns the port range as a pair of min and max port.
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange() {
return impl_->GetDynamicPortRange();
}
bool StartWifiHotspot() {
return impl_->StartWifiHotspot(&hotspot_credentials_);
}
bool StopWifiHotspot() { return impl_->StopWifiHotspot(); }
bool ConnectWifiHotspot(const std::string& ssid,
const std::string& password) {
hotspot_credentials_.SetSSID(ssid);
hotspot_credentials_.SetPassword(password);
return impl_->ConnectWifiHotspot(&hotspot_credentials_);
}
bool DisconnectWifiHotspot() { return impl_->DisconnectWifiHotspot(); }
HotspotCredentials* GetCredential() { return &hotspot_credentials_; }
bool IsValid() const { return impl_ != nullptr; }
// since impl_ could be nullptr if platform hasn't implemented this Medium,
// call IsValid() to check the availability before call this method
api::WifiHotspotMedium& GetImpl() {
CHECK(impl_);
return *impl_;
}
private:
Mutex mutex_;
std::unique_ptr<api::WifiHotspotMedium> impl_;
HotspotCredentials hotspot_credentials_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_PUBLIC_WIFI_HOTSPOT_H_
@@ -0,0 +1,86 @@
// Copyright 2020 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_HOTSPOT_CREDENTIAL_H_
#define PLATFORM_BASE_WIFI_HOTSPOT_CREDENTIAL_H_
#include <string>
#include "absl/strings/str_format.h"
#include "internal/platform/prng.h"
#include "proto/connections_enums.pb.h"
namespace location {
namespace nearby {
// Credentials for the currently-hosted Wifi hotspot (if any)
// Class HotspotCredentials is copyable & movable
class HotspotCredentials {
public:
HotspotCredentials() = default;
HotspotCredentials(const HotspotCredentials&) = default;
HotspotCredentials& operator=(const HotspotCredentials&) = default;
HotspotCredentials(HotspotCredentials&&) = default;
HotspotCredentials& operator=(HotspotCredentials&&) = default;
~HotspotCredentials() = default;
// Returns the SSID (Service Set Identifier) which the hotspot will
// periodically beacon. STA can start a wifi scan for this SSID to find the
// hotspot
std::string GetSSID() const { return ssid_; }
void SetSSID(const std::string& ssid) { ssid_ = ssid; }
std::string GetPassword() const { return password_; }
void SetPassword(const std::string& password) { password_ = password; }
// Gets IP Address, which is in byte sequence, in network order. For example,
// for "192.168.1.1", it'll be byte(129)+byte(168)+byte(1)+byte(1). Now only
// ipv4 is supported.
std::string GetIPAddress() const { return ip_address_; }
void SetIPAddress(const std::string& ip_address) { ip_address_ = ip_address; }
std::string GetGateway() const { return gateway_; }
void SetGateway(const std::string& gateway) { gateway_ = gateway; }
// Gets the Port number
int GetPort() const { return port_; }
// Set port_
void SetPort(const int port) { port_ = port; }
// Gets the Frequency
int GetFrequency() const { return frequency_; }
// Gets the Band
proto::connections::ConnectionBand GetBand() const { return band_; }
// Gets the Technology
proto::connections::ConnectionTechnology GetTechnology() const {
return technology_;
}
private:
std::string ssid_;
std::string password_;
std::string ip_address_;
std::string gateway_ = "0.0.0.0";
int port_ = 0;
int frequency_ = -1;
proto::connections::ConnectionBand band_;
proto::connections::ConnectionTechnology technology_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_WIFI_HOTSPOT_CREDENTIAL_H_
+75
View File
@@ -0,0 +1,75 @@
// Copyright 2020 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_hotspot.h"
#include <string>
#include "gtest/gtest.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/wifi_hotspot_credential.h"
namespace location {
namespace nearby {
namespace {
constexpr absl::string_view kSsid{"Direct-357a2d8c"};
constexpr absl::string_view kPassword{"b592f7d3"};
TEST(HotspotCredentialsTest, SetGetSsid) {
std::string ssid(kSsid);
HotspotCredentials hotspot_credentials;
hotspot_credentials.SetSSID(ssid);
EXPECT_EQ(kSsid, hotspot_credentials.GetSSID());
}
TEST(HotspotCredentialsTest, SetGetPassword) {
std::string password(kPassword);
HotspotCredentials hotspot_credentials;
hotspot_credentials.SetPassword(password);
EXPECT_EQ(kPassword, hotspot_credentials.GetPassword());
}
TEST(WifiHotspotMediumTest, ConstructorDestructorWorks) {
WifiHotspotMedium wifi_hotspot_a;
WifiHotspotMedium wifi_hotspot_b;
if (wifi_hotspot_a.IsValid() && wifi_hotspot_b.IsValid()) {
// Make sure we can create 2 distinct mediums.
EXPECT_NE(&wifi_hotspot_a.GetImpl(), &wifi_hotspot_b.GetImpl());
}
// TODO(b/227482970): Add test coverage for wifi_hotspot.cc
}
TEST(WifiHotspotMediumTest, CanConnectToService) {
CancellationFlag flag;
WifiHotspotMedium wifi_hotspot_a;
WifiHotspotMedium wifi_hotspot_b;
WifiHotspotSocket socket_a;
WifiHotspotServerSocket socket_b;
EXPECT_FALSE(socket_a.IsValid());
// TODO(b/227482970): Add test coverage for wifi_hotspot.cc
}
TEST(WifiHotspotMediumTest, CanSartHotspot) {
WifiHotspotMedium wifi_hotspot;
// TODO(b/227482970): Add test coverage for wifi_hotspot.cc
}
} // namespace
} // namespace nearby
} // namespace location