blob: 95697b2f81c7d237da132d9a81197a5dd485ee2f [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/public/cpp/net_adapters.h"
#include <limits>
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/strings/string_view_util.h"
#include "net/base/net_errors.h"
namespace network {
namespace {
constexpr size_t kMaxBufSize = 64 * 1024;
}
NetToMojoPendingBuffer::NetToMojoPendingBuffer(
mojo::ScopedDataPipeProducerHandle handle,
base::span<char> buffer)
: handle_(std::move(handle)), buffer_(buffer) {
CHECK_LE(buffer_.size(), std::numeric_limits<uint32_t>::max());
}
NetToMojoPendingBuffer::~NetToMojoPendingBuffer() {
if (handle_.is_valid())
handle_->EndWriteData(0);
}
MojoResult NetToMojoPendingBuffer::BeginWrite(
mojo::ScopedDataPipeProducerHandle* handle,
scoped_refptr<NetToMojoPendingBuffer>* pending) {
base::span<uint8_t> buf;
MojoResult result =
(*handle)->BeginWriteData(kMaxBufSize, MOJO_WRITE_DATA_FLAG_NONE, buf);
if (result != MOJO_RESULT_OK) {
*pending = nullptr;
return result;
}
if (buf.size() > kMaxBufSize) {
buf = buf.first(kMaxBufSize);
}
*pending = new NetToMojoPendingBuffer(std::move(*handle),
base::as_writable_chars(buf));
return MOJO_RESULT_OK;
}
mojo::ScopedDataPipeProducerHandle NetToMojoPendingBuffer::Complete(
uint32_t num_bytes) {
handle_->EndWriteData(num_bytes);
buffer_ = base::span<char>();
return std::move(handle_);
}
NetToMojoIOBuffer::NetToMojoIOBuffer(
scoped_refptr<NetToMojoPendingBuffer> pending_buffer,
size_t offset)
: net::WrappedIOBuffer(base::span(*pending_buffer).subspan(offset)),
pending_buffer_(std::move(pending_buffer)) {}
NetToMojoIOBuffer::~NetToMojoIOBuffer() {
// Avoid dangling ptr should this destructor remove the last reference
// to `pending_buffer_`.
ClearSpan();
}
MojoToNetPendingBuffer::MojoToNetPendingBuffer(
mojo::ScopedDataPipeConsumerHandle handle,
base::span<const char> buffer)
: handle_(std::move(handle)), buffer_(buffer) {
CHECK_LE(buffer_.size(), std::numeric_limits<uint32_t>::max());
}
MojoToNetPendingBuffer::~MojoToNetPendingBuffer() = default;
// static
MojoResult MojoToNetPendingBuffer::BeginRead(
mojo::ScopedDataPipeConsumerHandle* handle,
scoped_refptr<MojoToNetPendingBuffer>* pending) {
base::span<const uint8_t> buffer;
MojoResult result =
(*handle)->BeginReadData(MOJO_READ_DATA_FLAG_NONE, buffer);
if (result != MOJO_RESULT_OK) {
*pending = nullptr;
return result;
}
*pending = new MojoToNetPendingBuffer(std::move(*handle),
base::as_string_view(buffer));
return MOJO_RESULT_OK;
}
void MojoToNetPendingBuffer::CompleteRead(uint32_t num_bytes) {
handle_->EndReadData(num_bytes);
buffer_ = base::span<const char>();
}
mojo::ScopedDataPipeConsumerHandle MojoToNetPendingBuffer::ReleaseHandle() {
DCHECK(IsComplete());
return std::move(handle_);
}
bool MojoToNetPendingBuffer::IsComplete() const {
return buffer_.empty();
}
MojoToNetIOBuffer::MojoToNetIOBuffer(
scoped_refptr<MojoToNetPendingBuffer> pending_buffer,
int bytes_to_be_read)
: net::WrappedIOBuffer(*pending_buffer),
pending_buffer_(std::move(pending_buffer)),
bytes_to_be_read_(bytes_to_be_read) {}
MojoToNetIOBuffer::~MojoToNetIOBuffer() {
// We can safely notify mojo, that the data has been consumed and can be
// released at this point.
pending_buffer_->CompleteRead(bytes_to_be_read_);
// Prevent dangling ptr should this destructor remove the last reference
// to `pending_buffer_`.
ClearSpan();
}
} // namespace network