// Copyright 2020 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/wire/client_base.h>
#include <lib/fidl/txn_header.h>
#include <lib/fit/function.h>

namespace fidl {
namespace internal {

// TODO(madhaviyengar): Move this constant to zircon/fidl.h
constexpr uint32_t kUserspaceTxidMask = 0x7FFFFFFF;

std::shared_ptr<ClientBase> ClientBase::Create(
    AnyTransport&& transport, async_dispatcher_t* dispatcher,
    AnyIncomingEventDispatcher&& event_dispatcher, AsyncEventHandler* error_handler,
    fidl::AnyTeardownObserver&& teardown_observer, ThreadingPolicy threading_policy,
    std::weak_ptr<ClientControlBlock> client_object_lifetime) {
  std::shared_ptr client_base = std::make_shared<ClientBase>();
  client_base->Bind(std::move(transport), dispatcher, std::move(event_dispatcher), error_handler,
                    std::move(teardown_observer), threading_policy,
                    std::move(client_object_lifetime));
  return client_base;
}

void ClientBase::Bind(AnyTransport&& transport, async_dispatcher_t* dispatcher,
                      AnyIncomingEventDispatcher&& event_dispatcher,
                      AsyncEventHandler* error_handler, AnyTeardownObserver&& teardown_observer,
                      ThreadingPolicy threading_policy,
                      std::weak_ptr<ClientControlBlock> client_object_lifetime) {
  ZX_DEBUG_ASSERT(!binding_.lock());
  auto binding = AsyncClientBinding::Create(
      dispatcher, std::make_shared<fidl::internal::AnyTransport>(std::move(transport)),
      shared_from_this(), error_handler, std::move(teardown_observer), threading_policy);
  binding_ = WeakBindingRef<AsyncClientBinding>{binding, binding->shared_unbind_info()};
  client_object_lifetime_ = std::move(client_object_lifetime);
  dispatcher_ = dispatcher;
  event_dispatcher_ = std::move(event_dispatcher);
  binding->BeginFirstWait();
}

ClientBase::AsyncTeardownResult ClientBase::AsyncTeardown() {
  auto matchers = MatchVariant{
      [this](std::shared_ptr<AsyncClientBinding>&& binding) -> AsyncTeardownResult {
        fit::result teardown_result = binding->StartTeardown(std::move(binding));
        if (teardown_result.is_error()) {
          // Already torn down or raced with in-progress teardown.
          return fit::error(fidl::Status::Unbound());
        }

        // If there are pending two-way calls, do not allow the user to extract
        // the client endpoint.
        std::scoped_lock lock(lock_);
        if (!contexts_.is_empty()) {
          return fit::error(fidl::Status::PendingTwoWayCallPreventsUnbind());
        }

        return teardown_result.take_value();
      },
      [](fidl::UnbindInfo info) -> AsyncTeardownResult { return fit::error(info.ToError()); },
      [](WeakClientBindingRef::Invalid) -> AsyncTeardownResult {
        // Should not reach here if we check for a valid client before
        // user initiated teardown.
        __builtin_abort();
      },
  };
  return std::visit(matchers, binding_.lock_or_error());
}

void ClientBase::PrepareAsyncTxn(ResponseContext* context) {
  std::scoped_lock lock(lock_);

  // Generate the next txid. Verify that it doesn't overlap with any outstanding txids.
  do {
    do {
      context->txid_ = ++txid_base_ & kUserspaceTxidMask;  // txid must be within mask.
    } while (unlikely(!context->txid_));                   // txid must be non-zero.
  } while (unlikely(!contexts_.insert_or_find(context)));

  list_add_tail(&delete_list_, context);
}

void ClientBase::ForgetAsyncTxn(ResponseContext* context) {
  std::scoped_lock lock(lock_);

  ZX_ASSERT(context->InContainer());
  contexts_.erase(*context);
  list_delete(static_cast<list_node_t*>(context));
}

void ClientBase::ReleaseResponseContexts(fidl::UnbindInfo info) {
  // Release ownership on any outstanding |ResponseContext|s outside of locks.
  list_node_t delete_list;
  {
    std::scoped_lock lock(lock_);
    contexts_.clear();
    list_move(&delete_list_, &delete_list);
  }

  list_node_t* node = nullptr;
  list_node_t* temp_node = nullptr;
  list_for_every_safe(&delete_list, node, temp_node) {
    list_delete(node);
    auto* context = static_cast<ResponseContext*>(node);
    // |kClose| is never used on the client side.
    ZX_DEBUG_ASSERT(info.reason() != fidl::Reason::kClose);
    context->OnError(ErrorFromUnbindInfo(info));
  }
}

void ClientBase::SendTwoWay(fidl::OutgoingMessage& message, ResponseContext* context,
                            fidl::WriteOptions write_options) {
  auto matchers = MatchVariant{
      [&](std::shared_ptr<AnyTransport>&& transport) {
        {
          std::shared_ptr scoped_transport = std::move(transport);
          PrepareAsyncTxn(context);
          message.set_txid(context->Txid());
          message.Write(*scoped_transport, std::move(write_options));
        }
        // Handle error without holding onto the transport.
        if (!message.ok()) {
          ForgetAsyncTxn(context);
          TryAsyncDeliverError(message.error(), context);
          HandleSendError(message.error());
        }
      },
      [&](fidl::UnbindInfo info) { TryAsyncDeliverError(ErrorFromUnbindInfo(info), context); },
  };
  std::visit(matchers, GetTransportOrError());
}

fidl::OneWayStatus ClientBase::SendOneWay(fidl::OutgoingMessage& message,
                                          fidl::WriteOptions write_options) {
  auto matchers = MatchVariant{
      [&](std::shared_ptr<AnyTransport>&& transport) {
        {
          std::shared_ptr scoped_transport = std::move(transport);
          message.set_txid(0);
          message.Write(*scoped_transport, std::move(write_options));
        }
        // Handle error without holding onto the transport.
        if (!message.ok()) {
          HandleSendError(message.error());
          return fidl::OneWayStatus{message.error()};
        }
        return fidl::OneWayStatus{fidl::Status::Ok()};
      },
      [](fidl::UnbindInfo info) { return OneWayErrorFromUnbindInfo(info); },
  };
  return std::visit(matchers, GetTransportOrError());
}

void ClientBase::HandleSendError(fidl::Status error) {
  if (auto binding = binding_.lock()) {
    binding->HandleError(std::move(binding), {UnbindInfo{error}, ErrorOrigin::kSend});
  }
}

void ClientBase::TryAsyncDeliverError(::fidl::Status error, ResponseContext* context) {
  zx_status_t status = context->TryAsyncDeliverError(error, dispatcher_);
  if (status != ZX_OK) {
    context->OnError(error);
  }
}

ClientBase::TransportOrError ClientBase::GetTransportOrError() {
  auto matchers = MatchVariant{
      [](const std::shared_ptr<AsyncClientBinding>& binding) -> TransportOrError {
        if (auto transport = binding->GetTransport(); transport) {
          return transport;
        }
        // If the transport is gone, that means the user explicitly requested unbinding.
        return fidl::UnbindInfo::Unbind();
      },
      [](fidl::UnbindInfo info) -> TransportOrError { return info; },
      [](WeakClientBindingRef::Invalid) -> TransportOrError {
        // Should not reach here if we check for a valid client before
        // making calls.
        __builtin_abort();
      },
  };
  return std::visit(matchers, binding_.lock_or_error());
}

std::optional<UnbindInfo> ClientBase::Dispatch(fidl::IncomingHeaderAndMessage& msg,
                                               internal::MessageStorageViewBase* storage_view) {
  if (fidl_epitaph_t* epitaph = msg.maybe_epitaph(); unlikely(epitaph)) {
    return UnbindInfo::PeerClosed(epitaph->error);
  }

  auto* hdr = msg.header();
  if (hdr->txid == 0) {
    // Dispatch events (received messages with no txid).
    // Dispatch will always consume the message even if it is not recognized
    // (unknown interaction), so it is important to not reference the message or
    // header again after calling this.
    fidl::Status status = event_dispatcher_->DispatchEvent(msg, storage_view);
    if (status.ok()) {
      return std::nullopt;
    }
    return fidl::UnbindInfo{status};
  }

  // If this is a response, look up the corresponding ResponseContext based on the txid.
  ResponseContext* context = nullptr;
  {
    std::scoped_lock lock(lock_);
    context = contexts_.erase(hdr->txid);
    if (likely(context != nullptr)) {
      list_delete(static_cast<list_node_t*>(context));
    } else {
      // Received unknown txid.
      return UnbindInfo{
          Status::UnexpectedMessage(ZX_ERR_NOT_FOUND, fidl::internal::kErrorUnknownTxId)};
    }
  }
  return context->OnRawResult(std::move(msg), storage_view);
}

void ClientController::Bind(AnyTransport client_end, async_dispatcher_t* dispatcher,
                            AnyIncomingEventDispatcher&& event_dispatcher,
                            AsyncEventHandler* error_handler,
                            AnyTeardownObserver&& teardown_observer,
                            ThreadingPolicy threading_policy) {
  ZX_ASSERT(!client_impl_);
  // This three step dance is to setup a circular reference where |ClientBase|
  // weakly references |ClientControlBlock| and |ClientControlBlock| strongly
  // references |ClientBase|.
  control_ = std::make_shared<ClientControlBlock>(nullptr);
  client_impl_ = ClientBase::Create(std::move(client_end), dispatcher, std::move(event_dispatcher),
                                    error_handler, std::move(teardown_observer), threading_policy,
                                    control_->weak_from_this());
  // Actually fill in the |client_impl_|.
  *control_ = ClientControlBlock{client_impl_};
}

void ClientController::Unbind() { (void)UnbindMaybeGetEndpoint(); }

fit::result<fidl::Error, fidl::internal::AnyTransport> ClientController::UnbindMaybeGetEndpoint() {
  ZX_ASSERT(client_impl_);
  // Destroy |control| after |AsyncTeardown|.
  std::shared_ptr control = std::move(control_);
  return client_impl_->ClientBase::AsyncTeardown();
}

}  // namespace internal
}  // namespace fidl
