blob: dc84830782f9e9295eeb206c7d2deb08f03de5bd [file] [log] [blame]
// 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_OFFLINE_SIMULATION_USER_H_
#define CORE_INTERNAL_OFFLINE_SIMULATION_USER_H_
#include <string>
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "core/internal/client_proxy.h"
#include "core/internal/offline_service_controller.h"
#include "platform/public/atomic_boolean.h"
#include "platform/public/condition_variable.h"
#include "platform/public/count_down_latch.h"
#include "platform/public/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 location {
namespace nearby {
namespace connections {
class OfflineSimulationUser {
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 OfflineSimulationUser(
absl::string_view device_name,
BooleanMediumSelector allowed = BooleanMediumSelector())
: info_{ByteArray{std::string(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 ~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 found_latch is provided, will call found_latch->CountDown() in the
// endpoint_found_cb callback.
// If lost_latch is provided, will call lost_latch->CountDown() in the
// endpoint_lost_cb callback.
Status StartDiscovery(const std::string& service_id,
CountDownLatch* found_latch,
CountDownLatch* lost_latch = nullptr);
// Calls PcpManager::StopDiscovery().
void StopDiscovery();
// 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.
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_; }
ByteArray GetInfo() const { return info_; }
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() {
StopAdvertising();
StopDiscovery();
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 ByteArray& endpoint_info,
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_;
ByteArray info_;
AdvertisingOptions advertising_options_;
ConnectionOptions connection_options_;
DiscoveryOptions discovery_options_;
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_;
ClientProxy client_;
OfflineServiceController ctrl_;
};
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_INTERNAL_OFFLINE_SIMULATION_USER_H_