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