// 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. #ifdef __Fuchsia__ #include <lib/fidl/transport.h> #include <zircon/assert.h> #include <zircon/syscalls.h> zx_status_t fidl_socket_write_control(zx_handle_t socket, const void* buffer, size_t capacity) { for (;;) { zx_status_t status = zx_socket_write(socket, ZX_SOCKET_CONTROL, buffer, capacity, nullptr); if (status != ZX_ERR_SHOULD_WAIT) { return status; } zx_signals_t observed = ZX_SIGNAL_NONE; status = zx_object_wait_one(socket, ZX_SOCKET_CONTROL_WRITABLE | ZX_SOCKET_PEER_CLOSED, ZX_TIME_INFINITE, &observed); if (status != ZX_OK) { return status; } if (observed & ZX_SOCKET_PEER_CLOSED) { return ZX_ERR_PEER_CLOSED; } ZX_ASSERT(observed & ZX_SOCKET_CONTROL_WRITABLE); } } zx_status_t fidl_socket_read_control(zx_handle_t socket, void* buffer, size_t capacity, size_t* out_actual) { for (;;) { zx_status_t status = zx_socket_read(socket, ZX_SOCKET_CONTROL, buffer, capacity, out_actual); if (status != ZX_ERR_SHOULD_WAIT) { return status; } zx_signals_t observed = ZX_SIGNAL_NONE; status = zx_object_wait_one(socket, ZX_SOCKET_CONTROL_READABLE | ZX_SOCKET_PEER_CLOSED, ZX_TIME_INFINITE, &observed); if (status != ZX_OK) { return status; } if (observed & ZX_SOCKET_CONTROL_READABLE) { continue; } ZX_ASSERT(observed & ZX_SOCKET_PEER_CLOSED); return ZX_ERR_PEER_CLOSED; } } zx_status_t 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) { zx_status_t status = fidl_socket_write_control(socket, buffer, capacity); if (status != ZX_OK) { return status; } return fidl_socket_read_control(socket, out_buffer, out_capacity, out_actual); } #endif