Roll forward to cl/343785060

Signed-off-by: hai007 <hais@google.com>
This commit is contained in:
hai007
2020-11-23 22:28:06 -08:00
parent 25bf896257
commit e6d52359cf
27 changed files with 500 additions and 742 deletions
+13 -20
View File
@@ -6,6 +6,7 @@
#include "platform/base/byte_array.h"
#include "platform/base/input_stream.h"
#include "platform/base/listeners.h"
#include "platform/base/nsd_service_info.h"
#include "platform/base/output_stream.h"
#include "absl/strings/string_view.h"
@@ -13,23 +14,17 @@ namespace location {
namespace nearby {
namespace api {
// Opaque wrapper over a WifiLan service which contains packed
// |WifiLanServiceInfo| string name.
// Opaque wrapper over a WifiLan service which contains |NsdServiceInfo|.
class WifiLanService {
public:
virtual ~WifiLanService() = default;
// Returns the packed string of |WifiLanServiceInfo|. Note that the packed
// string would not include TXTRecord, which inheritor should save it in
// another store.
virtual std::string GetServiceName() const = 0;
// Returns the packed string of endpoint info with named key.
virtual std::string GetTxtRecord(const std::string& key) const = 0;
// Returns the local device's <IP address, port> as a pair.
// IP address is in byte sequence, in network order.
virtual std::pair<std::string, int> GetServiceAddress() const = 0;
// Returns the |NsdServiceInfo| which contains the packed string of
// |WifiLanServiceInfo| and the endpoint info with named key in a TXTRecord
// map.
// The details refer to
// https://developer.android.com/reference/android/net/nsd/NsdServiceInfo.html.
virtual NsdServiceInfo GetServiceInfo() const = 0;
};
class WifiLanSocket {
@@ -63,10 +58,8 @@ class WifiLanMedium {
public:
virtual ~WifiLanMedium() = default;
virtual bool StartAdvertising(
const std::string& service_id,
const std::string& wifi_lan_service_info_name,
const std::string& endpoint_info_name) = 0;
virtual bool StartAdvertising(const std::string& service_id,
const NsdServiceInfo& nsd_service_info) = 0;
virtual bool StopAdvertising(const std::string& service_id) = 0;
// Callback that is invoked when a discovered service is found or lost.
@@ -106,10 +99,10 @@ class WifiLanMedium {
// On success, returns a new WifiLanSocket.
// On error, returns nullptr.
virtual std::unique_ptr<WifiLanSocket> Connect(
WifiLanService& service, const std::string& service_id) = 0;
WifiLanService& wifi_lan_service, const std::string& service_id) = 0;
virtual WifiLanService* FindRemoteService(const std::string& ip_address,
int port) = 0;
virtual WifiLanService* GetRemoteService(const std::string& ip_address,
int port) = 0;
virtual std::pair<std::string, int> GetServiceAddress(
const std::string& service_id) = 0;
+17
View File
@@ -15,6 +15,7 @@ cc_library(
"exception.h",
"input_stream.h",
"listeners.h",
"nsd_service_info.h",
"output_stream.h",
"payload_id.h",
"prng.h",
@@ -29,6 +30,7 @@ cc_library(
"//platform/api:__subpackages__",
],
deps = [
"//absl/container:flat_hash_map",
"//absl/meta:type_traits",
"//absl/strings",
"//absl/strings:str_format",
@@ -41,11 +43,13 @@ cc_library(
srcs = [
"base_input_stream.cc",
"base_pipe.cc",
"byte_utils.cc",
],
hdrs = [
"base_input_stream.h",
"base_mutex_lock.h",
"base_pipe.h",
"byte_utils.h",
],
visibility = [
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
@@ -57,6 +61,7 @@ cc_library(
":base",
"//platform/api:types",
"//absl/base:core_headers",
"//absl/strings:str_format",
],
)
@@ -112,6 +117,18 @@ cc_test(
],
)
cc_test(
name = "platform_util_test",
srcs = [
"byte_utils_test.cc",
],
deps = [
":base",
":util",
"//testing/base/public:gunit_main",
],
)
cc_with_non_compile_test(
name = "exception_test",
srcs = [
+25
View File
@@ -0,0 +1,25 @@
#include "platform/base/byte_utils.h"
#include <cstdlib>
#include "platform/base/base_input_stream.h"
#include "absl/strings/str_format.h"
namespace location {
namespace nearby {
std::string ByteUtils::ToFourDigitString(ByteArray& bytes) {
int multiplier = 1;
int hashCode = 0;
BaseInputStream base_input_stream{bytes};
while (base_input_stream.IsAvailable(1)) {
auto byte = static_cast<int>(base_input_stream.ReadUint8());
hashCode = (hashCode + byte * multiplier) % kHashBasePrime;
multiplier = multiplier * kHashBaseMultiplier % kHashBasePrime;
}
return absl::StrFormat("%04d", abs(hashCode));
}
} // namespace nearby
} // namespace location
+24
View File
@@ -0,0 +1,24 @@
#ifndef PLATFORM_BASE_BYTE_UTILS_H_
#define PLATFORM_BASE_BYTE_UTILS_H_
#include "platform/base/byte_array.h"
namespace location {
namespace nearby {
class ByteUtils {
public:
static std::string ToFourDigitString(ByteArray& bytes);
private:
// The biggest prime number under 10000, used as a mod base to trim integers
// into 4 digits.
static constexpr int kHashBasePrime = 9973;
// The hash multiplier.
static constexpr int kHashBaseMultiplier = 31;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_BYTE_UTILS_H_
+30
View File
@@ -0,0 +1,30 @@
#include "platform/base/byte_utils.h"
#include "platform/base/byte_array.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
constexpr absl::string_view kFooBytes{"rawABCDE"};
constexpr absl::string_view kFooFourDigitsToken{"0392"};
constexpr absl::string_view kEmptyFourDigitsToken{"0000"};
TEST(ByteUtilsTest, ToFourDigitStringCorrect) {
ByteArray bytes{std::string(kFooBytes)};
auto four_digit_string = ByteUtils::ToFourDigitString(bytes);
EXPECT_EQ(std::string(kFooFourDigitsToken), four_digit_string);
}
TEST(ByteUtilsTest, TestEmptyByteArrayCorrect) {
ByteArray bytes;
auto four_digit_string = ByteUtils::ToFourDigitString(bytes);
EXPECT_EQ(std::string(kEmptyFourDigitsToken), four_digit_string);
}
} // namespace nearby
} // namespace location
+37 -30
View File
@@ -201,28 +201,32 @@ void MediumEnvironment::OnBlePeripheralStateChanged(
}
void MediumEnvironment::OnWifiLanServiceStateChanged(
WifiLanMediumContext& info, api::WifiLanService& service,
WifiLanMediumContext& info, api::WifiLanService& wifi_lan_service,
const std::string& service_id, bool enabled) {
if (!enabled_) return;
NEARBY_LOG(INFO,
"G3 OnWifiLanServiceStateChanged [service impl=%p]; context=%p; "
"service_id=%s; notify=%d",
&service, &info, service_id.c_str(), enable_notifications_.load());
NEARBY_LOG(
INFO,
"G3 OnWifiLanServiceStateChanged [wifi_lan_service impl=%p]; context=%p; "
"service_id=%s; notify=%d",
&wifi_lan_service, &info, service_id.c_str(),
enable_notifications_.load());
if (!enable_notifications_) return;
RunOnMediumEnvironmentThread([&info, enabled, &service, service_id]() {
NEARBY_LOG(INFO,
"G3 [Run] OnWifiLanServiceStateChanged [service impl=%p]; "
"context=%p; service_id=%s; enabled=%d",
&service, &info, service_id.c_str(), enabled);
RunOnMediumEnvironmentThread([&info, enabled, &wifi_lan_service,
service_id]() {
NEARBY_LOG(
INFO,
"G3 [Run] OnWifiLanServiceStateChanged [wifi_lan_service impl=%p]; "
"context=%p; service_id=%s; enabled=%d",
&wifi_lan_service, &info, service_id.c_str(), enabled);
auto service_id_context = info.services.find(service_id);
if (service_id_context == info.services.end()) return;
if (enabled) {
service_id_context->second.discovery_callback.service_discovered_cb(
service, service_id);
wifi_lan_service, service_id);
} else {
service_id_context->second.discovery_callback.service_lost_cb(service,
service_id);
service_id_context->second.discovery_callback.service_lost_cb(
wifi_lan_service, service_id);
}
});
}
@@ -477,10 +481,10 @@ void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) {
}
void MediumEnvironment::UpdateWifiLanMediumForAdvertising(
api::WifiLanMedium& medium, api::WifiLanService& service,
api::WifiLanMedium& medium, api::WifiLanService& wifi_lan_service,
const std::string& service_id, bool enabled) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, &service, service_id,
RunOnMediumEnvironmentThread([this, &medium, &wifi_lan_service, service_id,
enabled]() {
auto item = wifi_lan_mediums_.find(&medium);
if (item == wifi_lan_mediums_.end()) {
@@ -490,7 +494,7 @@ void MediumEnvironment::UpdateWifiLanMediumForAdvertising(
return;
}
auto& context = item->second;
context.wifi_lan_service = &service;
context.wifi_lan_service = &wifi_lan_service;
auto service_id_context = context.services.find(service_id);
if (service_id_context == context.services.end()) {
WifiLanServiceIdContext id_context{
@@ -500,17 +504,19 @@ void MediumEnvironment::UpdateWifiLanMediumForAdvertising(
} else {
service_id_context->second.advertising = enabled;
}
NEARBY_LOG(INFO,
"Update WifiLan medium for advertising: this=%p; medium=%p; "
"service_id=%s; name=%s; enabled=%d",
this, &medium, service_id.c_str(),
service.GetServiceName().c_str(), enabled);
NEARBY_LOG(
INFO,
"Update WifiLan medium for advertising: this=%p; medium=%p; "
"service_id=%s; wifi_lan_service=%p, service_info_name=%s; enabled=%d",
this, &medium, service_id.c_str(), &wifi_lan_service,
wifi_lan_service.GetServiceInfo().GetServiceInfoName().c_str(),
enabled);
for (auto& medium_info : wifi_lan_mediums_) {
auto& local_medium = medium_info.first;
auto& info = medium_info.second;
// Do not send notification to the same medium.
if (local_medium == &medium) continue;
OnWifiLanServiceStateChanged(info, service, service_id, enabled);
OnWifiLanServiceStateChanged(info, wifi_lan_service, service_id, enabled);
}
});
}
@@ -620,25 +626,26 @@ void MediumEnvironment::CallWifiLanAcceptedConnectionCallback(
});
}
api::WifiLanService* MediumEnvironment::FindWifiLanService(
api::WifiLanService* MediumEnvironment::GetWifiLanService(
const std::string& ip_address, int port) {
api::WifiLanService* remote_service = nullptr;
api::WifiLanService* remote_wifi_lan_service = nullptr;
CountDownLatch latch(1);
RunOnMediumEnvironmentThread(
[this, &remote_service, &ip_address, port, &latch]() {
[this, &remote_wifi_lan_service, &ip_address, port, &latch]() {
for (auto& item : wifi_lan_mediums_) {
auto* service = item.second.wifi_lan_service;
if (!service) continue;
auto addr = remote_service->GetServiceAddress();
auto* wifi_lan_service = item.second.wifi_lan_service;
if (!wifi_lan_service) continue;
auto addr =
remote_wifi_lan_service->GetServiceInfo().GetServiceAddress();
if (addr.first == ip_address && addr.second == port) {
remote_service = service;
remote_wifi_lan_service = wifi_lan_service;
break;
}
}
latch.CountDown();
});
latch.Await();
return remote_service;
return remote_wifi_lan_service;
}
} // namespace nearby
+5 -4
View File
@@ -8,6 +8,7 @@
#include "platform/api/webrtc.h"
#include "platform/base/byte_array.h"
#include "platform/base/listeners.h"
#include "platform/base/nsd_service_info.h"
#include "platform/public/single_thread_executor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
@@ -179,7 +180,7 @@ class MediumEnvironment {
// Updates advertising info to indicate the current medium is exposing
// advertising event.
void UpdateWifiLanMediumForAdvertising(api::WifiLanMedium& medium,
api::WifiLanService& service,
api::WifiLanService& wifi_lan_service,
const std::string& service_id,
bool enabled);
@@ -212,8 +213,8 @@ class MediumEnvironment {
const std::string& service_id);
// Returns WiFi LAN service matching IP address and port, or nullptr.
api::WifiLanService* FindWifiLanService(const std::string& ip_address,
int port);
api::WifiLanService* GetWifiLanService(const std::string& ip_address,
int port);
private:
struct BluetoothMediumContext {
@@ -261,7 +262,7 @@ class MediumEnvironment {
bool fast_advertisement, bool enabled);
void OnWifiLanServiceStateChanged(WifiLanMediumContext& info,
api::WifiLanService& service,
api::WifiLanService& wifi_lan_service,
const std::string& service_id,
bool enabled);
+67
View File
@@ -0,0 +1,67 @@
#ifndef PLATFORM_BASE_NSD_SERVICE_INFO_H_
#define PLATFORM_BASE_NSD_SERVICE_INFO_H_
#include <string>
#include "absl/container/flat_hash_map.h"
namespace location {
namespace nearby {
// https://developer.android.com/reference/android/net/nsd/NsdServiceInfo.html.
class NsdServiceInfo {
public:
NsdServiceInfo() = default;
NsdServiceInfo(const NsdServiceInfo&) = default;
NsdServiceInfo& operator=(const NsdServiceInfo&) = default;
NsdServiceInfo(NsdServiceInfo&&) = default;
NsdServiceInfo& operator=(NsdServiceInfo&&) = default;
~NsdServiceInfo() = default;
// Returns the packed string of |WifiLanServiceInfo|.
std::string GetServiceInfoName() const { return service_info_name_; }
// Sets the packed string of |WifiLanServiceInfo|.
void SetServiceInfoName(std::string service_info_name) {
service_info_name_ = std::move(service_info_name);
}
// Gets the TXTRecord value of the specified TXTRecord key assigned.
std::string GetTxtRecord(const std::string& txt_record_key) const {
if (txt_records_.empty()) return {};
auto record = txt_records_.find(txt_record_key);
if (record == txt_records_.end()) return {};
return record->second;
}
// Adds the TXTRecord with a pair of key and value.
void SetTxtRecord(const std::string& txt_record_key,
const std::string& txt_record_value) {
txt_records_.emplace(txt_record_key, txt_record_value);
}
// Returns the advertising device's <IP address, port> as a pair.
// IP address is in byte sequence, in network order.
std::pair<std::string, int> GetServiceAddress() const {
return std::make_pair(ip_address_, port_);
}
// Sets the ip address and port of the local device.
void SetServiceAddress(const std::string& ip_address, int port) {
ip_address_ = ip_address;
port_ = port;
}
bool IsValid() const { return !service_info_name_.empty(); }
private:
std::string service_info_name_;
absl::flat_hash_map<std::string, std::string> txt_records_;
std::string ip_address_;
int port_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_BASE_NSD_SERVICE_INFO_H_
+70 -47
View File
@@ -7,6 +7,7 @@
#include "platform/api/wifi_lan.h"
#include "platform/base/logging.h"
#include "platform/base/medium_environment.h"
#include "platform/base/nsd_service_info.h"
#include "platform/base/prng.h"
#include "absl/synchronization/mutex.h"
@@ -58,7 +59,7 @@ Exception WifiLanSocket::Close() {
WifiLanService* WifiLanSocket::GetRemoteWifiLanService() {
absl::MutexLock lock(&mutex_);
return service_;
return wifi_lan_service_;
}
void WifiLanSocket::DoClose() {
@@ -87,7 +88,7 @@ OutputStream& WifiLanSocket::GetLocalOutputStream() {
}
std::unique_ptr<api::WifiLanSocket> WifiLanServerSocket::Accept(
WifiLanService* service) {
WifiLanService* wifi_lan_service) {
absl::MutexLock lock(&mutex_);
if (closed_) return {};
while (pending_sockets_.empty()) {
@@ -98,7 +99,7 @@ std::unique_ptr<api::WifiLanSocket> WifiLanServerSocket::Accept(
auto* remote_socket =
pending_sockets_.extract(pending_sockets_.begin()).value();
CHECK(remote_socket);
auto local_socket = std::make_unique<WifiLanSocket>(service);
auto local_socket = std::make_unique<WifiLanSocket>(wifi_lan_service);
local_socket->Connect(*remote_socket);
remote_socket->Connect(*local_socket);
cond_.SignalAll();
@@ -156,22 +157,13 @@ Exception WifiLanServerSocket::DoClose() {
}
WifiLanMedium::WifiLanMedium() {
service_.SetMedium(this);
std::string ip_address;
ip_address.resize(4);
uint32_t raw_ip_addr = Prng().NextUint32();
uint16_t port = Prng().NextUint32();
ip_address[0] = static_cast<char>(raw_ip_addr >> 24);
ip_address[1] = static_cast<char>(raw_ip_addr >> 16);
ip_address[2] = static_cast<char>(raw_ip_addr >> 8);
ip_address[3] = static_cast<char>(raw_ip_addr >> 0);
service_.SetServiceAddress(ip_address, port);
wifi_lan_service_.SetMedium(this);
auto& env = MediumEnvironment::Instance();
env.RegisterWifiLanMedium(*this);
}
WifiLanMedium::~WifiLanMedium() {
service_.SetMedium(nullptr);
wifi_lan_service_.SetMedium(nullptr);
auto& env = MediumEnvironment::Instance();
env.UnregisterWifiLanMedium(*this);
@@ -191,15 +183,17 @@ WifiLanMedium::~WifiLanMedium() {
}
bool WifiLanMedium::StartAdvertising(const std::string& service_id,
const std::string& service_info_name,
const std::string& endpoint_info_name) {
const NsdServiceInfo& nsd_service_info) {
NEARBY_LOG(INFO,
"G3 WifiLan StartAdvertising: service_id=%s, service_info_name=%s",
service_id.c_str(), service_info_name.c_str());
"G3 WifiLan StartAdvertising: service_id=%s, nsd_service_info=%p, "
"service_info_name=%s",
service_id.c_str(), &nsd_service_info,
nsd_service_info.GetServiceInfoName().c_str());
auto& env = MediumEnvironment::Instance();
service_.SetServiceName(service_info_name);
service_.SetTxtRecord("n", endpoint_info_name);
env.UpdateWifiLanMediumForAdvertising(*this, service_, service_id, true);
NsdServiceInfo local_nsd_service_info{nsd_service_info};
SetWifiLanService(nsd_service_info);
env.UpdateWifiLanMediumForAdvertising(*this, wifi_lan_service_, service_id,
true);
absl::MutexLock lock(&mutex_);
if (server_socket_ != nullptr) server_socket_.release();
@@ -209,7 +203,7 @@ bool WifiLanMedium::StartAdvertising(const std::string& service_id,
accept_loops_runner_.Execute([&env, this, service_id]() mutable {
if (!accept_loops_runner_.InShutdown()) {
while (true) {
auto client_socket = server_socket_->Accept(&service_);
auto client_socket = server_socket_->Accept(&wifi_lan_service_);
if (client_socket == nullptr) break;
env.CallWifiLanAcceptedConnectionCallback(
*this, *(client_socket.release()), service_id);
@@ -236,7 +230,8 @@ bool WifiLanMedium::StopAdvertising(const std::string& service_id) {
}
auto& env = MediumEnvironment::Instance();
env.UpdateWifiLanMediumForAdvertising(*this, service_, service_id, false);
env.UpdateWifiLanMediumForAdvertising(*this, wifi_lan_service_, service_id,
false);
accept_loops_runner_.Shutdown();
if (server_socket_ == nullptr) {
NEARBY_LOGS(ERROR) << "G3 WifiLan StopAdvertising: failed to find WifiLan "
@@ -308,39 +303,46 @@ bool WifiLanMedium::StopAcceptingConnections(const std::string& service_id) {
}
std::unique_ptr<api::WifiLanSocket> WifiLanMedium::Connect(
api::WifiLanService& remote_service, const std::string& service_id) {
NEARBY_LOG(INFO,
"G3 WifiLan Connect: medium=%p, service=%p, service_info_name=%s, "
"service_id=%s",
this, &service_, remote_service.GetServiceName().c_str(),
service_id.c_str());
api::WifiLanService& remote_wifi_lan_service,
const std::string& service_id) {
NEARBY_LOG(
INFO,
"G3 WifiLan Connect: medium=%p, wifi_lan_service=%p, "
"service_info_name=%s, service_id=%s",
this, &wifi_lan_service_,
remote_wifi_lan_service.GetServiceInfo().GetServiceInfoName().c_str(),
service_id.c_str());
// First, find an instance of remote medium, that exposed this service.
auto* medium = static_cast<WifiLanService&>(remote_service).GetMedium();
auto* remote_medium =
static_cast<WifiLanService&>(remote_wifi_lan_service).GetMedium();
if (!medium) return {}; // Can't find medium. Bail out.
if (!remote_medium) return {}; // Can't find medium. Bail out.
WifiLanServerSocket* remote_server_socket = nullptr;
NEARBY_LOG(INFO,
"G3 WifiLan Connect [peer]: medium=%p, service=%p, "
"service_info_name=%s, service_id=%s",
medium, &remote_service, remote_service.GetServiceName().c_str(),
service_id.c_str());
NEARBY_LOG(
INFO,
"G3 WifiLan Connect [peer]: remote_wifi_lan_service=%p, "
"remote_service_info_name=%s, service_id=%s",
&remote_wifi_lan_service,
remote_wifi_lan_service.GetServiceInfo().GetServiceInfoName().c_str(),
service_id.c_str());
// Then, find our server socket context in this medium.
{
absl::MutexLock medium_lock(&medium->mutex_);
remote_server_socket = medium->server_socket_.get();
absl::MutexLock medium_lock(&remote_medium->mutex_);
remote_server_socket = remote_medium->server_socket_.get();
if (remote_server_socket == nullptr) {
NEARBY_LOG(ERROR,
"G3 WifiLan Connect: Failed to find WifiLan Server socket: "
"service_id=%s",
service_id.c_str());
NEARBY_LOGS(ERROR)
<< "G3 WifiLan Connect: Failed to find remote WifiLan Server socket: "
"service_id="
<< service_id;
// Fall through for server socket not found.
return {};
}
}
WifiLanService service = static_cast<WifiLanService&>(remote_service);
auto socket = std::make_unique<WifiLanSocket>(&service);
WifiLanService wifi_lan_service =
static_cast<WifiLanService&>(remote_wifi_lan_service);
auto socket = std::make_unique<WifiLanSocket>(&wifi_lan_service);
// Finally, Request to connect to this socket.
if (!remote_server_socket->Connect(*socket)) {
NEARBY_LOG(ERROR,
@@ -354,17 +356,38 @@ std::unique_ptr<api::WifiLanSocket> WifiLanMedium::Connect(
return socket;
}
api::WifiLanService* WifiLanMedium::FindRemoteService(
api::WifiLanService* WifiLanMedium::GetRemoteService(
const std::string& ip_address, int port) {
auto& env = MediumEnvironment::Instance();
return env.FindWifiLanService(ip_address, port);
return env.GetWifiLanService(ip_address, port);
}
std::pair<std::string, int> WifiLanMedium::GetServiceAddress(
const std::string& service_id) {
NEARBY_LOGS(INFO) << "G3 WifiLan GetServiceAddress: service_id="
<< service_id;
return service_.GetServiceAddress();
return wifi_lan_service_.GetServiceInfo().GetServiceAddress();
}
void WifiLanMedium::SetWifiLanService(const NsdServiceInfo& nsd_service_info) {
NsdServiceInfo local_nsd_service_info{nsd_service_info};
auto service_address = GetFakeServiceAddress();
local_nsd_service_info.SetServiceAddress(service_address.first,
service_address.second);
wifi_lan_service_.SetServiceInfo(local_nsd_service_info);
}
std::pair<std::string, int> WifiLanMedium::GetFakeServiceAddress() const {
std::string ip_address;
ip_address.resize(4);
uint32_t raw_ip_addr = Prng().NextUint32();
uint16_t port = Prng().NextUint32();
ip_address[0] = static_cast<char>(raw_ip_addr >> 24);
ip_address[1] = static_cast<char>(raw_ip_addr >> 16);
ip_address[2] = static_cast<char>(raw_ip_addr >> 8);
ip_address[3] = static_cast<char>(raw_ip_addr >> 0);
return std::make_pair(ip_address, port);
}
} // namespace g3
+20 -40
View File
@@ -8,6 +8,7 @@
#include "platform/api/wifi_lan.h"
#include "platform/base/byte_array.h"
#include "platform/base/input_stream.h"
#include "platform/base/nsd_service_info.h"
#include "platform/base/output_stream.h"
#include "platform/impl/g3/multi_thread_executor.h"
#include "platform/impl/g3/pipe.h"
@@ -21,39 +22,18 @@ namespace g3 {
class WifiLanMedium;
// Opaque wrapper over a WifiLan service which contains packed
// |WifiLanServiceInfo| string name.
// Opaque wrapper over a WifiLan service which contains |NsdServiceInfo|.
class WifiLanService : public api::WifiLanService {
public:
explicit WifiLanService(std::string service_info_name)
: service_info_name_(std::move(service_info_name)) {}
WifiLanService() = default;
explicit WifiLanService(NsdServiceInfo nsd_service_info)
: nsd_service_info_(std::move(nsd_service_info)) {}
~WifiLanService() override = default;
std::string GetServiceName() const override { return service_info_name_; }
NsdServiceInfo GetServiceInfo() const override { return nsd_service_info_; }
void SetServiceName(std::string service_info_name) {
service_info_name_ = std::move(service_info_name);
}
std::string GetTxtRecord(const std::string& txt_record_key) const override {
if (txt_records_.empty()) return {};
auto record = txt_records_.find(txt_record_key);
if (record == txt_records_.end()) return {};
return record->second;
}
void SetTxtRecord(const std::string& txt_record_key,
const std::string& txt_record_value) {
txt_records_.emplace(txt_record_key, txt_record_value);
}
std::pair<std::string, int> GetServiceAddress() const override {
return std::make_pair(ip_address_, port_);
}
void SetServiceAddress(const std::string& ip_address, int port) {
ip_address_ = ip_address;
port_ = port;
void SetServiceInfo(NsdServiceInfo nsd_service_info) {
nsd_service_info_ = std::move(nsd_service_info);
}
WifiLanMedium* GetMedium() { return medium_; }
@@ -61,17 +41,15 @@ class WifiLanService : public api::WifiLanService {
void SetMedium(WifiLanMedium* medium) { medium_ = medium; }
private:
std::string service_info_name_;
absl::flat_hash_map<std::string, std::string> txt_records_;
NsdServiceInfo nsd_service_info_;
WifiLanMedium* medium_ = nullptr;
std::string ip_address_;
int port_;
};
class WifiLanSocket : public api::WifiLanSocket {
public:
WifiLanSocket() = default;
explicit WifiLanSocket(WifiLanService* service) : service_(service) {}
explicit WifiLanSocket(WifiLanService* wifi_lan_service)
: wifi_lan_service_(wifi_lan_service) {}
~WifiLanSocket() override;
// Connect to another WifiLanSocket, to form a functional low-level channel.
@@ -124,7 +102,7 @@ class WifiLanSocket : public api::WifiLanSocket {
std::shared_ptr<Pipe> output_{new Pipe};
std::shared_ptr<Pipe> input_;
mutable absl::Mutex mutex_;
WifiLanService* service_;
WifiLanService* wifi_lan_service_;
WifiLanSocket* remote_socket_ ABSL_GUARDED_BY(mutex_) = nullptr;
bool closed_ ABSL_GUARDED_BY(mutex_) = false;
};
@@ -182,8 +160,7 @@ class WifiLanMedium : public api::WifiLanMedium {
~WifiLanMedium() override;
bool StartAdvertising(const std::string& service_id,
const std::string& service_info_name,
const std::string& endpoint_info_name) override
const NsdServiceInfo& nsd_service_info) override
ABSL_LOCKS_EXCLUDED(mutex_);
bool StopAdvertising(const std::string& service_id) override
ABSL_LOCKS_EXCLUDED(mutex_);
@@ -212,11 +189,11 @@ class WifiLanMedium : public api::WifiLanMedium {
// On success, returns a new WifiLanSocket.
// On error, returns nullptr.
std::unique_ptr<api::WifiLanSocket> Connect(
api::WifiLanService& remote_service,
api::WifiLanService& remote_wifi_lan_service,
const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_);
api::WifiLanService* FindRemoteService(const std::string& ip_address,
int port) override;
api::WifiLanService* GetRemoteService(const std::string& ip_address,
int port) override;
std::pair<std::string, int> GetServiceAddress(
const std::string& service_id) override ABSL_LOCKS_EXCLUDED(mutex_);
@@ -238,8 +215,11 @@ class WifiLanMedium : public api::WifiLanMedium {
std::string service_id;
};
void SetWifiLanService(const NsdServiceInfo& nsd_service_info);
std::pair<std::string, int> GetFakeServiceAddress() const;
absl::Mutex mutex_;
WifiLanService service_{"unknown G3 WifiLan service"};
WifiLanService wifi_lan_service_;
// A thread pool dedicated to running all the accept loops from
// StartAdvertising().
+30 -25
View File
@@ -7,10 +7,8 @@ namespace location {
namespace nearby {
bool WifiLanMedium::StartAdvertising(const std::string& service_id,
const std::string& service_info_name,
const std::string& endpoint_info_name) {
return impl_->StartAdvertising(service_id, service_info_name,
endpoint_info_name);
const NsdServiceInfo& nsd_service_info) {
return impl_->StartAdvertising(service_id, nsd_service_info);
}
bool WifiLanMedium::StopAdvertising(const std::string& service_id) {
@@ -28,40 +26,46 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_id,
service_id,
{
.service_discovered_cb =
[this](api::WifiLanService& service,
[this](api::WifiLanService& wifi_lan_service,
const std::string& service_id) {
MutexLock lock(&mutex_);
auto pair = services_.emplace(
&service, absl::make_unique<ServiceDiscoveryInfo>());
&wifi_lan_service,
absl::make_unique<ServiceDiscoveryInfo>());
auto& context = *pair.first->second;
if (!pair.second) {
NEARBY_LOG(INFO,
"Discovering (again) service=%p, impl=%p, "
"service_info_name=%s",
&context.service, &service,
service.GetServiceName().c_str());
&context.wifi_lan_service, &wifi_lan_service,
wifi_lan_service.GetServiceInfo()
.GetServiceInfoName()
.c_str());
} else {
context.service = WifiLanService(&service);
NEARBY_LOG(INFO,
"Discovering service=%p, impl=%p, "
"service_info_name=%s",
&context.service, &service,
service.GetServiceName().c_str());
context.wifi_lan_service = WifiLanService(&wifi_lan_service);
NEARBY_LOG(
INFO,
"Discovering wifi_lan_service=%p, service_info_name=%s",
&wifi_lan_service,
wifi_lan_service.GetServiceInfo()
.GetServiceInfoName()
.c_str());
}
discovered_service_callback_.service_discovered_cb(
context.service, service_id);
context.wifi_lan_service, service_id);
},
.service_lost_cb =
[this](api::WifiLanService& service,
[this](api::WifiLanService& wifi_lan_service,
const std::string& service_id) {
MutexLock lock(&mutex_);
if (services_.empty()) return;
auto context = services_.find(&service);
auto context = services_.find(&wifi_lan_service);
if (context == services_.end()) return;
NEARBY_LOG(INFO, "Removing service=%p, impl=%p",
&(context->second->service), &service);
NEARBY_LOG(INFO, "Removing wifi_lan_service=%p, impl=%p",
&(context->second->wifi_lan_service),
&wifi_lan_service);
discovered_service_callback_.service_lost_cb(
context->second->service, service_id);
context->second->wifi_lan_service, service_id);
},
});
}
@@ -117,18 +121,19 @@ bool WifiLanMedium::StopAcceptingConnections(const std::string& service_id) {
return impl_->StopAcceptingConnections(service_id);
}
WifiLanSocket WifiLanMedium::Connect(WifiLanService& service,
WifiLanSocket WifiLanMedium::Connect(WifiLanService& wifi_lan_service,
const std::string& service_id) {
NEARBY_LOG(
INFO,
"WifiLanMedium::Connect: service=%p [impl=%p, service_info_name=%s]",
&service, &service.GetImpl(), service.GetServiceName().c_str());
return WifiLanSocket(impl_->Connect(service.GetImpl(), service_id));
&wifi_lan_service, &wifi_lan_service.GetImpl(),
wifi_lan_service.GetServiceInfo().GetServiceInfoName().c_str());
return WifiLanSocket(impl_->Connect(wifi_lan_service.GetImpl(), service_id));
}
WifiLanService WifiLanMedium::FindRemoteService(const std::string& ip_address,
WifiLanService WifiLanMedium::GetRemoteService(const std::string& ip_address,
int port) {
return WifiLanService(impl_->FindRemoteService(ip_address, port));
return WifiLanService(impl_->GetRemoteService(ip_address, port));
}
std::pair<std::string, int> WifiLanMedium::GetServiceAddress(
+8 -13
View File
@@ -5,6 +5,7 @@
#include "platform/api/wifi_lan.h"
#include "platform/base/byte_array.h"
#include "platform/base/input_stream.h"
#include "platform/base/nsd_service_info.h"
#include "platform/base/output_stream.h"
#include "platform/public/mutex.h"
#include "absl/container/flat_hash_map.h"
@@ -12,8 +13,7 @@
namespace location {
namespace nearby {
// Opaque wrapper over a WifiLan service which contains packed
// |WifiLanServiceInfo| string name and the TXT Record.
// Opaque wrapper over a WifiLan service which contains |NsdServiceInfo|.
class WifiLanService final {
public:
WifiLanService() = default;
@@ -22,12 +22,7 @@ class WifiLanService final {
explicit WifiLanService(api::WifiLanService* service) : impl_(service) {}
~WifiLanService() = default;
std::string GetServiceName() const { return impl_->GetServiceName(); }
std::string GetTxtRecord(const std::string& key) const {
return impl_->GetTxtRecord(key);
}
NsdServiceInfo GetServiceInfo() const { return impl_->GetServiceInfo(); }
api::WifiLanService& GetImpl() { return *impl_; }
bool IsValid() const { return impl_ != nullptr; }
@@ -105,7 +100,7 @@ class WifiLanMedium final {
};
struct ServiceDiscoveryInfo {
WifiLanService service;
WifiLanService wifi_lan_service;
};
struct AcceptedConnectionCallback {
@@ -121,8 +116,7 @@ class WifiLanMedium final {
~WifiLanMedium() = default;
bool StartAdvertising(const std::string& service_id,
const std::string& service_info_name,
const std::string& endpoint_info_name);
const NsdServiceInfo& nsd_service_info);
bool StopAdvertising(const std::string& service_id);
// Returns true once the WifiLan discovery has been initiated.
@@ -142,13 +136,14 @@ class WifiLanMedium final {
// Returns a new WifiLanSocket. On Success, WifiLanSocket::IsValid()
// returns true.
WifiLanSocket Connect(WifiLanService& service, const std::string& service_id);
WifiLanSocket Connect(WifiLanService& wifi_lan_service,
const std::string& service_id);
bool IsValid() const { return impl_ != nullptr; }
api::WifiLanMedium& GetImpl() { return *impl_; }
WifiLanService FindRemoteService(const std::string& ip_address, int port);
WifiLanService GetRemoteService(const std::string& ip_address, int port);
std::pair<std::string, int> GetServiceAddress(const std::string& service_id);
+29 -8
View File
@@ -16,6 +16,7 @@ namespace {
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kServiceInfoName{"Simulated service info name"};
constexpr absl::string_view kEndpointName{"Simulated endpoint name"};
constexpr absl::string_view kEndpointInfoKey{"n"};
class WifiLanMediumTest : public ::testing::Test {
protected:
@@ -50,7 +51,11 @@ TEST_F(WifiLanMediumTest, CanStartAdvertising) {
std::string endpoint_info_name{kEndpointName};
CountDownLatch found_latch(1);
wifi_a.StartAdvertising(service_id, service_info_name, endpoint_info_name);
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
wifi_a.StartAdvertising(service_id, nsd_service_info);
EXPECT_TRUE(wifi_b.StartDiscovery(
service_id, DiscoveredServiceCallback{
@@ -89,8 +94,12 @@ TEST_F(WifiLanMediumTest, CanStartDiscovery) {
lost_latch.CountDown();
},
});
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, service_info_name,
endpoint_info_name));
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, nsd_service_info));
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_b.StopAdvertising(service_id));
EXPECT_TRUE(lost_latch.Await(absl::Milliseconds(1000)).result());
@@ -121,8 +130,13 @@ TEST_F(WifiLanMediumTest, CanStopDiscovery) {
lost_latch.CountDown();
},
});
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, service_info_name,
endpoint_info_name));
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
EXPECT_TRUE(wifi_b.StartAdvertising(service_id, nsd_service_info));
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
EXPECT_TRUE(wifi_a.StopDiscovery(service_id));
EXPECT_TRUE(wifi_b.StopAdvertising(service_id));
@@ -147,13 +161,20 @@ TEST_F(WifiLanMediumTest, CanStartAcceptingConnectionsAndConnect) {
.service_discovered_cb =
[&found_latch, &discovered_service](
WifiLanService& service, const std::string& service_id) {
NEARBY_LOG(INFO, "Service discovered: %s, %p",
service.GetServiceName().c_str(), &service);
NEARBY_LOG(
INFO, "Service discovered: %s, %p",
service.GetServiceInfo().GetServiceInfoName().c_str(),
&service);
discovered_service = &service;
found_latch.CountDown();
},
});
wifi_b.StartAdvertising(service_id, service_info_name, endpoint_info_name);
NsdServiceInfo nsd_service_info;
nsd_service_info.SetServiceInfoName(service_info_name);
nsd_service_info.SetTxtRecord(std::string(kEndpointInfoKey),
endpoint_info_name);
wifi_b.StartAdvertising(service_id, nsd_service_info);
wifi_b.StartAcceptingConnections(
service_id,
AcceptedConnectionCallback{