| // Copyright 2018 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 "fidl-handler.h" |
| |
| #include <fuchsia/io/c/fidl.h> |
| #include <lib/fidl/internal.h> |
| #include <lib/fidl/txn_header.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <zircon/assert.h> |
| #include <zircon/syscalls.h> |
| #include <zircon/types.h> |
| |
| namespace fs { |
| namespace { |
| |
| zx_status_t Reply(fidl_txn_t* txn, const fidl_outgoing_msg_t* msg) { |
| auto connection = FidlConnection::FromTxn(txn); |
| auto header = reinterpret_cast<fidl_message_header_t*>(msg->bytes); |
| header->txid = connection->Txid(); |
| return zx_channel_write_etc(connection->Channel(), 0, msg->bytes, msg->num_bytes, msg->handles, |
| msg->num_handles); |
| } |
| |
| // Don't actually send anything on a channel when completing this operation. |
| // This is useful for mocking out "close" requests. |
| zx_status_t NullReply(fidl_txn_t* reply, const fidl_outgoing_msg_t* msg) { return ZX_OK; } |
| |
| } // namespace |
| |
| zx_status_t ReadMessage(zx_handle_t h, FidlDispatchFunction dispatch) { |
| ZX_ASSERT(zx_object_get_info(h, ZX_INFO_HANDLE_VALID, NULL, 0, NULL, NULL) == ZX_OK); |
| uint8_t bytes[ZXFIDL_MAX_MSG_BYTES]; |
| zx_handle_info_t handles[ZXFIDL_MAX_MSG_HANDLES]; |
| fidl_incoming_msg_t msg = { |
| .bytes = bytes, |
| .handles = handles, |
| .num_bytes = 0, |
| .num_handles = 0, |
| }; |
| |
| zx_status_t r = zx_channel_read_etc(h, 0, bytes, handles, countof(bytes), countof(handles), |
| &msg.num_bytes, &msg.num_handles); |
| if (r != ZX_OK) { |
| return r; |
| } |
| |
| if (msg.num_bytes < sizeof(fidl_message_header_t)) { |
| FidlHandleInfoCloseMany(msg.handles, msg.num_handles); |
| return ZX_ERR_IO; |
| } |
| |
| auto header = reinterpret_cast<fidl_message_header_t*>(msg.bytes); |
| fidl_txn_t txn = { |
| .reply = Reply, |
| }; |
| FidlConnection connection(std::move(txn), h, header->txid); |
| |
| // Callback is responsible for decoding the message, and closing |
| // any associated handles. |
| return dispatch(&msg, &connection); |
| } |
| |
| zx_status_t CloseMessage(FidlDispatchFunction dispatch) { |
| fuchsia_io_NodeCloseRequest request; |
| memset(&request, 0, sizeof(request)); |
| fidl_init_txn_header(&request.hdr, 0, fuchsia_io_NodeCloseOrdinal); |
| fidl_incoming_msg_t msg = { |
| .bytes = &request, |
| .handles = NULL, |
| .num_bytes = sizeof(request), |
| .num_handles = 0u, |
| }; |
| |
| fidl_txn_t txn = { |
| .reply = NullReply, |
| }; |
| FidlConnection connection(std::move(txn), ZX_HANDLE_INVALID, 0); |
| |
| // Remote side was closed. |
| dispatch(&msg, &connection); |
| return ERR_DISPATCHER_DONE; |
| } |
| |
| } // namespace fs |