Refactor Pipe implementation

* Remove Pipe classes
* Rename BasePipe to Pipe
* Hide Pipe class in anonymous namespace in pipe.cc
* Add CreatePipe static method
* Replace Payload(std::function<InputStream&()>) with Payload(std::unique_ptr<InputStream>)
* Find&Replace Pipe usages

PiperOrigin-RevId: 557276980
This commit is contained in:
Janusz Sobczak
2023-08-15 15:53:58 -07:00
committed by Copybara-Service
parent 20db5da721
commit 2c55c0cdbd
48 changed files with 795 additions and 858 deletions
+2
View File
@@ -226,6 +226,7 @@ cc_test(
":internal",
":internal_test",
"//connections:core_types",
"//connections/implementation/analytics",
"//connections/implementation/flags:connections_flags",
"//connections/implementation/mediums",
"//connections/implementation/proto:offline_wire_formats_cc_proto",
@@ -241,6 +242,7 @@ cc_test(
"//internal/test",
"//proto:connections_enums_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
@@ -14,7 +14,9 @@
#include "connections/implementation/base_endpoint_channel.h"
#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include <utility>
@@ -22,9 +24,13 @@
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/encryption_runner.h"
#include "connections/implementation/endpoint_channel.h"
#include "connections/implementation/offline_frames.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
@@ -34,7 +40,6 @@
#include "internal/platform/multi_thread_executor.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
#include "internal/platform/single_thread_executor.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
@@ -44,6 +49,7 @@ namespace {
using ::location::nearby::proto::connections::DisconnectionReason;
using ::location::nearby::proto::connections::Medium;
using EncryptionContext = BaseEndpointChannel::EncryptionContext;
constexpr size_t kChunkSize = 64 * 1024;
class TestEndpointChannel : public BaseEndpointChannel {
public:
@@ -62,7 +68,7 @@ std::function<void()> MakeDataPump(
return [label, input, output, monitor]() {
NEARBY_LOGS(INFO) << "streaming data through '" << label << "'";
while (true) {
auto read_response = input->Read(Pipe::kChunkSize);
auto read_response = input->Read(kChunkSize);
if (!read_response.ok()) {
NEARBY_LOGS(INFO) << "Peer reader closed on '" << label << "'";
output->Close();
@@ -158,21 +164,17 @@ DoDhKeyExchange(BaseEndpointChannel* channel_a,
}
TEST(BaseEndpointChannelTest, ConstructorDestructorWorks) {
Pipe pipe;
InputStream& input_stream = pipe.GetInputStream();
OutputStream& output_stream = pipe.GetOutputStream();
auto [input, output] = CreatePipe();
TestEndpointChannel test_channel(&input_stream, &output_stream);
TestEndpointChannel test_channel(input.get(), output.get());
}
TEST(BaseEndpointChannelTest, ReadWrite) {
// Direct not-encrypted IO.
Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b.
Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(&pipe_b.GetInputStream(),
&pipe_a.GetOutputStream());
TestEndpointChannel channel_b(&pipe_a.GetInputStream(),
&pipe_b.GetOutputStream());
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
ByteArray tx_message{"data message"};
channel_a.Write(tx_message);
ByteArray rx_message = std::move(channel_b.Read().result());
@@ -180,8 +182,8 @@ TEST(BaseEndpointChannelTest, ReadWrite) {
}
TEST(BaseEndpointChannelTest, ChannelUnencryptedByDefault) {
Pipe pipe;
TestEndpointChannel channel(&pipe.GetInputStream(), &pipe.GetOutputStream());
auto pipe = CreatePipe();
TestEndpointChannel channel(pipe.first.get(), pipe.second.get());
ExceptionOr<ByteArray> result = channel.TryDecrypt(ByteArray("message"));
@@ -192,12 +194,10 @@ TEST(BaseEndpointChannelTest, ChannelUnencryptedByDefault) {
TEST(BaseEndpointChannelTest, TryDecrypt) {
absl::string_view kMessage = "message";
Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b.
Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(&pipe_b.GetInputStream(),
&pipe_a.GetOutputStream());
TestEndpointChannel channel_b(&pipe_a.GetInputStream(),
&pipe_b.GetOutputStream());
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
ASSERT_NE(context_a, nullptr);
ASSERT_NE(context_b, nullptr);
@@ -215,12 +215,10 @@ TEST(BaseEndpointChannelTest, TryDecrypt) {
}
TEST(BaseEndpointChannelTest, TryDecryptFailsWhenDecryptionFails) {
Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b.
Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(&pipe_b.GetInputStream(),
&pipe_a.GetOutputStream());
TestEndpointChannel channel_b(&pipe_a.GetInputStream(),
&pipe_b.GetOutputStream());
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
ASSERT_NE(context_a, nullptr);
channel_a.EnableEncryption(context_a);
@@ -240,25 +238,27 @@ TEST(BaseEndpointChannelTest, NotEncryptedReadWriteCanBeIntercepted) {
absl::Mutex mutex;
std::string capture_a;
std::string capture_b;
Pipe client_a; // Channel "a" writes to client "a", reads from server "a".
Pipe client_b; // Channel "b" writes to client "b", reads from server "b".
Pipe server_a; // Data pump "a" reads from client "a", writes to server "b".
Pipe server_b; // Data pump "b" reads from client "b", writes to server "a".
TestEndpointChannel channel_a(&server_a.GetInputStream(),
&client_a.GetOutputStream());
TestEndpointChannel channel_b(&server_b.GetInputStream(),
&client_b.GetOutputStream());
auto client_a =
CreatePipe(); // Channel "a" writes to client "a", reads from server "a".
auto client_b =
CreatePipe(); // Channel "b" writes to client "b", reads from server "b".
auto server_a = CreatePipe(); // Data pump "a" reads from client "a", writes
// to server "b".
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
// to server "a".
TestEndpointChannel channel_a(server_a.first.get(), client_a.second.get());
TestEndpointChannel channel_b(server_b.first.get(), client_b.second.get());
ON_CALL(channel_a, GetMedium).WillByDefault([]() { return Medium::BLE; });
ON_CALL(channel_b, GetMedium).WillByDefault([]() { return Medium::BLE; });
MultiThreadExecutor executor(2);
executor.Execute(MakeDataPump(
"pump_a", &client_a.GetInputStream(), &server_b.GetOutputStream(),
MakeDataMonitor("monitor_a", &capture_a, &mutex)));
executor.Execute(MakeDataPump(
"pump_b", &client_b.GetInputStream(), &server_a.GetOutputStream(),
MakeDataMonitor("monitor_b", &capture_b, &mutex)));
executor.Execute(
MakeDataPump("pump_a", client_a.first.get(), server_b.second.get(),
MakeDataMonitor("monitor_a", &capture_a, &mutex)));
executor.Execute(
MakeDataPump("pump_b", client_b.first.get(), server_a.second.get(),
MakeDataMonitor("monitor_b", &capture_b, &mutex)));
EXPECT_EQ(channel_a.GetType(), "BLE");
EXPECT_EQ(channel_b.GetType(), "BLE");
@@ -289,14 +289,16 @@ TEST(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
absl::Mutex mutex;
std::string capture_a;
std::string capture_b;
Pipe client_a; // Channel "a" writes to client "a", reads from server "a".
Pipe client_b; // Channel "b" writes to client "b", reads from server "b".
Pipe server_a; // Data pump "a" reads from client "a", writes to server "b".
Pipe server_b; // Data pump "b" reads from client "b", writes to server "a".
TestEndpointChannel channel_a(&server_a.GetInputStream(),
&client_a.GetOutputStream());
TestEndpointChannel channel_b(&server_b.GetInputStream(),
&client_b.GetOutputStream());
auto client_a =
CreatePipe(); // Channel "a" writes to client "a", reads from server "a".
auto client_b =
CreatePipe(); // Channel "b" writes to client "b", reads from server "b".
auto server_a = CreatePipe(); // Data pump "a" reads from client "a", writes
// to server "b".
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
// to server "a".
TestEndpointChannel channel_a(server_a.first.get(), client_a.second.get());
TestEndpointChannel channel_b(server_b.first.get(), client_b.second.get());
ON_CALL(channel_a, GetMedium).WillByDefault([]() {
return Medium::BLUETOOTH;
@@ -306,12 +308,12 @@ TEST(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
});
MultiThreadExecutor executor(2);
executor.Execute(MakeDataPump(
"pump_a", &client_a.GetInputStream(), &server_b.GetOutputStream(),
MakeDataMonitor("monitor_a", &capture_a, &mutex)));
executor.Execute(MakeDataPump(
"pump_b", &client_b.GetInputStream(), &server_a.GetOutputStream(),
MakeDataMonitor("monitor_b", &capture_b, &mutex)));
executor.Execute(
MakeDataPump("pump_a", client_a.first.get(), server_b.second.get(),
MakeDataMonitor("monitor_a", &capture_a, &mutex)));
executor.Execute(
MakeDataPump("pump_b", client_b.first.get(), server_a.second.get(),
MakeDataMonitor("monitor_b", &capture_b, &mutex)));
// Run DH key exchange; setup encryption contexts for channels.
auto [context_a, context_b] = DoDhKeyExchange(&channel_a, &channel_b);
@@ -346,12 +348,10 @@ TEST(BaseEndpointChannelTest, EncryptedReadWriteCanNotBeIntercepted) {
TEST(BaseEndpointChannelTest, CanBesuspendedAndResumed) {
// Setup test communication environment.
Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b.
Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(&pipe_b.GetInputStream(),
&pipe_a.GetOutputStream());
TestEndpointChannel channel_b(&pipe_a.GetInputStream(),
&pipe_b.GetOutputStream());
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
ON_CALL(channel_a, GetMedium).WillByDefault([]() {
return Medium::WIFI_LAN;
@@ -399,14 +399,12 @@ TEST(BaseEndpointChannelTest, CanBesuspendedAndResumed) {
}
TEST(BaseEndpointChannelTest, ReadAfterInputStreamClosed) {
Pipe pipe;
InputStream& input_stream = pipe.GetInputStream();
OutputStream& output_stream = pipe.GetOutputStream();
auto [input, output] = CreatePipe();
TestEndpointChannel test_channel(&input_stream, &output_stream);
TestEndpointChannel test_channel(input.get(), output.get());
// Close the output stream before trying to read from the input.
output_stream.Close();
output->Close();
// Trying to read should fail gracefully with an IO error.
ExceptionOr<ByteArray> read_data = test_channel.Read();
@@ -417,12 +415,10 @@ TEST(BaseEndpointChannelTest, ReadAfterInputStreamClosed) {
TEST(BaseEndpointChannelTest, ReadUnencryptedFrameOnEncryptedChannel) {
// Setup test communication environment.
Pipe pipe_a; // channel_a writes to pipe_a, reads from pipe_b.
Pipe pipe_b; // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(&pipe_b.GetInputStream(),
&pipe_a.GetOutputStream());
TestEndpointChannel channel_b(&pipe_a.GetInputStream(),
&pipe_b.GetOutputStream());
auto pipe_a = CreatePipe(); // channel_a writes to pipe_a, reads from pipe_b.
auto pipe_b = CreatePipe(); // channel_b writes to pipe_b, reads from pipe_a.
TestEndpointChannel channel_a(pipe_b.first.get(), pipe_a.second.get());
TestEndpointChannel channel_b(pipe_a.first.get(), pipe_b.second.get());
ON_CALL(channel_a, GetMedium).WillByDefault([]() {
return Medium::BLUETOOTH;
@@ -18,21 +18,32 @@
#include <atomic>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "connections/advertising_options.h"
#include "connections/connection_options.h"
#include "connections/discovery_options.h"
#include "connections/implementation/analytics/packet_meta_data.h"
#include "connections/implementation/base_endpoint_channel.h"
#include "connections/implementation/bwu_manager.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/encryption_runner.h"
#include "connections/implementation/endpoint_manager.h"
#include "connections/implementation/mediums/mediums.h"
#include "connections/implementation/offline_frames.h"
#include "connections/implementation/pcp.h"
#include "connections/implementation/proto/offline_wire_formats.pb.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/params.h"
#include "connections/status.h"
#include "connections/strategy.h"
@@ -41,7 +52,12 @@
#include "internal/interop/device_provider.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/future.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
#include "proto/connections_enums.pb.h"
#include "proto/connections_enums.proto.h"
@@ -108,9 +124,12 @@ class FakePresenceDeviceProvider : public NearbyDeviceProvider {
class MockEndpointChannel : public BaseEndpointChannel {
public:
explicit MockEndpointChannel(Pipe* reader, Pipe* writer)
: BaseEndpointChannel("service_id", "channel", &reader->GetInputStream(),
&writer->GetOutputStream()) {}
explicit MockEndpointChannel(std::unique_ptr<InputStream> reader,
std::unique_ptr<OutputStream> writer)
: BaseEndpointChannel("service_id", "channel", reader.get(),
writer.get()),
input_stream_(std::move(reader)),
output_stream_(std::move(writer)) {}
ExceptionOr<ByteArray> DoRead() { return BaseEndpointChannel::Read(); }
Exception DoWrite(const ByteArray& data) {
@@ -136,6 +155,10 @@ class MockEndpointChannel : public BaseEndpointChannel {
MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override));
bool broken_write_{false};
private:
std::unique_ptr<InputStream> input_stream_;
std::unique_ptr<OutputStream> output_stream_;
};
class MockPcpHandler : public BasePcpHandler {
@@ -459,10 +482,13 @@ class BasePcpHandlerTest
std::pair<std::unique_ptr<MockEndpointChannel>,
std::unique_ptr<MockEndpointChannel>>
SetupConnection(
Pipe& pipe_a, Pipe& pipe_b,
location::nearby::proto::connections::Medium medium) { // NOLINT
auto channel_a = std::make_unique<MockEndpointChannel>(&pipe_b, &pipe_a);
auto channel_b = std::make_unique<MockEndpointChannel>(&pipe_a, &pipe_b);
auto [input_a, output_a] = CreatePipe();
auto [input_b, output_b] = CreatePipe();
auto channel_a = std::make_unique<MockEndpointChannel>(std::move(input_a),
std::move(output_b));
auto channel_b = std::make_unique<MockEndpointChannel>(std::move(input_b),
std::move(output_a));
// On initiator (A) side, we drop the first write, since this is a
// connection establishment packet, and we don't have the peer entity, just
// the peer channel. The rest of the exchange must happen for the benefit of
@@ -648,9 +674,6 @@ class BasePcpHandlerTest
expected_result);
NEARBY_LOG(INFO, "Stopping Encryption Runner");
}
Pipe pipe_a_;
Pipe pipe_b_;
MockConnectionListener mock_connection_listener_;
MockDiscoveryListener mock_discovery_listener_;
ConnectionListener connection_listener_{
@@ -839,7 +862,7 @@ TEST_F(BasePcpHandlerTest, WifiMediumFailFallBackToBT) {
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -865,7 +888,7 @@ TEST_P(BasePcpHandlerTest, RequestConnectionChangesState) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -910,7 +933,7 @@ TEST_P(BasePcpHandlerTest, CanRequestConnectionPresence) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -941,7 +964,7 @@ TEST_P(BasePcpHandlerTest, CanRequestConnectionLegacy) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -968,7 +991,7 @@ TEST_P(BasePcpHandlerTest, IoError_RequestConnectionFails) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(AtLeast(1));
@@ -997,7 +1020,7 @@ TEST_P(BasePcpHandlerTest, AcceptConnectionChangesState) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -1028,7 +1051,7 @@ TEST_P(BasePcpHandlerTest, RejectConnectionChangesState) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
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(),
@@ -1056,7 +1079,7 @@ TEST_P(BasePcpHandlerTest, OnIncomingFrameChangesState) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -1098,7 +1121,7 @@ TEST_P(BasePcpHandlerTest, DestructorIsCalledOnProtocolEndpoint) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -1141,7 +1164,7 @@ TEST_P(BasePcpHandlerTest, MultipleMediumsProduceSingleEndpointLostEvent) {
StartDiscovery(&client, &pcp_handler);
auto mediums = pcp_handler.GetDiscoveryMediums(&client);
auto connect_medium = mediums[mediums.size() - 1];
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, connect_medium);
auto channel_pair = SetupConnection(connect_medium);
auto& channel_a = channel_pair.first;
auto& channel_b = channel_pair.second;
EXPECT_CALL(*channel_a, CloseImpl).Times(1);
@@ -1582,7 +1605,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithUnknown) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -1631,7 +1654,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithUnknown) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -1681,7 +1704,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithConnections) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -1732,7 +1755,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForPresenceWithPresence) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -1782,7 +1805,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithConnections) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -1832,7 +1855,7 @@ TEST_F(BasePcpHandlerTest, TestDeviceFilterForConnectionsWithPresence) {
.first.Ok());
ASSERT_TRUE(client.IsListeningForIncomingConnections());
ASSERT_TRUE(pcp_handler.CanReceiveIncomingConnection(&client));
auto channel_pair = SetupConnection(pipe_a_, pipe_b_, Medium::BLUETOOTH);
auto channel_pair = SetupConnection(Medium::BLUETOOTH);
ByteArray serialized_frame = parser::ForConnectionRequestConnections(
{}, {
.local_endpoint_id = "ABCD",
@@ -14,23 +14,30 @@
#include "connections/implementation/encryption_runner.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include <cstddef>
#include <string>
#include "gtest/gtest.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "connections/implementation/analytics/analytics_recorder.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/endpoint_channel.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/exception.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
#include "internal/platform/system_clock.h"
#include "proto/connections_enums.pb.h"
#include "third_party/ukey2/src/main/cpp/include/securegcm/ukey2_handshake.h"
namespace nearby {
namespace connections {
namespace {
using ::location::nearby::proto::connections::Medium;
constexpr size_t kChunkSize = 64 * 1024;
class FakeEndpointChannel : public EndpointChannel {
public:
@@ -38,13 +45,11 @@ class FakeEndpointChannel : public EndpointChannel {
: in_(in), out_(out) {}
ExceptionOr<ByteArray> Read() override {
read_timestamp_ = SystemClock::ElapsedRealtime();
return in_ ? in_->Read(Pipe::kChunkSize)
: ExceptionOr<ByteArray>{Exception::kIo};
return in_ ? in_->Read(kChunkSize) : ExceptionOr<ByteArray>{Exception::kIo};
}
ExceptionOr<ByteArray> Read(PacketMetaData& packet_meta_data) override {
read_timestamp_ = SystemClock::ElapsedRealtime();
return in_ ? in_->Read(Pipe::kChunkSize)
: ExceptionOr<ByteArray>{Exception::kIo};
return in_ ? in_->Read(kChunkSize) : ExceptionOr<ByteArray>{Exception::kIo};
}
Exception Write(const ByteArray& data) override {
write_timestamp_ = SystemClock::ElapsedRealtime();
@@ -103,8 +108,7 @@ class FakeEndpointChannel : public EndpointChannel {
};
struct User {
User(Pipe* reader, Pipe* writer)
: channel(&reader->GetInputStream(), &writer->GetOutputStream()) {}
User(InputStream* reader, OutputStream* writer) : channel(reader, writer) {}
FakeEndpointChannel channel;
EncryptionRunner crypto;
@@ -126,10 +130,12 @@ struct Response {
TEST(EncryptionRunnerTest, ConstructorDestructorWorks) { EncryptionRunner enc; }
TEST(EncryptionRunnerTest, ReadWrite) {
Pipe from_a_to_b;
Pipe from_b_to_a;
User user_a(/*reader=*/&from_b_to_a, /*writer=*/&from_a_to_b);
User user_b(/*reader=*/&from_a_to_b, /*writer=*/&from_b_to_a);
auto from_a_to_b = CreatePipe();
auto from_b_to_a = CreatePipe();
User user_a(/*reader=*/from_b_to_a.first.get(),
/*writer=*/from_a_to_b.second.get());
User user_b(/*reader=*/from_a_to_b.first.get(),
/*writer=*/from_b_to_a.second.get());
Response response;
user_a.crypto.StartServer(
@@ -14,20 +14,24 @@
#include "connections/implementation/endpoint_channel_manager.h"
#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "securegcm/d2d_connection_context_v1.h"
#include "securegcm/ukey2_handshake.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "connections/implementation/base_endpoint_channel.h"
#include "connections/implementation/client_proxy.h"
#include "connections/implementation/encryption_runner.h"
#include "connections/implementation/endpoint_channel.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/exception.h"
#include "internal/platform/input_stream.h"
@@ -45,6 +49,7 @@ using ::location::nearby::proto::connections::DisconnectionReason;
using ::location::nearby::proto::connections::Medium;
using EncryptionContext = BaseEndpointChannel::EncryptionContext;
constexpr size_t kChunkSize = 64 * 1024;
constexpr absl::string_view kEndpointId = "EndpointId";
constexpr absl::string_view kMonitorA = "MonitorA";
constexpr absl::string_view kMonitorB = "MonitorB";
@@ -66,7 +71,7 @@ std::function<void()> MakeDataPump(
return [label, input, output, monitor]() {
NEARBY_LOGS(INFO) << "streaming data through '" << label << "'";
while (true) {
auto read_response = input->Read(Pipe::kChunkSize);
auto read_response = input->Read(kChunkSize);
if (!read_response.ok()) {
NEARBY_LOGS(INFO) << "Peer reader closed on '" << label << "'";
output->Close();
@@ -169,14 +174,18 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
std::string capture_b;
ClientProxy proxy_a;
ClientProxy proxy_b;
Pipe client_a; // Channel "a" writes to client "a", reads from server "a".
Pipe client_b; // Channel "b" writes to client "b", reads from server "b".
Pipe server_a; // Data pump "a" reads from client "a", writes to server "b".
Pipe server_b; // Data pump "b" reads from client "b", writes to server "a".
auto channel_a = std::make_unique<MockEndpointChannel>(
&server_a.GetInputStream(), &client_a.GetOutputStream());
auto channel_b = std::make_unique<MockEndpointChannel>(
&server_b.GetInputStream(), &client_b.GetOutputStream());
auto client_a =
CreatePipe(); // Channel "a" writes to client "a", reads from server "a".
auto client_b =
CreatePipe(); // Channel "b" writes to client "b", reads from server "b".
auto server_a = CreatePipe(); // Data pump "a" reads from client "a", writes
// to server "b".
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
// to server "a".
auto channel_a = std::make_unique<MockEndpointChannel>(server_a.first.get(),
client_a.second.get());
auto channel_b = std::make_unique<MockEndpointChannel>(server_b.first.get(),
client_b.second.get());
auto channel_a_raw = channel_a.get();
auto channel_b_raw = channel_b.get();
@@ -188,12 +197,12 @@ TEST(BaseEndpointChannelManagerTest, RegisterChannelEncryptedReadwrite) {
});
MultiThreadExecutor executor(2);
executor.Execute(MakeDataPump(
kPumpA, &client_a.GetInputStream(), &server_b.GetOutputStream(),
MakeDataMonitor(kMonitorA, &capture_a, &mutex)));
executor.Execute(MakeDataPump(
kPumpB, &client_b.GetInputStream(), &server_a.GetOutputStream(),
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
executor.Execute(
MakeDataPump(kPumpA, client_a.first.get(), server_b.second.get(),
MakeDataMonitor(kMonitorA, &capture_a, &mutex)));
executor.Execute(
MakeDataPump(kPumpB, client_b.first.get(), server_a.second.get(),
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
// Run DH key exchange; setup encryption contexts for channels.
auto context = DoDhKeyExchange(channel_a.get(), channel_b.get());
@@ -240,14 +249,18 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
std::string capture_b;
ClientProxy proxy_a;
ClientProxy proxy_b;
Pipe client_a; // Channel "a" writes to client "a", reads from server "a".
Pipe client_b; // Channel "b" writes to client "b", reads from server "b".
Pipe server_a; // Data pump "a" reads from client "a", writes to server "b".
Pipe server_b; // Data pump "b" reads from client "b", writes to server "a".
auto channel_a = std::make_unique<MockEndpointChannel>(
&server_a.GetInputStream(), &client_a.GetOutputStream());
auto channel_b = std::make_unique<MockEndpointChannel>(
&server_b.GetInputStream(), &client_b.GetOutputStream());
auto client_a =
CreatePipe(); // Channel "a" writes to client "a", reads from server "a".
auto client_b =
CreatePipe(); // Channel "b" writes to client "b", reads from server "b".
auto server_a = CreatePipe(); // Data pump "a" reads from client "a", writes
// to server "b".
auto server_b = CreatePipe(); // Data pump "b" reads from client "b", writes
// to server "a".
auto channel_a = std::make_unique<MockEndpointChannel>(server_a.first.get(),
client_a.second.get());
auto channel_b = std::make_unique<MockEndpointChannel>(server_b.first.get(),
client_b.second.get());
auto channel_a_raw = channel_a.get();
auto channel_b_raw = channel_b.get();
@@ -259,12 +272,12 @@ TEST(BaseEndpointChannelManagerTest, ReplaceChannelNoEncrypted) {
});
MultiThreadExecutor executor(2);
executor.Execute(MakeDataPump(
kPumpA, &client_a.GetInputStream(), &server_b.GetOutputStream(),
MakeDataMonitor(kMonitorA, &capture_a, &mutex)));
executor.Execute(MakeDataPump(
kPumpB, &client_b.GetInputStream(), &server_a.GetOutputStream(),
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
executor.Execute(
MakeDataPump(kPumpA, client_a.first.get(), server_b.second.get(),
MakeDataMonitor(kMonitorA, &capture_a, &mutex)));
executor.Execute(
MakeDataPump(kPumpB, client_b.first.get(), server_a.second.get(),
MakeDataMonitor(kMonitorB, &capture_b, &mutex)));
// Run DH key exchange; setup encryption contexts for channels.
auto context = DoDhKeyExchange(channel_a.get(), channel_b.get());
@@ -14,24 +14,25 @@
#include "connections/implementation/internal_payload_factory.h"
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include "absl/memory/memory.h"
#include "connections/implementation/offline_frames_validator.h"
#include "absl/strings/str_cat.h"
#include "connections/implementation/internal_payload.h"
#include "connections/implementation/proto/offline_wire_formats.pb.h"
#include "connections/payload.h"
#include "connections/payload_type.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/condition_variable.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/file.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/implementation/shared/file.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex.h"
#include "internal/platform/os_name.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
namespace nearby {
@@ -155,8 +156,9 @@ class OutgoingStreamInternalPayload : public InternalPayload {
class IncomingStreamInternalPayload : public InternalPayload {
public:
IncomingStreamInternalPayload(Payload payload, std::shared_ptr<Pipe> pipe)
: InternalPayload(std::move(payload)), pipe_(pipe) {}
IncomingStreamInternalPayload(Payload payload,
std::unique_ptr<OutputStream> output)
: InternalPayload(std::move(payload)), output_(std::move(output)) {}
PayloadTransferFrame::PayloadHeader::PayloadType GetType() const override {
return PayloadTransferFrame::PayloadHeader::STREAM;
@@ -174,7 +176,7 @@ class IncomingStreamInternalPayload : public InternalPayload {
return {Exception::kSuccess};
}
return pipe_->GetOutputStream().Write(chunk);
return output_->Write(chunk);
}
ExceptionOr<size_t> SkipToOffset(size_t offset) override {
@@ -183,10 +185,10 @@ class IncomingStreamInternalPayload : public InternalPayload {
return {Exception::kIo};
}
void Close() override { pipe_->GetOutputStream().Close(); }
void Close() override { output_->Close(); }
private:
std::shared_ptr<Pipe> pipe_;
std::unique_ptr<OutputStream> output_;
};
class OutgoingFileInternalPayload : public InternalPayload {
@@ -311,14 +313,14 @@ std::unique_ptr<InternalPayload> CreateOutgoingInternalPayload(
Payload payload) {
switch (payload.GetType()) {
case PayloadType::kBytes:
return absl::make_unique<BytesInternalPayload>(std::move(payload));
return std::make_unique<BytesInternalPayload>(std::move(payload));
case PayloadType::kFile: {
return absl::make_unique<OutgoingFileInternalPayload>(std::move(payload));
return std::make_unique<OutgoingFileInternalPayload>(std::move(payload));
}
case PayloadType::kStream:
return absl::make_unique<OutgoingStreamInternalPayload>(
return std::make_unique<OutgoingStreamInternalPayload>(
std::move(payload));
default:
@@ -359,19 +361,15 @@ std::unique_ptr<InternalPayload> CreateIncomingInternalPayload(
const Payload::Id payload_id = frame.payload_header().id();
switch (frame.payload_header().type()) {
case PayloadTransferFrame::PayloadHeader::BYTES: {
return absl::make_unique<BytesInternalPayload>(
return std::make_unique<BytesInternalPayload>(
Payload(payload_id, ByteArray(frame.payload_chunk().body())));
}
case PayloadTransferFrame::PayloadHeader::STREAM: {
auto pipe = std::make_shared<Pipe>();
auto [input, output] = CreatePipe();
return absl::make_unique<IncomingStreamInternalPayload>(
Payload(payload_id,
[pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}),
pipe);
return std::make_unique<IncomingStreamInternalPayload>(
Payload(payload_id, std::move(input)), std::move(output));
}
case PayloadTransferFrame::PayloadHeader::FILE: {
@@ -411,11 +409,11 @@ std::unique_ptr<InternalPayload> CreateIncomingInternalPayload(
// there will be no input file to open.
// On Chrome the file path should be empty, so use the payload id.
if (ImplementationPlatform::GetCurrentOS() == OSName::kChromeOS) {
return absl::make_unique<IncomingFileInternalPayload>(
return std::make_unique<IncomingFileInternalPayload>(
Payload(payload_id, InputFile(payload_id, total_size)),
OutputFile(payload_id), total_size);
} else {
return absl::make_unique<IncomingFileInternalPayload>(
return std::make_unique<IncomingFileInternalPayload>(
Payload(payload_id, parent_folder, file_name,
InputFile(file_path, total_size)),
OutputFile(file_path), total_size);
@@ -14,15 +14,19 @@
#include "connections/implementation/internal_payload_factory.h"
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "connections/implementation/offline_frames.h"
#include "connections/implementation/internal_payload.h"
#include "connections/implementation/proto/offline_wire_formats.pb.h"
#include "connections/payload.h"
#include "connections/payload_type.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/file.h"
#include "internal/platform/pipe.h"
namespace nearby {
@@ -44,11 +48,9 @@ TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromBytePayload) {
}
TEST(InternalPayloadFactoryTest, CanCreateInternalPayloadFromStreamPayload) {
auto pipe = std::make_shared<Pipe>();
auto [input, output] = CreatePipe();
std::unique_ptr<InternalPayload> internal_payload =
CreateOutgoingInternalPayload(Payload{[pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}});
CreateOutgoingInternalPayload(Payload(std::move(input)));
EXPECT_NE(internal_payload, nullptr);
Payload payload = internal_payload->ReleasePayload();
EXPECT_EQ(payload.AsFile(), nullptr);
@@ -212,13 +214,11 @@ TEST(InternalPayloadFactoryTest,
SkipToOffset_StreamPayloadValidOffset_SkipsOffset) {
ByteArray contents("0123456789");
constexpr size_t kOffset = 6;
auto pipe = std::make_shared<Pipe>();
auto [input, output] = CreatePipe();
std::unique_ptr<InternalPayload> internal_payload =
CreateOutgoingInternalPayload(Payload{[pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}});
CreateOutgoingInternalPayload(Payload(std::move(input)));
EXPECT_NE(internal_payload, nullptr);
pipe->GetOutputStream().Write(contents);
output->Write(contents);
ExceptionOr<size_t> result = internal_payload->SkipToOffset(kOffset);
@@ -12,10 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdint>
#include <string>
#include <tuple>
#include <utility>
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/pipe.h"
#ifndef NO_WEBRTC
#include "connections/implementation/mediums/webrtc/webrtc_socket_impl.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
@@ -61,6 +69,7 @@ WebRtcSocket::WebRtcSocket(
: name_(name), data_channel_(std::move(data_channel)) {
NEARBY_LOGS(INFO) << "WebRtcSocket::WebRtcSocket(" << name_
<< ") this: " << this;
std::tie(pipe_input_, pipe_output_) = CreatePipe();
data_channel_->RegisterObserver(this);
}
@@ -77,7 +86,7 @@ WebRtcSocket::~WebRtcSocket() {
<< ") this: " << this << " done";
}
InputStream& WebRtcSocket::GetInputStream() { return pipe_.GetInputStream(); }
InputStream& WebRtcSocket::GetInputStream() { return *pipe_input_; }
OutputStream& WebRtcSocket::GetOutputStream() { return output_stream_; }
@@ -129,12 +138,12 @@ void WebRtcSocket::OnMessage(const webrtc::DataBuffer& buffer) {
// we don't block signaling.
OffloadFromSignalingThread(
[this, buffer = ByteArray(buffer.data.data<char>(), buffer.size())] {
if (!pipe_.GetOutputStream().Write(buffer).Ok()) {
if (!pipe_output_->Write(buffer).Ok()) {
Close();
return;
}
if (!pipe_.GetOutputStream().Flush().Ok()) {
if (!pipe_output_->Flush().Ok()) {
Close();
}
});
@@ -159,8 +168,8 @@ void WebRtcSocket::ClosePipe() {
// This is thread-safe to close these sockets even if a read or write is in
// process on another thread, Close will wait for the exclusive mutex before
// setting state.
pipe_.GetInputStream().Close();
pipe_.GetOutputStream().Close();
pipe_input_->Close();
pipe_output_->Close();
WakeUpWriter();
NEARBY_LOGS(INFO) << "WebRtcSocket::ClosePipe(" << name_ << ") this: " << this
<< " done";
@@ -100,8 +100,8 @@ class WebRtcSocket : public Socket, public webrtc::DataChannelObserver {
std::string name_;
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel_;
Pipe pipe_;
std::unique_ptr<InputStream> pipe_input_;
std::unique_ptr<OutputStream> pipe_output_;
OutputStreamImpl output_stream_{this};
AtomicBoolean closed_{false};
@@ -12,31 +12,42 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "connections/implementation/offline_service_controller.h"
#include <array>
#include <cstddef>
#include <string>
#include <utility>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "connections/advertising_options.h"
#include "connections/discovery_options.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "connections/implementation/offline_simulation_user.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/out_of_band_connection_metadata.h"
#include "connections/payload.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/output_stream.h"
#include "internal/platform/pipe.h"
#include "internal/platform/system_clock.h"
#include "proto/connections_enums.proto.h"
namespace nearby {
namespace connections {
namespace {
using ::testing::Eq;
constexpr size_t kChunkSize = 64 * 1024;
constexpr std::array<char, 6> kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'};
constexpr absl::string_view kServiceId = "service-id";
constexpr absl::string_view kDeviceA = "device-a";
@@ -302,12 +313,9 @@ TEST_P(OfflineServiceControllerTest, CanSendStreamPayload) {
user_b.ExpectPayload(payload_latch_);
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
}));
tx.Write(message);
auto [input, tx] = CreatePipe();
user_a.SendPayload(Payload(std::move(input)));
tx->Write(message);
EXPECT_TRUE(payload_latch_.Await(kLongTimeout));
ASSERT_NE(user_b.GetPayload().AsStream(), nullptr);
InputStream& rx = *user_b.GetPayload().AsStream();
@@ -316,7 +324,7 @@ TEST_P(OfflineServiceControllerTest, CanSendStreamPayload) {
return info.bytes_transferred >= size;
},
kLongTimeout));
EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message);
EXPECT_EQ(rx.Read(kChunkSize).result(), message);
user_a.Stop();
user_b.Stop();
env_.Stop();
@@ -329,12 +337,9 @@ TEST_P(OfflineServiceControllerTest, CanCancelStreamPayload) {
user_b.ExpectPayload(payload_latch_);
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
}));
tx.Write(message);
auto [input, tx] = CreatePipe();
user_a.SendPayload(Payload(std::move(input)));
tx->Write(message);
EXPECT_TRUE(payload_latch_.Await(kLongTimeout));
ASSERT_NE(user_b.GetPayload().AsStream(), nullptr);
InputStream& rx = *user_b.GetPayload().AsStream();
@@ -343,11 +348,11 @@ TEST_P(OfflineServiceControllerTest, CanCancelStreamPayload) {
return info.bytes_transferred >= size;
},
kLongTimeout));
EXPECT_EQ(rx.Read(Pipe::kChunkSize).result(), message);
EXPECT_EQ(rx.Read(kChunkSize).result(), message);
user_b.CancelPayload();
absl::Time start_time = SystemClock::ElapsedRealtime();
while (true) {
if (!tx.Write(message).Ok()) break;
if (!tx->Write(message).Ok()) break;
absl::Duration run_time = SystemClock::ElapsedRealtime() - start_time;
if (run_time >= kLongTimeout) {
EXPECT_LT(run_time, kLongTimeout);
@@ -14,19 +14,29 @@
#include "connections/implementation/payload_manager.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include <cstddef>
#include <string>
#include <utility>
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "connections/implementation/simulation_user.h"
#include "connections/listeners.h"
#include "connections/medium_selector.h"
#include "connections/payload.h"
#include "connections/status.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/pipe.h"
#include "internal/platform/system_clock.h"
namespace nearby {
namespace connections {
namespace {
constexpr size_t kChunkSize = 64 * 1024;
constexpr absl::string_view kServiceId = "service-id";
constexpr absl::string_view kDeviceA = "device-a";
constexpr absl::string_view kDeviceB = "device-b";
@@ -165,18 +175,14 @@ TEST_P(PayloadManagerTest, CanSendStreamPayload) {
PayloadSimulationUser user_b(kDeviceB, GetParam());
ASSERT_TRUE(SetupConnection(user_a, user_b));
auto pipe = std::make_shared<Pipe>();
OutputStream& tx = pipe->GetOutputStream();
auto [input, tx] = CreatePipe();
user_a.ExpectPayload(payload_latch_);
const ByteArray message{std::string(kMessage)};
// The first write to the output stream will send the first PAYLOAD_TRANSFER
// packet with payload info and message data.
tx.Write(message);
tx->Write(message);
user_b.SendPayload(Payload([pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}));
user_b.SendPayload(Payload(std::move(input)));
ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
ASSERT_NE(user_a.GetPayload().AsStream(), nullptr);
InputStream& rx = *user_a.GetPayload().AsStream();
@@ -187,22 +193,22 @@ TEST_P(PayloadManagerTest, CanSendStreamPayload) {
return info.bytes_transferred >= message.size();
},
kProgressTimeout));
ByteArray result = rx.Read(Pipe::kChunkSize).result();
ByteArray result = rx.Read(kChunkSize).result();
EXPECT_EQ(result, message);
NEARBY_LOG(INFO, "Packet 1 handled.");
tx.Write(message);
tx->Write(message);
EXPECT_TRUE(user_a.WaitForProgress(
[&message](const PayloadProgressInfo& info) {
return info.bytes_transferred >= 2 * message.size();
},
kProgressTimeout));
ByteArray result2 = rx.Read(Pipe::kChunkSize).result();
ByteArray result2 = rx.Read(kChunkSize).result();
EXPECT_EQ(result2, message);
NEARBY_LOG(INFO, "Packet 2 handled.");
rx.Close();
tx.Close();
tx->Close();
NEARBY_LOG(INFO, "Test completed.");
user_a.Stop();
user_b.Stop();
@@ -214,17 +220,12 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnReceiverSide) {
PayloadSimulationUser user_a(kDeviceA, GetParam());
PayloadSimulationUser user_b(kDeviceB, GetParam());
ASSERT_TRUE(SetupConnection(user_a, user_b));
auto pipe = std::make_shared<Pipe>();
OutputStream& tx = pipe->GetOutputStream();
auto [input, tx] = CreatePipe();
user_a.ExpectPayload(payload_latch_);
const ByteArray message{std::string(kMessage)};
tx.Write(message);
tx->Write(message);
user_b.SendPayload(Payload([pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}));
user_b.SendPayload(Payload(std::move(input)));
ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
ASSERT_NE(user_a.GetPayload().AsStream(), nullptr);
InputStream& rx = *user_a.GetPayload().AsStream();
@@ -235,7 +236,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnReceiverSide) {
return info.bytes_transferred >= message.size();
},
kProgressTimeout));
ByteArray result = rx.Read(Pipe::kChunkSize).result();
ByteArray result = rx.Read(kChunkSize).result();
EXPECT_EQ(result, message);
NEARBY_LOG(INFO, "Packet 1 handled.");
@@ -246,7 +247,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnReceiverSide) {
// Once cancel is handled, write will fail.
int count = 0;
while (true) {
if (!tx.Write(message).Ok()) break;
if (!tx->Write(message).Ok()) break;
SystemClock::Sleep(kDefaultTimeout);
count++;
}
@@ -258,7 +259,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnReceiverSide) {
kProgressTimeout));
NEARBY_LOG(INFO, "Stream cancelation received.");
tx.Close();
tx->Close();
rx.Close();
NEARBY_LOG(INFO, "Test completed.");
@@ -272,17 +273,12 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnSenderSide) {
PayloadSimulationUser user_a(kDeviceA, GetParam());
PayloadSimulationUser user_b(kDeviceB, GetParam());
ASSERT_TRUE(SetupConnection(user_a, user_b));
auto pipe = std::make_shared<Pipe>();
OutputStream& tx = pipe->GetOutputStream();
auto [input, tx] = CreatePipe();
user_a.ExpectPayload(payload_latch_);
const ByteArray message{std::string(kMessage)};
tx.Write(message);
tx->Write(message);
user_b.SendPayload(Payload([pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
}));
user_b.SendPayload(Payload(std::move(input)));
ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
ASSERT_NE(user_a.GetPayload().AsStream(), nullptr);
InputStream& rx = *user_a.GetPayload().AsStream();
@@ -293,7 +289,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnSenderSide) {
return info.bytes_transferred >= message.size();
},
kProgressTimeout));
ByteArray result = rx.Read(Pipe::kChunkSize).result();
ByteArray result = rx.Read(kChunkSize).result();
EXPECT_EQ(result, message);
NEARBY_LOG(INFO, "Packet 1 handled.");
@@ -304,7 +300,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnSenderSide) {
// Once cancel is handled, write will fail.
int count = 0;
while (true) {
if (!tx.Write(message).Ok()) break;
if (!tx->Write(message).Ok()) break;
SystemClock::Sleep(kDefaultTimeout);
count++;
}
@@ -316,7 +312,7 @@ TEST_P(PayloadManagerTest, CanCancelPayloadOnSenderSide) {
kProgressTimeout));
NEARBY_LOG(INFO, "Stream cancelation received.");
tx.Close();
tx->Close();
rx.Close();
NEARBY_LOG(INFO, "Test completed.");
@@ -331,19 +327,14 @@ TEST_P(PayloadManagerTest, SendPayloadWithSkip_StreamPayload) {
PayloadSimulationUser user_a(kDeviceA, GetParam());
PayloadSimulationUser user_b(kDeviceB, GetParam());
ASSERT_TRUE(SetupConnection(user_a, user_b));
auto pipe = std::make_shared<Pipe>();
OutputStream& tx = pipe->GetOutputStream();
auto [input, tx] = CreatePipe();
user_a.ExpectPayload(payload_latch_);
const ByteArray message{std::string(kMessage)};
// The first write to the output stream will send the first PAYLOAD_TRANSFER
// packet with payload info and message data.
tx.Write(message);
tx->Write(message);
Payload payload([pipe]() -> InputStream& {
return pipe->GetInputStream(); // NOLINT
});
Payload payload(std::move(input));
payload.SetOffset(kOffset);
user_b.SendPayload(std::move(payload));
ASSERT_TRUE(payload_latch_.Await(kDefaultTimeout).result());
@@ -356,22 +347,22 @@ TEST_P(PayloadManagerTest, SendPayloadWithSkip_StreamPayload) {
return info.bytes_transferred >= message.size() - kOffset;
},
kProgressTimeout));
ByteArray result = rx.Read(Pipe::kChunkSize).result();
ByteArray result = rx.Read(kChunkSize).result();
EXPECT_EQ(result, ByteArray("sage"));
NEARBY_LOG(INFO, "Packet 1 handled.");
tx.Write(message);
tx->Write(message);
EXPECT_TRUE(user_a.WaitForProgress(
[&message](const PayloadProgressInfo& info) {
return info.bytes_transferred >= 2 * message.size() - kOffset;
},
kProgressTimeout));
ByteArray result2 = rx.Read(Pipe::kChunkSize).result();
ByteArray result2 = rx.Read(kChunkSize).result();
EXPECT_EQ(result2, message);
NEARBY_LOG(INFO, "Packet 2 handled.");
rx.Close();
tx.Close();
tx->Close();
NEARBY_LOG(INFO, "Test completed.");
user_a.Stop();
user_b.Stop();