Move remaining payload processing into ShareTargetInfo.

PiperOrigin-RevId: 646185948
This commit is contained in:
Francis Tsui
2024-06-24 12:36:44 -07:00
committed by Copybara-Service
parent cdd6870af2
commit 822e1af2a5
15 changed files with 1069 additions and 496 deletions
+6 -1
View File
@@ -199,7 +199,6 @@ cc_library(
"//sharing/internal/public:types",
"//sharing/proto:wire_format_cc_proto",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
@@ -758,12 +757,15 @@ cc_test(
":attachments",
":connection_types",
":share_target_info",
":test_support",
":transfer_metadata",
":types",
"//internal/platform/implementation/g3", # fixdeps: keep
"//sharing/internal/test:nearby_test",
"//sharing/proto:wire_format_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
],
)
@@ -774,11 +776,14 @@ cc_test(
deps = [
":attachment_compare",
":attachments",
":connection_types",
":share_target_info",
":test_support",
":transfer_metadata",
":types",
"//internal/platform/implementation/g3", # fixdeps: keep
"//sharing/internal/public:logging",
"//sharing/internal/test:nearby_test",
"//sharing/proto:wire_format_cc_proto",
"//third_party/protobuf",
"@com_github_protobuf_matchers//protobuf-matchers",
-16
View File
@@ -83,20 +83,4 @@ void AttachmentContainer::Clear() {
wifi_credentials_attachments_.clear();
}
std::vector<int64_t> AttachmentContainer::GetAttachmentIds() const {
std::vector<int64_t> attachment_ids;
attachment_ids.reserve(GetAttachmentCount());
for (const auto& file : file_attachments_)
attachment_ids.push_back(file.id());
for (const auto& text : text_attachments_)
attachment_ids.push_back(text.id());
for (const auto& wifi_credentials : wifi_credentials_attachments_)
attachment_ids.push_back(wifi_credentials.id());
return attachment_ids;
}
} // namespace nearby::sharing
-3
View File
@@ -99,9 +99,6 @@ class AttachmentContainer {
// Delete all attachments.
void Clear();
// Returns the list of attachment IDs of attachments in this container.
std::vector<int64_t> GetAttachmentIds() const;
private:
std::vector<TextAttachment> text_attachments_;
std::vector<FileAttachment> file_attachments_;
-13
View File
@@ -192,19 +192,6 @@ TEST_F(AttachmentContainerTest, Clear) {
EXPECT_THAT(container.HasAttachments(), IsFalse());
}
TEST_F(AttachmentContainerTest, GetAttachmentIds) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
std::vector<WifiCredentialsAttachment>{wifi1_});
std::vector<int64_t> attachment_ids = container.GetAttachmentIds();
EXPECT_THAT(attachment_ids, SizeIs(4));
EXPECT_THAT(attachment_ids,
UnorderedElementsAre(text1_.id(), text2_.id(), file1_.id(),
wifi1_.id()));
}
TEST_F(AttachmentContainerTest, GetStorageSize) {
AttachmentContainer container(std::vector<TextAttachment>{text1_, text2_},
std::vector<FileAttachment>{file1_},
+180
View File
@@ -15,17 +15,26 @@
#include "sharing/incoming_share_target_info.h"
#include <cstdint>
#include <filesystem> // NOLINT
#include <functional>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "sharing/attachment_container.h"
#include "sharing/common/compatible_u8_string.h"
#include "sharing/constants.h"
#include "sharing/file_attachment.h"
#include "sharing/internal/public/context.h"
#include "sharing/internal/public/logging.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/payload_tracker.h"
#include "sharing/proto/wire_format.pb.h"
#include "sharing/share_target.h"
#include "sharing/share_target_info.h"
@@ -37,6 +46,7 @@ namespace nearby::sharing {
namespace {
using ::nearby::sharing::service::proto::IntroductionFrame;
using ::nearby::sharing::service::proto::WifiCredentials;
} // namespace
@@ -139,4 +149,174 @@ IncomingShareTargetInfo::ProcessIntroduction(
return std::nullopt;
}
void IncomingShareTargetInfo::RegisterPayloadListener(
Context* context,
NearbyConnectionsManager& connections_manager,
std::function<void(int64_t, TransferMetadata)> update_callback) {
const absl::flat_hash_map<int64_t, int64_t>& payload_map =
attachment_payload_map();
set_payload_tracker(std::make_shared<PayloadTracker>(
context, share_target().id, attachment_container(),
payload_map, std::move(update_callback)));
// Register status listener for all payloads.
for (auto it = payload_map.begin(); it != payload_map.end(); ++it) {
NL_VLOG(1) << __func__ << ": Started listening for progress on payload: "
<< it->second << " for attachment: " << it->first;
connections_manager.RegisterPayloadStatusListener(it->second,
payload_tracker());
NL_VLOG(1) << __func__ << ": Accepted incoming files from share target - "
<< share_target().id;
}
}
bool IncomingShareTargetInfo::UpdateFilePayloadPaths(
const NearbyConnectionsManager& connections_manager) {
AttachmentContainer& container = mutable_attachment_container();
bool result = true;
for (int i = 0; i < container.GetFileAttachments().size(); ++i) {
FileAttachment& file = container.GetMutableFileAttachment(i);
// Skip file if it already has file_path set.
if (file.file_path().has_value()) {
continue;
}
const auto it = attachment_payload_map().find(file.id());
if (it == attachment_payload_map().end()) {
NL_LOG(WARNING) << __func__ << ": No payload id found for file - "
<< file.id();
result = false;
continue;
}
const Payload* incoming_payload =
connections_manager.GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_file()) {
NL_LOG(WARNING) << __func__ << ": No payload found for file - "
<< file.id();
result = false;
continue;
}
auto file_path = incoming_payload->content.file_payload.file.path;
NL_VLOG(1) << __func__ << ": Updated file_path="
<< GetCompatibleU8String(file_path.u8string());
file.set_file_path(file_path);
}
return result;
}
bool IncomingShareTargetInfo::UpdatePayloadContents(
const NearbyConnectionsManager& connections_manager) {
if (!UpdateFilePayloadPaths(connections_manager)) {
return false;
}
AttachmentContainer& container = mutable_attachment_container();
for (int i = 0; i < container.GetTextAttachments().size(); ++i) {
TextAttachment& text = container.GetMutableTextAttachment(i);
const auto it = attachment_payload_map().find(text.id());
if (it == attachment_payload_map().end()) {
// This should never happen unless IntroductionFrame has not been
// processed.
NL_LOG(WARNING) << __func__ << ": No payload id found for text - "
<< text.id();
return false;
}
const Payload* incoming_payload =
connections_manager.GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_bytes()) {
NL_LOG(WARNING) << __func__ << ": No payload found for text - "
<< text.id();
return false;
}
std::vector<uint8_t> bytes = incoming_payload->content.bytes_payload.bytes;
if (bytes.empty()) {
NL_LOG(WARNING)
<< __func__
<< ": Incoming bytes is empty for text payload with payload_id - "
<< it->second;
return false;
}
std::string text_body(bytes.begin(), bytes.end());
text.set_text_body(text_body);
}
for (int i = 0; i < container.GetWifiCredentialsAttachments().size(); ++i) {
WifiCredentialsAttachment& wifi_credentials_attachment =
container.GetMutableWifiCredentialsAttachment(i);
const auto it =
attachment_payload_map().find(wifi_credentials_attachment.id());
if (it == attachment_payload_map().end()) {
// This should never happen unless IntroductionFrame has not been
// processed.
NL_LOG(WARNING) << __func__
<< ": No payload id found for WiFi credentials - "
<< wifi_credentials_attachment.id();
return false;
}
const Payload* incoming_payload =
connections_manager.GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_bytes()) {
NL_LOG(WARNING) << __func__
<< ": No payload found for WiFi credentials - "
<< wifi_credentials_attachment.id();
return false;
}
std::vector<uint8_t> bytes = incoming_payload->content.bytes_payload.bytes;
if (bytes.empty()) {
NL_LOG(WARNING) << __func__
<< ": Incoming bytes is empty for WiFi credentials "
"payload with payload_id - "
<< it->second;
return false;
}
WifiCredentials wifi_credentials;
if (!wifi_credentials.ParseFromArray(bytes.data(), bytes.size())) {
NL_LOG(WARNING) << __func__
<< ": Incoming bytes is invalid for WiFi credentials "
"payload with payload_id - "
<< it->second;
return false;
}
wifi_credentials_attachment.set_password(wifi_credentials.password());
wifi_credentials_attachment.set_is_hidden(wifi_credentials.hidden_ssid());
}
return true;
}
bool IncomingShareTargetInfo::FinalizePayloads(
const NearbyConnectionsManager& connections_manager) {
if (!UpdatePayloadContents(connections_manager)) {
mutable_attachment_container().ClearAttachments();
return false;
}
return true;
}
std::vector<std::filesystem::path>
IncomingShareTargetInfo::GetPayloadFilePaths() const {
std::vector<std::filesystem::path> file_paths;
const AttachmentContainer& container = attachment_container();
const absl::flat_hash_map<int64_t, int64_t>& attachment_paylod_map =
attachment_payload_map();
for (const auto& file : container.GetFileAttachments()) {
if (!file.file_path().has_value()) continue;
auto file_path = *file.file_path();
NL_VLOG(1) << __func__
<< ": file_path=" << GetCompatibleU8String(file_path.u8string());
if (attachment_paylod_map.find(file.id()) == attachment_paylod_map.end()) {
continue;
}
file_paths.push_back(file_path);
}
return file_paths;
}
} // namespace nearby::sharing
+27
View File
@@ -15,10 +15,16 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_INCOMING_SHARE_TARGET_INFO_H_
#define THIRD_PARTY_NEARBY_SHARING_INCOMING_SHARE_TARGET_INFO_H_
#include <cstdint>
#include <filesystem> // NOLINT
#include <functional>
#include <optional>
#include <string>
#include <vector>
#include "sharing/internal/public/context.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/proto/wire_format.pb.h"
#include "sharing/share_target.h"
#include "sharing/share_target_info.h"
@@ -46,11 +52,32 @@ class IncomingShareTargetInfo : public ShareTargetInfo {
const nearby::sharing::service::proto::IntroductionFrame&
introduction_frame);
// Update file attachment paths with payload paths.
bool UpdateFilePayloadPaths(
const NearbyConnectionsManager& connections_manager);
void RegisterPayloadListener(
Context* context,
NearbyConnectionsManager& connections_manager,
std::function<void(int64_t, TransferMetadata)> update_callback);
// Once transfer has completed, make payload content available in the
// corresponding Attachment.
// Returns true if all payloads were successfully finalized.
bool FinalizePayloads(const NearbyConnectionsManager& connections_manager);
// Returns the file paths of all file payloads.
std::vector<std::filesystem::path> GetPayloadFilePaths() const;
protected:
void InvokeTransferUpdateCallback(const TransferMetadata& metadata) override;
bool OnNewConnection(NearbyConnection* connection) override;
private:
// Copy payload contents from the NearbyConnection to the Attachment.
bool UpdatePayloadContents(
const NearbyConnectionsManager& connections_manager);
std::function<void(const IncomingShareTargetInfo&, const TransferMetadata&)>
transfer_update_callback_;
};
+346
View File
@@ -15,18 +15,24 @@
#include "sharing/incoming_share_target_info.h"
#include <cstdint>
#include <filesystem> // NOLINT
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "sharing/attachment_compare.h" // IWYU pragma: keep
#include "sharing/fake_nearby_connections_manager.h"
#include "sharing/file_attachment.h"
#include "sharing/internal/public/logging.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/proto/wire_format.pb.h"
#include "sharing/share_target.h"
#include "sharing/text_attachment.h"
@@ -40,14 +46,43 @@ namespace {
using ::nearby::sharing::service::proto::FileMetadata;
using ::nearby::sharing::service::proto::IntroductionFrame;
using ::nearby::sharing::service::proto::TextMetadata;
using ::nearby::sharing::service::proto::WifiCredentials;
using ::nearby::sharing::service::proto::WifiCredentialsMetadata;
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::IsFalse;
using ::testing::IsTrue;
using ::testing::UnorderedElementsAre;
constexpr absl::string_view kEndpointId = "ABCD";
std::unique_ptr<Payload> CreateFilePayload(int64_t payload_id,
std::filesystem::path file_path) {
auto file_payload =
std::make_unique<Payload>(InputFile(std::move(file_path)));
file_payload->id = payload_id;
return file_payload;
}
std::unique_ptr<Payload> CreateTextPayload(int64_t payload_id,
std::string text_body) {
auto text_payload =
std::make_unique<Payload>(text_body.data(), text_body.size());
text_payload->id = payload_id;
return text_payload;
}
std::unique_ptr<Payload> CreateWifiCredentialsPayload(
int64_t payload_id, const std::string& password, bool is_hidden) {
WifiCredentials wifi_credentials;
wifi_credentials.set_password(password);
wifi_credentials.set_hidden_ssid(is_hidden);
std::string wifi_content = wifi_credentials.SerializeAsString();
auto wifi_payload =
std::make_unique<Payload>(wifi_content.data(), wifi_content.size());
wifi_payload->id = payload_id;
return wifi_payload;
}
class IncomingShareTargetInfoTest : public ::testing::Test {
protected:
IncomingShareTargetInfoTest()
@@ -193,5 +228,316 @@ TEST_F(IncomingShareTargetInfoTest, ProcessIntroductionSuccess) {
EXPECT_THAT(info_.attachment_payload_map().at(wifimeta2.id()),
Eq(wifimeta2.payload_id()));
}
TEST_F(IncomingShareTargetInfoTest, UpdateFilePayloadPathsSuccess) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsTrue());
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[0].file_path(),
Eq(file1_path));
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[1].file_path(),
Eq(file2_path));
}
TEST_F(IncomingShareTargetInfoTest, UpdateFilePayloadPathsWrongType) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateTextPayload(payload_id1, "text1"));
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsFalse());
}
TEST_F(IncomingShareTargetInfoTest, GetPayloadFilePaths) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsTrue());
std::vector<std::filesystem::path> file_paths = info_.GetPayloadFilePaths();
EXPECT_THAT(file_paths, UnorderedElementsAre(file1_path, file2_path));
}
TEST_F(IncomingShareTargetInfoTest, FinalizePayloadsSuccess) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsTrue());
std::string text_content1 = "text1";
int64_t text_payload_id1 = introduction_frame_.text_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id1, CreateTextPayload(text_payload_id1, text_content1));
std::string text_content2 = "text2";
int64_t text_payload_id2 = introduction_frame_.text_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id2, CreateTextPayload(text_payload_id2, text_content2));
int64_t wifi_payload_id1 =
introduction_frame_.wifi_credentials_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id1,
CreateWifiCredentialsPayload(wifi_payload_id1, "password1", false));
int64_t wifi_payload_id2 =
introduction_frame_.wifi_credentials_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id2,
CreateWifiCredentialsPayload(wifi_payload_id2, "password2", true));
EXPECT_THAT(info_.FinalizePayloads(connections_manager), IsTrue());
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[0].file_path(),
Eq(file1_path));
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[1].file_path(),
Eq(file2_path));
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[0].text_body(),
Eq(text_content1));
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[1].text_body(),
Eq(text_content2));
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0].password(),
Eq("password1"));
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0]
.is_hidden(),
IsFalse());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.password(),
Eq("password2"));
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.is_hidden(),
IsTrue());
}
TEST_F(IncomingShareTargetInfoTest, FinalizePayloadsMissingFilePayloads) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsFalse());
std::string text_content1 = "text1";
int64_t text_payload_id1 = introduction_frame_.text_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id1, CreateTextPayload(text_payload_id1, text_content1));
std::string text_content2 = "text2";
int64_t text_payload_id2 = introduction_frame_.text_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id2, CreateTextPayload(text_payload_id2, text_content2));
int64_t wifi_payload_id1 =
introduction_frame_.wifi_credentials_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id1,
CreateWifiCredentialsPayload(wifi_payload_id1, "password1", false));
int64_t wifi_payload_id2 =
introduction_frame_.wifi_credentials_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id2,
CreateWifiCredentialsPayload(wifi_payload_id2, "password2", true));
EXPECT_THAT(info_.FinalizePayloads(connections_manager), IsFalse());
// Verify that attachments are cleared out
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[0].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[1].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[0].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[1].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0].password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0]
.is_hidden(),
IsFalse());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.is_hidden(),
IsFalse());
}
TEST_F(IncomingShareTargetInfoTest, FinalizePayloadsMissingTextPayloads) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsFalse());
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsTrue());
std::string text_content1 = "text1";
int64_t text_payload_id1 = introduction_frame_.text_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id1, CreateTextPayload(text_payload_id1, text_content1));
int64_t wifi_payload_id1 =
introduction_frame_.wifi_credentials_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id1,
CreateWifiCredentialsPayload(wifi_payload_id1, "password1", false));
int64_t wifi_payload_id2 =
introduction_frame_.wifi_credentials_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id2,
CreateWifiCredentialsPayload(wifi_payload_id2, "password2", true));
EXPECT_THAT(info_.FinalizePayloads(connections_manager), IsFalse());
// Verify that attachments are cleared out
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[0].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[1].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[0].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[1].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0].password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0]
.is_hidden(),
IsFalse());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.is_hidden(),
IsFalse());
}
TEST_F(IncomingShareTargetInfoTest, FinalizePayloadsMissingWifiPayloads) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
std::filesystem::path file1_path = "/usr/tmp/file1";
int64_t payload_id1 = introduction_frame_.file_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
payload_id1, CreateFilePayload(payload_id1, file1_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsFalse());
std::filesystem::path file2_path = "/usr/tmp/file2";
int64_t payload_id2 = introduction_frame_.file_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
payload_id2, CreateFilePayload(payload_id2, file2_path));
EXPECT_THAT(info_.UpdateFilePayloadPaths(connections_manager), IsTrue());
std::string text_content1 = "text1";
int64_t text_payload_id1 = introduction_frame_.text_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id1, CreateTextPayload(text_payload_id1, text_content1));
std::string text_content2 = "text2";
int64_t text_payload_id2 = introduction_frame_.text_metadata(1).payload_id();
connections_manager.SetIncomingPayload(
text_payload_id2, CreateTextPayload(text_payload_id2, text_content2));
int64_t wifi_payload_id1 =
introduction_frame_.wifi_credentials_metadata(0).payload_id();
connections_manager.SetIncomingPayload(
wifi_payload_id1,
CreateWifiCredentialsPayload(wifi_payload_id1, "password1", false));
EXPECT_THAT(info_.FinalizePayloads(connections_manager), IsFalse());
// Verify that attachments are cleared out
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[0].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetFileAttachments()[1].file_path(),
Eq(std::nullopt));
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[0].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container().GetTextAttachments()[1].text_body(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0].password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[0]
.is_hidden(),
IsFalse());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.password(),
IsEmpty());
EXPECT_THAT(info_.attachment_container()
.GetWifiCredentialsAttachments()[1]
.is_hidden(),
IsFalse());
}
TEST_F(IncomingShareTargetInfoTest, RegisterPayloadListenerSuccess) {
EXPECT_THAT(info_.ProcessIntroduction(introduction_frame_), Eq(std::nullopt));
FakeNearbyConnectionsManager connections_manager;
FakeContext context;
info_.RegisterPayloadListener(&context, connections_manager,
[](int64_t, TransferMetadata) {});
for (auto it : info_.attachment_payload_map()) {
EXPECT_THAT(
connections_manager.GetRegisteredPayloadStatusListener(it.second)
.lock(),
Eq(info_.payload_tracker().lock()));
}
}
} // namespace
} // namespace nearby::sharing
+92 -395
View File
@@ -59,7 +59,6 @@
#include "sharing/certificates/nearby_share_certificate_manager_impl.h"
#include "sharing/certificates/nearby_share_decrypted_public_certificate.h"
#include "sharing/certificates/nearby_share_encrypted_metadata_key.h"
#include "sharing/common/compatible_u8_string.h"
#include "sharing/common/nearby_share_enums.h"
#include "sharing/common/nearby_share_prefs.h"
#include "sharing/constants.h"
@@ -93,7 +92,6 @@
#include "sharing/nearby_sharing_util.h"
#include "sharing/outgoing_share_target_info.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/payload_tracker.h"
#include "sharing/proto/encrypted_metadata.pb.h"
#include "sharing/proto/enums.pb.h"
#include "sharing/proto/wire_format.pb.h"
@@ -101,11 +99,9 @@
#include "sharing/share_target.h"
#include "sharing/share_target_discovered_callback.h"
#include "sharing/share_target_info.h"
#include "sharing/text_attachment.h"
#include "sharing/transfer_metadata.h"
#include "sharing/transfer_metadata_builder.h"
#include "sharing/transfer_update_callback.h"
#include "sharing/wifi_credentials_attachment.h"
#include "sharing/wrapped_share_target_discovered_callback.h"
namespace nearby::sharing {
@@ -115,7 +111,6 @@ using BlockedVendorId = ::nearby::sharing::Advertisement::BlockedVendorId;
using ::nearby::sharing::api::SharingPlatform;
using ::nearby::sharing::proto::DataUsage;
using ::nearby::sharing::proto::DeviceVisibility;
using Type = ::nearby::sharing::service::proto::TextMetadata;
using ::location::nearby::proto::sharing::AttachmentTransmissionStatus;
using ::location::nearby::proto::sharing::EstablishConnectionStatus;
using ::location::nearby::proto::sharing::OSType;
@@ -350,7 +345,6 @@ void NearbySharingServiceImpl::Cleanup() {
last_incoming_metadata_.reset();
last_outgoing_metadata_.reset();
attachment_payload_map_.clear();
locally_cancelled_share_target_ids_.clear();
mutual_acceptance_timeout_alarm_->Stop();
@@ -824,7 +818,7 @@ void NearbySharingServiceImpl::Accept(
std::move(status_codes_callback)(StatusCodes::kInvalidArgument);
return;
}
if (!info->connection()) {
if (!info->IsConnected()) {
NL_LOG(WARNING) << __func__
<< ": Accept invoked for unconnected share target";
std::move(status_codes_callback)(StatusCodes::kOutOfOrderApiCall);
@@ -847,8 +841,10 @@ void NearbySharingServiceImpl::Accept(
is_waiting_to_record_accept_to_transfer_start_metric_ = is_incoming;
if (is_incoming) {
IncomingShareTargetInfo* incoming_info =
GetIncomingShareTargetInfo(share_target_id);
incoming_share_accepted_timestamp_ = context_->GetClock()->Now();
ReceivePayloads(*info, std::move(status_codes_callback));
ReceivePayloads(*incoming_info, std::move(status_codes_callback));
return;
}
@@ -874,7 +870,7 @@ void NearbySharingServiceImpl::Reject(
std::move(status_codes_callback)(StatusCodes::kInvalidArgument);
return;
}
if (!info->connection()) {
if (!info->IsConnected()) {
NL_LOG(WARNING) << __func__
<< ": Reject invoked for unconnected share target";
std::move(status_codes_callback)(StatusCodes::kOutOfOrderApiCall);
@@ -887,10 +883,8 @@ void NearbySharingServiceImpl::Reject(
// kRejected status already sent below, no need to send on disconnect.
info->set_disconnect_status(TransferMetadata::Status::kUnknown);
NearbyConnection* connection = info->connection();
WriteResponseFrame(
*connection,
nearby::sharing::service::proto::ConnectionResponseFrame::REJECT);
info->WriteResponseFrame(
service::proto::ConnectionResponseFrame::REJECT);
NL_VLOG(1) << __func__
<< ": Successfully wrote a rejection response frame";
@@ -945,13 +939,7 @@ void NearbySharingServiceImpl::DoCancel(
// cancellation signals. Also, note that there might not be any ongoing
// payload transfer, for example, if a connection has not been established
// yet.
for (int64_t attachment_id :
info->attachment_container().GetAttachmentIds()) {
std::optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id);
if (payload_id) {
nearby_connections_manager_->Cancel(*payload_id);
}
}
info->CancelPayloads(*nearby_connections_manager_);
// Inform the user that the transfer has been cancelled before disconnecting
// because subsequent disconnections might be interpreted as failure.
@@ -971,7 +959,7 @@ void NearbySharingServiceImpl::DoCancel(
// from endpoint id directly. Note: A share attempt can be cancelled by the
// user before a connection is fully established, in which case,
// info->connection() will be null.
if (info->connection()) {
if (info->IsConnected()) {
NL_LOG(INFO) << "Disconnect fully established endpoint id:"
<< info->endpoint_id();
if (is_initiator_of_cancellation) {
@@ -985,7 +973,7 @@ void NearbySharingServiceImpl::DoCancel(
CloseConnection(share_target_id);
});
WriteCancelFrame(*info->connection());
info->WriteCancelFrame();
} else {
info->connection()->Close();
}
@@ -2499,34 +2487,46 @@ void NearbySharingServiceImpl::OnTransferStarted(bool is_incoming) {
}
void NearbySharingServiceImpl::ReceivePayloads(
ShareTargetInfo& share_target_info,
IncomingShareTargetInfo& share_target_info,
std::function<void(StatusCodes status_codes)> status_codes_callback) {
mutual_acceptance_timeout_alarm_->Stop();
std::filesystem::path download_path =
std::filesystem::u8path(settings_->GetCustomSavePath());
// Log analytics event of starting to receive payloads.
analytics_recorder_->NewReceiveAttachmentsStart(
receiving_session_id_, share_target_info.attachment_container());
share_target_info.RegisterPayloadListener(
context_, *nearby_connections_manager_,
absl::bind_front(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
this));
share_target_info.WriteResponseFrame(
nearby::sharing::service::proto::ConnectionResponseFrame::ACCEPT);
NL_VLOG(1) << __func__ << ": Successfully wrote response frame";
const AttachmentContainer& container =
share_target_info.attachment_container();
// Register payload path for all valid file payloads.
for (const auto& file : container.GetFileAttachments()) {
std::optional<int64_t> payload_id = GetAttachmentPayloadId(file.id());
if (!payload_id) {
NL_LOG(WARNING)
<< __func__
<< ": Failed to register payload path for attachment id - "
<< file.id();
continue;
}
share_target_info.UpdateTransferMetadata(
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
.set_token(share_target_info.token())
.build());
if (share_target_info.attachment_container().GetTotalAttachmentsSize() >=
kAttachmentsSizeThresholdOverHighQualityMedium) {
// Upgrade bandwidth regardless of advertising visibility because either
// the system or the user has verified the sender's identity; the
// stable identifiers potentially exposed by performing a bandwidth
// upgrade are no longer a concern.
NL_LOG(INFO) << __func__ << ": Upgrade bandwidth when receiving accept.";
nearby_connections_manager_->UpgradeBandwidth(
share_target_info.endpoint_id());
}
OnPayloadPathsRegistered(share_target_info, std::move(status_codes_callback));
std::move(status_codes_callback)(StatusCodes::kOk);
}
NearbySharingService::StatusCodes NearbySharingServiceImpl::SendPayloads(
ShareTargetInfo& info) {
NL_VLOG(1) << __func__ << ": Preparing to send payloads to "
<< info.share_target().id;
if (!info.connection()) {
if (!info.IsConnected()) {
NL_LOG(WARNING) << __func__
<< ": Failed to send payload due to missing connection.";
return StatusCodes::kOutOfOrderApiCall;
@@ -2548,72 +2548,6 @@ NearbySharingService::StatusCodes NearbySharingServiceImpl::SendPayloads(
return StatusCodes::kOk;
}
void NearbySharingServiceImpl::OnPayloadPathsRegistered(
ShareTargetInfo& info,
std::function<void(StatusCodes status_codes)> status_codes_callback) {
if (!info.connection()) {
NL_LOG(WARNING) << __func__ << ": Accept invoked for unknown share target";
std::move(status_codes_callback)(StatusCodes::kOutOfOrderApiCall);
return;
}
NearbyConnection* connection = info.connection();
// Log analytics event of starting to receive payloads.
analytics_recorder_->NewReceiveAttachmentsStart(receiving_session_id_,
info.attachment_container());
int64_t share_target_id = info.share_target().id;
info.set_payload_tracker(std::make_shared<PayloadTracker>(
context_, share_target_id, info.attachment_container(),
attachment_payload_map_,
absl::bind_front(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
this)));
// Register status listener for all payloads.
for (int64_t attachment_id : info.attachment_container().GetAttachmentIds()) {
std::optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id);
if (!payload_id) {
NL_LOG(WARNING) << __func__
<< ": Failed to retrieve payload for attachment id - "
<< attachment_id;
continue;
}
NL_VLOG(1) << __func__ << ": Started listening for progress on payload - "
<< *payload_id;
nearby_connections_manager_->RegisterPayloadStatusListener(
*payload_id, info.payload_tracker());
NL_VLOG(1) << __func__ << ": Accepted incoming files from share target - "
<< share_target_id;
}
WriteResponseFrame(
*connection,
nearby::sharing::service::proto::ConnectionResponseFrame::ACCEPT);
NL_VLOG(1) << __func__ << ": Successfully wrote response frame";
info.UpdateTransferMetadata(
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
.set_token(info.token())
.build());
std::string endpoint_id = info.endpoint_id();
if (info.attachment_container().GetTotalAttachmentsSize() >=
kAttachmentsSizeThresholdOverHighQualityMedium) {
// Upgrade bandwidth regardless of advertising visibility because either
// the system or the user has verified the sender's identity; the
// stable identifiers potentially exposed by performing a bandwidth
// upgrade are no longer a concern.
NL_LOG(INFO) << __func__ << ": Upgrade bandwidth when receiving accept.";
nearby_connections_manager_->UpgradeBandwidth(endpoint_id);
}
std::move(status_codes_callback)(StatusCodes::kOk);
}
void NearbySharingServiceImpl::OnOutgoingConnection(
absl::Time connect_start_time, NearbyConnection* connection,
OutgoingShareTargetInfo& info) {
@@ -2668,7 +2602,7 @@ void NearbySharingServiceImpl::SendIntroduction(
NL_VLOG(1) << __func__ << ": Preparing to send introduction to "
<< info.share_target().id;
if (!info.connection()) {
if (!info.IsConnected()) {
NL_LOG(WARNING) << __func__ << ": No NearbyConnection tied to "
<< info.share_target().id;
return;
@@ -2690,30 +2624,15 @@ void NearbySharingServiceImpl::SendIntroduction(
return;
}
// Build the introduction.
std::unique_ptr<nearby::sharing::service::proto::IntroductionFrame>
introduction = info.CreateIntroductionFrame();
if (!introduction) {
NL_VLOG(1) << __func__ << ": Sending attachments to "
<< info.share_target().id;
if (!info.WriteIntroductionFrame()) {
NL_LOG(WARNING) << __func__
<< ": No payloads tied to transfer, disconnecting.";
AbortAndCloseConnectionIfNecessary(
TransferMetadata::Status::kMissingPayloads, info.share_target().id);
return;
}
introduction->set_start_transfer(true);
NL_VLOG(1) << __func__ << ": Sending attachments to "
<< info.share_target().id;
// Write the introduction to the remote device.
nearby::sharing::service::proto::Frame frame;
frame.set_version(nearby::sharing::service::proto::Frame::V1);
nearby::sharing::service::proto::V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(nearby::sharing::service::proto::V1Frame::INTRODUCTION);
v1_frame->set_allocated_introduction(introduction.release());
std::vector<uint8_t> data(frame.ByteSizeLong());
frame.SerializeToArray(data.data(), frame.ByteSizeLong());
connection->Write(std::move(data));
// We've successfully written the introduction, so we now have to wait for the
// remote side to accept.
@@ -2760,7 +2679,6 @@ void NearbySharingServiceImpl::CreatePayloads(
return;
}
bool result = info->CreateFilePayloads(file_infos);
attachment_payload_map_ = info->attachment_payload_map();
std::move(callback)(*info, result);
});
});
@@ -2826,70 +2744,13 @@ void NearbySharingServiceImpl::OnCreatePayloads(
});
}
void NearbySharingServiceImpl::WriteResponseFrame(
NearbyConnection& connection,
nearby::sharing::service::proto::ConnectionResponseFrame::Status
response_status) {
nearby::sharing::service::proto::Frame frame;
frame.set_version(nearby::sharing::service::proto::Frame::V1);
nearby::sharing::service::proto::V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(nearby::sharing::service::proto::V1Frame::RESPONSE);
v1_frame->mutable_connection_response()->set_status(response_status);
std::vector<uint8_t> data(frame.ByteSizeLong());
frame.SerializeToArray(data.data(), frame.ByteSizeLong());
connection.Write(std::move(data));
}
void NearbySharingServiceImpl::WriteCancelFrame(NearbyConnection& connection) {
NL_LOG(INFO) << __func__ << ": Writing cancel frame.";
nearby::sharing::service::proto::Frame frame;
frame.set_version(nearby::sharing::service::proto::Frame::V1);
nearby::sharing::service::proto::V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(nearby::sharing::service::proto::V1Frame::CANCEL);
std::vector<uint8_t> data(frame.ByteSizeLong());
frame.SerializeToArray(data.data(), frame.ByteSizeLong());
connection.Write(std::move(data));
}
void NearbySharingServiceImpl::WriteProgressUpdateFrame(
NearbyConnection& connection, std::optional<bool> start_transfer,
std::optional<float> progress) {
NL_LOG(INFO) << __func__ << ": Writing progress update frame. start_transfer="
<< (start_transfer.has_value() ? *start_transfer : false)
<< ", progress=" << (progress.has_value() ? *progress : 0.0);
nearby::sharing::service::proto::Frame frame;
frame.set_version(nearby::sharing::service::proto::Frame::V1);
nearby::sharing::service::proto::V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(nearby::sharing::service::proto::V1Frame::PROGRESS_UPDATE);
nearby::sharing::service::proto::ProgressUpdateFrame* progress_frame =
v1_frame->mutable_progress_update();
if (start_transfer.has_value()) {
progress_frame->set_start_transfer(*start_transfer);
}
if (progress.has_value()) {
progress_frame->set_progress(*progress);
}
std::vector<uint8_t> data(frame.ByteSizeLong());
frame.SerializeToArray(data.data(), frame.ByteSizeLong());
connection.Write(std::move(data));
}
void NearbySharingServiceImpl::Fail(int64_t share_target_id,
TransferMetadata::Status status) {
ShareTargetInfo* info = GetShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
NL_LOG(WARNING) << __func__ << ": Fail invoked for unknown share target.";
return;
}
NearbyConnection* connection = info->connection();
RunOnNearbySharingServiceThreadDelayed(
"incoming_rejection_delay", kIncomingRejectionDelay,
[this, share_target_id]() { CloseConnection(share_target_id); });
@@ -2921,8 +2782,7 @@ void NearbySharingServiceImpl::Fail(int64_t share_target_id,
break;
}
WriteResponseFrame(*connection, response_status);
info->WriteResponseFrame(response_status);
info->UpdateTransferMetadata(
TransferMetadataBuilder().set_status(status).build());
}
@@ -2932,8 +2792,7 @@ void NearbySharingServiceImpl::OnIncomingAdvertisementDecoded(
const IncomingShareTargetInfo& share_target_info,
std::unique_ptr<Advertisement> advertisement) {
int64_t placeholder_share_target_id = share_target_info.share_target().id;
NearbyConnection* connection = share_target_info.connection();
if (!connection) {
if (!share_target_info.IsConnected()) {
NL_LOG(WARNING) << __func__ << ": Invalid connection for endpoint id - "
<< endpoint_id;
return;
@@ -3095,15 +2954,7 @@ void NearbySharingServiceImpl::OnOutgoingTransferUpdate(
metadata.in_progress_attachment_total_bytes().has_value() &&
*metadata.in_progress_attachment_transferred_bytes() ==
*metadata.in_progress_attachment_total_bytes()) {
std::optional<Payload> payload = share_target_info.ExtractNextPayload();
if (payload.has_value()) {
NL_LOG(INFO) << __func__ << ": Send payload " << payload->id;
nearby_connections_manager_->Send(share_target_info.endpoint_id(),
std::make_unique<Payload>(*payload),
share_target_info.payload_tracker());
} else {
NL_LOG(WARNING) << __func__ << ": There is no paylaods to send.";
}
share_target_info.SendNextPayload(*nearby_connections_manager_);
}
}
@@ -3120,29 +2971,36 @@ void NearbySharingServiceImpl::OnOutgoingTransferUpdate(
}
void NearbySharingServiceImpl::CloseConnection(int64_t share_target_id) {
NearbyConnection* connection = GetConnection(share_target_id);
if (!connection) {
NL_LOG(WARNING) << __func__ << ": Invalid connection for target - "
<< share_target_id;
ShareTargetInfo* share_target_info = GetShareTargetInfo(share_target_id);
if (share_target_info != nullptr && share_target_info->IsConnected()) {
share_target_info->connection()->Close();
return;
}
connection->Close();
NL_LOG(WARNING) << __func__ << ": Invalid connection for target - "
<< share_target_id;
}
void NearbySharingServiceImpl::OnIncomingDecryptedCertificate(
absl::string_view endpoint_id, const Advertisement& advertisement,
int64_t placeholder_share_target_id,
std::optional<NearbyShareDecryptedPublicCertificate> certificate) {
NearbyConnection* connection = GetConnection(placeholder_share_target_id);
if (!connection) {
auto it = incoming_share_target_info_map_.find(placeholder_share_target_id);
if (it == incoming_share_target_info_map_.end()) {
NL_VLOG(1) << __func__ << ": Invalid connection for endpoint id - "
<< endpoint_id;
return;
}
if (!it->second.IsConnected()) {
NL_VLOG(1) << __func__ << ": Connection has been closedfor endpoint id - "
<< endpoint_id;
incoming_share_target_info_map_.erase(it);
return;
}
NearbyConnection* connection = it->second.connection();
// Remove placeholder share target since we are creating the actual share
// target below.
incoming_share_target_info_map_.erase(placeholder_share_target_id);
incoming_share_target_info_map_.erase(it);
std::optional<ShareTarget> share_target =
CreateShareTarget(endpoint_id, advertisement, certificate,
@@ -3195,7 +3053,7 @@ void NearbySharingServiceImpl::OnIncomingConnectionKeyVerificationDone(
PairedKeyVerificationRunner::PairedKeyVerificationResult result,
OSType share_target_os_type) {
IncomingShareTargetInfo* info = GetIncomingShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
NL_VLOG(1) << __func__ << ": Invalid connection or endpoint id";
return;
}
@@ -3243,7 +3101,7 @@ void NearbySharingServiceImpl::OnOutgoingConnectionKeyVerificationDone(
PairedKeyVerificationRunner::PairedKeyVerificationResult result,
OSType share_target_os_type) {
OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
return;
}
@@ -3305,7 +3163,7 @@ void NearbySharingServiceImpl::ReceiveIntroduction(
std::optional<std::string> four_digit_token) {
NL_LOG(INFO) << __func__ << ": Receiving introduction from "
<< info.share_target().id;
NL_DCHECK(info.connection());
NL_DCHECK(info.IsConnected());
info.frames_reader()->ReadFrame(
nearby::sharing::service::proto::V1Frame::INTRODUCTION,
@@ -3322,7 +3180,7 @@ void NearbySharingServiceImpl::OnReceivedIntroduction(
int64_t share_target_id, std::optional<std::string> four_digit_token,
std::optional<nearby::sharing::service::proto::V1Frame> frame) {
IncomingShareTargetInfo* info = GetIncomingShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
NL_LOG(WARNING)
<< __func__
<< ": Ignore received introduction, due to no connection established.";
@@ -3344,7 +3202,6 @@ void NearbySharingServiceImpl::OnReceivedIntroduction(
Fail(share_target_id, *status);
return;
}
attachment_payload_map_ = info->attachment_payload_map();
// Log analytics event of receiving introduction.
analytics_recorder_->NewReceiveIntroduction(
@@ -3383,7 +3240,7 @@ void NearbySharingServiceImpl::ReceiveConnectionResponse(
ShareTargetInfo& info) {
NL_VLOG(1) << __func__ << ": Receiving response frame from "
<< info.share_target().id;
NL_DCHECK(info.connection());
NL_DCHECK(info.IsConnected());
info.frames_reader()->ReadFrame(
nearby::sharing::service::proto::V1Frame::RESPONSE,
@@ -3398,7 +3255,7 @@ void NearbySharingServiceImpl::OnReceiveConnectionResponse(
int64_t share_target_id,
std::optional<nearby::sharing::service::proto::V1Frame> frame) {
OutgoingShareTargetInfo* info = GetOutgoingShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
NL_LOG(WARNING) << __func__
<< ": Ignore received connection response, due to no "
"connection established.";
@@ -3425,7 +3282,8 @@ void NearbySharingServiceImpl::OnReceiveConnectionResponse(
switch (response.status()) {
case nearby::sharing::service::proto::ConnectionResponseFrame::ACCEPT: {
// Write progress update frame to remote machine.
WriteProgressUpdateFrame(*info->connection(), true, std::nullopt);
info->WriteProgressUpdateFrame(/*start_transfer=*/true,
/*progress=*/std::nullopt);
info->frames_reader()->ReadFrame(
[this, share_target_id](
@@ -3438,36 +3296,19 @@ void NearbySharingServiceImpl::OnReceiveConnectionResponse(
.set_status(TransferMetadata::Status::kInProgress)
.build());
info->set_payload_tracker(std::make_unique<PayloadTracker>(
context_, share_target_id, info->attachment_container(),
attachment_payload_map_,
absl::bind_front(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
this)));
if (NearbyFlags::GetInstance().GetBoolFlag(
config_package_nearby::nearby_sharing_feature::
kEnableTransferCancellationOptimization)) {
std::optional<Payload> payload = info->ExtractNextPayload();
if (payload.has_value()) {
NL_LOG(INFO) << __func__ << ": Send payload " << payload->id;
nearby_connections_manager_->Send(info->endpoint_id(),
std::make_unique<Payload>(*payload),
info->payload_tracker());
} else {
NL_LOG(WARNING) << __func__ << ": There is no payloads to send.";
}
info->InitSendPayload(
context_, *nearby_connections_manager_,
absl::bind_front(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
this));
info->SendNextPayload(*nearby_connections_manager_);
} else {
for (auto& payload : info->ExtractTextPayloads()) {
nearby_connections_manager_->Send(info->endpoint_id(),
std::make_unique<Payload>(payload),
info->payload_tracker());
}
for (auto& payload : info->ExtractFilePayloads()) {
nearby_connections_manager_->Send(info->endpoint_id(),
std::make_unique<Payload>(payload),
info->payload_tracker());
}
info->SendAllPayloads(
context_, *nearby_connections_manager_,
absl::bind_front(&NearbySharingServiceImpl::OnPayloadTransferUpdate,
this));
}
NL_VLOG(1)
<< __func__
@@ -3527,7 +3368,7 @@ void NearbySharingServiceImpl::OnStorageCheckCompleted(
return;
}
ShareTargetInfo* info = GetShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
if (!info || !info->IsConnected()) {
NL_LOG(WARNING) << __func__ << ": Invalid connection for share target - "
<< share_target_id;
return;
@@ -3776,19 +3617,19 @@ void NearbySharingServiceImpl::OnPayloadTransferUpdate(
is_waiting_to_record_accept_to_transfer_start_metric_) {
is_waiting_to_record_accept_to_transfer_start_metric_ = false;
}
IncomingShareTargetInfo* incoming_info =
GetIncomingShareTargetInfo(share_target_id);
// Update file paths during progress. It may impact transfer speed.
// TODO: b/289290115 - Revisit UpdateFilePath to enhance transfer speed for
// MacOS.
if (update_file_paths_in_progress_) {
UpdateFilePath(info->mutable_attachment_container());
incoming_info->UpdateFilePayloadPaths(*nearby_connections_manager_);
}
if (metadata.status() == TransferMetadata::Status::kComplete) {
if (!OnIncomingPayloadsComplete(share_target_id)) {
if (!incoming_info->FinalizePayloads(*nearby_connections_manager_)) {
payload_incomplete = true;
info->mutable_attachment_container().ClearAttachments();
}
fast_initiation_scanner_cooldown_timer_->Stop();
@@ -3801,7 +3642,7 @@ void NearbySharingServiceImpl::OnPayloadTransferUpdate(
} else if (metadata.status() == TransferMetadata::Status::kCancelled) {
NL_VLOG(1) << __func__ << ": Update file paths for cancelled transfer";
if (!update_file_paths_in_progress_) {
UpdateFilePath(info->mutable_attachment_container());
incoming_info->UpdateFilePayloadPaths(*nearby_connections_manager_);
}
}
}
@@ -3830,127 +3671,6 @@ void NearbySharingServiceImpl::OnPayloadTransferUpdate(
}
}
bool NearbySharingServiceImpl::OnIncomingPayloadsComplete(
int64_t share_target_id) {
ShareTargetInfo* info = GetShareTargetInfo(share_target_id);
if (!info || !info->connection()) {
NL_VLOG(1) << __func__ << ": Connection not found for target - "
<< share_target_id;
return false;
}
if (!update_file_paths_in_progress_) {
UpdateFilePath(info->mutable_attachment_container());
}
AttachmentContainer& container = info->mutable_attachment_container();
for (int i = 0; i < container.GetTextAttachments().size(); ++i) {
TextAttachment& text = container.GetMutableTextAttachment(i);
const auto it = attachment_payload_map_.find(text.id());
if (it == attachment_payload_map_.end()) {
NL_LOG(WARNING) << __func__ << ": No payload id found for text - "
<< text.id();
return false;
}
const Payload* incoming_payload =
nearby_connections_manager_->GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_bytes()) {
NL_LOG(WARNING) << __func__ << ": No payload found for text - "
<< text.id();
return false;
}
std::vector<uint8_t> bytes = incoming_payload->content.bytes_payload.bytes;
if (bytes.empty()) {
NL_LOG(WARNING)
<< __func__
<< ": Incoming bytes is empty for text payload with payload_id - "
<< it->second;
return false;
}
std::string text_body(bytes.begin(), bytes.end());
text.set_text_body(text_body);
}
for (int i = 0; i < container.GetWifiCredentialsAttachments().size(); ++i) {
WifiCredentialsAttachment& wifi_credentials_attachment =
container.GetMutableWifiCredentialsAttachment(i);
const auto it =
attachment_payload_map_.find(wifi_credentials_attachment.id());
if (it == attachment_payload_map_.end()) {
NL_LOG(WARNING) << __func__
<< ": No payload id found for WiFi credentials - "
<< wifi_credentials_attachment.id();
return false;
}
const Payload* incoming_payload =
nearby_connections_manager_->GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_bytes()) {
NL_LOG(WARNING) << __func__
<< ": No payload found for WiFi credentials - "
<< wifi_credentials_attachment.id();
return false;
}
std::vector<uint8_t> bytes = incoming_payload->content.bytes_payload.bytes;
if (bytes.empty()) {
NL_LOG(WARNING) << __func__
<< ": Incoming bytes is empty for WiFi credentials "
"payload with payload_id - "
<< it->second;
return false;
}
auto wifi_credentials =
std::make_unique<nearby::sharing::service::proto::WifiCredentials>();
if (!wifi_credentials->ParseFromArray(bytes.data(), bytes.size())) {
NL_LOG(WARNING) << __func__
<< ": Incoming bytes is invalid for WiFi credentials "
"payload with payload_id - "
<< it->second;
return false;
}
wifi_credentials_attachment.set_password(wifi_credentials->password());
wifi_credentials_attachment.set_is_hidden(wifi_credentials->hidden_ssid());
}
return true;
}
void NearbySharingServiceImpl::UpdateFilePath(
AttachmentContainer& attachment_container) {
for (int i = 0; i < attachment_container.GetFileAttachments().size(); ++i) {
FileAttachment& file = attachment_container.GetMutableFileAttachment(i);
// Skip file if it already has file_path set.
if (file.file_path().has_value()) {
continue;
}
const auto it = attachment_payload_map_.find(file.id());
if (it == attachment_payload_map_.end()) {
NL_LOG(WARNING) << __func__ << ": No payload id found for file - "
<< file.id();
continue;
}
const Payload* incoming_payload =
nearby_connections_manager_->GetIncomingPayload(it->second);
if (!incoming_payload || !incoming_payload->content.is_file()) {
NL_LOG(WARNING) << __func__ << ": No payload found for file - "
<< file.id();
continue;
}
auto file_path = incoming_payload->content.file_payload.file.path;
NL_VLOG(1) << __func__ << ": Updated file_path="
<< GetCompatibleU8String(file_path.u8string());
file.set_file_path(file_path);
}
}
void NearbySharingServiceImpl::RemoveIncomingPayloads(
const IncomingShareTargetInfo& share_target_info) {
NL_LOG(INFO) << __func__ << ": Cleaning up payloads due to transfer failure";
@@ -3967,19 +3687,10 @@ void NearbySharingServiceImpl::RemoveIncomingPayloads(
files_for_deletion.push_back(*it);
}
}
const AttachmentContainer& container =
share_target_info.attachment_container();
for (const auto& file : container.GetFileAttachments()) {
if (!file.file_path().has_value()) continue;
auto file_path = *file.file_path();
NL_VLOG(1) << __func__
<< ": file_path=" << GetCompatibleU8String(file_path.u8string());
if (attachment_payload_map_.find(file.id()) ==
attachment_payload_map_.end()) {
continue;
}
files_for_deletion.push_back(file_path);
}
std::vector<std::filesystem::path> payload_file_path =
share_target_info.GetPayloadFilePaths();
files_for_deletion.insert(files_for_deletion.end(), payload_file_path.begin(),
payload_file_path.end());
file_handler_.DeleteFilesFromDisk(std::move(files_for_deletion), []() {});
}
@@ -3998,7 +3709,7 @@ void NearbySharingServiceImpl::Disconnect(int64_t share_target_id,
// Failed to send or receive. No point in continuing, so disconnect
// immediately.
if (metadata.status() != TransferMetadata::Status::kComplete) {
if (share_target_info->connection()) {
if (share_target_info->IsConnected()) {
share_target_info->connection()->Close();
} else {
nearby_connections_manager_->Disconnect(endpoint_id);
@@ -4008,7 +3719,7 @@ void NearbySharingServiceImpl::Disconnect(int64_t share_target_id,
// Files received successfully. Receivers can immediately cancel.
if (share_target_info->IsIncoming()) {
if (share_target_info->connection()) {
if (share_target_info->IsConnected()) {
share_target_info->connection()->Close();
} else {
nearby_connections_manager_->Disconnect(endpoint_id);
@@ -4114,12 +3825,6 @@ OutgoingShareTargetInfo* NearbySharingServiceImpl::GetOutgoingShareTargetInfo(
return &it->second;
}
NearbyConnection* NearbySharingServiceImpl::GetConnection(
int64_t share_target_id) {
ShareTargetInfo* share_target_info = GetShareTargetInfo(share_target_id);
return share_target_info ? share_target_info->connection() : nullptr;
}
std::optional<std::vector<uint8_t>>
NearbySharingServiceImpl::GetBluetoothMacAddressForShareTarget(
OutgoingShareTargetInfo& info) {
@@ -4144,14 +3849,6 @@ void NearbySharingServiceImpl::ClearOutgoingShareTargetInfoMap() {
NL_DCHECK(outgoing_share_target_info_map_.empty());
}
std::optional<int64_t> NearbySharingServiceImpl::GetAttachmentPayloadId(
int64_t attachment_id) {
const auto it = attachment_payload_map_.find(attachment_id);
if (it == attachment_payload_map_.end()) return std::nullopt;
return it->second;
}
void NearbySharingServiceImpl::UnregisterShareTarget(int64_t share_target_id) {
NL_VLOG(1) << __func__ << ": Unregistering share target - "
<< share_target_id;
@@ -4283,7 +3980,7 @@ void NearbySharingServiceImpl::AbortAndCloseConnectionIfNecessary(
info->UpdateTransferMetadata(metadata);
// Close connection if necessary.
if (info->connection()) {
if (info->IsConnected()) {
// Final status already sent above. No need to send it again.
info->set_disconnect_status(TransferMetadata::Status::kUnknown);
info->connection()->Close();
+1 -18
View File
@@ -315,12 +315,9 @@ class NearbySharingServiceImpl
void OnTransferStarted(bool is_incoming);
void ReceivePayloads(
ShareTargetInfo& share_target_info,
IncomingShareTargetInfo& share_target_info,
std::function<void(StatusCodes status_codes)> status_codes_callback);
StatusCodes SendPayloads(ShareTargetInfo& info);
void OnPayloadPathsRegistered(
ShareTargetInfo& info,
std::function<void(StatusCodes status_codes)> status_codes_callback);
void OnOutgoingConnection(absl::Time connect_start_time,
NearbyConnection* connection,
@@ -334,14 +331,6 @@ class NearbySharingServiceImpl
void OnCreatePayloads(std::vector<uint8_t> endpoint_info,
OutgoingShareTargetInfo& info, bool success);
void WriteResponseFrame(
NearbyConnection& connection,
nearby::sharing::service::proto::ConnectionResponseFrame::Status
response_status);
void WriteCancelFrame(NearbyConnection& connection);
void WriteProgressUpdateFrame(NearbyConnection& connection,
std::optional<bool> start_transfer,
std::optional<float> progress);
void Fail(int64_t share_target_id, TransferMetadata::Status status);
void OnIncomingAdvertisementDecoded(
absl::string_view endpoint_id,
@@ -402,7 +391,6 @@ class NearbySharingServiceImpl
void OnPayloadTransferUpdate(int64_t share_target_id,
TransferMetadata metadata);
bool OnIncomingPayloadsComplete(int64_t share_target_id);
void RemoveIncomingPayloads(const IncomingShareTargetInfo& share_target_info);
void Disconnect(int64_t share_target_id, TransferMetadata metadata);
void OnDisconnectingConnectionTimeout(absl::string_view endpoint_id);
@@ -418,12 +406,10 @@ class NearbySharingServiceImpl
IncomingShareTargetInfo* GetIncomingShareTargetInfo(int64_t share_target_id);
OutgoingShareTargetInfo* GetOutgoingShareTargetInfo(int64_t share_target_id);
NearbyConnection* GetConnection(int64_t share_target_id);
std::optional<std::vector<uint8_t>> GetBluetoothMacAddressForShareTarget(
OutgoingShareTargetInfo& info);
void ClearOutgoingShareTargetInfoMap();
std::optional<int64_t> GetAttachmentPayloadId(int64_t attachment_id);
void UnregisterShareTarget(int64_t share_target_id);
void OnStartAdvertisingResult(bool used_device_name, Status status);
@@ -578,9 +564,6 @@ class NearbySharingServiceImpl
// unnecessary backend API call.
absl::flat_hash_set<std::string> discovered_advertisements_retried_set_;
// A mapping of Attachment ID to payload ID .
absl::flat_hash_map<int64_t, int64_t> attachment_payload_map_;
// This alarm is used to disconnect the sharing connection if both sides do
// not press accept within the timeout.
std::unique_ptr<Timer> mutual_acceptance_timeout_alarm_;
+84 -7
View File
@@ -27,10 +27,13 @@
#include "absl/strings/string_view.h"
#include "sharing/attachment_container.h"
#include "sharing/file_attachment.h"
#include "sharing/internal/public/context.h"
#include "sharing/internal/public/logging.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/payload_tracker.h"
#include "sharing/share_target.h"
#include "sharing/share_target_info.h"
#include "sharing/text_attachment.h"
@@ -39,6 +42,11 @@
namespace nearby::sharing {
using ::nearby::sharing::service::proto::Frame;
using ::nearby::sharing::service::proto::IntroductionFrame;
using ::nearby::sharing::service::proto::ProgressUpdateFrame;
using ::nearby::sharing::service::proto::V1Frame;
OutgoingShareTargetInfo::OutgoingShareTargetInfo(
std::string endpoint_id, const ShareTarget& share_target,
std::function<void(OutgoingShareTargetInfo&, const TransferMetadata&)>
@@ -154,20 +162,18 @@ bool OutgoingShareTargetInfo::CreateFilePayloads(
return true;
}
std::unique_ptr<nearby::sharing::service::proto::IntroductionFrame>
OutgoingShareTargetInfo::CreateIntroductionFrame() const {
bool OutgoingShareTargetInfo::FillIntroductionFrame(
IntroductionFrame* introduction) const {
const AttachmentContainer& container = attachment_container();
if (!container.HasAttachments()) {
return nullptr;
return false;
}
if (file_payloads_.size() != container.GetFileAttachments().size() ||
text_payloads_.size() != container.GetTextAttachments().size() ||
wifi_credentials_payloads_.size() !=
container.GetWifiCredentialsAttachments().size()) {
return nullptr;
return false;
}
auto introduction =
std::make_unique<nearby::sharing::service::proto::IntroductionFrame>();
// Write introduction of file payloads.
const std::vector<FileAttachment>& file_attachments =
container.GetFileAttachments();
@@ -209,7 +215,78 @@ OutgoingShareTargetInfo::CreateIntroductionFrame() const {
wifi_credentials.security_type());
wifi_credentials_metadata->set_payload_id(wifi_credentials_payloads_[i].id);
}
return introduction;
return true;
}
void OutgoingShareTargetInfo::SendAllPayloads(
Context* context, NearbyConnectionsManager& connection_manager,
std::function<void(int64_t, TransferMetadata)> update_callback) {
set_payload_tracker(std::make_unique<PayloadTracker>(
context, share_target().id, attachment_container(),
attachment_payload_map(), std::move(update_callback)));
for (auto& payload : ExtractTextPayloads()) {
connection_manager.Send(endpoint_id(), std::make_unique<Payload>(payload),
payload_tracker());
}
for (auto& payload : ExtractFilePayloads()) {
connection_manager.Send(endpoint_id(), std::make_unique<Payload>(payload),
payload_tracker());
}
}
void OutgoingShareTargetInfo::InitSendPayload(
Context* context, NearbyConnectionsManager& connection_manager,
std::function<void(int64_t, TransferMetadata)> update_callback) {
set_payload_tracker(std::make_unique<PayloadTracker>(
context, share_target().id, attachment_container(),
attachment_payload_map(), std::move(update_callback)));
}
void OutgoingShareTargetInfo::SendNextPayload(
NearbyConnectionsManager& connection_manager) {
std::optional<Payload> payload = ExtractNextPayload();
if (payload.has_value()) {
NL_LOG(INFO) << __func__ << ": Send payload " << payload->id;
connection_manager.Send(endpoint_id(), std::make_unique<Payload>(*payload),
payload_tracker());
} else {
NL_LOG(WARNING) << __func__ << ": There is no paylaods to send.";
}
}
void OutgoingShareTargetInfo::WriteProgressUpdateFrame(
std::optional<bool> start_transfer, std::optional<float> progress) {
NL_LOG(INFO) << __func__ << ": Writing progress update frame. start_transfer="
<< (start_transfer.has_value() ? *start_transfer : false)
<< ", progress=" << (progress.has_value() ? *progress : 0.0);
Frame frame;
frame.set_version(Frame::V1);
V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::PROGRESS_UPDATE);
ProgressUpdateFrame* progress_frame = v1_frame->mutable_progress_update();
if (start_transfer.has_value()) {
progress_frame->set_start_transfer(*start_transfer);
}
if (progress.has_value()) {
progress_frame->set_progress(*progress);
}
WriteFrame(frame);
}
bool OutgoingShareTargetInfo::WriteIntroductionFrame() {
Frame frame;
frame.set_version(Frame::V1);
V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::INTRODUCTION);
IntroductionFrame* introduction_frame = v1_frame->mutable_introduction();
introduction_frame->set_start_transfer(true);
if (!FillIntroductionFrame(introduction_frame)) {
return false;
}
WriteFrame(frame);
return true;
}
std::vector<Payload> OutgoingShareTargetInfo::ExtractTextPayloads() {
+27 -7
View File
@@ -15,15 +15,17 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_OUTGOING_SHARE_TARGET_INFO_H_
#define THIRD_PARTY_NEARBY_SHARING_OUTGOING_SHARE_TARGET_INFO_H_
#include <cstdint>
#include <filesystem> // NOLINT
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "sharing/internal/public/context.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/share_target.h"
@@ -79,13 +81,24 @@ class OutgoingShareTargetInfo : public ShareTargetInfo {
bool CreateFilePayloads(
const std::vector<NearbyFileHandler::FileInfo>& files);
std::unique_ptr<nearby::sharing::service::proto::IntroductionFrame>
CreateIntroductionFrame() const;
// Create a payload status listener to send status change to
// |update_callback|. Send all payloads to NearbyConnectionManager.
void SendAllPayloads(
Context* context, NearbyConnectionsManager& connection_manager,
std::function<void(int64_t, TransferMetadata)> update_callback);
std::vector<Payload> ExtractTextPayloads();
std::vector<Payload> ExtractFilePayloads();
std::vector<Payload> ExtractWifiCredentialsPayloads();
std::optional<Payload> ExtractNextPayload();
// Create a payload status listener to send status change to
// |update_callback|.
void InitSendPayload(
Context* context, NearbyConnectionsManager& connection_manager,
std::function<void(int64_t, TransferMetadata)> update_callback);
// Send the next payload to NearbyConnectionManager.
void SendNextPayload(NearbyConnectionsManager& connection_manager);
void WriteProgressUpdateFrame(std::optional<bool> start_transfer,
std::optional<float> progress);
// Returns true if the introduction frame is written successfully.
bool WriteIntroductionFrame();
protected:
void InvokeTransferUpdateCallback(const TransferMetadata& metadata) override;
@@ -93,6 +106,13 @@ class OutgoingShareTargetInfo : public ShareTargetInfo {
private:
std::vector<Payload> ExtractTextPayloads();
std::vector<Payload> ExtractFilePayloads();
std::vector<Payload> ExtractWifiCredentialsPayloads();
std::optional<Payload> ExtractNextPayload();
bool FillIntroductionFrame(
nearby::sharing::service::proto::IntroductionFrame* introduction) const;
std::optional<std::string> obfuscated_gaia_id_;
// All payloads are in the same order as the attachments in the share target.
std::vector<Payload> text_payloads_;
+188 -27
View File
@@ -16,6 +16,7 @@
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -24,8 +25,13 @@
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "sharing/attachment_container.h"
#include "sharing/fake_nearby_connection.h"
#include "sharing/fake_nearby_connections_manager.h"
#include "sharing/file_attachment.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_connections_types.h"
#include "sharing/nearby_file_handler.h"
#include "sharing/proto/wire_format.pb.h"
@@ -36,13 +42,19 @@
namespace nearby::sharing {
namespace {
using ::nearby::sharing::service::proto::Frame;
using ::nearby::sharing::service::proto::IntroductionFrame;
using ::nearby::sharing::service::proto::ProgressUpdateFrame;
using ::nearby::sharing::service::proto::V1Frame;
using ::nearby::sharing::service::proto::WifiCredentials;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::IsEmpty;
using ::testing::IsFalse;
using ::testing::IsTrue;
using ::testing::MockFunction;
using ::testing::SizeIs;
using ::testing::_;
constexpr absl::string_view kEndpointId = "ABCD";
@@ -204,11 +216,13 @@ TEST_F(OutgoingShareTargetInfoTest, CreateWifiCredentialsPayloads) {
EXPECT_THAT(attachment_payload_map.at(wifi1_.id()), Eq(payloads[0].id));
}
TEST_F(OutgoingShareTargetInfoTest, CreateIntroductionFrameWithoutPayloads) {
EXPECT_THAT(info_.CreateIntroductionFrame(), Eq(nullptr));
TEST_F(OutgoingShareTargetInfoTest, WriteIntroductionFrameWithoutPayloads) {
EXPECT_THAT(info_.WriteIntroductionFrame(), IsFalse());
}
TEST_F(OutgoingShareTargetInfoTest, CreateIntroductionFrameSuccess) {
TEST_F(OutgoingShareTargetInfoTest, WriteIntroductionFrameSuccess) {
FakeNearbyConnection connection;
info_.OnConnected(absl::Now(), &connection);
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
@@ -217,41 +231,188 @@ TEST_F(OutgoingShareTargetInfoTest, CreateIntroductionFrameSuccess) {
info_.CreateFilePayloads(file_infos);
info_.CreateTextPayloads();
info_.CreateWifiCredentialsPayloads();
std::unique_ptr<IntroductionFrame> frame = info_.CreateIntroductionFrame();
EXPECT_THAT(info_.WriteIntroductionFrame(), IsTrue());
std::vector<uint8_t> frame_data = connection.GetWrittenData();
Frame frame;
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
IsTrue());
ASSERT_THAT(frame.version(), Eq(Frame::V1));
ASSERT_THAT(frame.v1().type(), Eq(V1Frame::INTRODUCTION));
const IntroductionFrame& intro_frame = frame.v1().introduction();
EXPECT_THAT(intro_frame.start_transfer(), IsTrue());
const std::vector<Payload>& text_payloads = info_.text_payloads();
ASSERT_THAT(frame->text_metadata_size(), Eq(2));
EXPECT_THAT(frame->text_metadata(0).id(), Eq(text1_.id()));
EXPECT_THAT(frame->text_metadata(0).text_title(), Eq(text1_.text_title()));
EXPECT_THAT(frame->text_metadata(0).type(), Eq(text1_.type()));
EXPECT_THAT(frame->text_metadata(0).size(), Eq(text1_.size()));
EXPECT_THAT(frame->text_metadata(0).payload_id(), Eq(text_payloads[0].id));
ASSERT_THAT(intro_frame.text_metadata_size(), Eq(2));
EXPECT_THAT(intro_frame.text_metadata(0).id(), Eq(text1_.id()));
EXPECT_THAT(intro_frame.text_metadata(0).text_title(),
Eq(text1_.text_title()));
EXPECT_THAT(intro_frame.text_metadata(0).type(), Eq(text1_.type()));
EXPECT_THAT(intro_frame.text_metadata(0).size(), Eq(text1_.size()));
EXPECT_THAT(intro_frame.text_metadata(0).payload_id(),
Eq(text_payloads[0].id));
EXPECT_THAT(frame->text_metadata(1).id(), Eq(text2_.id()));
EXPECT_THAT(frame->text_metadata(1).text_title(), Eq(text2_.text_title()));
EXPECT_THAT(frame->text_metadata(1).type(), Eq(text2_.type()));
EXPECT_THAT(frame->text_metadata(1).size(), Eq(text2_.size()));
EXPECT_THAT(frame->text_metadata(1).payload_id(), Eq(text_payloads[1].id));
EXPECT_THAT(intro_frame.text_metadata(1).id(), Eq(text2_.id()));
EXPECT_THAT(intro_frame.text_metadata(1).text_title(),
Eq(text2_.text_title()));
EXPECT_THAT(intro_frame.text_metadata(1).type(), Eq(text2_.type()));
EXPECT_THAT(intro_frame.text_metadata(1).size(), Eq(text2_.size()));
EXPECT_THAT(intro_frame.text_metadata(1).payload_id(),
Eq(text_payloads[1].id));
const std::vector<Payload>& file_payloads = info_.file_payloads();
ASSERT_THAT(frame->file_metadata_size(), Eq(1));
EXPECT_THAT(frame->file_metadata(0).id(), Eq(file1_.id()));
ASSERT_THAT(intro_frame.file_metadata_size(), Eq(1));
EXPECT_THAT(intro_frame.file_metadata(0).id(), Eq(file1_.id()));
// File attachment size has been updated by CreateFilePayloads().
EXPECT_THAT(frame->file_metadata(0).size(), Eq(file_infos[0].size));
EXPECT_THAT(frame->file_metadata(0).name(), Eq(file1_.file_name()));
EXPECT_THAT(frame->file_metadata(0).payload_id(), Eq(file_payloads[0].id));
EXPECT_THAT(frame->file_metadata(0).type(), Eq(file1_.type()));
EXPECT_THAT(frame->file_metadata(0).mime_type(), Eq(file1_.mime_type()));
EXPECT_THAT(intro_frame.file_metadata(0).size(), Eq(file_infos[0].size));
EXPECT_THAT(intro_frame.file_metadata(0).name(), Eq(file1_.file_name()));
EXPECT_THAT(intro_frame.file_metadata(0).payload_id(),
Eq(file_payloads[0].id));
EXPECT_THAT(intro_frame.file_metadata(0).type(), Eq(file1_.type()));
EXPECT_THAT(intro_frame.file_metadata(0).mime_type(), Eq(file1_.mime_type()));
const std::vector<Payload>& wifi_payloads = info_.wifi_credentials_payloads();
ASSERT_THAT(frame->wifi_credentials_metadata_size(), Eq(1));
EXPECT_THAT(frame->wifi_credentials_metadata(0).id(), Eq(wifi1_.id()));
EXPECT_THAT(frame->wifi_credentials_metadata(0).ssid(), Eq(wifi1_.ssid()));
EXPECT_THAT(frame->wifi_credentials_metadata(0).security_type(),
ASSERT_THAT(intro_frame.wifi_credentials_metadata_size(), Eq(1));
EXPECT_THAT(intro_frame.wifi_credentials_metadata(0).id(), Eq(wifi1_.id()));
EXPECT_THAT(intro_frame.wifi_credentials_metadata(0).ssid(),
Eq(wifi1_.ssid()));
EXPECT_THAT(intro_frame.wifi_credentials_metadata(0).security_type(),
Eq(wifi1_.security_type()));
EXPECT_THAT(frame->wifi_credentials_metadata(0).payload_id(),
EXPECT_THAT(intro_frame.wifi_credentials_metadata(0).payload_id(),
Eq(wifi_payloads[0].id));
}
TEST_F(OutgoingShareTargetInfoTest, SendAllPayloads) {
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
info_.CreateFilePayloads(file_infos);
info_.CreateTextPayloads();
info_.CreateWifiCredentialsPayloads();
MockFunction<void(int64_t, TransferMetadata)> transfer_metadata_callback;
MockFunction<void(
std::unique_ptr<Payload>,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>)>
send_payload_callback;
FakeNearbyConnectionsManager connections_manager;
FakeContext context;
connections_manager.set_send_payload_callback(
send_payload_callback.AsStdFunction());
EXPECT_CALL(send_payload_callback, Call(_, _))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(file1_.id());
}))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(text1_.id());
}))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(text2_.id());
}));
info_.SendAllPayloads(&context, connections_manager,
transfer_metadata_callback.AsStdFunction());
auto payload_listener = info_.payload_tracker().lock();
EXPECT_THAT(payload_listener, IsTrue());
}
TEST_F(OutgoingShareTargetInfoTest, InitSendPayload) {
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
info_.CreateFilePayloads(file_infos);
info_.CreateTextPayloads();
info_.CreateWifiCredentialsPayloads();
MockFunction<void(int64_t, TransferMetadata)> transfer_metadata_callback;
MockFunction<void(
std::unique_ptr<Payload>,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>)>
send_payload_callback;
FakeNearbyConnectionsManager connections_manager;
FakeContext context;
connections_manager.set_send_payload_callback(
send_payload_callback.AsStdFunction());
info_.InitSendPayload(&context, connections_manager,
transfer_metadata_callback.AsStdFunction());
auto payload_listener = info_.payload_tracker().lock();
EXPECT_THAT(payload_listener, IsTrue());
}
TEST_F(OutgoingShareTargetInfoTest, SendNextPayload) {
std::vector<NearbyFileHandler::FileInfo> file_infos;
file_infos.push_back({
.size = 12355L,
.file_path = file1_.file_path().value(),
});
info_.CreateFilePayloads(file_infos);
info_.CreateTextPayloads();
info_.CreateWifiCredentialsPayloads();
MockFunction<void(int64_t, TransferMetadata)> transfer_metadata_callback;
MockFunction<void(
std::unique_ptr<Payload>,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>)>
send_payload_callback;
FakeNearbyConnectionsManager connections_manager;
FakeContext context;
connections_manager.set_send_payload_callback(
send_payload_callback.AsStdFunction());
info_.InitSendPayload(&context, connections_manager,
transfer_metadata_callback.AsStdFunction());
EXPECT_CALL(send_payload_callback, Call(_, _))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(file1_.id());
}));
info_.SendNextPayload(connections_manager);
EXPECT_CALL(send_payload_callback, Call(_, _))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(text1_.id());
}));
info_.SendNextPayload(connections_manager);
EXPECT_CALL(send_payload_callback, Call(_, _))
.WillOnce(Invoke(
[this](std::unique_ptr<Payload> payload,
std::weak_ptr<NearbyConnectionsManager::PayloadStatusListener>) {
payload->id = info_.attachment_payload_map().at(text2_.id());
}));
info_.SendNextPayload(connections_manager);
}
TEST_F(OutgoingShareTargetInfoTest, WriteInProgressUpdateFrameSuccess) {
FakeNearbyConnection connection;
info_.OnConnected(absl::Now(), &connection);
info_.WriteProgressUpdateFrame(true, 0.5);
std::vector<uint8_t> frame_data = connection.GetWrittenData();
Frame frame;
ASSERT_THAT(frame.ParseFromArray(frame_data.data(), frame_data.size()),
IsTrue());
ASSERT_THAT(frame.version(), Eq(Frame::V1));
ASSERT_THAT(frame.v1().type(), Eq(V1Frame::PROGRESS_UPDATE));
const ProgressUpdateFrame& progress_frame = frame.v1().progress_update();
EXPECT_THAT(progress_frame.start_transfer(), IsTrue());
EXPECT_THAT(progress_frame.progress(), Eq(0.5));
}
} // namespace
} // namespace nearby::sharing
+46
View File
@@ -29,8 +29,10 @@
#include "sharing/internal/public/context.h"
#include "sharing/internal/public/logging.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_connections_manager.h"
#include "sharing/nearby_sharing_decoder.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/proto/wire_format.pb.h"
#include "sharing/share_target.h"
#include "sharing/transfer_metadata.h"
#include "sharing/transfer_metadata_builder.h"
@@ -39,6 +41,9 @@ namespace nearby::sharing {
namespace {
using ::location::nearby::proto::sharing::OSType;
using ::nearby::sharing::service::proto::ConnectionResponseFrame;
using ::nearby::sharing::service::proto::Frame;
using ::nearby::sharing::service::proto::V1Frame;
} // namespace
@@ -131,4 +136,45 @@ void ShareTargetInfo::SetAttachmentPayloadId(int64_t attachment_id,
attachment_payload_map_[attachment_id] = payload_id;
}
void ShareTargetInfo::CancelPayloads(
NearbyConnectionsManager& connections_manager) {
for (const auto& [attachment_id, payload_id] : attachment_payload_map_) {
connections_manager.Cancel(payload_id);
}
}
void ShareTargetInfo::WriteFrame(const Frame& frame) {
if (connection_ == nullptr) {
NL_LOG(WARNING) << __func__ << ": Failed to write response frame, due to "
"no connection established.";
return;
}
std::vector<uint8_t> data(frame.ByteSizeLong());
frame.SerializeToArray(data.data(), frame.ByteSizeLong());
connection_->Write(std::move(data));
}
void ShareTargetInfo::WriteResponseFrame(
ConnectionResponseFrame::Status response_status) {
Frame frame;
frame.set_version(Frame::V1);
V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::RESPONSE);
v1_frame->mutable_connection_response()->set_status(response_status);
WriteFrame(frame);
}
void ShareTargetInfo::WriteCancelFrame() {
NL_LOG(INFO) << __func__ << ": Writing cancel frame.";
Frame frame;
frame.set_version(Frame::V1);
V1Frame* v1_frame = frame.mutable_v1();
v1_frame->set_type(V1Frame::CANCEL);
WriteFrame(frame);
}
} // namespace nearby::sharing
+19 -9
View File
@@ -36,6 +36,7 @@
#include "sharing/nearby_sharing_decoder.h"
#include "sharing/paired_key_verification_runner.h"
#include "sharing/payload_tracker.h"
#include "sharing/proto/wire_format.pb.h"
#include "sharing/share_target.h"
#include "sharing/transfer_metadata.h"
@@ -63,6 +64,7 @@ class ShareTargetInfo {
}
NearbyConnection* connection() const { return connection_; }
bool IsConnected() const { return connection_ != nullptr; }
void UpdateTransferMetadata(const TransferMetadata& transfer_metadata);
@@ -77,10 +79,6 @@ class ShareTargetInfo {
return payload_tracker_->GetWeakPtr();
}
void set_payload_tracker(std::shared_ptr<PayloadTracker> payload_tracker) {
payload_tracker_ = std::move(payload_tracker);
}
int64_t session_id() const { return session_id_; }
void set_session_id(int64_t session_id) { session_id_ = session_id; }
@@ -132,22 +130,34 @@ class ShareTargetInfo {
return attachment_container_;
}
AttachmentContainer& mutable_attachment_container() {
return attachment_container_;
}
void CancelPayloads(NearbyConnectionsManager& connections_manager);
const absl::flat_hash_map<int64_t, int64_t>& attachment_payload_map()
const {
return attachment_payload_map_;
}
protected:
void SetAttachmentPayloadId(int64_t attachment_id, int64_t payload_id);
void WriteResponseFrame(
nearby::sharing::service::proto::ConnectionResponseFrame::Status
response_status);
void WriteCancelFrame();
protected:
virtual void InvokeTransferUpdateCallback(
const TransferMetadata& metadata) = 0;
virtual bool OnNewConnection(NearbyConnection* connection) = 0;
void SetAttachmentPayloadId(int64_t attachment_id, int64_t payload_id);
void set_payload_tracker(std::shared_ptr<PayloadTracker> payload_tracker) {
payload_tracker_ = std::move(payload_tracker);
}
AttachmentContainer& mutable_attachment_container() {
return attachment_container_;
}
void WriteFrame(const nearby::sharing::service::proto::Frame& frame);
private:
std::string endpoint_id_;
std::optional<NearbyShareDecryptedPublicCertificate> certificate_;
+53
View File
@@ -27,6 +27,7 @@
#include "absl/time/time.h"
#include "sharing/certificates/fake_nearby_share_certificate_manager.h"
#include "sharing/fake_nearby_connection.h"
#include "sharing/fake_nearby_connections_manager.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/nearby_connection.h"
#include "sharing/nearby_sharing_decoder_impl.h"
@@ -39,6 +40,9 @@ namespace nearby::sharing {
namespace {
using ::location::nearby::proto::sharing::OSType;
using ::nearby::sharing::service::proto::Frame;
using ::nearby::sharing::service::proto::ConnectionResponseFrame;
using ::nearby::sharing::service::proto::V1Frame;
constexpr absl::string_view kEndpointId = "12345";
@@ -63,6 +67,10 @@ class TestShareTargetInfo : public ShareTargetInfo {
on_new_connection_result_ = result;
}
void SetAttachmentPayloadId(int64_t attachment_id, int64_t payload_id) {
ShareTargetInfo::SetAttachmentPayloadId(attachment_id, payload_id);
}
protected:
void InvokeTransferUpdateCallback(
const TransferMetadata& metadata) override {
@@ -227,5 +235,50 @@ TEST(ShareTargetInfoTest, OnDisconnect) {
EXPECT_TRUE(info.LastTransferMetadata()->is_final_status());
}
TEST(ShareTargetInfoTest, CancelPayloads) {
ShareTarget share_target;
TestShareTargetInfo info(std::string(kEndpointId), share_target);
info.SetAttachmentPayloadId(1, 2);
info.SetAttachmentPayloadId(3, 4);
FakeNearbyConnectionsManager connections_manager;
info.CancelPayloads(connections_manager);
EXPECT_TRUE(connections_manager.WasPayloadCanceled(2));
EXPECT_TRUE(connections_manager.WasPayloadCanceled(4));
}
TEST(ShareTargetInfoTest, WriteResponseFrame) {
ShareTarget share_target;
TestShareTargetInfo info(std::string(kEndpointId), share_target);
FakeNearbyConnection connection;
EXPECT_TRUE(info.OnConnected(absl::Now(), &connection));
info.WriteResponseFrame(ConnectionResponseFrame::REJECT);
std::vector<uint8_t> frame_data = connection.GetWrittenData();
Frame frame;
ASSERT_TRUE(frame.ParseFromArray(frame_data.data(), frame_data.size()));
ASSERT_EQ(frame.version(), Frame::V1);
ASSERT_EQ(frame.v1().type(), V1Frame::RESPONSE);
EXPECT_EQ(frame.v1().connection_response().status(),
ConnectionResponseFrame::REJECT);
}
TEST(ShareTargetInfoTest, WriteCancelFrame) {
ShareTarget share_target;
TestShareTargetInfo info(std::string(kEndpointId), share_target);
FakeNearbyConnection connection;
EXPECT_TRUE(info.OnConnected(absl::Now(), &connection));
info.WriteCancelFrame();
std::vector<uint8_t> frame_data = connection.GetWrittenData();
Frame frame;
ASSERT_TRUE(frame.ParseFromArray(frame_data.data(), frame_data.size()));
ASSERT_EQ(frame.version(), Frame::V1);
EXPECT_EQ(frame.v1().type(), V1Frame::CANCEL);
}
} // namespace
} // namespace nearby::sharing