Roll forward to cl/328359974

Change-Id: If2b57ecc852aecf7dea454648f485fd7c08e72a9
This commit is contained in:
Alexey Polyudov
2020-08-25 11:27:27 -07:00
parent 6f9228fa6b
commit c673bf6ac0
110 changed files with 4758 additions and 1245 deletions
+4
View File
@@ -4,10 +4,12 @@ cc_library(
name = "base",
srcs = [
"base64_utils.cc",
"bluetooth_utils.cc",
"prng.cc",
],
hdrs = [
"base64_utils.h",
"bluetooth_utils.h",
"byte_array.h",
"callable.h",
"exception.h",
@@ -28,6 +30,7 @@ cc_library(
deps = [
"//absl/meta:type_traits",
"//absl/strings",
"//absl/strings:str_format",
"//absl/time",
],
)
@@ -96,6 +99,7 @@ cc_library(
cc_test(
name = "platform_base_test",
srcs = [
"bluetooth_utils_test.cc",
"byte_array_test.cc",
"prng_test.cc",
],
+61
View File
@@ -0,0 +1,61 @@
#include "platform_v2/base/bluetooth_utils.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_format.h"
namespace location {
namespace nearby {
std::string BluetoothUtils::ToString(const ByteArray& bluetooth_mac_address) {
std::string colon_delimited_string;
if (bluetooth_mac_address.size() != kBluetoothMacAddressLength)
return colon_delimited_string;
if (IsBluetoothMacAddressUnset(bluetooth_mac_address))
return colon_delimited_string;
for (auto byte : std::string(bluetooth_mac_address)) {
if (!colon_delimited_string.empty())
absl::StrAppend(&colon_delimited_string, ":");
absl::StrAppend(&colon_delimited_string, absl::StrFormat("%02X", byte));
}
return colon_delimited_string;
}
ByteArray BluetoothUtils::FromString(absl::string_view bluetooth_mac_address) {
std::string bt_mac_address(bluetooth_mac_address);
// Remove the colon delimiters.
bt_mac_address.erase(
std::remove(bt_mac_address.begin(), bt_mac_address.end(), ':'),
bt_mac_address.end());
// If the bluetooth mac address is invalid (wrong size), return a null byte
// array.
if (bt_mac_address.length() != kBluetoothMacAddressLength * 2) {
return ByteArray();
}
// Convert to bytes. If MAC Address bytes are unset, return a null byte array.
auto bt_mac_address_string(absl::HexStringToBytes(bt_mac_address));
auto bt_mac_address_bytes =
ByteArray(bt_mac_address_string.data(), bt_mac_address_string.size());
if (IsBluetoothMacAddressUnset(bt_mac_address_bytes)) {
return ByteArray();
}
return bt_mac_address_bytes;
}
bool BluetoothUtils::IsBluetoothMacAddressUnset(
const ByteArray& bluetooth_mac_address_bytes) {
for (int i = 0; i < bluetooth_mac_address_bytes.size(); i++) {
if (bluetooth_mac_address_bytes.data()[i] != 0) {
return false;
}
}
return true;
}
} // namespace nearby
} // namespace location
+32
View File
@@ -0,0 +1,32 @@
#ifndef PLATFORM_V2_BASE_BLUETOOTH_UTILS_H_
#define PLATFORM_V2_BASE_BLUETOOTH_UTILS_H_
#include "platform_v2/base/byte_array.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
class BluetoothUtils {
public:
static constexpr int kBluetoothMacAddressLength = 6;
// Converts a Bluetooth MAC address from byte array to String format. Returns
// empty if input byte array is not of correct format.
// e.g. {-84, 55, 67, -68, -87, 40} -> "AC:37:43:BC:A9:28".
static std::string ToString(const ByteArray& bluetooth_mac_address);
// Converts a Bluetooth MAC address from String format to byte array. Returns
// empty if input string is not of correct format.
// e.g. "AC:37:43:BC:A9:28" -> {-84, 55, 67, -68, -87, 40}.
static ByteArray FromString(absl::string_view bluetooth_mac_address);
// Checks if a Bluetooth MAC address is zero for every byte.
static bool IsBluetoothMacAddressUnset(
const ByteArray& bluetooth_mac_address);
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_BASE_BLUETOOTH_UTILS_H_
@@ -0,0 +1,75 @@
#include "platform_v2/base/bluetooth_utils.h"
#include "gtest/gtest.h"
namespace location {
namespace nearby {
constexpr absl::string_view kBluetoothMacAddress{"00:00:E6:88:64:13"};
constexpr char kBluetoothMacAddressBytes[] = {0x00, 0x00, 0xe6,
0x88, 0x64, 0x13};
TEST(BluetoothUtilsTest, ToStringWorks) {
ByteArray bt_mac_address_bytes{
kBluetoothMacAddressBytes, sizeof(kBluetoothMacAddressBytes)};
auto bt_mac_address = BluetoothUtils::ToString(bt_mac_address_bytes);
EXPECT_EQ(kBluetoothMacAddress, bt_mac_address);
}
TEST(BluetoothUtilsTest, FromStringWorks) {
ByteArray bt_mac_address_bytes{
kBluetoothMacAddressBytes, sizeof(kBluetoothMacAddressBytes)};
auto bt_mac_address_bytes_result =
BluetoothUtils::FromString(kBluetoothMacAddress);
EXPECT_EQ(bt_mac_address_bytes, bt_mac_address_bytes_result);
}
TEST(BluetoothUtilsTest, InvalidBytesReturnsEmptyString) {
std::string string_result;
char bad_bt_mac_address_1[] = {0x02, 0x20, 0x00};
ByteArray bad_bt_mac_address_bytes_1{bad_bt_mac_address_1,
sizeof(bad_bt_mac_address_1)};
string_result = BluetoothUtils::ToString(bad_bt_mac_address_bytes_1);
EXPECT_TRUE(string_result.empty());
char bad_bt_mac_address_2[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
ByteArray bad_bt_mac_address_bytes_2{bad_bt_mac_address_2,
sizeof(bad_bt_mac_address_2)};
string_result = BluetoothUtils::ToString(bad_bt_mac_address_bytes_2);
EXPECT_TRUE(string_result.empty());
char bad_bt_mac_address_3[] = {0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99};
ByteArray bad_bt_mac_address_bytes_3{bad_bt_mac_address_3,
sizeof(bad_bt_mac_address_3)};
string_result = BluetoothUtils::ToString(bad_bt_mac_address_bytes_3);
EXPECT_TRUE(string_result.empty());
}
TEST(BluetoothUtilsTest, InvalidStringReturnsEmptyByteArray) {
ByteArray bytes_result;
std::string bad_bt_mac_address_1 = "022:00";
bytes_result = BluetoothUtils::FromString(bad_bt_mac_address_1);
EXPECT_TRUE(bytes_result.Empty());
std::string bad_bt_mac_address_2 = "22:00:11:33:77:aa::bb::99";
bytes_result = BluetoothUtils::FromString(bad_bt_mac_address_2);
EXPECT_TRUE(bytes_result.Empty());
std::string bad_bt_mac_address_3 = "00:00:00:00:00:00";
bytes_result = BluetoothUtils::FromString(bad_bt_mac_address_3);
EXPECT_TRUE(bytes_result.Empty());
std::string bad_bt_mac_address_4 = "BLUETOOTHCHIP";
bytes_result = BluetoothUtils::FromString(bad_bt_mac_address_4);
EXPECT_TRUE(bytes_result.Empty());
}
} // namespace nearby
} // namespace location
+1 -1
View File
@@ -74,7 +74,7 @@ class ByteArray {
// Moves string out of temporary ByteArray, allowing for a zero-copy
// operation.
explicit operator std::string() const&& { return std::move(data_); }
explicit operator std::string() && { return std::move(data_); }
private:
std::string data_;
+188
View File
@@ -5,6 +5,7 @@
#include <new>
#include <type_traits>
#include "platform_v2/api/ble.h"
#include "platform_v2/api/bluetooth_adapter.h"
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/api/wifi_lan.h"
@@ -42,6 +43,7 @@ void MediumEnvironment::Reset() {
NEARBY_LOG(INFO, "MediumEnvironment::Reset()");
bluetooth_adapters_.clear();
bluetooth_mediums_.clear();
ble_mediums_.clear();
wifi_lan_mediums_.clear();
});
Sync();
@@ -154,6 +156,48 @@ void MediumEnvironment::OnBluetoothDeviceStateChanged(
}
}
api::BluetoothDevice* MediumEnvironment::FindBluetoothDevice(
const std::string& mac_address) {
api::BluetoothDevice* device = nullptr;
CountDownLatch latch(1);
RunOnMediumEnvironmentThread([this, &device, &latch, &mac_address](){
for (auto& item : bluetooth_mediums_) {
auto* adapter = item.second.adapter;
if (!adapter) continue;
if (adapter->GetMacAddress() == mac_address) {
device = bluetooth_adapters_[adapter];
break;
}
}
latch.CountDown();
});
latch.Await();
return device;
}
void MediumEnvironment::OnBlePeripheralStateChanged(
BleMediumContext& info, api::BlePeripheral& peripheral,
const std::string& service_id, bool enabled) {
if (!enabled_) return;
NEARBY_LOG(INFO,
"G3 OnBleServiceStateChanged [peripheral impl=%p]; context=%p; "
"service_id=%s; notify=%d",
&peripheral, &info, service_id.c_str(),
enable_notifications_.load());
if (!enable_notifications_) return;
RunOnMediumEnvironmentThread([&info, enabled, &peripheral, service_id]() {
NEARBY_LOG(INFO,
"G3 [Run] OnBlePeripheralStateChanged [peripheral impl=%p]; "
"context=%p; service_id=%s; enabled=%d",
&peripheral, &info, service_id.c_str(), enabled);
if (enabled) {
info.discovery_callback.peripheral_discovered_cb(peripheral, service_id);
} else {
info.discovery_callback.peripheral_lost_cb(peripheral, service_id);
}
});
}
void MediumEnvironment::OnWifiLanServiceStateChanged(
WifiLanMediumContext& info, api::WifiLanService& service,
const std::string& service_id, bool enabled) {
@@ -164,6 +208,10 @@ void MediumEnvironment::OnWifiLanServiceStateChanged(
&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);
auto service_id_context = info.services.find(service_id);
if (service_id_context == info.services.end()) return;
@@ -246,6 +294,125 @@ void MediumEnvironment::UnregisterBluetoothMedium(
});
}
void MediumEnvironment::RegisterBleMedium(api::BleMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
ble_mediums_.insert({&medium, BleMediumContext{}});
NEARBY_LOG(INFO, "Registered: medium=%p", &medium);
});
}
void MediumEnvironment::UpdateBleMediumForAdvertising(
api::BleMedium& medium, api::BlePeripheral& peripheral,
const std::string& service_id, bool enabled) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, &peripheral, service_id,
enabled]() {
auto item = ble_mediums_.find(&medium);
if (item == ble_mediums_.end()) {
NEARBY_LOG(INFO,
"UpdateBleMediumForAdvertising failed. There is no medium "
"registered.");
return;
}
auto& context = item->second;
context.ble_peripheral = &peripheral;
context.advertising = enabled;
NEARBY_LOG(INFO,
"Update Ble medium for advertising: this=%p; medium=%p; "
"service_id=%s; name=%s; enabled=%d; ",
this, &medium, service_id.c_str(), peripheral.GetName().c_str(),
enabled);
for (auto& medium_info : ble_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;
OnBlePeripheralStateChanged(info, peripheral, service_id, enabled);
}
});
}
void MediumEnvironment::UpdateBleMediumForScanning(
api::BleMedium& medium, const std::string& service_id,
BleDiscoveredPeripheralCallback callback, bool enabled) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, service_id,
callback = std::move(callback), enabled]() {
auto item = ble_mediums_.find(&medium);
if (item == ble_mediums_.end()) {
NEARBY_LOG(INFO,
"UpdateBleMediumFoScanning failed. There is no medium "
"registered.");
return;
}
auto& context = item->second;
context.discovery_callback = std::move(callback);
NEARBY_LOG(INFO,
"Update Ble medium for scanning: this=%p; medium=%p; "
"service_id=%s; enabled=%d ;",
this, &medium, service_id.c_str(), enabled);
for (auto& medium_info : ble_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;
// Search advertising mediums and send notification.
if (info.advertising && enabled) {
OnBlePeripheralStateChanged(context, *(info.ble_peripheral), service_id,
enabled);
}
}
});
}
void MediumEnvironment::UpdateBleMediumForAcceptedConnection(
api::BleMedium& medium, const std::string& service_id,
BleAcceptedConnectionCallback callback) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, service_id,
callback = std::move(callback)]() {
auto item = ble_mediums_.find(&medium);
if (item == ble_mediums_.end()) {
NEARBY_LOG(
INFO, "Update Ble medium failed. There is no medium registered.");
return;
}
auto& context = item->second;
context.accepted_connection_callback = std::move(callback);
NEARBY_LOG(INFO,
"Update Ble medium for accepted callback: this=%p; "
"medium=%p; service_id=%s; ",
this, &medium, service_id.c_str());
});
}
void MediumEnvironment::UnregisterBleMedium(api::BleMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
auto item = ble_mediums_.extract(&medium);
if (item.empty()) return;
NEARBY_LOG(INFO, "Unregistered Ble medium");
});
}
void MediumEnvironment::CallBleAcceptedConnectionCallback(
api::BleMedium& medium, api::BleSocket& socket,
const std::string& service_id) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, &socket, service_id]() {
auto item = ble_mediums_.find(&medium);
if (item == ble_mediums_.end()) {
NEARBY_LOG(INFO,
"Call AcceptedConnectionCallback failed.. There is no medium "
"registered.");
return;
}
auto& info = item->second;
info.accepted_connection_callback.accepted_cb(socket, service_id);
});
}
void MediumEnvironment::RegisterWebRtcSignalingMessenger(
absl::string_view self_id, OnSignalingMessageCallback callback) {
if (!enabled_) return;
@@ -437,5 +604,26 @@ void MediumEnvironment::CallWifiLanAcceptedConnectionCallback(
});
}
api::WifiLanService* MediumEnvironment::FindWifiLanService(
const std::string& ip_address, int port) {
api::WifiLanService* remote_service = nullptr;
CountDownLatch latch(1);
RunOnMediumEnvironmentThread(
[this, &remote_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();
if (addr.first == ip_address && addr.second == port) {
remote_service = service;
break;
}
}
latch.CountDown();
});
latch.Await();
return remote_service;
}
} // namespace nearby
} // namespace location
+70 -3
View File
@@ -33,6 +33,10 @@ class MediumEnvironment {
public:
using BluetoothDiscoveryCallback =
api::BluetoothClassicMedium::DiscoveryCallback;
using BleDiscoveredPeripheralCallback =
api::BleMedium::DiscoveredPeripheralCallback;
using BleAcceptedConnectionCallback =
api::BleMedium::AcceptedConnectionCallback;
using OnSignalingMessageCallback =
api::WebRtcSignalingMessenger::OnSignalingMessageCallback;
using WifiLanDiscoveredServiceCallback =
@@ -103,6 +107,9 @@ class MediumEnvironment {
// Removes medium-related info. This should correspond to device power off.
void UnregisterBluetoothMedium(api::BluetoothClassicMedium& medium);
// Returns a Bluetooth Device object matching given mac address to nullptr.
api::BluetoothDevice* FindBluetoothDevice(const std::string& mac_address);
const EnvironmentConfig& GetEnvironmentConfig();
// Registers |callback| to receive messages sent to device with id |self_id|.
@@ -116,6 +123,48 @@ class MediumEnvironment {
// |peer_id|.
void SendWebRtcSignalingMessage(absl::string_view peer_id,
const ByteArray& message);
// Adds medium-related info to allow for scanning/advertising to work.
// This provides acccess to this medium from other mediums, when protocol
// expects they should communicate.
void RegisterBleMedium(api::BleMedium& medium);
// Updates advertising info to indicate the current medium is exposing
// advertising event.
void UpdateBleMediumForAdvertising(api::BleMedium& medium,
api::BlePeripheral& peripheral,
const std::string& service_id,
bool enabled);
// Updates discovery callback info to allow for dispatch of discovery events.
//
// Invokes callback asynchronously when any changes happen to discoverable
// devices, or if the defice is turned off, whether or not it is discoverable,
// if it was ever reported as discoverable.
//
// This should be called when discoverable state changes.
// with user-specified callback when discovery is enabled, and with default
// (empty) callback otherwise.
void UpdateBleMediumForScanning(api::BleMedium& medium,
const std::string& service_id,
BleDiscoveredPeripheralCallback callback,
bool enabled);
// Updates Accepted connection callback info to allow for dispatch of
// advertising events.
void UpdateBleMediumForAcceptedConnection(
api::BleMedium& medium, const std::string& service_id,
BleAcceptedConnectionCallback callback);
// Removes medium-related info. This should correspond to device power off.
void UnregisterBleMedium(api::BleMedium& medium);
// Call back when advertising has created the server socket and is ready for
// connect.
void CallBleAcceptedConnectionCallback(api::BleMedium& medium,
api::BleSocket& socket,
const std::string& service_id);
// Adds medium-related info to allow for discovery/advertising to work.
// This provides acccess to this medium from other mediums, when protocol
// expects they should communicate.
@@ -123,9 +172,10 @@ class MediumEnvironment {
// Updates advertising info to indicate the current medium is exposing
// advertising event.
void UpdateWifiLanMediumForAdvertising(
api::WifiLanMedium& medium, api::WifiLanService& service,
const std::string& service_id, bool enabled);
void UpdateWifiLanMediumForAdvertising(api::WifiLanMedium& medium,
api::WifiLanService& service,
const std::string& service_id,
bool enabled);
// Updates discovery callback info to allow for dispatch of discovery events.
//
@@ -155,6 +205,10 @@ class MediumEnvironment {
api::WifiLanSocket& socket,
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);
private:
struct BluetoothMediumContext {
BluetoothDiscoveryCallback callback;
@@ -163,6 +217,13 @@ class MediumEnvironment {
absl::flat_hash_map<api::BluetoothDevice*, std::string> devices;
};
struct BleMediumContext {
BleDiscoveredPeripheralCallback discovery_callback;
BleAcceptedConnectionCallback accepted_connection_callback;
api::BlePeripheral* ble_peripheral = nullptr;
bool advertising = false;
};
struct WifiLanServiceIdContext {
WifiLanDiscoveredServiceCallback discovery_callback;
WifiLanAcceptedConnectionCallback accepted_connection_callback;
@@ -187,6 +248,10 @@ class MediumEnvironment {
api::BluetoothAdapter::ScanMode mode,
bool enabled);
void OnBlePeripheralStateChanged(BleMediumContext& info,
api::BlePeripheral& peripheral,
const std::string& service_id, bool enabled);
void OnWifiLanServiceStateChanged(WifiLanMediumContext& info,
api::WifiLanService& service,
const std::string& service_id,
@@ -207,6 +272,8 @@ class MediumEnvironment {
absl::flat_hash_map<api::BluetoothClassicMedium*, BluetoothMediumContext>
bluetooth_mediums_;
absl::flat_hash_map<api::BleMedium*, BleMediumContext> ble_mediums_;
// Maps peer id to callback for receiving signaling messages.
absl::flat_hash_map<std::string, OnSignalingMessageCallback>
webrtc_signaling_callback_;