// Copyright 2019 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/llcpp/async_binding.h>
#include <lib/fidl/llcpp/async_transaction.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/llcpp/server.h>
#include <zircon/assert.h>

namespace fidl {

namespace internal {

//
// Synchronous transaction methods
//

std::optional<DispatchError> SyncTransaction::Dispatch(
    fidl::IncomingMessage&& msg, internal::MessageStorageViewBase* storage_view) {
  ZX_ASSERT(binding_);
  binding_->interface()->dispatch_message(std::move(msg), this, storage_view);
  return error_;
}

zx_status_t SyncTransaction::Reply(fidl::OutgoingMessage* message, WriteOptions write_options) {
  ZX_ASSERT(txid_ != 0);
  auto txid = txid_;
  txid_ = 0;

  ZX_ASSERT(binding_);
  message->set_txid(txid);
  message->Write(binding_->transport(), std::move(write_options));
  return message->status();
}

void SyncTransaction::EnableNextDispatch() {
  if (!binding_)
    return;
  // Only allow one |EnableNextDispatch| call per transaction instance.
  if (binding_lifetime_extender_)
    return;

  // Keeping another strong reference to the binding ensures that binding
  // teardown will not complete until this |SyncTransaction| destructs, i.e.
  // until the server method handler returns.
  binding_lifetime_extender_ = binding_->shared_from_this();
  if (binding_->CheckForTeardownAndBeginNextWait() == ZX_OK) {
    *next_wait_begun_early_ = true;
  } else {
    // Propagate a placeholder error, such that the message handler will
    // terminate dispatch right after the processing of this transaction.
    error_ = DispatchError{UnbindInfo::Unbind(), ErrorOrigin::kReceive};
  }
}

void SyncTransaction::Close(zx_status_t epitaph) {
  if (!binding_)
    return;
  binding_ = nullptr;

  // If |EnableNextDispatch| was called, the dispatcher will not monitor
  // our |unbind_info_|; we should asynchronously request teardown.
  if (binding_lifetime_extender_) {
    binding_lifetime_extender_->Close(std::move(binding_lifetime_extender_), epitaph);
    return;
  }

  error_ = DispatchError{UnbindInfo::Close(epitaph), ErrorOrigin::kReceive};
}

void SyncTransaction::InternalError(UnbindInfo error, ErrorOrigin origin) {
  if (!binding_)
    return;
  binding_ = nullptr;

  // If |EnableNextDispatch| was called, the dispatcher will not monitor
  // our |unbind_info_|; we should asynchronously request teardown.
  if (binding_lifetime_extender_) {
    binding_lifetime_extender_->HandleError(std::move(binding_lifetime_extender_),
                                            DispatchError{error, origin});
    return;
  }

  error_ = DispatchError{error, origin};
}

std::unique_ptr<Transaction> SyncTransaction::TakeOwnership() {
  ZX_ASSERT(binding_);
  auto transaction = std::make_unique<AsyncTransaction>(std::move(*this));
  binding_ = nullptr;
  return transaction;
}

bool SyncTransaction::DidOrGoingToUnbind() {
  ZX_ASSERT(binding_);
  return binding_->IsDestructionImminent();
}

//
// Asynchronous transaction methods
//

zx_status_t AsyncTransaction::Reply(fidl::OutgoingMessage* message, WriteOptions write_options) {
  ZX_ASSERT(txid_ != 0);
  auto txid = txid_;
  txid_ = 0;

  std::shared_ptr<AsyncServerBinding> binding = binding_.lock();
  if (!binding)
    return ZX_ERR_CANCELED;

  message->set_txid(txid);
  message->Write(binding->transport(), std::move(write_options));
  return message->status();
}

void AsyncTransaction::EnableNextDispatch() {
  // Unreachable. Async completers don't expose |EnableNextDispatch|.
  __builtin_abort();
}

void AsyncTransaction::Close(zx_status_t epitaph) {
  if (auto binding = binding_.lock()) {
    binding->Close(std::move(binding), epitaph);
  }
}

void AsyncTransaction::InternalError(UnbindInfo error, ErrorOrigin origin) {
  if (auto binding = binding_.lock()) {
    binding->HandleError(std::move(binding), {error, origin});
  }
}

std::unique_ptr<Transaction> AsyncTransaction::TakeOwnership() {
  // Unreachable. Async completers don't expose |ToAsync|.
  __builtin_abort();
}

bool AsyncTransaction::DidOrGoingToUnbind() {
  if (auto binding = binding_.lock()) {
    return binding->IsDestructionImminent();
  }
  return true;
}

}  // namespace internal

}  // namespace fidl
