blob: 885f78bd173690ce5e2370b39a45385f12465e9a [file]
// Copyright 2021 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 "transport_socket.h"
#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/message.h>
#include <zircon/assert.h>
#include <zircon/fidl.h>
#include <zircon/types.h>
#include <cstring>
#include <memory>
namespace fidl {
namespace internal {
namespace {
zx_status_t socket_write(fidl_handle_t handle, const WriteOptions& write_options, const void* data,
uint32_t data_count, const fidl_handle_t* handles,
const void* handle_metadata, uint32_t handles_count) {
ZX_ASSERT(handles_count == 0);
ZX_ASSERT(data_count == 1); // 1 iovec
size_t actual;
zx_channel_iovec_t iovec = static_cast<const zx_channel_iovec_t*>(data)[0];
zx_status_t status = zx_socket_write(handle, 0, iovec.buffer, iovec.capacity, &actual);
if (status != ZX_OK) {
return status;
}
ZX_ASSERT(actual == iovec.capacity);
return ZX_OK;
}
zx_status_t socket_read(fidl_handle_t handle, const ReadOptions& read_options, void* data,
uint32_t data_capacity, fidl_handle_t* handles, void* handle_metadata,
uint32_t handles_capacity, uint32_t* out_data_actual_count,
uint32_t* out_handles_actual_count) {
size_t actual;
zx_status_t status = zx_socket_read(handle, 0, data, data_capacity, &actual);
if (status != ZX_OK) {
return status;
}
*out_data_actual_count = static_cast<uint32_t>(actual);
*out_handles_actual_count = 0;
return ZX_OK;
}
zx_status_t socket_create_waiter(fidl_handle_t handle, async_dispatcher_t* dispatcher,
TransportWaitSuccessHandler success_handler,
TransportWaitFailureHandler failure_handler,
AnyTransportWaiter& any_transport_waiter) {
any_transport_waiter.emplace<SocketWaiter>(handle, dispatcher, std::move(success_handler),
std::move(failure_handler));
return ZX_OK;
}
void socket_close(fidl_handle_t handle) { zx_handle_close(handle); }
} // namespace
const TransportVTable SocketTransport::VTable = {
.type = FIDL_TRANSPORT_TYPE_TEST,
.encoding_configuration = &SocketTransport::EncodingConfiguration,
.write = socket_write,
.read = socket_read,
.create_waiter = socket_create_waiter,
.close = socket_close,
};
void SocketWaiter::HandleWaitFinished(async_dispatcher_t* dispatcher, zx_status_t status,
const zx_packet_signal_t* signal) {
if (status != ZX_OK) {
return failure_handler_(fidl::UnbindInfo::DispatcherError(status));
}
if (!(signal->observed & ZX_SOCKET_READABLE)) {
ZX_ASSERT(signal->observed & ZX_SOCKET_PEER_CLOSED);
return failure_handler_(fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED));
}
FIDL_INTERNAL_DISABLE_AUTO_VAR_INIT InlineMessageBuffer<ZX_CHANNEL_MAX_MSG_BYTES> bytes;
IncomingMessage msg = fidl::MessageRead(zx::unowned_socket(async_wait_t::object), bytes.view(),
nullptr, nullptr, 0);
if (!msg.ok()) {
return failure_handler_(fidl::UnbindInfo{msg});
}
return success_handler_(msg, nullptr);
}
const CodingConfig SocketTransport::EncodingConfiguration = {};
AnyTransport MakeAnyTransport(zx::socket socket) {
return AnyTransport::Make<SocketTransport>(socket.release());
}
AnyUnownedTransport MakeAnyUnownedTransport(const zx::socket& socket) {
return MakeAnyUnownedTransport(socket.borrow());
}
AnyUnownedTransport MakeAnyUnownedTransport(const zx::unowned_socket& socket) {
return AnyUnownedTransport::Make<SocketTransport>(socket->get());
}
} // namespace internal
} // namespace fidl