mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
212 lines
6.8 KiB
C++
212 lines
6.8 KiB
C++
// Copyright 2016 The Fuchsia Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/glue/data_pipe_utils.h"
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
#include <utility>
|
|
|
|
#include "lib/ftl/files/file_descriptor.h"
|
|
#include "mojo/public/cpp/environment/async_waiter.h"
|
|
#include "mojo/public/cpp/environment/environment.h"
|
|
|
|
namespace glue {
|
|
namespace {
|
|
|
|
// CopyToFileHandler -----------------------------------------------------------
|
|
|
|
class CopyToFileHandler {
|
|
public:
|
|
CopyToFileHandler(mojo::ScopedDataPipeConsumerHandle source,
|
|
ftl::UniqueFD destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback);
|
|
|
|
private:
|
|
~CopyToFileHandler();
|
|
|
|
void SendCallback(bool value);
|
|
void OnHandleReady(MojoResult result);
|
|
static void WaitComplete(void* context, MojoResult result);
|
|
|
|
mojo::ScopedDataPipeConsumerHandle source_;
|
|
ftl::UniqueFD destination_;
|
|
ftl::RefPtr<ftl::TaskRunner> task_runner_;
|
|
std::function<void(bool)> callback_;
|
|
const MojoAsyncWaiter* waiter_;
|
|
MojoAsyncWaitID wait_id_;
|
|
|
|
FTL_DISALLOW_COPY_AND_ASSIGN(CopyToFileHandler);
|
|
};
|
|
|
|
CopyToFileHandler::CopyToFileHandler(mojo::ScopedDataPipeConsumerHandle source,
|
|
ftl::UniqueFD destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback)
|
|
: source_(std::move(source)),
|
|
destination_(std::move(destination)),
|
|
task_runner_(task_runner),
|
|
callback_(callback),
|
|
waiter_(mojo::Environment::GetDefaultAsyncWaiter()),
|
|
wait_id_(0) {
|
|
task_runner_->PostTask([this]() { OnHandleReady(MOJO_RESULT_OK); });
|
|
}
|
|
|
|
CopyToFileHandler::~CopyToFileHandler() {}
|
|
|
|
void CopyToFileHandler::SendCallback(bool value) {
|
|
FTL_DCHECK(!wait_id_);
|
|
auto callback = callback_;
|
|
delete this;
|
|
callback(value);
|
|
}
|
|
|
|
void CopyToFileHandler::OnHandleReady(MojoResult result) {
|
|
if (result == MOJO_RESULT_OK) {
|
|
const void* buffer = nullptr;
|
|
uint32_t size = 0;
|
|
result = BeginReadDataRaw(source_.get(), &buffer, &size,
|
|
MOJO_READ_DATA_FLAG_NONE);
|
|
if (result == MOJO_RESULT_OK) {
|
|
bool write_success = ftl::WriteFileDescriptor(
|
|
destination_.get(), static_cast<const char*>(buffer), size);
|
|
result = EndReadDataRaw(source_.get(), size);
|
|
if (!write_success || result != MOJO_RESULT_OK) {
|
|
SendCallback(false);
|
|
} else {
|
|
task_runner_->PostTask([this]() { OnHandleReady(MOJO_RESULT_OK); });
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (result == MOJO_RESULT_FAILED_PRECONDITION) {
|
|
SendCallback(true);
|
|
return;
|
|
}
|
|
if (result == MOJO_RESULT_SHOULD_WAIT) {
|
|
wait_id_ =
|
|
waiter_->AsyncWait(source_.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
|
|
MOJO_DEADLINE_INDEFINITE, &WaitComplete, this);
|
|
return;
|
|
}
|
|
SendCallback(false);
|
|
}
|
|
|
|
void CopyToFileHandler::WaitComplete(void* context, MojoResult result) {
|
|
CopyToFileHandler* handler = static_cast<CopyToFileHandler*>(context);
|
|
handler->wait_id_ = 0;
|
|
handler->OnHandleReady(result);
|
|
}
|
|
|
|
// CopyFromFileHandler ---------------------------------------------------------
|
|
|
|
class CopyFromFileHandler {
|
|
public:
|
|
CopyFromFileHandler(ftl::UniqueFD source,
|
|
mojo::ScopedDataPipeProducerHandle destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback);
|
|
|
|
private:
|
|
~CopyFromFileHandler();
|
|
|
|
void SendCallback(bool value);
|
|
void OnHandleReady(MojoResult result);
|
|
static void WaitComplete(void* context, MojoResult result);
|
|
|
|
ftl::UniqueFD source_;
|
|
mojo::ScopedDataPipeProducerHandle destination_;
|
|
ftl::RefPtr<ftl::TaskRunner> task_runner_;
|
|
std::function<void(bool)> callback_;
|
|
const MojoAsyncWaiter* waiter_;
|
|
MojoAsyncWaitID wait_id_;
|
|
|
|
FTL_DISALLOW_COPY_AND_ASSIGN(CopyFromFileHandler);
|
|
};
|
|
|
|
CopyFromFileHandler::CopyFromFileHandler(
|
|
ftl::UniqueFD source,
|
|
mojo::ScopedDataPipeProducerHandle destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback)
|
|
: source_(std::move(source)),
|
|
destination_(std::move(destination)),
|
|
task_runner_(task_runner),
|
|
callback_(callback),
|
|
waiter_(mojo::Environment::GetDefaultAsyncWaiter()),
|
|
wait_id_(0) {
|
|
task_runner_->PostTask([this]() { OnHandleReady(MOJO_RESULT_OK); });
|
|
}
|
|
|
|
CopyFromFileHandler::~CopyFromFileHandler() {}
|
|
|
|
void CopyFromFileHandler::SendCallback(bool value) {
|
|
FTL_DCHECK(!wait_id_);
|
|
auto callback = callback_;
|
|
delete this;
|
|
callback(value);
|
|
}
|
|
|
|
void CopyFromFileHandler::OnHandleReady(MojoResult result) {
|
|
if (result == MOJO_RESULT_OK) {
|
|
void* buffer = nullptr;
|
|
uint32_t size = 0;
|
|
result = BeginWriteDataRaw(destination_.get(), &buffer, &size,
|
|
MOJO_WRITE_DATA_FLAG_NONE);
|
|
if (result == MOJO_RESULT_OK) {
|
|
FTL_DCHECK(size < static_cast<uint32_t>(std::numeric_limits<int>::max()));
|
|
ssize_t bytes_read = ftl::ReadFileDescriptor(
|
|
source_.get(), static_cast<char*>(buffer), size);
|
|
result = EndWriteDataRaw(destination_.get(),
|
|
std::max<ssize_t>(0l, bytes_read));
|
|
if (bytes_read == -1 || result != MOJO_RESULT_OK) {
|
|
SendCallback(false);
|
|
} else if (bytes_read < size) {
|
|
// Reached EOF. Stop the process.
|
|
SendCallback(true);
|
|
} else {
|
|
task_runner_->PostTask([this]() { OnHandleReady(MOJO_RESULT_OK); });
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (result == MOJO_RESULT_SHOULD_WAIT) {
|
|
wait_id_ = waiter_->AsyncWait(
|
|
destination_.get().value(), MOJO_HANDLE_SIGNAL_WRITABLE,
|
|
MOJO_DEADLINE_INDEFINITE, &WaitComplete, this);
|
|
return;
|
|
}
|
|
SendCallback(false);
|
|
}
|
|
|
|
void CopyFromFileHandler::WaitComplete(void* context, MojoResult result) {
|
|
CopyFromFileHandler* handler = static_cast<CopyFromFileHandler*>(context);
|
|
handler->wait_id_ = 0;
|
|
handler->OnHandleReady(result);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void CopyToFileDescriptor(mojo::ScopedDataPipeConsumerHandle source,
|
|
ftl::UniqueFD destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback) {
|
|
new CopyToFileHandler(std::move(source), std::move(destination), task_runner,
|
|
callback);
|
|
}
|
|
|
|
void CopyFromFileDescriptor(ftl::UniqueFD source,
|
|
mojo::ScopedDataPipeProducerHandle destination,
|
|
ftl::TaskRunner* task_runner,
|
|
const std::function<void(bool)>& callback) {
|
|
new CopyFromFileHandler(std::move(source), std::move(destination),
|
|
task_runner, callback);
|
|
}
|
|
|
|
} // namespace glue
|