// 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 "mac_adapter.h"

#include <lib/sync/completion.h>

#include <fbl/auto_lock.h>

namespace network {
namespace tun {

zx::result<std::unique_ptr<MacAdapter>> MacAdapter::Create(MacAdapterParent* parent,
                                                           fuchsia_net::wire::MacAddress mac,
                                                           bool promisc_only) {
  fbl::AllocChecker ac;
  std::unique_ptr<MacAdapter> adapter(new (&ac) MacAdapter(parent, mac, promisc_only));
  if (!ac.check()) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  mac_addr_protocol_t* proto = adapter->proto();
  zx::result device = MacAddrDeviceInterface::Create(ddk::MacAddrProtocolClient(proto));
  if (device.is_error()) {
    return device.take_error();
  }
  adapter->device_ = std::move(device.value());
  return zx::ok(std::move(adapter));
}

zx_status_t MacAdapter::Bind(async_dispatcher_t* dispatcher,
                             fidl::ServerEnd<netdev::MacAddressing> req) {
  return device_->Bind(dispatcher, std::move(req));
}

void MacAdapter::Teardown(fit::callback<void()> callback) {
  device_->Teardown(std::move(callback));
}

void MacAdapter::TeardownSync() {
  sync_completion_t completion;
  Teardown([&completion]() { sync_completion_signal(&completion); });
  sync_completion_wait_deadline(&completion, ZX_TIME_INFINITE);
}

void MacAdapter::MacAddrGetAddress(mac_address_t* out_mac) {
  std::copy(mac_.octets.begin(), mac_.octets.end(), out_mac->octets);
}

void MacAdapter::MacAddrGetFeatures(features_t* out_features) {
  if (promisc_only_) {
    out_features->multicast_filter_count = 0;
    out_features->supported_modes = SUPPORTED_MAC_FILTER_MODE_MULTICAST_PROMISCUOUS;
  } else {
    out_features->multicast_filter_count = fuchsia_net_tun::wire::kMaxMulticastFilters;
    out_features->supported_modes = SUPPORTED_MAC_FILTER_MODE_PROMISCUOUS |
                                    SUPPORTED_MAC_FILTER_MODE_MULTICAST_FILTER |
                                    SUPPORTED_MAC_FILTER_MODE_MULTICAST_PROMISCUOUS;
  }
}

void MacAdapter::MacAddrSetMode(mac_filter_mode_t mode, const mac_address_t* multicast_macs_list,
                                size_t multicast_macs_count) {
  fbl::AutoLock lock(&state_lock_);
  fuchsia_hardware_network::wire::MacFilterMode filter_mode;
  switch (mode) {
    case MAC_FILTER_MODE_PROMISCUOUS:
      filter_mode = fuchsia_hardware_network::wire::MacFilterMode::kPromiscuous;
      break;
    case MAC_FILTER_MODE_MULTICAST_PROMISCUOUS:
      filter_mode = fuchsia_hardware_network::wire::MacFilterMode::kMulticastPromiscuous;
      break;
    case MAC_FILTER_MODE_MULTICAST_FILTER:
      filter_mode = fuchsia_hardware_network::wire::MacFilterMode::kMulticastFilter;
      break;
    default:
      ZX_ASSERT_MSG(false, "Unexpected filter mode %d", mode);
  }

  mac_state_.mode = filter_mode;
  mac_state_.multicast_filters.clear();
  mac_state_.multicast_filters.reserve(multicast_macs_count);
  while (multicast_macs_count--) {
    auto& n = mac_state_.multicast_filters.emplace_back();
    std::copy_n(multicast_macs_list->octets, n.octets.size(), n.octets.begin());
    multicast_macs_list++;
  }
  parent_->OnMacStateChanged(this);
}

MacState MacAdapter::GetMacState() {
  fbl::AutoLock lock(&state_lock_);
  return mac_state_;
}

}  // namespace tun
}  // namespace network
