Merge branch 'master' into release

Change-Id: I56ea2217899e92bdd9d6cb56797ac9895e194fff
This commit is contained in:
Alexey Polyudov
2020-06-24 11:01:46 -07:00
147 changed files with 8642 additions and 1214 deletions
+6 -1
View File
@@ -28,9 +28,11 @@ cc_library(
"input_stream.h",
"listeners.h",
"output_stream.h",
"payload_id.h",
"prng.h",
"runnable.h",
"socket.h",
"types.h",
],
visibility = [
"//core_v2:__subpackages__",
@@ -56,6 +58,7 @@ cc_library(
"base_pipe.h",
],
visibility = [
"//core_v2:__subpackages__",
"//platform_v2/impl:__subpackages__",
"//platform_v2/public:__pkg__",
],
@@ -75,7 +78,8 @@ cc_library(
"//platform_v2:__subpackages__",
],
deps = [
"//platform:logging",
"//platform_v2/api:platform",
"//platform_v2/api:types",
],
)
@@ -99,6 +103,7 @@ cc_library(
"//platform_v2/api:comm",
"//platform_v2/public:types",
"//absl/container:flat_hash_map",
"//absl/strings",
],
)
+1 -2
View File
@@ -41,13 +41,12 @@ class BaseInputStream : public InputStream {
std::uint16_t ReadUint16();
std::uint32_t ReadUint32();
std::uint64_t ReadUint64();
ByteArray ReadBytes(int size);
bool IsAvailable(int size) const {
return buffer_.size() - position_ >= size;
}
private:
ByteArray ReadBytes(int size);
ByteArray &buffer_;
int position_{0};
};
+20 -5
View File
@@ -15,10 +15,11 @@
#ifndef PLATFORM_V2_BASE_BYTE_ARRAY_H_
#define PLATFORM_V2_BASE_BYTE_ARRAY_H_
#include <array>
#include <cstdint>
#include <string>
#include "absl/strings/string_view.h"
#include <type_traits>
#include <utility>
namespace location {
namespace nearby {
@@ -27,13 +28,22 @@ class ByteArray {
public:
// Create an empty ByteArray
ByteArray() = default;
template <size_t N>
explicit ByteArray(const std::array<char, N>& data) {
SetData(data.data(), data.size());
}
ByteArray(const ByteArray&) = default;
ByteArray& operator=(const ByteArray&) = default;
ByteArray(ByteArray&&) = default;
ByteArray& operator=(ByteArray&&) = default;
// Create ByteArray from string.
explicit ByteArray(absl::string_view source) {
// Moves string out of temporary, allowing for a zero-copy constructions.
// This is an optimization for very large strings.
explicit ByteArray(std::string&& source) : data_(std::move(source)) {}
// Create ByteArray by copy of a std::string. This can't be a string_view,
// because it will conflict with std::string&& version of constructor.
explicit ByteArray(const std::string& source) {
SetData(source.data(), source.size());
}
@@ -73,7 +83,12 @@ class ByteArray {
friend bool operator!=(const ByteArray& lhs, const ByteArray& rhs);
friend bool operator<(const ByteArray& lhs, const ByteArray& rhs);
explicit operator std::string() const { return data_; }
// Returns a copy of internal representation as std::string.
explicit operator std::string() const& { return data_; }
// Moves string out of temporary ByteArray, allowing for a zero-copy
// operation.
explicit operator std::string() const&& { return std::move(data_); }
private:
std::string data_;
+8
View File
@@ -79,4 +79,12 @@ TEST(ByteArrayTest, SetExplicitData) {
EXPECT_EQ(0, memcmp(message, bytes.data(), kMessageSize));
}
TEST(ByteArrayTest, CreateFromNonNullTerminatedStdArray) {
constexpr static const std::array data{'a', '\x00', 'b'};
ByteArray bytes{data};
EXPECT_EQ(bytes.size(), 3);
EXPECT_EQ(bytes.size(), std::string(bytes).size());
EXPECT_EQ(std::string(bytes), std::string(data.data(), data.size()));
}
} // namespace
+55 -1
View File
@@ -15,6 +15,60 @@
#ifndef PLATFORM_V2_BASE_LOGGING_H_
#define PLATFORM_V2_BASE_LOGGING_H_
#include "platform/logging.h"
#include "platform_v2/api/log_message.h"
#include "platform_v2/api/platform.h"
namespace location {
namespace nearby {
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
LogMessageVoidify() = default;
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) {}
};
} // namespace nearby
} // namespace location
// Severity enum conversion
#define NEARBY_SEVERITY_INFO location::nearby::api::LogMessage::Severity::kInfo
#define NEARBY_SEVERITY_WARNING \
location::nearby::api::LogMessage::Severity::kWarning
#define NEARBY_SEVERITY_ERROR \
location::nearby::api::LogMessage::Severity::kError
#define NEARBY_SEVERITY_FATAL \
location::nearby::api::LogMessage::Severity::kFatal
#define NEARBY_SEVERITY(severity) NEARBY_SEVERITY_##severity
// Log enabling
#define NEARBY_LOG_IS_ON(severity) \
location::nearby::api::LogMessage::ShouldCreateLogMessage( \
NEARBY_SEVERITY(severity))
#define NEARBY_LOG_SET_SEVERITY(severity) \
location::nearby::api::LogMessage::SetMinLogSeverity( \
NEARBY_SEVERITY(severity))
// Log message creation
#define NEARBY_LOG_MESSAGE(severity) \
location::nearby::api::ImplementationPlatform::CreateLogMessage( \
__FILE__, __LINE__, NEARBY_SEVERITY(severity))
// Public APIs
// The stream statement must come last or otherwise it won't compile.
#define NEARBY_LOGS(severity) \
!(NEARBY_LOG_IS_ON(severity)) ? (void)0 \
: location::nearby::LogMessageVoidify() & \
NEARBY_LOG_MESSAGE(severity)->Stream()
#define NEARBY_LOG(severity, ...) \
NEARBY_LOG_IS_ON(severity) \
? NEARBY_LOG_MESSAGE(severity)->Print(__VA_ARGS__) : (void)0
#endif // PLATFORM_V2_BASE_LOGGING_H_
+146 -13
View File
@@ -21,6 +21,7 @@
#include "platform_v2/api/bluetooth_adapter.h"
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/api/wifi_lan.h"
#include "platform_v2/base/logging.h"
#include "platform_v2/public/count_down_latch.h"
@@ -54,6 +55,7 @@ void MediumEnvironment::Reset() {
NEARBY_LOG(INFO, "MediumEnvironment::Reset()");
bluetooth_adapters_.clear();
bluetooth_mediums_.clear();
wifi_lan_mediums_.clear();
});
Sync();
}
@@ -91,7 +93,7 @@ void MediumEnvironment::OnBluetoothAdapterChangedState(
if (info.adapter == &adapter) continue;
NEARBY_LOG(INFO, "[adapter=%p, device=%p] notify: adapter=%p", &adapter,
&adapter_device, info.adapter);
OnDeviceStateChanged(info, adapter_device, name, mode, enabled);
OnBluetoothDeviceStateChanged(info, adapter_device, name, mode, enabled);
}
// We don't care if there is an adapter already since all we store is a
// pointer. Pointer must remain valid for the duration of a Core session
@@ -101,16 +103,17 @@ void MediumEnvironment::OnBluetoothAdapterChangedState(
});
}
void MediumEnvironment::OnDeviceStateChanged(
void MediumEnvironment::OnBluetoothDeviceStateChanged(
BluetoothMediumContext& info, api::BluetoothDevice& device,
const std::string& name, api::BluetoothAdapter::ScanMode mode,
bool enabled) {
if (!enabled_) return;
auto item = info.devices.find(&device);
if (item == info.devices.end()) {
NEARBY_LOG(
INFO, "G3 OnDeviceStateChanged [device impl=%p]: new device; notify=%d",
&device, enable_notifications_.load());
NEARBY_LOG(INFO,
"G3 OnBluetoothDeviceStateChanged [device impl=%p]: new device; "
"notify=%d",
&device, enable_notifications_.load());
if (mode == api::BluetoothAdapter::ScanMode::kConnectableDiscoverable &&
enabled) {
// New device is turned on, and is in discoverable state.
@@ -122,10 +125,10 @@ void MediumEnvironment::OnDeviceStateChanged(
}
}
} else {
NEARBY_LOG(
INFO,
"G3 OnDeviceStateChanged [device impl=%p]: exisitng device; notify=%d",
&device, enable_notifications_.load());
NEARBY_LOG(INFO,
"G3 OnBluetoothDeviceStateChanged [device impl=%p]: exisitng "
"device; notify=%d",
&device, enable_notifications_.load());
auto& discovered_name = item->second;
if (mode == api::BluetoothAdapter::ScanMode::kConnectableDiscoverable &&
enabled) {
@@ -159,6 +162,39 @@ void MediumEnvironment::OnDeviceStateChanged(
}
}
void MediumEnvironment::OnWifiLanServiceStateChanged(
WifiLanMediumContext& info, api::WifiLanService& service,
const std::string& service_id, bool enabled) {
if (!enabled_) return;
auto item = info.services.find(&service);
if (item == info.services.end()) {
NEARBY_LOG(INFO,
"G3 OnWifiLanServiceStateChanged [service impl=%p]: new service",
&service);
info.services.emplace(&service, service.GetName());
if (enabled) {
RunOnMediumEnvironmentThread([&info, &service, service_id]() {
info.discovery_callback.service_discovered_cb(service, service_id);
});
}
} else {
NEARBY_LOG(INFO,
"G3 OnWifiLanServiceStateChanged [service impl=%p]: exisitng "
"service",
&service);
if (enabled) {
RunOnMediumEnvironmentThread([&info, &service, service_id]() {
info.discovery_callback.service_discovered_cb(service, service_id);
});
} else {
RunOnMediumEnvironmentThread([&info, &service, service_id]() {
info.discovery_callback.service_lost_cb(service, service_id);
});
info.services.erase(item);
}
}
}
void MediumEnvironment::RunOnMediumEnvironmentThread(
std::function<void()> runnable) {
job_count_++;
@@ -181,8 +217,9 @@ void MediumEnvironment::RegisterBluetoothMedium(
owned_adapter);
for (auto& [adapter, device] : bluetooth_adapters_) {
if (adapter == nullptr) continue;
OnDeviceStateChanged(context, *device, adapter->GetName(),
adapter->GetScanMode(), adapter->IsEnabled());
OnBluetoothDeviceStateChanged(context, *device, adapter->GetName(),
adapter->GetScanMode(),
adapter->IsEnabled());
}
});
}
@@ -204,8 +241,9 @@ void MediumEnvironment::UpdateBluetoothMedium(
owned_adapter->IsEnabled(), owned_adapter->GetScanMode());
for (auto& [adapter, device] : bluetooth_adapters_) {
if (adapter == nullptr) continue;
OnDeviceStateChanged(context, *device, adapter->GetName(),
adapter->GetScanMode(), adapter->IsEnabled());
OnBluetoothDeviceStateChanged(context, *device, adapter->GetName(),
adapter->GetScanMode(),
adapter->IsEnabled());
}
});
}
@@ -222,5 +260,100 @@ void MediumEnvironment::UnregisterBluetoothMedium(
});
}
void MediumEnvironment::RegisterWebRtcSignalingMessenger(
absl::string_view self_id, OnSignalingMessageCallback callback) {
if (!enabled_) return;
RunOnMediumEnvironmentThread(
[this, self_id{std::string(self_id)}, callback{std::move(callback)}]() {
webrtc_signaling_callback_[self_id] = std::move(callback);
NEARBY_LOG(INFO, "Registered signaling message callback for id = %s",
self_id.c_str());
});
}
void MediumEnvironment::UnregisterWebRtcSignalingMessenger(
absl::string_view self_id) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, self_id{std::string(self_id)}]() {
auto item = webrtc_signaling_callback_.extract(self_id);
if (item.empty()) return;
NEARBY_LOG(INFO, "Unregistered signaling message callback for id = %s",
self_id.c_str());
});
}
void MediumEnvironment::SendWebRtcSignalingMessage(absl::string_view peer_id,
const ByteArray& message) {
if (!enabled_) return;
RunOnMediumEnvironmentThread(
[this, peer_id{std::string(peer_id)}, message]() {
auto item = webrtc_signaling_callback_.find(peer_id);
if (item == webrtc_signaling_callback_.end()) {
NEARBY_LOG(WARNING, "No callback registered for peer id = %s",
peer_id.c_str());
return;
}
item->second(message);
});
}
void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
wifi_lan_mediums_.insert({&medium, WifiLanMediumContext{}});
NEARBY_LOG(INFO, "Registered: medium=%p", &medium);
});
}
void MediumEnvironment::UpdateWifiLanMediumForDiscovery(
api::WifiLanMedium& medium, api::WifiLanService& service,
const std::string& service_id, WifiLanDiscoveredServiceCallback callback,
bool enabled) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, &service, service_id,
callback = std::move(callback), enabled]() {
auto item = wifi_lan_mediums_.find(&medium);
if (item == wifi_lan_mediums_.end()) {
NEARBY_LOG(
INFO, "Update WifiLan medium failed. There is no medium registered.");
return;
}
auto& context = item->second;
context.discovery_callback = std::move(callback);
NEARBY_LOG(INFO, "Updated: this=%p; medium=%p", this, &medium);
OnWifiLanServiceStateChanged(context, service, service_id, enabled);
});
}
void MediumEnvironment::UpdateWifiLanMediumForAcceptedConnection(
api::WifiLanMedium& medium, const std::string& service_id,
WifiLanAcceptedConnectionCallback accepted_connection_callback) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium,
accepted_connection_callback =
std::move(accepted_connection_callback)]() {
auto item = wifi_lan_mediums_.find(&medium);
if (item == wifi_lan_mediums_.end()) {
NEARBY_LOG(
INFO, "Update WifiLan medium failed. There is no medium registered.");
return;
}
auto& context = item->second;
context.accepted_connection_callback =
std::move(accepted_connection_callback);
NEARBY_LOG(INFO, "Updated: this=%p; medium=%p", this, &medium);
});
}
void MediumEnvironment::UnregisterWifiLanMedium(api::WifiLanMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
auto item = wifi_lan_mediums_.extract(&medium);
if (item.empty()) return;
NEARBY_LOG(INFO, "Unregistered WifiLan medium");
});
}
} // namespace nearby
} // namespace location
+56 -4
View File
@@ -19,9 +19,12 @@
#include "platform_v2/api/bluetooth_adapter.h"
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/api/webrtc.h"
#include "platform_v2/base/byte_array.h"
#include "platform_v2/base/listeners.h"
#include "platform_v2/public/single_thread_executor.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
@@ -35,6 +38,12 @@ class MediumEnvironment {
public:
using BluetoothDiscoveryCallback =
api::BluetoothClassicMedium::DiscoveryCallback;
using OnSignalingMessageCallback =
api::WebRtcSignalingMessenger::OnSignalingMessageCallback;
using WifiLanDiscoveredServiceCallback =
api::WifiLanMedium::DiscoveredServiceCallback;
using WifiLanAcceptedConnectionCallback =
api::WifiLanMedium::AcceptedConnectionCallback;
MediumEnvironment(const MediumEnvironment&) = delete;
MediumEnvironment& operator=(const MediumEnvironment&) = delete;
@@ -98,6 +107,28 @@ class MediumEnvironment {
// Removes medium-related info. This should correspond to device power off.
void UnregisterBluetoothMedium(api::BluetoothClassicMedium& medium);
// Registers |callback| to receive messages sent to device with id |self_id|.
void RegisterWebRtcSignalingMessenger(absl::string_view self_id,
OnSignalingMessageCallback callback);
// Unregisters the callback listening to incoming messages for |self_id|.
void UnregisterWebRtcSignalingMessenger(absl::string_view self_id);
// Simulates sending a signaling message |message| to device with id
// |peer_id|.
void SendWebRtcSignalingMessage(absl::string_view peer_id,
const ByteArray& message);
// Wifi-Lan medium registration/update calls.
void RegisterWifiLanMedium(api::WifiLanMedium& medium);
void UpdateWifiLanMediumForDiscovery(
api::WifiLanMedium& medium, api::WifiLanService& service,
const std::string& service_id,
WifiLanDiscoveredServiceCallback discovery_callback, bool enabled);
void UpdateWifiLanMediumForAcceptedConnection(
api::WifiLanMedium& medium, const std::string& service_id,
WifiLanAcceptedConnectionCallback accepted_connection_callback);
void UnregisterWifiLanMedium(api::WifiLanMedium& medium);
private:
struct BluetoothMediumContext {
BluetoothDiscoveryCallback callback;
@@ -106,6 +137,13 @@ class MediumEnvironment {
absl::flat_hash_map<api::BluetoothDevice*, std::string> devices;
};
struct WifiLanMediumContext {
WifiLanDiscoveredServiceCallback discovery_callback;
WifiLanAcceptedConnectionCallback accepted_connection_callback;
// discovered service vs service name map.
absl::flat_hash_map<api::WifiLanService*, std::string> services;
};
// This is a singleton object, for which destructor will never be called.
// Constructor will be invoked once from Instance() static method.
// Object is create in-place (with a placement new) to guarantee that
@@ -113,10 +151,17 @@ class MediumEnvironment {
MediumEnvironment() = default;
~MediumEnvironment() = default;
void OnDeviceStateChanged(BluetoothMediumContext& info,
api::BluetoothDevice& device,
const std::string& name,
api::BluetoothAdapter::ScanMode mode, bool enabled);
void OnBluetoothDeviceStateChanged(BluetoothMediumContext& info,
api::BluetoothDevice& device,
const std::string& name,
api::BluetoothAdapter::ScanMode mode,
bool enabled);
void OnWifiLanServiceStateChanged(WifiLanMediumContext& info,
api::WifiLanService& service,
const std::string& service_id,
bool enabled);
void RunOnMediumEnvironmentThread(std::function<void()> runnable);
std::atomic_bool enabled_ = true;
@@ -130,6 +175,13 @@ class MediumEnvironment {
bluetooth_adapters_;
absl::flat_hash_map<api::BluetoothClassicMedium*, BluetoothMediumContext>
bluetooth_mediums_;
// Maps peer id to callback for receiving signaling messages.
absl::flat_hash_map<std::string, OnSignalingMessageCallback>
webrtc_signaling_callback_;
absl::flat_hash_map<api::WifiLanMedium*, WifiLanMediumContext>
wifi_lan_mediums_;
};
} // namespace nearby
+14
View File
@@ -0,0 +1,14 @@
#ifndef PLATFORM_V2_BASE_PAYLOAD_ID_H_
#define PLATFORM_V2_BASE_PAYLOAD_ID_H_
#include <cstdint>
namespace location {
namespace nearby {
using PayloadId = std::int64_t;
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_BASE_PAYLOAD_ID_H_
+1 -1
View File
@@ -52,7 +52,7 @@ std::uint32_t Prng::NextUint32() {
std::int64_t Prng::NextInt64() {
return (static_cast<std::int64_t>(NextInt32()) << 32) |
(static_cast<std::int64_t>(NextInt32()));
(static_cast<std::int64_t>(NextUint32()));
}
} // namespace nearby
+50
View File
@@ -19,6 +19,13 @@
namespace location {
namespace nearby {
enum class TestMode {
kUpperHalfOfInt64,
kLowerHalfOfInt64,
kInt32,
kUint32,
};
TEST(PrngTest, NextInt32) {
std::int32_t i = Prng().NextInt32();
EXPECT_LE(i, std::numeric_limits<std::int32_t>::max());
@@ -37,5 +44,48 @@ TEST(PrngTest, NextInt64) {
EXPECT_GE(i, std::numeric_limits<std::int64_t>::min());
}
void ValidateRandom(TestMode mode) {
int count_all_zeros = 0;
int count_all_ones = 0;
std::uint32_t i;
Prng prng;
for (int count = 0; count < 100; ++count) {
switch (mode) {
case TestMode::kUpperHalfOfInt64:
i = static_cast<std::uint32_t>(prng.NextInt64() >> 32);
break;
case TestMode::kLowerHalfOfInt64:
i = static_cast<std::uint32_t>(prng.NextInt64());
break;
case TestMode::kInt32:
i = static_cast<std::uint32_t>(prng.NextInt32());
break;
case TestMode::kUint32:
i = static_cast<std::uint32_t>(prng.NextUint32());
break;
}
if (!i) count_all_zeros++;
if (i == 0xFFFFFFFF) count_all_ones++;
}
EXPECT_LE(count_all_zeros, 1);
EXPECT_LE(count_all_ones, 1);
}
TEST(PrngTest, ValidateUpperHalfOfInt64) {
ValidateRandom(TestMode::kUpperHalfOfInt64);
}
TEST(PrngTest, ValidateLowerHalfOfInt64) {
ValidateRandom(TestMode::kLowerHalfOfInt64);
}
TEST(PrngTest, ValidateInt32) {
ValidateRandom(TestMode::kInt32);
}
TEST(PrngTest, ValidateUint32) {
ValidateRandom(TestMode::kUint32);
}
} // namespace nearby
} // namespace location
+29
View File
@@ -0,0 +1,29 @@
#ifndef PLATFORM_V2_BASE_TYPES_H_
#define PLATFORM_V2_BASE_TYPES_H_
#include <type_traits>
namespace location {
namespace nearby {
// Similar to static_cast, but will assert that Derived is a derived type of
// Base.
// Usage:
// class A {};
// class B : public A {};
// class C {};
// B b;
// A* a = &b;
// B* b2 = down_cast<B*>(a); // This is OK.
// C* c = down_cast<C*>(a); // This will fail to compile.
template <typename Derived, typename Base>
inline Derived down_cast(Base* value) {
using DerivedType = typename std::remove_pointer<Derived>::type;
static_assert(std::is_base_of<Base, DerivedType>::value);
return static_cast<Derived>(value);
}
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_BASE_TYPES_H_