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 <lib/fdio/util.h>
6 #include <lib/zxio/null.h>
7 #include <lib/zxio/ops.h>
8 #include <string.h>
9 #include <zircon/compiler.h>
10 #include <zircon/syscalls.h>
11 
12 typedef struct fdio_waitable {
13     zxio_t io;
14 
15     // arbitrary handle
16     zx_handle_t handle;
17 
18     // signals that cause ZXIO_READABLE
19     zx_signals_t readable;
20 
21     // signals that cause ZXIO_WRITABLE
22     zx_signals_t writable;
23 
24     // if true, don't close handle on close() op
25     bool shared_handle;
26 } fdio_waitable_t;
27 
28 static_assert(sizeof(fdio_waitable_t) <= sizeof(zxio_storage_t),
29               "fdio_waitable_t must fit inside zxio_storage_t.");
30 
fdio_waitable_close(zxio_t * io)31 static zx_status_t fdio_waitable_close(zxio_t* io) {
32     fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
33     if (!waitable->shared_handle) {
34         zx_handle_t handle = waitable->handle;
35         waitable->handle = ZX_HANDLE_INVALID;
36         zx_handle_close(handle);
37     }
38     return ZX_OK;
39 }
40 
fdio_waitable_wait_begin(zxio_t * io,zxio_signals_t zxio_signals,zx_handle_t * out_handle,zx_signals_t * out_zx_signals)41 static void fdio_waitable_wait_begin(zxio_t* io, zxio_signals_t zxio_signals,
42                                      zx_handle_t* out_handle,
43                                      zx_signals_t* out_zx_signals) {
44     fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
45     zx_signals_t zx_signals = ZX_SIGNAL_NONE;
46     if (zxio_signals & ZXIO_READABLE) {
47         zx_signals |= waitable->readable;
48     }
49     if (zxio_signals & ZXIO_WRITABLE) {
50         zx_signals |= waitable->writable;
51     }
52     *out_handle = waitable->handle;
53     *out_zx_signals = zx_signals;
54 }
55 
fdio_waitable_wait_end(zxio_t * io,zx_signals_t zx_signals,zxio_signals_t * out_zxio_signals)56 static void fdio_waitable_wait_end(zxio_t* io, zx_signals_t zx_signals,
57                                    zxio_signals_t* out_zxio_signals) {
58     fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
59     zxio_signals_t zxio_signals = ZXIO_SIGNAL_NONE;
60     if (zx_signals & waitable->readable) {
61         zxio_signals |= ZXIO_READABLE;
62     }
63     if (zx_signals & waitable->writable) {
64         zxio_signals |= ZXIO_WRITABLE;
65     }
66     *out_zxio_signals = zxio_signals;
67 }
68 
__anon8cb3e9c50102() 69 static constexpr zxio_ops_t fdio_waitable_ops = []() {
70     zxio_ops_t ops = zxio_default_ops;
71     ops.close = fdio_waitable_close;
72     ops.wait_begin = fdio_waitable_wait_begin;
73     ops.wait_end = fdio_waitable_wait_end;
74     return ops;
75 }();
76 
fdio_waitable_init(zxio_storage_t * storage,zx_handle_t handle,zx_signals_t readable,zx_signals_t writable,bool shared_handle)77 static void fdio_waitable_init(zxio_storage_t* storage,
78                                zx_handle_t handle,
79                                zx_signals_t readable,
80                                zx_signals_t writable,
81                                bool shared_handle) {
82     fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(storage);
83     zxio_init(&waitable->io, &fdio_waitable_ops);
84     waitable->handle = handle;
85     waitable->readable = readable;
86     waitable->writable = writable;
87     waitable->shared_handle = shared_handle;
88 }
89 
90 __BEGIN_CDECLS
91 
fdio_waitable_create(zx_handle_t handle,zx_signals_t readable,zx_signals_t writable,bool shared_handle)92 fdio_t* fdio_waitable_create(zx_handle_t handle, zx_signals_t readable,
93                              zx_signals_t writable, bool shared_handle) {
94     zxio_storage_t* storage = nullptr;
95     fdio_t* io = fdio_zxio_create(&storage);
96     if (io == nullptr) {
97         if (!shared_handle) {
98             zx_handle_close(handle);
99         }
100         return nullptr;
101     }
102     fdio_waitable_init(storage, handle, readable, writable, shared_handle);
103     return io;
104 }
105 
106 __END_CDECLS
107