1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fs/handler.h>
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <fuchsia/io/c/fidl.h>
10 #include <zircon/assert.h>
11 #include <zircon/syscalls.h>
12 #include <zircon/types.h>
13
14 namespace fs {
15 namespace {
16
Reply(fidl_txn_t * txn,const fidl_msg_t * msg)17 zx_status_t Reply(fidl_txn_t* txn, const fidl_msg_t* msg) {
18 auto connection = FidlConnection::FromTxn(txn);
19 auto header = reinterpret_cast<fidl_message_header_t*>(msg->bytes);
20 header->txid = connection->Txid();
21 return zx_channel_write(connection->Channel(), 0, msg->bytes, msg->num_bytes,
22 msg->handles, msg->num_handles);
23 };
24
25 // Don't actually send anything on a channel when completing this operation.
26 // This is useful for mocking out "close" requests.
NullReply(fidl_txn_t * reply,const fidl_msg_t * msg)27 zx_status_t NullReply(fidl_txn_t* reply, const fidl_msg_t* msg) {
28 return ZX_OK;
29 }
30
31 } // namespace
32
ReadMessage(zx_handle_t h,FidlDispatchFunction dispatch)33 zx_status_t ReadMessage(zx_handle_t h, FidlDispatchFunction dispatch) {
34 ZX_ASSERT(zx_object_get_info(h, ZX_INFO_HANDLE_VALID, NULL, 0,
35 NULL, NULL) == ZX_OK);
36 uint8_t bytes[ZXFIDL_MAX_MSG_BYTES];
37 zx_handle_t handles[ZXFIDL_MAX_MSG_HANDLES];
38 fidl_msg_t msg = {
39 .bytes = bytes,
40 .handles = handles,
41 .num_bytes = 0,
42 .num_handles = 0,
43 };
44
45 zx_status_t r = zx_channel_read(h, 0, bytes, handles, countof(bytes),
46 countof(handles), &msg.num_bytes,
47 &msg.num_handles);
48 if (r != ZX_OK) {
49 return r;
50 }
51
52 if (msg.num_bytes < sizeof(fidl_message_header_t)) {
53 zx_handle_close_many(msg.handles, msg.num_handles);
54 return ZX_ERR_IO;
55 }
56
57 auto header = reinterpret_cast<fidl_message_header_t*>(msg.bytes);
58 fidl_txn_t txn = {
59 .reply = Reply,
60 };
61 FidlConnection connection(std::move(txn), h, header->txid);
62
63 // Callback is responsible for decoding the message, and closing
64 // any associated handles.
65 return dispatch(&msg, &connection);
66 }
67
CloseMessage(FidlDispatchFunction dispatch)68 zx_status_t CloseMessage(FidlDispatchFunction dispatch) {
69 fuchsia_io_NodeCloseRequest request;
70 memset(&request, 0, sizeof(request));
71 request.hdr.ordinal = fuchsia_io_NodeCloseOrdinal;
72 fidl_msg_t msg = {
73 .bytes = &request,
74 .handles = NULL,
75 .num_bytes = sizeof(request),
76 .num_handles = 0u,
77 };
78
79 fidl_txn_t txn = {
80 .reply = NullReply,
81 };
82 FidlConnection connection(std::move(txn), ZX_HANDLE_INVALID, 0);
83
84 // Remote side was closed.
85 dispatch(&msg, &connection);
86 return ERR_DISPATCHER_DONE;
87 }
88
89 } // namespace fs
90