diff --git a/Package.swift b/Package.swift index cf908132..9524da8a 100644 --- a/Package.swift +++ b/Package.swift @@ -459,6 +459,7 @@ let package = Package( "connections/implementation/base_endpoint_channel_test.cc", "connections/v3/connections_device_test.cc", "connections/v3/connections_device_provider_test.cc", + "connections/implementation/connections_authentication_transport_test.cc", "connections/core_test.cc", "connections/status_test.cc", "connections/payload_test.cc", diff --git a/connections/implementation/BUILD b/connections/implementation/BUILD index ffbde30f..546f98ce 100644 --- a/connections/implementation/BUILD +++ b/connections/implementation/BUILD @@ -27,6 +27,7 @@ cc_library( "bluetooth_endpoint_channel.cc", "bwu_manager.cc", "client_proxy.cc", + "connections_authentication_transport.cc", "encryption_runner.cc", "endpoint_channel_manager.cc", "endpoint_manager.cc", @@ -66,6 +67,7 @@ cc_library( "bwu_handler.h", "bwu_manager.h", "client_proxy.h", + "connections_authentication_transport.h", "encryption_runner.h", "endpoint_channel.h", "endpoint_channel_manager.h", @@ -116,6 +118,7 @@ cc_library( "//connections/v3:v3_types", "//internal/analytics:event_logger", "//internal/flags:nearby_flags", + "//internal/interop:authentication_transport_interface", "//internal/interop:device", "//internal/platform:base", "//internal/platform:cancellation_flag", @@ -199,6 +202,7 @@ cc_test( "bluetooth_device_name_test.cc", "bwu_manager_test.cc", "client_proxy_test.cc", + "connections_authentication_transport_test.cc", "encryption_runner_test.cc", "endpoint_channel_manager_test.cc", "endpoint_manager_test.cc", diff --git a/connections/implementation/connections_authentication_transport.cc b/connections/implementation/connections_authentication_transport.cc new file mode 100644 index 00000000..21c4c316 --- /dev/null +++ b/connections/implementation/connections_authentication_transport.cc @@ -0,0 +1,53 @@ +// Copyright 2023 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 "connections/implementation/connections_authentication_transport.h" + +#include + +#include "absl/strings/string_view.h" +#include "connections/implementation/endpoint_channel.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace connections { + +ConnectionsAuthenticationTransport::ConnectionsAuthenticationTransport( + const EndpointChannel& channel) { + channel_ = const_cast(&channel); +} + +void ConnectionsAuthenticationTransport::WriteMessage( + absl::string_view message) const { + // channel_ should never be null. + CHECK(channel_ != nullptr); + channel_->Write(ByteArray(message.data(), message.size())); +} + +std::string ConnectionsAuthenticationTransport::ReadMessage() const { + // channel_ should never be null. + CHECK(channel_ != nullptr); + auto response = channel_->Read(); + if (response.ok()) { + return response.result().string_data(); + } + NEARBY_LOGS(WARNING) << "ConnectionsAuthenticationTransport: read failed " + "with exception/result: " + << response.exception(); + return ""; +} + +} // namespace connections +} // namespace nearby diff --git a/connections/implementation/connections_authentication_transport.h b/connections/implementation/connections_authentication_transport.h new file mode 100644 index 00000000..ab7886d4 --- /dev/null +++ b/connections/implementation/connections_authentication_transport.h @@ -0,0 +1,44 @@ +// Copyright 2023 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 THIRD_PARTY_NEARBY_CONNECTIONS_IMPLEMENTATION_CONNECTIONS_AUTHENTICATION_TRANSPORT_H_ +#define THIRD_PARTY_NEARBY_CONNECTIONS_IMPLEMENTATION_CONNECTIONS_AUTHENTICATION_TRANSPORT_H_ + +#include + +#include "absl/strings/string_view.h" +#include "connections/implementation/endpoint_channel.h" +#include "internal/interop/authentication_transport.h" + +namespace nearby { +namespace connections { + +// The messages passed through this channel should not be UTF-8 decoded, as they +// will consist of protobuf-serialized data, and std::string is used as a +// container for bytes. +class ConnectionsAuthenticationTransport + : public nearby::AuthenticationTransport { + public: + explicit ConnectionsAuthenticationTransport(const EndpointChannel& channel); + void WriteMessage(absl::string_view message) const override; + std::string ReadMessage() const override; + + private: + EndpointChannel* channel_; +}; + +} // namespace connections +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_CONNECTIONS_IMPLEMENTATION_CONNECTIONS_AUTHENTICATION_TRANSPORT_H_ diff --git a/connections/implementation/connections_authentication_transport_test.cc b/connections/implementation/connections_authentication_transport_test.cc new file mode 100644 index 00000000..492430e0 --- /dev/null +++ b/connections/implementation/connections_authentication_transport_test.cc @@ -0,0 +1,110 @@ +// Copyright 2023 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 "connections/implementation/connections_authentication_transport.h" + +#include +#include +#include + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" +#include "connections/implementation/endpoint_channel.h" +#include "internal/platform/byte_array.h" +#include "internal/platform/exception.h" +#include "proto/connections_enums.pb.h" + +namespace nearby { +namespace connections { +namespace { + +using ::testing::_; + +class MockEndpointChannel : public EndpointChannel { + public: + MOCK_METHOD(ExceptionOr, Read, (), (override)); + MOCK_METHOD(ExceptionOr, Read, (PacketMetaData&), (override)); + MOCK_METHOD(Exception, Write, (const ByteArray& data), (override)); + MOCK_METHOD(Exception, Write, (const ByteArray&, PacketMetaData&), + (override)); + MOCK_METHOD(void, Close, (), (override)); + MOCK_METHOD( + void, Close, + (location::nearby::proto::connections::DisconnectionReason reason), + (override)); + MOCK_METHOD(std::string, GetType, (), (const override)); + MOCK_METHOD(std::string, GetServiceId, (), (const override)); + MOCK_METHOD(std::string, GetName, (), (const override)); + MOCK_METHOD(location::nearby::proto::connections::Medium, GetMedium, (), + (const override)); + MOCK_METHOD(location::nearby::proto::connections::ConnectionTechnology, + GetTechnology, (), (const override)); + MOCK_METHOD(location::nearby::proto::connections::ConnectionBand, GetBand, (), + (const override)); + MOCK_METHOD(int, GetFrequency, (), (const override)); + MOCK_METHOD(int, GetTryCount, (), (const override)); + MOCK_METHOD(int, GetMaxTransmitPacketSize, (), (const override)); + MOCK_METHOD(void, EnableEncryption, (std::shared_ptr), + (override)); + MOCK_METHOD(void, DisableEncryption, (), (override)); + MOCK_METHOD(bool, IsPaused, (), (const override)); + MOCK_METHOD(void, Pause, (), (override)); + MOCK_METHOD(void, Resume, (), (override)); + MOCK_METHOD(absl::Time, GetLastReadTimestamp, (), (const override)); + MOCK_METHOD(absl::Time, GetLastWriteTimestamp, (), (const override)); + MOCK_METHOD(void, SetAnalyticsRecorder, + (analytics::AnalyticsRecorder*, const std::string&), (override)); + + std::vector messages_; +}; + +TEST(ConnectionsAuthenticationTransportTest, TestWriteMessage) { + MockEndpointChannel channel; + ConnectionsAuthenticationTransport transport(channel); + EXPECT_CALL(channel, Write(_)).WillOnce([&channel](const ByteArray& data) { + channel.messages_.push_back(data.string_data()); + return Exception{ + .value = Exception::Value::kSuccess, + }; + }); + transport.WriteMessage("hello world"); + EXPECT_THAT(channel.messages_, testing::ElementsAre("hello world")); +} + +TEST(ConnectionsAuthenticationTransportTest, TestReadMessage) { + MockEndpointChannel channel; + ConnectionsAuthenticationTransport transport(channel); + channel.messages_.push_back("hello world"); + EXPECT_CALL(channel, Read()).WillOnce([&channel]() { + std::string ret = channel.messages_[0]; + channel.messages_.erase(channel.messages_.begin()); + return ExceptionOr(ByteArray(ret)); + }); + EXPECT_EQ(transport.ReadMessage(), "hello world"); +} + +TEST(ConnectionsAuthenticationTransportTest, TestReadMessageFail) { + MockEndpointChannel channel; + ConnectionsAuthenticationTransport transport(channel); + channel.messages_.push_back("hello world"); + EXPECT_CALL(channel, Read()).WillOnce([]() { + return ExceptionOr(Exception::Value::kIo); + }); + EXPECT_EQ(transport.ReadMessage(), ""); +} + +} // namespace +} // namespace connections +} // namespace nearby