| // 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 |