mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Roll forward to cl/318932159
Signed-off-by: Alexey Polyudov <apolyudov@google.com> Change-Id: Ia0cddfc8cf46c66d5739bdb45ab7825422912082
This commit is contained in:
+3
-1
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "core_v2/internal/client_proxy.h"
|
||||
#include "core_v2/internal/offline_service_controller.h"
|
||||
#include "core_v2/internal/service_controller.h"
|
||||
#include "core_v2/internal/service_controller_router.h"
|
||||
#include "core_v2/listeners.h"
|
||||
@@ -19,7 +20,8 @@ namespace connections {
|
||||
// This class defines the API of the Nearby Connections Core library.
|
||||
class Core {
|
||||
public:
|
||||
explicit Core(std::function<ServiceController*()> factory)
|
||||
explicit Core(std::function<ServiceController*()> factory =
|
||||
[]() { return new OfflineServiceController; })
|
||||
: router_(factory) {}
|
||||
~Core();
|
||||
Core(Core&&) = default;
|
||||
|
||||
@@ -13,6 +13,7 @@ cc_library(
|
||||
"internal_payload.cc",
|
||||
"internal_payload_factory.cc",
|
||||
"offline_frames.cc",
|
||||
"offline_service_controller.cc",
|
||||
"p2p_cluster_pcp_handler.cc",
|
||||
"p2p_point_to_point_pcp_handler.cc",
|
||||
"p2p_star_pcp_handler.cc",
|
||||
@@ -37,6 +38,7 @@ cc_library(
|
||||
"internal_payload.h",
|
||||
"internal_payload_factory.h",
|
||||
"offline_frames.h",
|
||||
"offline_service_controller.h",
|
||||
"p2p_cluster_pcp_handler.h",
|
||||
"p2p_point_to_point_pcp_handler.h",
|
||||
"p2p_star_pcp_handler.h",
|
||||
@@ -80,10 +82,12 @@ cc_library(
|
||||
name = "internal_test",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"offline_simulation_user.cc",
|
||||
"simulation_user.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"mock_service_controller.h",
|
||||
"offline_simulation_user.h",
|
||||
"simulation_user.h",
|
||||
],
|
||||
visibility = [
|
||||
@@ -96,6 +100,7 @@ cc_library(
|
||||
"//platform_v2/public:types",
|
||||
"//testing/base/public:gunit",
|
||||
"//absl/functional:bind_front",
|
||||
"//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -113,6 +118,7 @@ cc_test(
|
||||
"endpoint_manager_test.cc",
|
||||
"internal_payload_factory_test.cc",
|
||||
"offline_frames_test.cc",
|
||||
"offline_service_controller_test.cc",
|
||||
"p2p_cluster_pcp_handler_test.cc",
|
||||
"payload_manager_test.cc",
|
||||
"pcp_manager_test.cc",
|
||||
|
||||
@@ -32,12 +32,9 @@ BasePcpHandler::BasePcpHandler(EndpointManager* endpoint_manager,
|
||||
pcp_(pcp) {}
|
||||
|
||||
BasePcpHandler::~BasePcpHandler() {
|
||||
// Unregister ourselves from the FrameProcessors.
|
||||
NEARBY_LOGS(INFO) << "BasePcpHandler: going down; strategy="
|
||||
<< strategy_.GetName();
|
||||
endpoint_manager_->UnregisterFrameProcessor(V1Frame::CONNECTION_RESPONSE,
|
||||
handle_);
|
||||
|
||||
<< strategy_.GetName() << "; handle=" << handle_;
|
||||
DisconnectFromEndpointManager();
|
||||
// Stop all the ongoing Runnables (as gracefully as possible).
|
||||
NEARBY_LOGS(INFO) << "BasePcpHandler: bringing down executors; strategy="
|
||||
<< strategy_.GetName();
|
||||
@@ -47,8 +44,17 @@ BasePcpHandler::~BasePcpHandler() {
|
||||
<< strategy_.GetName();
|
||||
}
|
||||
|
||||
void BasePcpHandler::DisconnectFromEndpointManager() {
|
||||
if (stop_.Set(true)) return;
|
||||
NEARBY_LOGS(INFO) << "BasePcpHandler: Unregister from EPM; strategy="
|
||||
<< strategy_.GetName() << "; handle=" << handle_;
|
||||
// Unregister ourselves from EPM message dispatcher.
|
||||
endpoint_manager_->UnregisterFrameProcessor(V1Frame::CONNECTION_RESPONSE,
|
||||
handle_, true);
|
||||
}
|
||||
|
||||
Status BasePcpHandler::StartAdvertising(ClientProxy* client,
|
||||
const string& service_id,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const ConnectionRequestInfo& info) {
|
||||
Future<Status> response;
|
||||
@@ -85,7 +91,7 @@ void BasePcpHandler::StopAdvertising(ClientProxy* client) {
|
||||
}
|
||||
|
||||
Status BasePcpHandler::StartDiscovery(ClientProxy* client,
|
||||
const string& service_id,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const DiscoveryListener& listener) {
|
||||
Future<Status> response;
|
||||
@@ -122,7 +128,7 @@ void BasePcpHandler::StopDiscovery(ClientProxy* client) {
|
||||
WaitForLatch("stopDiscovery", &latch);
|
||||
}
|
||||
|
||||
void BasePcpHandler::WaitForLatch(const string& method_name,
|
||||
void BasePcpHandler::WaitForLatch(const std::string& method_name,
|
||||
CountDownLatch* latch) {
|
||||
Exception await_exception = latch->Await();
|
||||
if (!await_exception.Ok()) {
|
||||
@@ -132,7 +138,7 @@ void BasePcpHandler::WaitForLatch(const string& method_name,
|
||||
}
|
||||
}
|
||||
|
||||
Status BasePcpHandler::WaitForResult(const string& method_name,
|
||||
Status BasePcpHandler::WaitForResult(const std::string& method_name,
|
||||
std::int64_t client_id,
|
||||
Future<Status>* future) {
|
||||
if (!future) {
|
||||
@@ -156,9 +162,10 @@ void BasePcpHandler::RunOnPcpHandlerThread(Runnable runnable) {
|
||||
EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() {
|
||||
return {
|
||||
.on_success_cb =
|
||||
[this](const string& endpoint_id,
|
||||
[this](const std::string& endpoint_id,
|
||||
std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const string& auth_token, const ByteArray& raw_auth_token) {
|
||||
const std::string& auth_token,
|
||||
const ByteArray& raw_auth_token) {
|
||||
RunOnPcpHandlerThread([this, endpoint_id,
|
||||
raw_ukey2 = ukey2.release(), auth_token,
|
||||
raw_auth_token]() mutable {
|
||||
@@ -168,7 +175,7 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() {
|
||||
});
|
||||
},
|
||||
.on_failure_cb =
|
||||
[this](const string& endpoint_id, EndpointChannel* channel) {
|
||||
[this](const std::string& endpoint_id, EndpointChannel* channel) {
|
||||
RunOnPcpHandlerThread([this, endpoint_id, channel]() {
|
||||
OnEncryptionFailureRunnable(endpoint_id, channel);
|
||||
});
|
||||
@@ -177,8 +184,8 @@ EncryptionRunner::ResultListener BasePcpHandler::GetResultListener() {
|
||||
}
|
||||
|
||||
void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
const string& endpoint_id, std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const string& auth_token, const ByteArray& raw_auth_token) {
|
||||
const std::string& endpoint_id, std::unique_ptr<UKey2Handshake> ukey2,
|
||||
const std::string& auth_token, const ByteArray& raw_auth_token) {
|
||||
// Quick fail if we've been removed from pending connections while we were
|
||||
// busy running UKEY2.
|
||||
auto it = pending_connections_.find(endpoint_id);
|
||||
@@ -203,7 +210,8 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
|
||||
// Set ourselves up so that we receive all acceptance/rejection messages
|
||||
handle_ = endpoint_manager_->RegisterFrameProcessor(
|
||||
V1Frame::CONNECTION_RESPONSE, this);
|
||||
V1Frame::CONNECTION_RESPONSE,
|
||||
static_cast<EndpointManager::FrameProcessor*>(this));
|
||||
|
||||
// Now we register our endpoint so that we can listen for both sides to
|
||||
// accept.
|
||||
@@ -225,7 +233,7 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
}
|
||||
|
||||
void BasePcpHandler::OnEncryptionFailureRunnable(
|
||||
const string& endpoint_id, EndpointChannel* endpoint_channel) {
|
||||
const std::string& endpoint_id, EndpointChannel* endpoint_channel) {
|
||||
auto it = pending_connections_.find(endpoint_id);
|
||||
if (it == pending_connections_.end()) {
|
||||
NEARBY_LOG(INFO,
|
||||
@@ -256,7 +264,7 @@ void BasePcpHandler::OnEncryptionFailureRunnable(
|
||||
}
|
||||
|
||||
Status BasePcpHandler::RequestConnection(ClientProxy* client,
|
||||
const string& endpoint_id,
|
||||
const std::string& endpoint_id,
|
||||
const ConnectionRequestInfo& info) {
|
||||
Future<Status> result;
|
||||
RunOnPcpHandlerThread([this, client, &info, endpoint_id, &result]() {
|
||||
@@ -358,7 +366,7 @@ Status BasePcpHandler::RequestConnection(ClientProxy* client,
|
||||
}
|
||||
|
||||
BasePcpHandler::DiscoveredEndpoint* BasePcpHandler::GetDiscoveredEndpoint(
|
||||
const string& endpoint_id) {
|
||||
const std::string& endpoint_id) {
|
||||
auto it = discovered_endpoints_.find(endpoint_id);
|
||||
if (it == discovered_endpoints_.end()) {
|
||||
return nullptr;
|
||||
@@ -400,15 +408,15 @@ bool BasePcpHandler::CanReceiveIncomingConnection(ClientProxy* client) const {
|
||||
}
|
||||
|
||||
Exception BasePcpHandler::WriteConnectionRequestFrame(
|
||||
EndpointChannel* endpoint_channel, const string& local_endpoint_id,
|
||||
const string& local_endpoint_name, std::int32_t nonce,
|
||||
EndpointChannel* endpoint_channel, const std::string& local_endpoint_id,
|
||||
const std::string& local_endpoint_name, std::int32_t nonce,
|
||||
const std::vector<proto::connections::Medium>& supported_mediums) {
|
||||
return endpoint_channel->Write(parser::ForConnectionRequest(
|
||||
local_endpoint_id, local_endpoint_name, nonce, supported_mediums));
|
||||
}
|
||||
|
||||
void BasePcpHandler::ProcessPreConnectionInitiationFailure(
|
||||
const string& endpoint_id, EndpointChannel* channel, Status status,
|
||||
const std::string& endpoint_id, EndpointChannel* channel, Status status,
|
||||
Future<Status>* result) {
|
||||
if (channel != nullptr) {
|
||||
channel->Close();
|
||||
@@ -423,7 +431,7 @@ void BasePcpHandler::ProcessPreConnectionInitiationFailure(
|
||||
}
|
||||
|
||||
void BasePcpHandler::ProcessPreConnectionResultFailure(
|
||||
ClientProxy* client, const string& endpoint_id) {
|
||||
ClientProxy* client, const std::string& endpoint_id) {
|
||||
auto item = pending_connections_.extract(endpoint_id);
|
||||
endpoint_manager_->DiscardEndpoint(client, endpoint_id);
|
||||
client->OnConnectionRejected(endpoint_id, {Status::kError});
|
||||
@@ -448,7 +456,7 @@ bool BasePcpHandler::AutoUpgradeBandwidth() const {
|
||||
}
|
||||
|
||||
Status BasePcpHandler::AcceptConnection(
|
||||
ClientProxy* client, const string& endpoint_id,
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
const PayloadListener& payload_listener) {
|
||||
Future<Status> response;
|
||||
RunOnPcpHandlerThread(
|
||||
@@ -503,7 +511,7 @@ Status BasePcpHandler::AcceptConnection(
|
||||
}
|
||||
|
||||
Status BasePcpHandler::RejectConnection(ClientProxy* client,
|
||||
const string& endpoint_id) {
|
||||
const std::string& endpoint_id) {
|
||||
Future<Status> response;
|
||||
RunOnPcpHandlerThread([this, client, endpoint_id, &response]() {
|
||||
NEARBY_LOG(INFO, "RejectConnection: id=%s", endpoint_id.c_str());
|
||||
@@ -559,7 +567,7 @@ Status BasePcpHandler::RejectConnection(ClientProxy* client,
|
||||
//}
|
||||
|
||||
void BasePcpHandler::OnIncomingFrame(OfflineFrame& frame,
|
||||
const string& endpoint_id,
|
||||
const std::string& endpoint_id,
|
||||
ClientProxy* client,
|
||||
proto::connections::Medium medium) {
|
||||
CountDownLatch latch(1);
|
||||
@@ -595,8 +603,12 @@ void BasePcpHandler::OnIncomingFrame(OfflineFrame& frame,
|
||||
}
|
||||
|
||||
void BasePcpHandler::OnEndpointDisconnect(ClientProxy* client,
|
||||
const string& endpoint_id,
|
||||
const std::string& endpoint_id,
|
||||
CountDownLatch* barrier) {
|
||||
if (stop_.Get()) {
|
||||
if (barrier) barrier->CountDown();
|
||||
return;
|
||||
}
|
||||
RunOnPcpHandlerThread([this, client, endpoint_id, barrier]() {
|
||||
auto item = pending_alarms_.find(endpoint_id);
|
||||
if (item != pending_alarms_.end()) {
|
||||
@@ -702,7 +714,7 @@ bool BasePcpHandler::IsPreferred(
|
||||
}
|
||||
|
||||
Exception BasePcpHandler::OnIncomingConnection(
|
||||
ClientProxy* client, const string& remote_device_name,
|
||||
ClientProxy* client, const std::string& remote_device_name,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
proto::connections::Medium medium) {
|
||||
absl::Time start_time = SystemClock::ElapsedRealtime();
|
||||
@@ -797,7 +809,8 @@ Exception BasePcpHandler::OnIncomingConnection(
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
bool BasePcpHandler::BreakTie(ClientProxy* client, const string& endpoint_id,
|
||||
bool BasePcpHandler::BreakTie(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
std::int32_t incoming_nonce,
|
||||
EndpointChannel* endpoint_channel) {
|
||||
auto it = pending_connections_.find(endpoint_id);
|
||||
@@ -835,7 +848,7 @@ bool BasePcpHandler::BreakTie(ClientProxy* client, const string& endpoint_id,
|
||||
}
|
||||
|
||||
void BasePcpHandler::ProcessTieBreakLoss(
|
||||
ClientProxy* client, const string& endpoint_id,
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
BasePcpHandler::PendingConnectionInfo* info) {
|
||||
ProcessPreConnectionInitiationFailure(endpoint_id, info->channel.get(),
|
||||
{Status::kEndpointIoError},
|
||||
@@ -845,7 +858,7 @@ void BasePcpHandler::ProcessTieBreakLoss(
|
||||
}
|
||||
|
||||
void BasePcpHandler::InitiateBandwidthUpgrade(
|
||||
ClientProxy* client, const string& endpoint_id,
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
const std::vector<proto::connections::Medium>& supported_mediums) {
|
||||
// When we successfully connect to a remote endpoint and a bandwidth upgrade
|
||||
// medium has not yet been decided, we'll pick the highest bandwidth medium
|
||||
@@ -894,7 +907,7 @@ proto::connections::Medium BasePcpHandler::ChooseBestUpgradeMedium(
|
||||
}
|
||||
|
||||
void BasePcpHandler::EvaluateConnectionResult(ClientProxy* client,
|
||||
const string& endpoint_id,
|
||||
const std::string& endpoint_id,
|
||||
bool can_close_immediately) {
|
||||
// Short-circuit immediately if we're not in an actionable state yet. We will
|
||||
// be called again once the other side has made their decision.
|
||||
@@ -1032,12 +1045,12 @@ BasePcpHandler::PendingConnectionInfo::~PendingConnectionInfo() {
|
||||
}
|
||||
|
||||
void BasePcpHandler::PendingConnectionInfo::LocalEndpointAcceptedConnection(
|
||||
const string& endpoint_id, const PayloadListener& payload_listener) {
|
||||
const std::string& endpoint_id, const PayloadListener& payload_listener) {
|
||||
client->LocalEndpointAcceptedConnection(endpoint_id, payload_listener);
|
||||
}
|
||||
|
||||
void BasePcpHandler::PendingConnectionInfo::LocalEndpointRejectedConnection(
|
||||
const string& endpoint_id) {
|
||||
const std::string& endpoint_id) {
|
||||
client->LocalEndpointRejectedConnection(endpoint_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "core_v2/status.h"
|
||||
#include "proto/connections/offline_wire_formats.pb.h"
|
||||
#include "platform_v2/base/prng.h"
|
||||
#include "platform_v2/public/atomic_boolean.h"
|
||||
#include "platform_v2/public/atomic_reference.h"
|
||||
#include "platform_v2/public/cancelable_alarm.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
@@ -139,6 +140,7 @@ class BasePcpHandler : public PcpHandler,
|
||||
|
||||
Pcp GetPcp() const override { return pcp_; }
|
||||
Strategy GetStrategy() const override { return strategy_; }
|
||||
void DisconnectFromEndpointManager();
|
||||
|
||||
protected:
|
||||
// The result of a call to startAdvertisingImpl() or startDiscoveryImpl().
|
||||
@@ -423,6 +425,8 @@ class BasePcpHandler : public PcpHandler,
|
||||
// stops discovering because it might still be useful downstream of
|
||||
// discovery (eg: connection speed, etc.)
|
||||
ConnectionOptions discovery_options_;
|
||||
|
||||
AtomicBoolean stop_{false};
|
||||
Pcp pcp_;
|
||||
Strategy strategy_{PcpToStrategy(pcp_)};
|
||||
Prng prng_;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace {
|
||||
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::MockFunction;
|
||||
using ::testing::Return;
|
||||
@@ -125,8 +126,7 @@ class MockContext {
|
||||
|
||||
struct MockDiscoveredEndpoint : public MockPcpHandler::DiscoveredEndpoint {
|
||||
MockDiscoveredEndpoint(DiscoveredEndpoint endpoint, MockContext context)
|
||||
: DiscoveredEndpoint(std::move(endpoint)),
|
||||
context(std::move(context)) {}
|
||||
: DiscoveredEndpoint(std::move(endpoint)), context(std::move(context)) {}
|
||||
|
||||
MockContext context;
|
||||
};
|
||||
@@ -310,148 +310,144 @@ class BasePcpHandlerTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(BasePcpHandlerTest, ConstructorDestructorWorks) {
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, StartAdvertisingChangesState) {
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartAdvertising(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartAdvertising(&client, &pcp_handler);
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, StopAdvertisingChangesState) {
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartAdvertising(client.get(), pcp_handler.get());
|
||||
EXPECT_CALL(*pcp_handler, StopAdvertisingImpl(client.get())).Times(1);
|
||||
EXPECT_TRUE(client->IsAdvertising());
|
||||
pcp_handler->StopAdvertising(client.get());
|
||||
EXPECT_FALSE(client->IsAdvertising());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartAdvertising(&client, &pcp_handler);
|
||||
EXPECT_CALL(pcp_handler, StopAdvertisingImpl(&client)).Times(1);
|
||||
EXPECT_TRUE(client.IsAdvertising());
|
||||
pcp_handler.StopAdvertising(&client);
|
||||
EXPECT_FALSE(client.IsAdvertising());
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, StartDiscoveryChangesState) {
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, StopDiscoveryChangesState) {
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
EXPECT_CALL(*pcp_handler, StopDiscoveryImpl(client.get())).Times(1);
|
||||
EXPECT_TRUE(client->IsDiscovering());
|
||||
pcp_handler->StopDiscovery(client.get());
|
||||
EXPECT_FALSE(client->IsDiscovering());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
EXPECT_CALL(pcp_handler, StopDiscoveryImpl(&client)).Times(1);
|
||||
EXPECT_TRUE(client.IsDiscovering());
|
||||
pcp_handler.StopDiscovery(&client);
|
||||
EXPECT_FALSE(client.IsDiscovering());
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, RequestConnectionChangesState) {
|
||||
std::string endpoint_id{"1234"};
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
client.get(), pcp_handler.get());
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
|
||||
&pcp_handler);
|
||||
NEARBY_LOG(INFO, "RequestConnection complete");
|
||||
channel_b->Close();
|
||||
pcp_handler.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, AcceptConnectionChangesState) {
|
||||
std::string endpoint_id{"1234"};
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
client.get(), pcp_handler.get());
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
|
||||
&pcp_handler);
|
||||
NEARBY_LOG(INFO, "Attempting to accept connection: id=%s",
|
||||
endpoint_id.c_str());
|
||||
EXPECT_EQ(pcp_handler->AcceptConnection(client.get(), endpoint_id, {}),
|
||||
EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
|
||||
Status{Status::kSuccess});
|
||||
NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str());
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
|
||||
channel_b->Close();
|
||||
pcp_handler.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, RejectConnectionChangesState) {
|
||||
std::string endpoint_id{"1234"};
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_b = channel_pair.second;
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
client.get(), pcp_handler.get());
|
||||
NEARBY_LOG(INFO, "Attempting to reject connection: id=%s",
|
||||
endpoint_id.c_str());
|
||||
EXPECT_EQ(pcp_handler->RejectConnection(client.get(), endpoint_id),
|
||||
&client, &pcp_handler);
|
||||
NEARBY_LOGS(INFO) << "Attempting to reject connection: id=" << endpoint_id;
|
||||
EXPECT_EQ(pcp_handler.RejectConnection(&client, endpoint_id),
|
||||
Status{Status::kSuccess});
|
||||
NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str());
|
||||
NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
|
||||
channel_b->Close();
|
||||
pcp_handler.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, OnIncomingFrameChangesState) {
|
||||
std::string endpoint_id{"1234"};
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
ClientProxy client;
|
||||
EndpointChannelManager ecm;
|
||||
EndpointManager em(&ecm);
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
client.get(), pcp_handler.get());
|
||||
NEARBY_LOG(INFO, "Attempting to accept connection: id=%s",
|
||||
endpoint_id.c_str());
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(), &client,
|
||||
&pcp_handler);
|
||||
NEARBY_LOGS(INFO) << "Attempting to accept connection: id=" << endpoint_id;
|
||||
EXPECT_CALL(mock_connection_listener_.accepted_cb, Call).Times(1);
|
||||
EXPECT_EQ(pcp_handler->AcceptConnection(client.get(), endpoint_id, {}),
|
||||
EXPECT_CALL(mock_connection_listener_.disconnected_cb, Call)
|
||||
.Times(AtLeast(0));
|
||||
EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
|
||||
Status{Status::kSuccess});
|
||||
NEARBY_LOG(INFO, "Simulating remote accept: id=%s", endpoint_id.c_str());
|
||||
auto frame =
|
||||
parser::FromBytes(parser::ForConnectionResponse(Status::kSuccess));
|
||||
pcp_handler->OnIncomingFrame(frame.result(), endpoint_id, client.get(),
|
||||
Medium::BLE);
|
||||
NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str());
|
||||
pcp_handler.OnIncomingFrame(frame.result(), endpoint_id, &client,
|
||||
Medium::BLE);
|
||||
NEARBY_LOGS(INFO) << "Closing connection: id=" << endpoint_id;
|
||||
channel_b->Close();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, OnEndpointDisconnectChangesState) {
|
||||
std::string endpoint_id{"1234"};
|
||||
auto client = std::make_unique<ClientProxy>();
|
||||
auto ecm = std::make_unique<EndpointChannelManager>();
|
||||
auto em = std::make_unique<EndpointManager>(ecm.get());
|
||||
auto pcp_handler = std::make_unique<MockPcpHandler>(em.get(), ecm.get());
|
||||
StartDiscovery(client.get(), pcp_handler.get());
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_b = channel_pair.second;
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first), channel_b.get(),
|
||||
client.get(), pcp_handler.get());
|
||||
NEARBY_LOG(INFO, "Simulating disconnect event: id=%s", endpoint_id.c_str());
|
||||
CountDownLatch latch(1);
|
||||
pcp_handler->OnEndpointDisconnect(client.get(), endpoint_id, &latch);
|
||||
channel_b->Close();
|
||||
EXPECT_TRUE(latch.Await(absl::Milliseconds(5000)).result());
|
||||
pcp_handler.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
TEST_F(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) {
|
||||
@@ -464,15 +460,20 @@ TEST_F(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) {
|
||||
MockPcpHandler pcp_handler(&em, &ecm);
|
||||
StartDiscovery(&client, &pcp_handler);
|
||||
auto channel_pair = SetupConnection(pipe_a_, pipe_b_);
|
||||
auto& channel_a = channel_pair.first;
|
||||
auto& channel_b = channel_pair.second;
|
||||
RequestConnection(endpoint_id, std::move(channel_pair.first),
|
||||
channel_b.get(), &client, &pcp_handler, &destroyed_flag);
|
||||
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
|
||||
EXPECT_CALL(*channel_b, CloseImpl).Times(1);
|
||||
RequestConnection(endpoint_id, std::move(channel_a), channel_b.get(),
|
||||
&client, &pcp_handler, &destroyed_flag);
|
||||
NEARBY_LOG(INFO, "Attempting to accept connection: id=%s",
|
||||
endpoint_id.c_str());
|
||||
EXPECT_EQ(pcp_handler.AcceptConnection(&client, endpoint_id, {}),
|
||||
Status{Status::kSuccess});
|
||||
EXPECT_CALL(mock_connection_listener_.rejected_cb, Call).Times(AtLeast(0));
|
||||
NEARBY_LOG(INFO, "Closing connection: id=%s", endpoint_id.c_str());
|
||||
channel_b->Close();
|
||||
pcp_handler.DisconnectFromEndpointManager();
|
||||
}
|
||||
EXPECT_TRUE(destroyed_flag.load());
|
||||
}
|
||||
|
||||
@@ -200,6 +200,7 @@ EndpointManager::EndpointManager(EndpointChannelManager* manager)
|
||||
: channel_manager_(manager) {}
|
||||
|
||||
EndpointManager::~EndpointManager() {
|
||||
NEARBY_LOG(INFO, "EndpointManager going down");
|
||||
CountDownLatch latch(1);
|
||||
RunOnEndpointManagerThread([this, &latch]() {
|
||||
NEARBY_LOG(INFO, "Bringing down endpoints");
|
||||
@@ -208,10 +209,8 @@ EndpointManager::~EndpointManager() {
|
||||
EndpointState& state = item.second;
|
||||
// This will close the channel; all workers will sense that and
|
||||
// terminate.
|
||||
NEARBY_LOG(INFO, "Bringing down endpoint channels: id=%s",
|
||||
endpoint_id.c_str());
|
||||
WaitForEndpointDisconnectionProcessing(state.client, endpoint_id);
|
||||
channel_manager_->UnregisterChannelForEndpoint(endpoint_id);
|
||||
state.barrier.Await();
|
||||
}
|
||||
latch.CountDown();
|
||||
});
|
||||
@@ -236,9 +235,12 @@ EndpointManager::RegisterFrameProcessor(
|
||||
RunOnEndpointManagerThread([this, frame_type, &latch, processor]() {
|
||||
auto it = frame_processors_.find(frame_type);
|
||||
if (it != frame_processors_.end()) {
|
||||
NEARBY_LOG(INFO, "Frame processor found, updated; type=%d", frame_type);
|
||||
NEARBY_LOGS(INFO) << "Frame processor found: updated; type=" << frame_type
|
||||
<< "; processor=" << processor << "; self=" << this;
|
||||
it->second = processor;
|
||||
} else {
|
||||
NEARBY_LOGS(INFO) << "Frame processor added; type=" << frame_type
|
||||
<< "; processor=" << processor << "; self=" << this;
|
||||
frame_processors_.emplace(frame_type, processor);
|
||||
}
|
||||
latch.CountDown();
|
||||
@@ -249,14 +251,22 @@ EndpointManager::RegisterFrameProcessor(
|
||||
|
||||
void EndpointManager::UnregisterFrameProcessor(V1Frame::FrameType frame_type,
|
||||
const void* handle, bool sync) {
|
||||
NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [enter]: handle=" << handle;
|
||||
if (handle == nullptr) return;
|
||||
CountDownLatch latch(1);
|
||||
RunOnEndpointManagerThread([this, frame_type, handle, &latch, sync]() {
|
||||
auto it = frame_processors_.find(frame_type);
|
||||
if (it == frame_processors_.end()) return;
|
||||
if (it == frame_processors_.end()) {
|
||||
NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [not found]: handle="
|
||||
<< handle;
|
||||
if (sync) latch.CountDown();
|
||||
return;
|
||||
}
|
||||
NEARBY_LOGS(INFO) << "UnregisterFrameProcessor [found]: handle=" << handle;
|
||||
if (it->second == handle) {
|
||||
frame_processors_.erase(it);
|
||||
NEARBY_LOG(INFO, "Unregistered: type=%d", frame_type);
|
||||
NEARBY_LOGS(INFO) << "Unregistered: type=" << frame_type
|
||||
<< "; processor=" << handle << "; self=" << this;
|
||||
} else {
|
||||
NEARBY_LOG(INFO,
|
||||
"Failed to unregister: type=%d; handle mismatch: passed=%p, "
|
||||
@@ -267,7 +277,8 @@ void EndpointManager::UnregisterFrameProcessor(V1Frame::FrameType frame_type,
|
||||
});
|
||||
if (sync) {
|
||||
latch.Await();
|
||||
NEARBY_LOG(INFO, "Unregistered: [sync done] type=%d", frame_type);
|
||||
NEARBY_LOGS(INFO) << "Unregistered [sync done]: type=" << frame_type
|
||||
<< "; processor=" << handle << "; self=" << this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,10 +305,13 @@ void EndpointManager::EnsureWorkersTerminated(const std::string& endpoint_id) {
|
||||
// If another instance of data and keep-alive handlers is running, it will
|
||||
// terminate soon; we should block until it happens.
|
||||
EndpointState& endpoint_state = item->second;
|
||||
NEARBY_LOG(INFO, "Waiting for workers to terminate for endpoint_id='%s'",
|
||||
endpoint_id.c_str());
|
||||
NEARBY_LOGS(INFO) << "Waiting for workers to terminate for id: "
|
||||
<< endpoint_id;
|
||||
endpoint_state.barrier.Await();
|
||||
endpoints_.erase(item);
|
||||
NEARBY_LOGS(INFO) << "Workers terminated for id: " << endpoint_id;
|
||||
} else {
|
||||
NEARBY_LOGS(INFO) << "EndpointState not found for id: " << endpoint_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,8 +392,8 @@ void EndpointManager::UnregisterEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id) {
|
||||
CountDownLatch latch(1);
|
||||
RunOnEndpointManagerThread([this, client, endpoint_id, &latch]() {
|
||||
channel_manager_->UnregisterChannelForEndpoint(endpoint_id);
|
||||
RemoveEndpoint(client, endpoint_id, /*notify=*/false);
|
||||
RemoveEndpoint(client, endpoint_id,
|
||||
client->IsConnectedToEndpoint(endpoint_id));
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
@@ -391,7 +405,6 @@ void EndpointManager::UnregisterEndpoint(ClientProxy* client,
|
||||
void EndpointManager::DiscardEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id) {
|
||||
RunOnEndpointManagerThread([this, client, endpoint_id]() {
|
||||
channel_manager_->UnregisterChannelForEndpoint(endpoint_id);
|
||||
RemoveEndpoint(client, endpoint_id,
|
||||
/*notify=*/
|
||||
client->IsConnectedToEndpoint(endpoint_id));
|
||||
@@ -435,25 +448,50 @@ void EndpointManager::RemoveEndpoint(ClientProxy* client,
|
||||
// should be no further interactions with the endpoint.
|
||||
// (See b/37352254 for history)
|
||||
WaitForEndpointDisconnectionProcessing(client, endpoint_id);
|
||||
EnsureWorkersTerminated(endpoint_id);
|
||||
|
||||
client->OnDisconnected(endpoint_id, notify);
|
||||
NEARBY_LOG(INFO, "Removed endpoint; id=%s",
|
||||
endpoint_id.c_str());
|
||||
NEARBY_LOG(INFO, "Removed endpoint; id=%s", endpoint_id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// @EndpointManagerThread
|
||||
void EndpointManager::WaitForEndpointDisconnectionProcessing(
|
||||
ClientProxy* client, const std::string& endpoint_id) {
|
||||
CountDownLatch barrier(frame_processors_.size());
|
||||
NEARBY_LOGS(INFO) << "Wait: client=" << client << "; id=" << endpoint_id;
|
||||
auto total_size = frame_processors_.size();
|
||||
NEARBY_LOGS(INFO) << "Total frame processors: " << total_size;
|
||||
if (!total_size) return;
|
||||
CountDownLatch barrier(total_size);
|
||||
|
||||
int valid = 0;
|
||||
for (auto& item : frame_processors_) {
|
||||
auto& processor = item.second;
|
||||
processor->OnEndpointDisconnect(client, endpoint_id, &barrier);
|
||||
auto* processor = item.second;
|
||||
NEARBY_LOGS(INFO) << "processor=" << processor << "; type=" << item.first;
|
||||
if (processor) {
|
||||
valid++;
|
||||
processor->OnEndpointDisconnect(client, endpoint_id, &barrier);
|
||||
} else {
|
||||
barrier.CountDown();
|
||||
}
|
||||
}
|
||||
|
||||
barrier.Await(kProcessEndpointDisconnectionTimeout);
|
||||
if (!valid) {
|
||||
NEARBY_LOGS(INFO) << "No valid frame processors.";
|
||||
return;
|
||||
} else {
|
||||
NEARBY_LOGS(INFO) << "Valid frame processors: " << valid;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Waiting for " << valid
|
||||
<< " frame processors to disconnect from: " << endpoint_id;
|
||||
if (!barrier.Await(kProcessEndpointDisconnectionTimeout).result()) {
|
||||
NEARBY_LOGS(INFO) << "Failed to disconnect frame processors from: "
|
||||
<< endpoint_id;
|
||||
} else {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Finished waiting for frame processors to disconnect from: "
|
||||
<< endpoint_id;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> EndpointManager::SendTransferFrameBytes(
|
||||
|
||||
@@ -138,11 +138,11 @@ class WebRtc {
|
||||
std::vector<::location::nearby::mediums::IceCandidate>
|
||||
pending_local_ice_candidates_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
WebRtcMedium medium_;
|
||||
std::unique_ptr<ConnectionFlow> connection_flow_;
|
||||
std::unique_ptr<WebRtcSignalingMessenger> signaling_messenger_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
WebRtcSocketWrapper socket_ ABSL_GUARDED_BY(mutex_);
|
||||
WebRtcMedium medium_;
|
||||
|
||||
SingleThreadExecutor single_thread_executor_;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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 "core_v2/internal/offline_service_controller.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
OfflineServiceController::~OfflineServiceController() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void OfflineServiceController::Stop() {
|
||||
if (stop_.Set(true)) return;
|
||||
payload_manager_.DisconnectFromEndpointManager();
|
||||
pcp_manager_.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
Status OfflineServiceController::StartAdvertising(
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const ConnectionOptions& options, const ConnectionRequestInfo& info) {
|
||||
return pcp_manager_.StartAdvertising(client, service_id, options, info);
|
||||
}
|
||||
|
||||
void OfflineServiceController::StopAdvertising(ClientProxy* client) {
|
||||
pcp_manager_.StopAdvertising(client);
|
||||
}
|
||||
|
||||
Status OfflineServiceController::StartDiscovery(
|
||||
ClientProxy* client, const std::string& service_id,
|
||||
const ConnectionOptions& options, const DiscoveryListener& listener) {
|
||||
return pcp_manager_.StartDiscovery(client, service_id, options, listener);
|
||||
}
|
||||
|
||||
void OfflineServiceController::StopDiscovery(ClientProxy* client) {
|
||||
pcp_manager_.StopDiscovery(client);
|
||||
}
|
||||
|
||||
Status OfflineServiceController::RequestConnection(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
const ConnectionRequestInfo& info) {
|
||||
return pcp_manager_.RequestConnection(client, endpoint_id, info);
|
||||
}
|
||||
|
||||
Status OfflineServiceController::AcceptConnection(
|
||||
ClientProxy* client, const std::string& endpoint_id,
|
||||
const PayloadListener& listener) {
|
||||
return pcp_manager_.AcceptConnection(client, endpoint_id, listener);
|
||||
}
|
||||
|
||||
Status OfflineServiceController::RejectConnection(
|
||||
ClientProxy* client, const std::string& endpoint_id) {
|
||||
return pcp_manager_.RejectConnection(client, endpoint_id);
|
||||
}
|
||||
|
||||
void OfflineServiceController::InitiateBandwidthUpgrade(
|
||||
ClientProxy* client, const std::string& endpoint_id) {
|
||||
// TODO(apolyudov): implement.
|
||||
}
|
||||
|
||||
void OfflineServiceController::SendPayload(
|
||||
ClientProxy* client, const std::vector<std::string>& endpoint_ids,
|
||||
Payload payload) {
|
||||
payload_manager_.SendPayload(client, endpoint_ids, std::move(payload));
|
||||
}
|
||||
|
||||
Status OfflineServiceController::CancelPayload(ClientProxy* client,
|
||||
std::int64_t payload_id) {
|
||||
return payload_manager_.CancelPayload(client, payload_id);
|
||||
}
|
||||
|
||||
void OfflineServiceController::DisconnectFromEndpoint(
|
||||
ClientProxy* client, const std::string& endpoint_id) {
|
||||
endpoint_manager_.UnregisterEndpoint(client, endpoint_id);
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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 CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
|
||||
#define CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core_v2/internal/client_proxy.h"
|
||||
#include "core_v2/internal/endpoint_channel_manager.h"
|
||||
#include "core_v2/internal/endpoint_manager.h"
|
||||
#include "core_v2/internal/mediums/mediums.h"
|
||||
#include "core_v2/internal/payload_manager.h"
|
||||
#include "core_v2/internal/pcp_manager.h"
|
||||
#include "core_v2/internal/service_controller.h"
|
||||
#include "core_v2/listeners.h"
|
||||
#include "core_v2/options.h"
|
||||
#include "core_v2/payload.h"
|
||||
#include "core_v2/status.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
class OfflineServiceController : public ServiceController {
|
||||
public:
|
||||
OfflineServiceController() = default;
|
||||
~OfflineServiceController() override;
|
||||
|
||||
Status StartAdvertising(ClientProxy* client,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const ConnectionRequestInfo& info) override;
|
||||
void StopAdvertising(ClientProxy* client) override;
|
||||
|
||||
Status StartDiscovery(ClientProxy* client,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const DiscoveryListener& listener) override;
|
||||
void StopDiscovery(ClientProxy* client) override;
|
||||
|
||||
Status RequestConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
const ConnectionRequestInfo& info) override;
|
||||
Status AcceptConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
const PayloadListener& listener) override;
|
||||
Status RejectConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id) override;
|
||||
|
||||
void InitiateBandwidthUpgrade(ClientProxy* client,
|
||||
const std::string& endpoint_id) override;
|
||||
|
||||
void SendPayload(ClientProxy* client,
|
||||
const std::vector<std::string>& endpoint_ids,
|
||||
Payload payload) override;
|
||||
Status CancelPayload(ClientProxy* client,
|
||||
Payload::Id payload_id) override;
|
||||
|
||||
void DisconnectFromEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id) override;
|
||||
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
// Note that the order of declaration of these is crucial, because we depend
|
||||
// on the destructors running (strictly) in the reverse order; a deviation
|
||||
// from that will lead to crashes at runtime.
|
||||
AtomicBoolean stop_{false};
|
||||
Mediums mediums_;
|
||||
EndpointChannelManager channel_manager_;
|
||||
EndpointManager endpoint_manager_{&channel_manager_};
|
||||
PayloadManager payload_manager_{endpoint_manager_};
|
||||
PcpManager pcp_manager_{mediums_, channel_manager_, endpoint_manager_};
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_V2_INTERNAL_OFFLINE_SERVICE_CONTROLLER_H_
|
||||
@@ -0,0 +1,335 @@
|
||||
// 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 "core_v2/internal/offline_service_controller.h"
|
||||
|
||||
#include "core_v2/internal/offline_simulation_user.h"
|
||||
#include "platform_v2/base/medium_environment.h"
|
||||
#include "platform_v2/base/output_stream.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
#include "platform_v2/public/logging.h"
|
||||
#include "platform_v2/public/pipe.h"
|
||||
#include "platform_v2/public/system_clock.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace {
|
||||
|
||||
using ::testing::Eq;
|
||||
|
||||
constexpr absl::string_view kServiceId = "service-id";
|
||||
constexpr absl::string_view kDeviceA = "device-a";
|
||||
constexpr absl::string_view kDeviceB = "device-b";
|
||||
constexpr absl::string_view kMessage = "message";
|
||||
constexpr absl::Duration kProgressTimeout = absl::Milliseconds(1000);
|
||||
constexpr absl::Duration kDefaultTimeout = absl::Milliseconds(1000);
|
||||
constexpr absl::Duration kDisconnectTimeout = absl::Milliseconds(15000);
|
||||
|
||||
class OfflineServiceControllerTest : public ::testing::Test {
|
||||
protected:
|
||||
OfflineServiceControllerTest() { env_.Stop(); }
|
||||
|
||||
bool SetupConnection(OfflineSimulationUser& user_a,
|
||||
OfflineSimulationUser& user_b) {
|
||||
user_a.StartAdvertising(std::string(kServiceId), &connect_latch_);
|
||||
user_b.StartDiscovery(std::string(kServiceId), &discover_latch_);
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_EQ(user_b.GetDiscovered().service_id, kServiceId);
|
||||
EXPECT_EQ(user_b.GetDiscovered().endpoint_name, user_a.GetName());
|
||||
EXPECT_FALSE(user_b.GetDiscovered().endpoint_id.empty());
|
||||
NEARBY_LOG(INFO, "EP-B: [discovered] %s",
|
||||
user_b.GetDiscovered().endpoint_id.c_str());
|
||||
user_b.RequestConnection(&connect_latch_);
|
||||
EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_FALSE(user_a.GetDiscovered().endpoint_id.empty());
|
||||
NEARBY_LOG(INFO, "EP-A: [discovered] %s",
|
||||
user_a.GetDiscovered().endpoint_id.c_str());
|
||||
NEARBY_LOG(INFO, "Both users discovered their peers.");
|
||||
user_a.AcceptConnection(&accept_latch_);
|
||||
user_b.AcceptConnection(&accept_latch_);
|
||||
EXPECT_TRUE(accept_latch_.Await(kDefaultTimeout).result());
|
||||
NEARBY_LOG(INFO, "Both users reached connected state.");
|
||||
return user_a.IsConnected() && user_b.IsConnected();
|
||||
}
|
||||
|
||||
CountDownLatch discover_latch_{1};
|
||||
CountDownLatch connect_latch_{2};
|
||||
CountDownLatch accept_latch_{2};
|
||||
CountDownLatch payload_latch_{1};
|
||||
MediumEnvironment& env_ = MediumEnvironment::Instance();
|
||||
};
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanCreateOne) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanCreateMany) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanStartAdvertising) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_FALSE(user_a.IsAdvertising());
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_a.IsAdvertising());
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanStartDiscoveryBeforeAdvertising) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_FALSE(user_b.IsDiscovering());
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_b.IsDiscovering());
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanStartDiscoveryAfterAdvertising) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_FALSE(user_b.IsDiscovering());
|
||||
EXPECT_FALSE(user_b.IsAdvertising());
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_a.IsAdvertising());
|
||||
EXPECT_TRUE(user_b.IsDiscovering());
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanStopAdvertising) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_FALSE(user_a.IsAdvertising());
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_a.IsAdvertising());
|
||||
user_a.StopAdvertising();
|
||||
EXPECT_FALSE(user_a.IsAdvertising());
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_b.IsDiscovering());
|
||||
EXPECT_FALSE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanStopDiscovery) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_FALSE(user_b.IsDiscovering());
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(user_b.IsDiscovering());
|
||||
user_b.StopDiscovery();
|
||||
EXPECT_FALSE(user_b.IsDiscovering());
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), nullptr),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_FALSE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanConnect) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_THAT(user_b.RequestConnection(&connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanAcceptConnection) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_THAT(user_b.RequestConnection(&connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_THAT(user_a.AcceptConnection(&accept_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_THAT(user_b.AcceptConnection(&accept_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(accept_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_TRUE(user_a.IsConnected());
|
||||
EXPECT_TRUE(user_b.IsConnected());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanRejectConnection) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
CountDownLatch reject_latch(1);
|
||||
EXPECT_THAT(user_a.StartAdvertising(std::string(kServiceId), &connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_THAT(user_b.StartDiscovery(std::string(kServiceId), &discover_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(discover_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_THAT(user_b.RequestConnection(&connect_latch_),
|
||||
Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(connect_latch_.Await(kDefaultTimeout).result());
|
||||
user_a.ExpectRejectedConnection(reject_latch);
|
||||
EXPECT_THAT(user_b.RejectConnection(nullptr), Eq(Status{Status::kSuccess}));
|
||||
EXPECT_TRUE(reject_latch.Await(kDefaultTimeout).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanSendBytePayload) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
ASSERT_TRUE(SetupConnection(user_a, user_b));
|
||||
ByteArray message(std::string{kMessage});
|
||||
user_a.SendPayload(Payload(message));
|
||||
user_b.ExpectPayload(payload_latch_);
|
||||
EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_EQ(user_b.GetPayload().AsBytes(), message);
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanSendStreamPayload) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
ASSERT_TRUE(SetupConnection(user_a, user_b));
|
||||
ByteArray message(std::string{kMessage});
|
||||
auto pipe = std::make_shared<Pipe>();
|
||||
OutputStream& tx = pipe->GetOutputStream();
|
||||
user_a.SendPayload(Payload([pipe]() -> InputStream& {
|
||||
return pipe->GetInputStream(); // NOLINT
|
||||
}));
|
||||
user_b.ExpectPayload(payload_latch_);
|
||||
tx.Write(message);
|
||||
EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_NE(user_b.GetPayload().AsStream(), nullptr);
|
||||
InputStream& rx = *user_b.GetPayload().AsStream();
|
||||
ASSERT_TRUE(user_b.WaitForProgress(
|
||||
[size = message.size()](const PayloadProgressInfo& info) -> bool {
|
||||
return info.bytes_transferred >= size;
|
||||
},
|
||||
kProgressTimeout));
|
||||
EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message);
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanCancelStreamPayload) {
|
||||
env_.Start();
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
ASSERT_TRUE(SetupConnection(user_a, user_b));
|
||||
ByteArray message(std::string{kMessage});
|
||||
auto pipe = std::make_shared<Pipe>();
|
||||
OutputStream& tx = pipe->GetOutputStream();
|
||||
user_a.SendPayload(Payload([pipe]() -> InputStream& {
|
||||
return pipe->GetInputStream(); // NOLINT
|
||||
}));
|
||||
user_b.ExpectPayload(payload_latch_);
|
||||
tx.Write(message);
|
||||
EXPECT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
|
||||
EXPECT_NE(user_b.GetPayload().AsStream(), nullptr);
|
||||
InputStream& rx = *user_b.GetPayload().AsStream();
|
||||
ASSERT_TRUE(user_b.WaitForProgress(
|
||||
[size = message.size()](const PayloadProgressInfo& info) -> bool {
|
||||
return info.bytes_transferred >= size;
|
||||
},
|
||||
kProgressTimeout));
|
||||
EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message);
|
||||
user_b.CancelPayload();
|
||||
int count = 0;
|
||||
while (true) {
|
||||
count++;
|
||||
if (!tx.Write(message).Ok()) break;
|
||||
SystemClock::Sleep(kDefaultTimeout);
|
||||
}
|
||||
EXPECT_TRUE(user_a.WaitForProgress(
|
||||
[](const PayloadProgressInfo& info) -> bool {
|
||||
return info.status == PayloadProgressInfo::Status::kCanceled;
|
||||
},
|
||||
kProgressTimeout));
|
||||
EXPECT_LT(count, 10);
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(OfflineServiceControllerTest, CanDisconnect) {
|
||||
env_.Start();
|
||||
CountDownLatch disconnect_latch(1);
|
||||
OfflineSimulationUser user_a(kDeviceA);
|
||||
OfflineSimulationUser user_b(kDeviceB);
|
||||
ASSERT_TRUE(SetupConnection(user_a, user_b));
|
||||
NEARBY_LOGS(INFO) << "Disconnecting";
|
||||
user_b.ExpectDisconnect(disconnect_latch);
|
||||
user_b.Disconnect();
|
||||
EXPECT_TRUE(disconnect_latch.Await(kDisconnectTimeout).result());
|
||||
NEARBY_LOGS(INFO) << "Disconnected";
|
||||
EXPECT_FALSE(user_b.IsConnected());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,191 @@
|
||||
// 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 "core_v2/internal/offline_simulation_user.h"
|
||||
|
||||
#include "core_v2/listeners.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
#include "platform_v2/public/system_clock.h"
|
||||
#include "absl/functional/bind_front.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
void OfflineSimulationUser::OnConnectionInitiated(
|
||||
const std::string& endpoint_id, const ConnectionResponseInfo& info,
|
||||
bool is_outgoing) {
|
||||
if (is_outgoing) {
|
||||
NEARBY_LOG(INFO, "RequestConnection: initiated_cb called");
|
||||
} else {
|
||||
NEARBY_LOG(INFO, "StartAdvertising: initiated_cb called");
|
||||
discovered_ = DiscoveredInfo{
|
||||
.endpoint_id = endpoint_id,
|
||||
.endpoint_name = name_,
|
||||
.service_id = service_id_,
|
||||
};
|
||||
}
|
||||
if (initiated_latch_) initiated_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnConnectionAccepted(
|
||||
const std::string& endpoint_id) {
|
||||
if (accept_latch_) accept_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnConnectionRejected(const std::string& endpoint_id,
|
||||
Status status) {
|
||||
if (reject_latch_) reject_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnEndpointDisconnect(
|
||||
const std::string& endpoint_id) {
|
||||
NEARBY_LOGS(INFO) << "OnEndpointDisconnect: self=" << this
|
||||
<< "; id=" << endpoint_id;
|
||||
if (disconnect_latch_) disconnect_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnEndpointFound(const std::string& endpoint_id,
|
||||
const std::string& endpoint_name,
|
||||
const std::string& service_id) {
|
||||
NEARBY_LOG(INFO, "Device discovered: id=%s", endpoint_id.c_str());
|
||||
discovered_ = DiscoveredInfo{
|
||||
.endpoint_id = endpoint_id,
|
||||
.endpoint_name = endpoint_name,
|
||||
.service_id = service_id,
|
||||
};
|
||||
if (found_latch_) found_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnEndpointLost(const std::string& endpoint_id) {
|
||||
if (lost_latch_) lost_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnPayload(const std::string& endpoint_id,
|
||||
Payload payload) {
|
||||
payload_ = std::move(payload);
|
||||
if (payload_latch_) payload_latch_->CountDown();
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::OnPayloadProgress(const std::string& endpoint_id,
|
||||
const PayloadProgressInfo& info) {
|
||||
MutexLock lock(&progress_mutex_);
|
||||
progress_info_ = info;
|
||||
if (future_ && predicate_ && predicate_(info)) future_->Set(true);
|
||||
}
|
||||
|
||||
bool OfflineSimulationUser::WaitForProgress(
|
||||
std::function<bool(const PayloadProgressInfo&)> predicate,
|
||||
absl::Duration timeout) {
|
||||
Future<bool> future;
|
||||
{
|
||||
MutexLock lock(&progress_mutex_);
|
||||
if (predicate(progress_info_)) return true;
|
||||
future_ = &future;
|
||||
predicate_ = std::move(predicate);
|
||||
}
|
||||
auto response = future.Get(timeout);
|
||||
{
|
||||
MutexLock lock(&progress_mutex_);
|
||||
future_ = nullptr;
|
||||
predicate_ = nullptr;
|
||||
}
|
||||
return response.ok() && response.result();
|
||||
}
|
||||
|
||||
Status OfflineSimulationUser::StartAdvertising(const std::string& service_id,
|
||||
CountDownLatch* latch) {
|
||||
initiated_latch_ = latch;
|
||||
service_id_ = service_id;
|
||||
ConnectionListener listener = {
|
||||
.initiated_cb =
|
||||
std::bind(&OfflineSimulationUser::OnConnectionInitiated, this,
|
||||
std::placeholders::_1, std::placeholders::_2, false),
|
||||
.accepted_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnConnectionAccepted, this),
|
||||
.rejected_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnConnectionRejected, this),
|
||||
.disconnected_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnEndpointDisconnect, this),
|
||||
};
|
||||
return ctrl_.StartAdvertising(&client_, service_id_, options_,
|
||||
{
|
||||
.name = name_,
|
||||
.listener = std::move(listener),
|
||||
});
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::StopAdvertising() {
|
||||
ctrl_.StopAdvertising(&client_);
|
||||
}
|
||||
|
||||
Status OfflineSimulationUser::StartDiscovery(const std::string& service_id,
|
||||
CountDownLatch* latch) {
|
||||
found_latch_ = latch;
|
||||
DiscoveryListener listener = {
|
||||
.endpoint_found_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnEndpointFound, this),
|
||||
.endpoint_lost_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnEndpointLost, this),
|
||||
};
|
||||
return ctrl_.StartDiscovery(&client_, service_id, options_,
|
||||
std::move(listener));
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::StopDiscovery() { ctrl_.StopDiscovery(&client_); }
|
||||
|
||||
Status OfflineSimulationUser::RequestConnection(CountDownLatch* latch) {
|
||||
initiated_latch_ = latch;
|
||||
ConnectionListener listener = {
|
||||
.initiated_cb =
|
||||
std::bind(&OfflineSimulationUser::OnConnectionInitiated, this,
|
||||
std::placeholders::_1, std::placeholders::_2, true),
|
||||
.accepted_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnConnectionAccepted, this),
|
||||
.rejected_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnConnectionRejected, this),
|
||||
.disconnected_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnEndpointDisconnect, this),
|
||||
};
|
||||
return ctrl_.RequestConnection(&client_, discovered_.endpoint_id,
|
||||
{
|
||||
.name = discovered_.endpoint_name,
|
||||
.listener = std::move(listener),
|
||||
});
|
||||
}
|
||||
|
||||
Status OfflineSimulationUser::AcceptConnection(CountDownLatch* latch) {
|
||||
accept_latch_ = latch;
|
||||
PayloadListener listener = {
|
||||
.payload_cb = absl::bind_front(&OfflineSimulationUser::OnPayload, this),
|
||||
.payload_progress_cb =
|
||||
absl::bind_front(&OfflineSimulationUser::OnPayloadProgress, this),
|
||||
};
|
||||
return ctrl_.AcceptConnection(&client_, discovered_.endpoint_id,
|
||||
std::move(listener));
|
||||
}
|
||||
|
||||
Status OfflineSimulationUser::RejectConnection(CountDownLatch* latch) {
|
||||
reject_latch_ = latch;
|
||||
return ctrl_.RejectConnection(&client_, discovered_.endpoint_id);
|
||||
}
|
||||
|
||||
void OfflineSimulationUser::Disconnect() {
|
||||
NEARBY_LOGS(INFO) << "Disconnecting from id=" << discovered_.endpoint_id;
|
||||
ctrl_.DisconnectFromEndpoint(&client_, discovered_.endpoint_id);
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,175 @@
|
||||
// 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 CORE_V2_INTERNAL_OFFLINE_SIMULATION_USER_H_
|
||||
#define CORE_V2_INTERNAL_OFFLINE_SIMULATION_USER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "core_v2/internal/client_proxy.h"
|
||||
#include "core_v2/internal/offline_service_controller.h"
|
||||
#include "platform_v2/public/atomic_boolean.h"
|
||||
#include "platform_v2/public/condition_variable.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
#include "platform_v2/public/future.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
// Test-only class to help run end-to-end simulations for nearby connections
|
||||
// protocol.
|
||||
//
|
||||
// This is a "standalone" version of PcpManager. It can run independently,
|
||||
// provided MediumEnvironment has adequate support for all medium types in use.
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
class OfflineSimulationUser {
|
||||
public:
|
||||
struct DiscoveredInfo {
|
||||
std::string endpoint_id;
|
||||
std::string endpoint_name;
|
||||
std::string service_id;
|
||||
|
||||
bool Empty() const { return endpoint_id.empty(); }
|
||||
void Clear() { endpoint_id.clear(); }
|
||||
};
|
||||
|
||||
explicit OfflineSimulationUser(absl::string_view device_name)
|
||||
: name_(device_name) {}
|
||||
virtual ~OfflineSimulationUser() = default;
|
||||
|
||||
// Calls PcpManager::StartAdvertising().
|
||||
// If latch is provided, will call latch->CountDown() in the initiated_cb
|
||||
// callback.
|
||||
Status StartAdvertising(const std::string& service_id, CountDownLatch* latch);
|
||||
|
||||
// Calls PcpManager::StopAdvertising().
|
||||
void StopAdvertising();
|
||||
|
||||
// Calls PcpManager::StartDiscovery().
|
||||
// If latch is provided, will call latch->CountDown() in the endpoint_found_cb
|
||||
// callback.
|
||||
Status StartDiscovery(const std::string& service_id, CountDownLatch* latch);
|
||||
|
||||
// Calls PcpManager::StopDiscovery().
|
||||
void StopDiscovery();
|
||||
|
||||
// Calls PcpManager::RequestConnection().
|
||||
// If latch is provided, latch->CountDown() will be called in the initiated_cb
|
||||
// callback.
|
||||
Status RequestConnection(CountDownLatch* latch);
|
||||
|
||||
// Calls PcpManager::AcceptConnection.
|
||||
// If latch is provided, latch->CountDown() will be called in the accepted_cb
|
||||
// callback.
|
||||
Status AcceptConnection(CountDownLatch* latch);
|
||||
|
||||
// Calls PcpManager::RejectConnection.
|
||||
// If latch is provided, latch->CountDown() will be called in the rejected_cb
|
||||
// callback.
|
||||
Status RejectConnection(CountDownLatch* latch);
|
||||
|
||||
// Unlike acceptance, rejection does not have to be mutual, in order to work.
|
||||
// This method will allow to synchronize on the remote rejection, without
|
||||
// performing a local rejection.
|
||||
// latch.CountDown() will be called in the rejected_cb callback.
|
||||
void ExpectRejectedConnection(CountDownLatch& latch) {
|
||||
reject_latch_ = &latch;
|
||||
}
|
||||
|
||||
void ExpectPayload(CountDownLatch& latch) { payload_latch_ = &latch; }
|
||||
void ExpectDisconnect(CountDownLatch& latch) { disconnect_latch_ = &latch; }
|
||||
|
||||
const DiscoveredInfo& GetDiscovered() const { return discovered_; }
|
||||
std::string GetName() const { return name_; }
|
||||
|
||||
bool WaitForProgress(std::function<bool(const PayloadProgressInfo&)> pred,
|
||||
absl::Duration timeout);
|
||||
|
||||
Payload& GetPayload() { return payload_; }
|
||||
void SendPayload(Payload payload) {
|
||||
sender_payload_id_ = payload.GetId();
|
||||
ctrl_.SendPayload(&client_, {discovered_.endpoint_id}, std::move(payload));
|
||||
}
|
||||
|
||||
Status CancelPayload() {
|
||||
if (sender_payload_id_) {
|
||||
return ctrl_.CancelPayload(&client_, sender_payload_id_);
|
||||
} else {
|
||||
return ctrl_.CancelPayload(&client_, payload_.GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void Disconnect();
|
||||
|
||||
bool IsAdvertising() const { return client_.IsAdvertising(); }
|
||||
|
||||
bool IsDiscovering() const { return client_.IsDiscovering(); }
|
||||
|
||||
bool IsConnected() const {
|
||||
return client_.IsConnectedToEndpoint(discovered_.endpoint_id);
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
ctrl_.Stop();
|
||||
}
|
||||
|
||||
protected:
|
||||
// ConnectionListener callbacks
|
||||
void OnConnectionInitiated(const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info,
|
||||
bool is_outgoing);
|
||||
void OnConnectionAccepted(const std::string& endpoint_id);
|
||||
void OnConnectionRejected(const std::string& endpoint_id, Status status);
|
||||
void OnEndpointDisconnect(const std::string& endpoint_id);
|
||||
|
||||
// DiscoveryListener callbacks
|
||||
void OnEndpointFound(const std::string& endpoint_id,
|
||||
const std::string& endpoint_name,
|
||||
const std::string& service_id);
|
||||
void OnEndpointLost(const std::string& endpoint_id);
|
||||
|
||||
// PayloadListener callbacks
|
||||
void OnPayload(const std::string& endpoint_id, Payload payload);
|
||||
void OnPayloadProgress(const std::string& endpoint_id,
|
||||
const PayloadProgressInfo& info);
|
||||
|
||||
std::string service_id_;
|
||||
DiscoveredInfo discovered_;
|
||||
Mutex progress_mutex_;
|
||||
ConditionVariable progress_sync_{&progress_mutex_};
|
||||
PayloadProgressInfo progress_info_;
|
||||
Payload payload_;
|
||||
Payload::Id sender_payload_id_ = 0;
|
||||
CountDownLatch* initiated_latch_ = nullptr;
|
||||
CountDownLatch* accept_latch_ = nullptr;
|
||||
CountDownLatch* reject_latch_ = nullptr;
|
||||
CountDownLatch* found_latch_ = nullptr;
|
||||
CountDownLatch* lost_latch_ = nullptr;
|
||||
CountDownLatch* payload_latch_ = nullptr;
|
||||
CountDownLatch* disconnect_latch_ = nullptr;
|
||||
Future<bool>* future_ = nullptr;
|
||||
std::function<bool(const PayloadProgressInfo&)> predicate_;
|
||||
std::string name_;
|
||||
ConnectionOptions options_{.strategy = Strategy::kP2pCluster};
|
||||
ClientProxy client_;
|
||||
OfflineServiceController ctrl_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_V2_INTERNAL_OFFLINE_SIMULATION_USER_H_
|
||||
@@ -44,7 +44,7 @@ bool PayloadManager::SendPayloadLoop(
|
||||
for (const auto& endpoint : unavailable_endpoints) {
|
||||
HandleFinishedOutgoingPayload(
|
||||
client, {endpoint->id}, payload_header, next_chunk_offset,
|
||||
EndpointInfoStatusToPayloadStatus(endpoint->status));
|
||||
EndpointInfoStatusToPayloadStatus(endpoint->status.Get()));
|
||||
}
|
||||
|
||||
// Update the still-active recipients of this payload.
|
||||
@@ -142,8 +142,8 @@ PayloadManager::GetAvailableAndUnavailableEndpoints(
|
||||
Endpoints unavailable;
|
||||
for (auto* endpoint_info : pending_payload.GetEndpoints()) {
|
||||
NEARBY_LOG(INFO, "EndpointInfo: %p; id=%s; status=%d", endpoint_info,
|
||||
endpoint_info->id.c_str(), endpoint_info->status);
|
||||
if (endpoint_info->status ==
|
||||
endpoint_info->id.c_str(), endpoint_info->status.Get());
|
||||
if (endpoint_info->status.Get() ==
|
||||
PayloadManager::EndpointInfo::Status::kAvailable) {
|
||||
available.push_back(endpoint_info);
|
||||
} else {
|
||||
@@ -239,12 +239,16 @@ void PayloadManager::CancelAllPayloads() {
|
||||
}
|
||||
}
|
||||
|
||||
PayloadManager::~PayloadManager() {
|
||||
NEARBY_LOG(INFO, "PayloadManager: going down; self=%p", this);
|
||||
shutdown_.Set(true);
|
||||
void PayloadManager::DisconnectFromEndpointManager() {
|
||||
if (shutdown_.Set(true)) return;
|
||||
// Unregister ourselves from the FrameProcessors.
|
||||
endpoint_manager_->UnregisterFrameProcessor(V1Frame::PAYLOAD_TRANSFER,
|
||||
handle_, true);
|
||||
}
|
||||
|
||||
PayloadManager::~PayloadManager() {
|
||||
NEARBY_LOG(INFO, "PayloadManager: going down; self=%p", this);
|
||||
DisconnectFromEndpointManager();
|
||||
CancelAllPayloads();
|
||||
NEARBY_LOG(INFO, "PayloadManager: turn down payload executors; self=%p",
|
||||
this);
|
||||
@@ -385,7 +389,11 @@ void PayloadManager::OnIncomingFrame(
|
||||
void PayloadManager::OnEndpointDisconnect(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
CountDownLatch* barrier) {
|
||||
RunOnStatusUpdateThread([this, client, endpoint_id, &barrier]() {
|
||||
if (shutdown_.Get()) {
|
||||
if (barrier) barrier->CountDown();
|
||||
return;
|
||||
}
|
||||
RunOnStatusUpdateThread([this, client, endpoint_id, barrier]() {
|
||||
// Iterate through all our payloads and look for payloads associated
|
||||
// with this endpoint.
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -907,7 +915,7 @@ PayloadManager::EndpointInfo::ControlMessageEventToEndpointInfoStatus(
|
||||
|
||||
void PayloadManager::EndpointInfo::SetStatusFromControlMessage(
|
||||
const PayloadTransferFrame::ControlMessage& control_message) {
|
||||
status = ControlMessageEventToEndpointInfoStatus(control_message.event());
|
||||
status.Set(ControlMessageEventToEndpointInfoStatus(control_message.event()));
|
||||
}
|
||||
|
||||
//////////////////////////////// PendingPayload ////////////////////////////////
|
||||
@@ -924,7 +932,7 @@ PayloadManager::PendingPayload::PendingPayload(
|
||||
for (const auto& id : endpoint_ids) {
|
||||
endpoints_.emplace(id, EndpointInfo{
|
||||
.id = id,
|
||||
.status = EndpointInfo::Status::kAvailable,
|
||||
.status {EndpointInfo::Status::kAvailable},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "proto/connections/offline_wire_formats.pb.h"
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "platform_v2/public/atomic_boolean.h"
|
||||
#include "platform_v2/public/atomic_reference.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
#include "platform_v2/public/mutex.h"
|
||||
#include "proto/connections_enums.pb.h"
|
||||
@@ -47,6 +48,8 @@ class PayloadManager : public EndpointManager::FrameProcessor {
|
||||
void OnEndpointDisconnect(ClientProxy* client, const std::string& endpoint_id,
|
||||
CountDownLatch* barrier) override;
|
||||
|
||||
void DisconnectFromEndpointManager();
|
||||
|
||||
private:
|
||||
// Information about an endpoint for a particular payload.
|
||||
struct EndpointInfo {
|
||||
@@ -65,7 +68,7 @@ class PayloadManager : public EndpointManager::FrameProcessor {
|
||||
PayloadTransferFrame::ControlMessage::EventType event);
|
||||
|
||||
std::string id;
|
||||
Status status = Status::kUnknown;
|
||||
AtomicReference<Status> status {Status::kUnknown};
|
||||
std::int64_t offset = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class PayloadSimulationUser : public SimulationUser {
|
||||
explicit PayloadSimulationUser(absl::string_view name)
|
||||
: SimulationUser(std::string(name)) {}
|
||||
~PayloadSimulationUser() override {
|
||||
NEARBY_LOGS(INFO) << "PayloadSimulationUser: [down] name=" << name_;
|
||||
// SystemClock::Sleep(kDefaultTimeout);
|
||||
}
|
||||
|
||||
@@ -109,6 +110,8 @@ TEST_F(PayloadManagerTest, CanSendBytePayload) {
|
||||
EXPECT_EQ(user_a.GetPayload().AsBytes(), ByteArray(std::string(kMessage)));
|
||||
NEARBY_LOG(INFO, "Test completed.");
|
||||
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
@@ -157,6 +160,8 @@ TEST_F(PayloadManagerTest, CanSendStreamPayload) {
|
||||
rx.Close();
|
||||
tx.Close();
|
||||
NEARBY_LOG(INFO, "Test completed.");
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
@@ -213,6 +218,8 @@ TEST_F(PayloadManagerTest, CanCancelPayloadOnReceiverSide) {
|
||||
rx.Close();
|
||||
|
||||
NEARBY_LOG(INFO, "Test completed.");
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
@@ -269,6 +276,8 @@ TEST_F(PayloadManagerTest, CanCancelPayloadOnSenderSide) {
|
||||
rx.Close();
|
||||
|
||||
NEARBY_LOG(INFO, "Test completed.");
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,18 @@ PcpManager::PcpManager(Mediums& mediums,
|
||||
channel_manager);
|
||||
}
|
||||
|
||||
void PcpManager::DisconnectFromEndpointManager() {
|
||||
if (shutdown_.Set(true)) return;
|
||||
for (auto& item : handlers_) {
|
||||
if (!item.second) continue;
|
||||
item.second->DisconnectFromEndpointManager();
|
||||
}
|
||||
}
|
||||
|
||||
PcpManager::~PcpManager() {
|
||||
DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
Status PcpManager::StartAdvertising(ClientProxy* client,
|
||||
const string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "core_v2/internal/base_pcp_handler.h"
|
||||
#include "core_v2/internal/client_proxy.h"
|
||||
#include "core_v2/internal/endpoint_channel_manager.h"
|
||||
#include "core_v2/internal/endpoint_manager.h"
|
||||
#include "core_v2/internal/mediums/mediums.h"
|
||||
#include "core_v2/internal/pcp_handler.h"
|
||||
#include "core_v2/listeners.h"
|
||||
#include "core_v2/options.h"
|
||||
#include "core_v2/status.h"
|
||||
#include "core_v2/strategy.h"
|
||||
#include "platform_v2/public/atomic_boolean.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
|
||||
namespace location {
|
||||
@@ -29,7 +30,7 @@ class PcpManager {
|
||||
public:
|
||||
PcpManager(Mediums& mediums, EndpointChannelManager& channel_manager,
|
||||
EndpointManager& endpoint_manager);
|
||||
~PcpManager() = default;
|
||||
~PcpManager();
|
||||
|
||||
Status StartAdvertising(ClientProxy* client_proxy, const string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
@@ -48,13 +49,15 @@ class PcpManager {
|
||||
Status RejectConnection(ClientProxy* client_proxy, const string& endpoint_id);
|
||||
|
||||
proto::connections::Medium GetBandwidthUpgradeMedium();
|
||||
void DisconnectFromEndpointManager();
|
||||
|
||||
private:
|
||||
bool SetCurrentPcpHandler(Strategy strategy);
|
||||
PcpHandler* GetPcpHandler(Pcp pcp) const;
|
||||
|
||||
absl::flat_hash_map<Pcp, std::unique_ptr<PcpHandler>> handlers_;
|
||||
PcpHandler* current_;
|
||||
AtomicBoolean shutdown_{false};
|
||||
absl::flat_hash_map<Pcp, std::unique_ptr<BasePcpHandler>> handlers_;
|
||||
PcpHandler* current_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
|
||||
@@ -73,6 +73,8 @@ TEST_F(PcpManagerTest, CanConnect) {
|
||||
EXPECT_EQ(user_b.GetDiscovered().endpoint_name, user_a.GetName());
|
||||
user_b.RequestConnection(&connection_latch);
|
||||
EXPECT_TRUE(connection_latch.Await(absl::Milliseconds(1000)).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
@@ -93,6 +95,8 @@ TEST_F(PcpManagerTest, CanAccept) {
|
||||
user_a.AcceptConnection(&accept_latch);
|
||||
user_b.AcceptConnection(&accept_latch);
|
||||
EXPECT_TRUE(accept_latch.Await(absl::Milliseconds(1000)).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
@@ -113,6 +117,8 @@ TEST_F(PcpManagerTest, CanReject) {
|
||||
user_b.ExpectRejectedConnection(reject_latch);
|
||||
user_a.RejectConnection(nullptr);
|
||||
EXPECT_TRUE(reject_latch.Await(absl::Milliseconds(1000)).result());
|
||||
user_a.Stop();
|
||||
user_b.Stop();
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,38 +35,38 @@ class ServiceController {
|
||||
ServiceController& operator=(const ServiceController&) = delete;
|
||||
|
||||
// Starts advertising an endpoint for a local app.
|
||||
virtual Status StartAdvertising(ClientProxy* client_proxy,
|
||||
virtual Status StartAdvertising(ClientProxy* client,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const ConnectionRequestInfo& info) = 0;
|
||||
virtual void StopAdvertising(ClientProxy* client_proxy) = 0;
|
||||
virtual void StopAdvertising(ClientProxy* client) = 0;
|
||||
|
||||
virtual Status StartDiscovery(ClientProxy* client_proxy,
|
||||
virtual Status StartDiscovery(ClientProxy* client,
|
||||
const std::string& service_id,
|
||||
const ConnectionOptions& options,
|
||||
const DiscoveryListener& listener) = 0;
|
||||
virtual void StopDiscovery(ClientProxy* client_proxy) = 0;
|
||||
virtual void StopDiscovery(ClientProxy* client) = 0;
|
||||
|
||||
virtual Status RequestConnection(ClientProxy* client_proxy,
|
||||
virtual Status RequestConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
const ConnectionRequestInfo& info) = 0;
|
||||
virtual Status AcceptConnection(ClientProxy* client_proxy,
|
||||
virtual Status AcceptConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id,
|
||||
const PayloadListener& listener) = 0;
|
||||
virtual Status RejectConnection(ClientProxy* client_proxy,
|
||||
virtual Status RejectConnection(ClientProxy* client,
|
||||
const std::string& endpoint_id) = 0;
|
||||
|
||||
virtual void InitiateBandwidthUpgrade(ClientProxy* client_proxy,
|
||||
virtual void InitiateBandwidthUpgrade(ClientProxy* client,
|
||||
const std::string& endpoint_id) = 0;
|
||||
|
||||
virtual void SendPayload(ClientProxy* client_proxy,
|
||||
virtual void SendPayload(ClientProxy* client,
|
||||
const std::vector<std::string>& endpoint_ids,
|
||||
Payload payload) = 0;
|
||||
|
||||
virtual Status CancelPayload(ClientProxy* client_proxy,
|
||||
std::int64_t payload_id) = 0;
|
||||
virtual Status CancelPayload(ClientProxy* client,
|
||||
Payload::Id payload_id) = 0;
|
||||
|
||||
virtual void DisconnectFromEndpoint(ClientProxy* client_proxy,
|
||||
virtual void DisconnectFromEndpoint(ClientProxy* client,
|
||||
const std::string& endpoint_id) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,13 @@ class SimulationUser {
|
||||
|
||||
explicit SimulationUser(const std::string& device_name)
|
||||
: name_(device_name) {}
|
||||
virtual ~SimulationUser() = default;
|
||||
virtual ~SimulationUser() {
|
||||
Stop();
|
||||
}
|
||||
void Stop() {
|
||||
pm_.DisconnectFromEndpointManager();
|
||||
mgr_.DisconnectFromEndpointManager();
|
||||
}
|
||||
|
||||
// Calls PcpManager::StartAdvertising.
|
||||
// If latch is provided, will call latch->CountDown() in the initiated_cb
|
||||
|
||||
@@ -69,5 +69,6 @@ cc_test(
|
||||
":file",
|
||||
"//file/util:temp_path",
|
||||
"//testing/base/public:gunit_main",
|
||||
"//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "file/util/temp_path.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
@@ -20,7 +21,7 @@ class FileImplTest : public ::testing::Test {
|
||||
file_ = std::fstream(path_, std::fstream::in | std::fstream::out);
|
||||
}
|
||||
|
||||
void WriteToFile(const std::string& text) {
|
||||
void WriteToFile(absl::string_view text) {
|
||||
file_ << text;
|
||||
file_.flush();
|
||||
size_ += text.size();
|
||||
|
||||
@@ -72,6 +72,5 @@ cc_library(
|
||||
":types",
|
||||
"//platform_v2/base",
|
||||
"//absl/strings",
|
||||
"//absl/types:any",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -27,7 +27,6 @@ class ConditionVariable {
|
||||
// Waits while timeout has not expired for Notify to be called.
|
||||
// May return prematurely in case of interrupt, if supported by platform.
|
||||
// Returns kSuccess, or kInterrupted on interrupt.
|
||||
// If Timeout expired, and Notify was not called, returns kTimeout.
|
||||
virtual Exception Wait(absl::Duration timeout) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace api {
|
||||
|
||||
int GetCurrentTid();
|
||||
|
||||
// This abstract class is the superclass of all classes representing an
|
||||
// Executor.
|
||||
class Executor {
|
||||
@@ -19,6 +21,8 @@ class Executor {
|
||||
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual int GetTid(int index) const = 0;
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -29,7 +29,12 @@ class LogMessageVoidify {
|
||||
location::nearby::api::LogMessage::Severity::kError
|
||||
#define NEARBY_SEVERITY_FATAL \
|
||||
location::nearby::api::LogMessage::Severity::kFatal
|
||||
|
||||
#if defined(_WIN32)
|
||||
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets substituted
|
||||
// with 0, and it expands to NEARBY_SEVERITY_0. To allow us to keep using this
|
||||
// syntax, we define this macro to do the same thing as NEARBY_SEVERITY_ERROR.
|
||||
#define NEARBY_SEVERITY_0 location::nearby::api::LogMessage::Severity::kError
|
||||
#endif // defined(_WIN32)
|
||||
#define NEARBY_SEVERITY(severity) NEARBY_SEVERITY_##severity
|
||||
|
||||
// Log enabling
|
||||
|
||||
@@ -31,7 +31,6 @@ cc_library(
|
||||
"//absl/base:core_headers",
|
||||
"//absl/synchronization",
|
||||
"//absl/time",
|
||||
"//absl/types:any",
|
||||
"//thread",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -20,9 +20,8 @@ class ConditionVariable : public api::ConditionVariable {
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
Exception Wait(absl::Duration timeout) override {
|
||||
return cond_var_.WaitWithTimeout(mutex_, timeout)
|
||||
? Exception{Exception::kTimeout}
|
||||
: Exception{Exception::kSuccess};
|
||||
cond_var_.WaitWithTimeout(mutex_, timeout);
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
void Notify() override { cond_var_.SignalAll(); }
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@ class MultiThreadExecutor : public api::SubmittableExecutor {
|
||||
void Shutdown() override { DoShutdown(); }
|
||||
~MultiThreadExecutor() override { DoShutdown(); }
|
||||
|
||||
int GetTid(int index) const override {
|
||||
const auto* thread = thread_pool_.thread(index);
|
||||
return thread ? thread->tid() : 0;
|
||||
}
|
||||
|
||||
void ScheduleAfter(absl::Duration delay, Runnable&& runnable) {
|
||||
if (shutdown_) return;
|
||||
thread_pool_.ScheduleAt(absl::Now() + delay, std::move(runnable));
|
||||
|
||||
@@ -47,6 +47,11 @@ std::string GetPayloadPath(PayloadId payload_id) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int GetCurrentTid() {
|
||||
const LiveThread* my = Thread_GetMyLiveThread();
|
||||
return LiveThread_Pthread_TID(my);
|
||||
}
|
||||
|
||||
std::unique_ptr<SubmittableExecutor>
|
||||
ImplementationPlatform::CreateSingleThreadExecutor() {
|
||||
return absl::make_unique<g3::SingleThreadExecutor>();
|
||||
|
||||
@@ -31,6 +31,9 @@ class ScheduledExecutor final : public api::ScheduledExecutor {
|
||||
absl::Duration delay) override;
|
||||
void Shutdown() override { executor_.Shutdown(); }
|
||||
|
||||
int GetTid(int index) const override {
|
||||
return executor_.GetTid(index);
|
||||
}
|
||||
private:
|
||||
SingleThreadExecutor executor_;
|
||||
};
|
||||
|
||||
@@ -51,5 +51,6 @@ cc_test(
|
||||
"//file/util:temp_path",
|
||||
"//platform_v2/base",
|
||||
"//testing/base/public:gunit_main",
|
||||
"//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "file/util/temp_path.h"
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
@@ -22,7 +23,7 @@ class FileTest : public ::testing::Test {
|
||||
file_ = std::fstream(path_, std::fstream::in | std::fstream::out);
|
||||
}
|
||||
|
||||
void WriteToFile(const std::string& text) {
|
||||
void WriteToFile(absl::string_view text) {
|
||||
file_ << text;
|
||||
file_.flush();
|
||||
size_ += text.size();
|
||||
|
||||
@@ -39,7 +39,6 @@ cc_library(
|
||||
"//absl/base:core_headers",
|
||||
"//absl/container:flat_hash_map",
|
||||
"//absl/time",
|
||||
"//absl/types:any",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "platform_v2/public/logging.h"
|
||||
#include "platform_v2/public/mutex.h"
|
||||
#include "platform_v2/public/single_thread_executor.h"
|
||||
#include "platform_v2/public/system_clock.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/time.h"
|
||||
@@ -54,7 +55,12 @@ TEST(ConditionVariableTest, WaitTerminatesOnTimeoutWithoutNotify) {
|
||||
Mutex mutex;
|
||||
ConditionVariable cond{&mutex};
|
||||
MutexLock lock(&mutex);
|
||||
EXPECT_EQ(cond.Wait(absl::Milliseconds(100)), Exception{Exception::kTimeout});
|
||||
|
||||
const absl::Duration kWaitTime = absl::Milliseconds(100);
|
||||
absl::Time start = SystemClock::ElapsedRealtime();
|
||||
cond.Wait(kWaitTime);
|
||||
absl::Duration duration = SystemClock::ElapsedRealtime() - start;
|
||||
EXPECT_GE(duration, kWaitTime);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -50,6 +50,12 @@ class ScheduledExecutor final {
|
||||
DoShutdown();
|
||||
}
|
||||
|
||||
int GetTid(int index) const {
|
||||
MutexLock lock(&mutex_);
|
||||
return impl_->GetTid(index);
|
||||
}
|
||||
int Tid() const { return GetTid(0); }
|
||||
|
||||
Cancelable Schedule(Runnable&& runnable, absl::Duration duration)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_) {
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -65,7 +71,7 @@ class ScheduledExecutor final {
|
||||
}
|
||||
}
|
||||
|
||||
Mutex mutex_;
|
||||
mutable Mutex mutex_;
|
||||
std::unique_ptr<api::ScheduledExecutor> ABSL_GUARDED_BY(mutex_) impl_;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ class SettableFuture : public api::SettableFuture<T> {
|
||||
MutexLock lock(&mutex_);
|
||||
while (!done_) {
|
||||
absl::Time start_time = SystemClock::ElapsedRealtime();
|
||||
if (completed_.Wait(timeout).Raised(Exception::kTimeout)) {
|
||||
SetExceptionLocked({Exception::kTimeout});
|
||||
if (completed_.Wait(timeout).Raised(Exception::kInterrupted)) {
|
||||
SetExceptionLocked({Exception::kInterrupted});
|
||||
break;
|
||||
}
|
||||
absl::Duration spent = SystemClock::ElapsedRealtime() - start_time;
|
||||
|
||||
@@ -18,6 +18,7 @@ class SingleThreadExecutor final : public SubmittableExecutor {
|
||||
~SingleThreadExecutor() override = default;
|
||||
SingleThreadExecutor(SingleThreadExecutor&&) = default;
|
||||
SingleThreadExecutor& operator=(SingleThreadExecutor&&) = default;
|
||||
int Tid() const { return GetTid(0); }
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
inline int GetCurrentTid() { return api::GetCurrentTid(); }
|
||||
|
||||
// Main interface to be used by platform as a base class for
|
||||
// - MultiThreadExecutor
|
||||
// - SingleThreadExecutor
|
||||
@@ -41,6 +43,11 @@ class SubmittableExecutor : public api::SubmittableExecutor {
|
||||
if (impl_) impl_->Execute(std::move(runnable));
|
||||
}
|
||||
|
||||
int GetTid(int index) const ABSL_LOCKS_EXCLUDED(mutex_) override {
|
||||
MutexLock lock(&mutex_);
|
||||
return impl_ ? impl_->GetTid(index) : 0;
|
||||
}
|
||||
|
||||
void Shutdown() ABSL_LOCKS_EXCLUDED(mutex_) override {
|
||||
MutexLock lock(&mutex_);
|
||||
DoShutdown();
|
||||
@@ -86,7 +93,7 @@ class SubmittableExecutor : public api::SubmittableExecutor {
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) override {
|
||||
return impl_ ? impl_->DoSubmit(std::move(wrapped_callable)) : false;
|
||||
}
|
||||
Mutex mutex_;
|
||||
mutable Mutex mutex_;
|
||||
std::unique_ptr<api::SubmittableExecutor> ABSL_GUARDED_BY(mutex_) impl_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user