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

#ifndef SRC_VIRTUALIZATION_TESTS_FAKE_NETSTACK_H_
#define SRC_VIRTUALIZATION_TESTS_FAKE_NETSTACK_H_

#include <fuchsia/hardware/ethernet/c/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/bridge.h>
#include <zircon/device/ethernet.h>

#include <map>
#include <vector>

class Device {
 public:
  static zx_status_t Create(fuchsia::hardware::ethernet::DeviceSyncPtr eth_device,
                            std::unique_ptr<Device>* out);

  zx_status_t Start(async_dispatcher_t* dispatcher);

  fit::promise<std::vector<uint8_t>, zx_status_t> ReadPacket();
  fit::promise<void, zx_status_t> WritePacket(std::vector<uint8_t> packet);

 private:
  Device(fuchsia::hardware::ethernet::DeviceSyncPtr eth_device, zx::fifo rx, zx::fifo tx,
         zx::vmo vmo, uintptr_t io_addr)
      : eth_device_(std::move(eth_device)),
        rx_(std::move(rx)),
        tx_(std::move(tx)),
        vmo_(std::move(vmo)),
        io_addr_(io_addr) {
    rx_wait_.set_trigger(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED);
    rx_wait_.set_object(rx_.get());

    tx_wait_.set_trigger(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED);
    tx_wait_.set_object(tx_.get());
  }

  void OnReceive(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
                 const zx_packet_signal_t* signal);
  void OnTransmit(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
                  const zx_packet_signal_t* signal);

  fit::promise<eth_fifo_entry_t, zx_status_t> GetRxEntry();
  fit::promise<eth_fifo_entry_t, zx_status_t> GetTxEntry();

  fuchsia::hardware::ethernet::DeviceSyncPtr eth_device_;
  zx::fifo rx_;
  zx::fifo tx_;
  zx::vmo vmo_;
  const uintptr_t io_addr_;

  std::mutex mutex_;
  std::vector<fit::completer<eth_fifo_entry_t, zx_status_t>> rx_completers_ __TA_GUARDED(mutex_);
  std::vector<fit::completer<eth_fifo_entry_t, zx_status_t>> tx_completers_ __TA_GUARDED(mutex_);
  async::WaitMethod<Device, &Device::OnReceive> rx_wait_{this};
  async::WaitMethod<Device, &Device::OnTransmit> tx_wait_{this};
};

class FakeNetstack : public fuchsia::netstack::Netstack {
 public:
  FakeNetstack() {
    // Start a thread for the Device waiters. We can't use the main test thread, because it will
    // block to run test utils and deadlock the test.
    loop_.StartThread("FakeNetstack");
  }

  ~FakeNetstack() {
    loop_.Quit();
    loop_.JoinThreads();
    loop_.Shutdown();
  }

  void GetInterfaces(GetInterfacesCallback callback) override {}
  void GetInterfaces2(GetInterfaces2Callback callback) override {}

  void GetRouteTable(GetRouteTableCallback callback) override {}
  void GetRouteTable2(GetRouteTable2Callback callback) override {}

  void SetInterfaceStatus(uint32_t nicid, bool enabled) override {}

  void SetInterfaceAddress(uint32_t nicid, fuchsia::net::IpAddress addr, uint8_t prefixLen,
                           SetInterfaceAddressCallback callback) override;

  void RemoveInterfaceAddress(uint32_t nicid, fuchsia::net::IpAddress addr, uint8_t prefixLen,
                              RemoveInterfaceAddressCallback callback) override {}

  void SetInterfaceMetric(uint32_t nicid, uint32_t metric,
                          SetInterfaceMetricCallback callback) override {}

  void GetDhcpClient(uint32_t nicid, ::fidl::InterfaceRequest<::fuchsia::net::dhcp::Client> client,
                     GetDhcpClientCallback callback) override {}

  void BridgeInterfaces(std::vector<uint32_t> nicids, BridgeInterfacesCallback callback) override {}

  void AddEthernetDevice(std::string topological_path,
                         fuchsia::netstack::InterfaceConfig interfaceConfig,
                         ::fidl::InterfaceHandle<::fuchsia::hardware::ethernet::Device> device,
                         AddEthernetDeviceCallback callback) override;

  void StartRouteTableTransaction(
      ::fidl::InterfaceRequest<fuchsia::netstack::RouteTableTransaction> routeTableTransaction,
      StartRouteTableTransactionCallback callback) override {}

  fidl::InterfaceRequestHandler<fuchsia::netstack::Netstack> GetHandler() {
    return bindings_.GetHandler(this);
  }

  // Send a packet with UDP headers, including the ethernet and IPv6 headers, to the interface with
  // the specified MAC address.
  fit::promise<void, zx_status_t> SendUdpPacket(
      const fuchsia::hardware::ethernet::MacAddress& mac_addr, std::vector<uint8_t> packet);

  // Send a raw packet to the interface with the specified MAC address.
  fit::promise<void, zx_status_t> SendPacket(
      const fuchsia::hardware::ethernet::MacAddress& mac_addr, std::vector<uint8_t> packet);

  // Receive a raw packet from the interface with the specified MAC address.
  fit::promise<std::vector<uint8_t>, zx_status_t> ReceivePacket(
      const fuchsia::hardware::ethernet::MacAddress& mac_addr);

 private:
  struct CompareMacAddress {
    bool operator()(const fuchsia::hardware::ethernet::MacAddress& a,
                    const fuchsia::hardware::ethernet::MacAddress& b) const {
      // The octets of a MacAddress are a std::array, which implements lexigraphical ordering.
      return a.octets < b.octets;
    }
  };

  fit::promise<Device*> GetDevice(const fuchsia::hardware::ethernet::MacAddress& mac_addr);

  fidl::BindingSet<fuchsia::netstack::Netstack> bindings_;
  std::mutex mutex_;
  // Maps MAC addresses to devices.
  std::map<fuchsia::hardware::ethernet::MacAddress, std::unique_ptr<Device>, CompareMacAddress>
      devices_ __TA_GUARDED(mutex_);
  // Maps MAC addresses to completers, to enable the GetDevice promises.
  std::map<fuchsia::hardware::ethernet::MacAddress, std::vector<fit::completer<Device*>>,
           CompareMacAddress>
      completers_ __TA_GUARDED(mutex_);

  async::Loop loop_{&kAsyncLoopConfigNoAttachToCurrentThread};

  uint8_t nic_counter_ = 0;
};

#endif  // SRC_VIRTUALIZATION_TESTS_FAKE_NETSTACK_H_
