Files
nearby/connections/implementation/simulation_user.h
T
Juliet Levesque 8be118a3d0 [Nearby Connections] Plumb remote device information much deeper into the stack
This will be needed for the authentication transport as the verifier will need the information about the remote device. This CL is based on logic from
awadhera@ in cl/539175992 with additional unit test coverage.

PiperOrigin-RevId: 565037849
2023-09-13 06:59:50 -07:00

223 lines
8.2 KiB
C++

// Copyright 2021 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_INTERNAL_SIMULATION_USER_H_
#define CORE_INTERNAL_SIMULATION_USER_H_
#include <cstdint>
#include <string>
#include "gtest/gtest.h"
#include "connections/implementation/bwu_manager.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/endpoint_channel_manager.h"
#include "connections/implementation/endpoint_manager.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/injected_bluetooth_device_store.h"
#include "connections/implementation/payload_manager.h"
#include "connections/implementation/pcp_manager.h"
#include "connections/v3/connections_device.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/condition_variable.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/future.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 nearby {
namespace connections {
class SetSafeToDisconnect {
public:
explicit SetSafeToDisconnect(bool safe_to_disconnect,
bool payload_received_ack,
std::int32_t safe_to_disconnect_version) {
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnableSafeToDisconnect,
safe_to_disconnect);
NearbyFlags::GetInstance().OverrideBoolFlagValue(
config_package_nearby::nearby_connections_feature::
kEnablePayloadReceivedAck,
payload_received_ack);
NearbyFlags::GetInstance().OverrideInt64FlagValue(
config_package_nearby::nearby_connections_feature::
kSafeToDisconnectVersion,
safe_to_disconnect_version);
}
};
class SimulationUser {
public:
struct DiscoveredInfo {
std::string endpoint_id;
ByteArray endpoint_info;
std::string service_id;
bool Empty() const { return endpoint_id.empty(); }
void Clear() { endpoint_id.clear(); }
};
explicit SimulationUser(
const std::string& device_name,
BooleanMediumSelector allowed = BooleanMediumSelector())
: info_{ByteArray{device_name}},
advertising_options_{
{
Strategy::kP2pCluster,
allowed,
},
},
connection_options_{
.keep_alive_interval_millis = FeatureFlags::GetInstance()
.GetFlags()
.keep_alive_interval_millis,
.keep_alive_timeout_millis = FeatureFlags::GetInstance()
.GetFlags()
.keep_alive_timeout_millis,
},
discovery_options_{
{
Strategy::kP2pCluster,
allowed,
},
} {}
virtual ~SimulationUser() { Stop(); }
void Stop() {
pm_.DisconnectFromEndpointManager();
mgr_.DisconnectFromEndpointManager();
bwu_.Shutdown();
}
// Calls PcpManager::StartAdvertising.
// If latch is provided, will call latch->CountDown() in the initiated_cb
// callback.
void StartAdvertising(const std::string& service_id, CountDownLatch* latch);
// Calls PcpManager::StartDiscovery.
// If latch is provided, will call latch->CountDown() in the endpoint_found_cb
// callback.
void StartDiscovery(const std::string& service_id, CountDownLatch* latch);
void StopDiscovery();
// Calls PcpManager::UpdateDiscoveryOptions.
Status UpdateDiscoveryOptions(absl::string_view service_id);
// Calls PcpManager::InjectEndpoint.
void InjectEndpoint(const std::string& service_id,
const OutOfBandConnectionMetadata& metadata);
// Calls PcpManager::RequestConnection.
// If latch is provided, latch->CountDown() will be called in the initiated_cb
// callback.
void RequestConnection(CountDownLatch* latch);
// Calls PcpManager::RequestConnectionV3.
// If latch is provided, latch->CountDown() will be called in the initiated_cb
// callback.
void RequestConnectionV3(CountDownLatch* latch,
const NearbyDevice& remote_device);
// Calls PcpManager::AcceptConnection.
// If latch is provided, latch->CountDown() will be called in the accepted_cb
// callback.
void AcceptConnection(CountDownLatch* latch);
// Calls PcpManager::RejectConnection.
// If latch is provided, latch->CountDown() will be called in the rejected_cb
// callback.
void RejectConnection(CountDownLatch* latch);
// Calls PcpManager::StartListeningForIncomingConnections.
// If latch is provided, latch->CountDown() will be called on call completion.
void StartListeningForIncomingConnections(
CountDownLatch* latch, absl::string_view service_id,
const v3::ConnectionListeningOptions& options, Status expected_status);
// 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; }
const DiscoveredInfo& GetDiscovered() const { return discovered_; }
ByteArray GetInfo() const { return info_; }
bool WaitForProgress(
absl::AnyInvocable<bool(const PayloadProgressInfo&)> pred,
absl::Duration timeout);
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);
// DiscoveryListener callbacks
void OnEndpointFound(const std::string& endpoint_id,
const ByteArray& endpoint_info,
const std::string& service_id);
void OnEndpointLost(const std::string& endpoint_id);
// PayloadListener callbacks
void OnPayload(absl::string_view, Payload payload);
void OnPayloadProgress(absl::string_view endpoint_id,
const PayloadProgressInfo& info);
std::string service_id_;
DiscoveredInfo discovered_;
Mutex progress_mutex_;
ConditionVariable progress_sync_{&progress_mutex_};
PayloadProgressInfo progress_info_;
Payload payload_;
CountDownLatch* initiated_latch_ = nullptr;
CountDownLatch* accept_latch_ = nullptr;
CountDownLatch* reject_latch_ = nullptr;
CountDownLatch* found_latch_ = nullptr;
CountDownLatch* lost_latch_ = nullptr;
CountDownLatch* payload_latch_ = nullptr;
Future<bool>* future_ = nullptr;
absl::AnyInvocable<bool(const PayloadProgressInfo&)> predicate_;
ByteArray info_;
Mediums mediums_;
AdvertisingOptions advertising_options_;
ConnectionOptions connection_options_;
DiscoveryOptions discovery_options_;
SetSafeToDisconnect set_safe_to_disconnect_{true, true, 2};
ClientProxy client_;
EndpointChannelManager ecm_;
EndpointManager em_{&ecm_};
BwuManager bwu_{mediums_, em_, ecm_, {}, {}};
InjectedBluetoothDeviceStore injected_bluetooth_device_store_;
PcpManager mgr_{mediums_, ecm_, em_, bwu_, injected_bluetooth_device_store_};
PayloadManager pm_{em_};
};
} // namespace connections
} // namespace nearby
#endif // CORE_INTERNAL_SIMULATION_USER_H_