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 #ifdef __Fuchsia__
6
7 #include <lib/fidl/transport.h>
8 #include <zircon/assert.h>
9 #include <zircon/syscalls.h>
10
fidl_socket_write_control(zx_handle_t socket,const void * buffer,size_t capacity)11 zx_status_t fidl_socket_write_control(zx_handle_t socket, const void* buffer,
12 size_t capacity) {
13 for (;;) {
14 zx_status_t status = zx_socket_write(socket, ZX_SOCKET_CONTROL, buffer,
15 capacity, nullptr);
16 if (status != ZX_ERR_SHOULD_WAIT) {
17 return status;
18 }
19
20 zx_signals_t observed = ZX_SIGNAL_NONE;
21 status = zx_object_wait_one(socket, ZX_SOCKET_CONTROL_WRITABLE | ZX_SOCKET_PEER_CLOSED,
22 ZX_TIME_INFINITE, &observed);
23 if (status != ZX_OK) {
24 return status;
25 }
26
27 if (observed & ZX_SOCKET_PEER_CLOSED) {
28 return ZX_ERR_PEER_CLOSED;
29 }
30
31 ZX_ASSERT(observed & ZX_SOCKET_CONTROL_WRITABLE);
32 }
33 }
34
fidl_socket_read_control(zx_handle_t socket,void * buffer,size_t capacity,size_t * out_actual)35 zx_status_t fidl_socket_read_control(zx_handle_t socket, void* buffer,
36 size_t capacity, size_t* out_actual) {
37 for (;;) {
38 zx_status_t status = zx_socket_read(socket, ZX_SOCKET_CONTROL, buffer,
39 capacity, out_actual);
40 if (status != ZX_ERR_SHOULD_WAIT) {
41 return status;
42 }
43
44 zx_signals_t observed = ZX_SIGNAL_NONE;
45 status = zx_object_wait_one(socket, ZX_SOCKET_CONTROL_READABLE | ZX_SOCKET_PEER_CLOSED,
46 ZX_TIME_INFINITE, &observed);
47 if (status != ZX_OK) {
48 return status;
49 }
50
51 if (observed & ZX_SOCKET_CONTROL_READABLE) {
52 continue;
53 }
54
55 ZX_ASSERT(observed & ZX_SOCKET_PEER_CLOSED);
56 return ZX_ERR_PEER_CLOSED;
57 }
58 }
59
fidl_socket_call_control(zx_handle_t socket,const void * buffer,size_t capacity,void * out_buffer,size_t out_capacity,size_t * out_actual)60 zx_status_t fidl_socket_call_control(zx_handle_t socket, const void* buffer,
61 size_t capacity, void* out_buffer,
62 size_t out_capacity, size_t* out_actual) {
63 zx_status_t status = fidl_socket_write_control(socket, buffer, capacity);
64 if (status != ZX_OK) {
65 return status;
66 }
67 return fidl_socket_read_control(socket, out_buffer, out_capacity, out_actual);
68 }
69
70 #endif
71