diff --git a/sharing/BUILD b/sharing/BUILD index 61c9d32d..83c10b5b 100644 --- a/sharing/BUILD +++ b/sharing/BUILD @@ -24,6 +24,7 @@ cc_library( "//internal/base:file_path", "//internal/base:files", "//internal/crypto_cros", # buildcleaner: keep + "//internal/platform:base", "//internal/interop:authentication_status", "@com_google_absl//absl/random", "@com_google_absl//absl/strings:string_view", diff --git a/sharing/nearby_connections_service.cc b/sharing/nearby_connections_service.cc index 3d8f5799..db617206 100644 --- a/sharing/nearby_connections_service.cc +++ b/sharing/nearby_connections_service.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,61 @@ using NcPayload = ::nearby::connections::Payload; using NcStatus = ::nearby::connections::Status; using NcStrategy = ::nearby::connections::Strategy; +class VectorInputStream final : public InputStream { + public: + explicit VectorInputStream(std::vector bytes) + : bytes_(std::move(bytes)) {} + + ExceptionOr Read(std::int64_t size) override { + if (closed_) { + return ExceptionOr(Exception::kIo); + } + if (offset_ >= bytes_.size() || size <= 0) { + return ExceptionOr(ByteArray()); + } + + const size_t remaining = bytes_.size() - offset_; + const size_t chunk_size = std::min(remaining, static_cast(size)); + ByteArray chunk(reinterpret_cast(bytes_.data() + offset_), + chunk_size); + offset_ += chunk_size; + return ExceptionOr(std::move(chunk)); + } + + Exception Close() override { + closed_ = true; + return {Exception::kSuccess}; + } + + private: + std::vector bytes_; + size_t offset_ = 0; + bool closed_ = false; +}; + +class SharedInputStream final : public InputStream { + public: + explicit SharedInputStream(std::shared_ptr stream) + : stream_(std::move(stream)) {} + + ExceptionOr Read(std::int64_t size) override { + if (stream_ == nullptr) { + return ExceptionOr(Exception::kIo); + } + return stream_->Read(size); + } + + Exception Close() override { + if (stream_ == nullptr) { + return {Exception::kIo}; + } + return stream_->Close(); + } + + private: + std::shared_ptr stream_; +}; + Status ConvertToStatus(NcStatus status) { return static_cast(status.value); } @@ -86,6 +142,17 @@ NcPayload ConvertToServicePayload(Payload payload) { return NcPayload(payload.id, ByteArray(std::string(bytes.begin(), bytes.end()))); } + case PayloadContent::Type::kStream: { + if (payload.content.stream_payload.input_stream != nullptr) { + return NcPayload( + payload.id, + std::make_unique( + std::move(payload.content.stream_payload.input_stream))); + } + auto stream = std::make_unique( + std::move(payload.content.stream_payload.bytes)); + return NcPayload(payload.id, std::move(stream)); + } default: return NcPayload(); } diff --git a/sharing/nearby_connections_types.h b/sharing/nearby_connections_types.h index 6112778e..6fade2f4 100644 --- a/sharing/nearby_connections_types.h +++ b/sharing/nearby_connections_types.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "internal/base/file_path.h" +#include "internal/platform/input_stream.h" #include "internal/interop/authentication_status.h" namespace nearby { @@ -362,6 +364,14 @@ struct BytesPayload { std::vector bytes; }; +// A stream payload backed by an in-memory byte buffer on the sender side. +struct StreamPayload { + // The bytes to expose through the stream. + std::vector bytes; + // Optional live stream source for long-lived outgoing stream payloads. + std::shared_ptr input_stream; +}; + // A file payload representing a file. struct FilePayload { // The file to which this payload points to. When sending this payload, the @@ -375,6 +385,8 @@ struct FilePayload { struct PayloadContent { // A Payload consisting of a single byte array. BytesPayload bytes_payload; + // A Payload exposed to Nearby as a finite stream. + StreamPayload stream_payload; // A Payload representing a file on the device. FilePayload file_payload; enum class Type { kUnknown = 0, kBytes = 1, kStream = 2, kFile = 3 }; @@ -400,6 +412,9 @@ struct Payload { explicit Payload(std::vector bytes) : Payload(GenerateId(), std::move(bytes)) {} + explicit Payload(StreamPayload stream_payload) + : Payload(GenerateId(), std::move(stream_payload)) {} + explicit Payload(FilePath file_path, absl::string_view parent_folder = absl::string_view()) : Payload(std::hash()(file_path.ToString()), file_path, @@ -410,6 +425,12 @@ struct Payload { content.bytes_payload.bytes = std::move(bytes); } + Payload(int64_t id, StreamPayload stream_payload) : id(id) { + content.type = PayloadContent::Type::kStream; + content.stream_payload.bytes = std::move(stream_payload.bytes); + content.stream_payload.input_stream = std::move(stream_payload.input_stream); + } + Payload(int64_t id, FilePath file_path, absl::string_view parent_folder = absl::string_view()) : id(id) {