// 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. #include <lib/fidl/cpp/message.h> #include <string.h> #include <lib/fidl/coding.h> #include <lib/fidl/cpp/builder.h> #ifdef __Fuchsia__ #include <zircon/syscalls.h> #endif namespace fidl { Message::Message() = default; Message::Message(BytePart bytes, HandlePart handles) : bytes_(static_cast<BytePart&&>(bytes)), handles_(static_cast<HandlePart&&>(handles)) {} Message::~Message() { #ifdef __Fuchsia__ zx_handle_close_many(handles_.data(), handles_.actual()); #endif ClearHandlesUnsafe(); } Message::Message(Message&& other) : bytes_(static_cast<BytePart&&>(other.bytes_)), handles_(static_cast<HandlePart&&>(other.handles_)) {} Message& Message::operator=(Message&& other) { bytes_ = static_cast<BytePart&&>(other.bytes_); handles_ = static_cast<HandlePart&&>(other.handles_); return *this; } zx_status_t Message::Encode(const fidl_type_t* type, const char** error_msg_out) { uint32_t actual_handles = 0u; zx_status_t status = fidl_encode(type, bytes_.data(), bytes_.actual(), handles_.data(), handles_.capacity(), &actual_handles, error_msg_out); if (status == ZX_OK) handles_.set_actual(actual_handles); return status; } zx_status_t Message::Decode(const fidl_type_t* type, const char** error_msg_out) { zx_status_t status = fidl_decode(type, bytes_.data(), bytes_.actual(), handles_.data(), handles_.actual(), error_msg_out); ClearHandlesUnsafe(); return status; } zx_status_t Message::Validate(const fidl_type_t* type, const char** error_msg_out) const { return fidl_validate(type, bytes_.data(), bytes_.actual(), handles_.actual(), error_msg_out); } #ifdef __Fuchsia__ zx_status_t Message::Read(zx_handle_t channel, uint32_t flags) { uint32_t actual_bytes = 0u; uint32_t actual_handles = 0u; zx_status_t status = zx_channel_read( channel, flags, bytes_.data(), handles_.data(), bytes_.capacity(), handles_.capacity(), &actual_bytes, &actual_handles); if (status == ZX_OK) { bytes_.set_actual(actual_bytes); handles_.set_actual(actual_handles); } return status; } zx_status_t Message::Write(zx_handle_t channel, uint32_t flags) { zx_status_t status = zx_channel_write(channel, flags, bytes_.data(), bytes_.actual(), handles_.data(), handles_.actual()); ClearHandlesUnsafe(); return status; } zx_status_t Message::Call(zx_handle_t channel, uint32_t flags, zx_time_t deadline, Message* response) { zx_channel_call_args_t args; args.wr_bytes = bytes_.data(); args.wr_handles = handles_.data(); args.rd_bytes = response->bytes_.data(); args.rd_handles = response->handles_.data(); args.wr_num_bytes = bytes_.actual(); args.wr_num_handles = handles_.actual(); args.rd_num_bytes = response->bytes_.capacity(); args.rd_num_handles = response->handles_.capacity(); uint32_t actual_bytes = 0u; uint32_t actual_handles = 0u; zx_status_t status = zx_channel_call(channel, flags, deadline, &args, &actual_bytes, &actual_handles); ClearHandlesUnsafe(); if (status == ZX_OK) { response->bytes_.set_actual(actual_bytes); response->handles_.set_actual(actual_handles); } return status; } #endif void Message::ClearHandlesUnsafe() { handles_.set_actual(0u); } } // namespace fidl