/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 *
 * Parts of this implementation is based on daemondo command of MacPorts
 * (https://www.macports.org/):
 *
 *    Copyright (c) 2005-2007 James Berry <jberry@macports.org>
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. Neither the name of The MacPorts Project nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "ndn-cxx-config.hpp"

#include "network-monitor-impl-osx.hpp"
#include "../../name.hpp"
#include "../../util/logger.hpp"
#include "../network-address.hpp"

#include <ifaddrs.h>       // for getifaddrs()
#include <arpa/inet.h>     // for inet_ntop()
#include <netinet/in.h>    // for struct sockaddr_in{,6}
#include <net/if_dl.h>     // for struct sockaddr_dl
#include <net/if_types.h>  // for IFT_* constants

#include <boost/asio.hpp>

namespace ndn {
namespace net {

using util::CFReleaser;

NDN_LOG_INIT(ndn.NetworkMonitor);

NetworkMonitorImplOsx::NetworkMonitorImplOsx(boost::asio::io_service& io)
  : m_scheduler(io)
  , m_cfLoopEvent(m_scheduler)
  , m_context{0, this, nullptr, nullptr, nullptr}
  , m_scStore(SCDynamicStoreCreate(nullptr, CFSTR("net.named-data.ndn-cxx.NetworkMonitor"),
                                   &NetworkMonitorImplOsx::onConfigChanged, &m_context))
  , m_loopSource(SCDynamicStoreCreateRunLoopSource(nullptr, m_scStore.get(), 0))
  , m_nullUdpSocket(io, boost::asio::ip::udp::v4())

{
  scheduleCfLoop();

  // Notifications from Darwin Notify Center:
  //
  // com.apple.system.config.network_change
  //
  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                  static_cast<void*>(this),
                                  &NetworkMonitorImplOsx::afterNotificationCenterEvent,
                                  CFSTR("com.apple.system.config.network_change"),
                                  nullptr, // object to observe
                                  CFNotificationSuspensionBehaviorDeliverImmediately);

  io.post([this] { enumerateInterfaces(); });

  CFRunLoopAddSource(CFRunLoopGetCurrent(), m_loopSource.get(), kCFRunLoopDefaultMode);

  // Notifications from SystemConfiguration:
  //
  // State:/Network/Interface/.*/Link
  // State:/Network/Interface/.*/IPv4
  // State:/Network/Interface/.*/IPv6
  // State:/Network/Global/DNS
  // State:/Network/Global/IPv4
  //
  auto patterns = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
  CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/.*/Link"));
  CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/.*/IPv4"));
  CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/.*/IPv6"));
  // CFArrayAppendValue(patterns, CFSTR("State:/Network/Global/DNS"));
  // CFArrayAppendValue(patterns, CFSTR("State:/Network/Global/IPv4"));

  SCDynamicStoreSetNotificationKeys(m_scStore.get(), nullptr, patterns);
}

NetworkMonitorImplOsx::~NetworkMonitorImplOsx()
{
  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_loopSource.get(), kCFRunLoopDefaultMode);

  CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                          static_cast<void*>(this));
}

shared_ptr<const NetworkInterface>
NetworkMonitorImplOsx::getNetworkInterface(const std::string& ifname) const
{
  auto it = m_interfaces.find(ifname);
  return it == m_interfaces.end() ? nullptr : it->second;
}

std::vector<shared_ptr<const NetworkInterface>>
NetworkMonitorImplOsx::listNetworkInterfaces() const
{
  std::vector<shared_ptr<const NetworkInterface>> v;
  v.reserve(m_interfaces.size());

  for (const auto& e : m_interfaces) {
    v.push_back(e.second);
  }
  return v;
}

void
NetworkMonitorImplOsx::afterNotificationCenterEvent(CFNotificationCenterRef center,
                                                    void* observer,
                                                    CFStringRef name,
                                                    const void* object,
                                                    CFDictionaryRef userInfo)
{
  static_cast<NetworkMonitorImplOsx*>(observer)->emitSignal(onNetworkStateChanged);
}

void
NetworkMonitorImplOsx::scheduleCfLoop()
{
  // poll each second for new events
  m_cfLoopEvent = m_scheduler.scheduleEvent(time::seconds(1), [this] { pollCfLoop(); });
}

void
NetworkMonitorImplOsx::pollCfLoop()
{
  // this should dispatch ready events and exit
  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);

  scheduleCfLoop();
}

void
NetworkMonitorImplOsx::addNewInterface(const std::string& ifName)
{
  shared_ptr<NetworkInterface> interface = makeNetworkInterface();
  interface->setName(ifName);
  interface->setState(getInterfaceState(interface->getName()));
  updateInterfaceInfo(*interface);
  if (interface->getType() == InterfaceType::UNKNOWN) {
    NDN_LOG_DEBUG("ignoring " << ifName << " because it has unhandled interface type");
    return;
  }

  NDN_LOG_DEBUG("adding interface " << interface->getName());
  m_interfaces.insert(make_pair(interface->getName(), interface));
  this->emitSignal(onInterfaceAdded, interface);
}

void
NetworkMonitorImplOsx::enumerateInterfaces()
{
  for (const auto& ifName : getInterfaceNames()) {
    addNewInterface(ifName);
  }
  this->emitSignal(onEnumerationCompleted);
}

static std::string
convertToStdString(CFStringRef cfString)
{
  const char* cStr = CFStringGetCStringPtr(cfString, kCFStringEncodingASCII);
  if (cStr != nullptr) {
    return cStr;
  }

  size_t stringSize = CFStringGetLength(cfString);
  char* buffer = new char[stringSize + 1];
  CFStringGetCString(cfString, buffer, sizeof(buffer), kCFStringEncodingASCII);
  std::string retval = buffer;
  delete[] buffer;
  return retval;
}

std::set<std::string>
NetworkMonitorImplOsx::getInterfaceNames()
{
  CFReleaser<CFDictionaryRef> dict =
    (CFDictionaryRef)SCDynamicStoreCopyValue(m_scStore.get(), CFSTR("State:/Network/Interface"));
  CFArrayRef interfaces = (CFArrayRef)CFDictionaryGetValue(dict.get(), CFSTR("Interfaces"));

  std::set<std::string> ifNames;
  size_t count = CFArrayGetCount(interfaces);
  for (size_t i = 0; i != count; ++i) {
    auto ifName = (CFStringRef)CFArrayGetValueAtIndex(interfaces, i);
    ifNames.insert(convertToStdString(ifName));
  }
  return ifNames;
}

InterfaceState
NetworkMonitorImplOsx::getInterfaceState(const std::string& ifName)
{
  CFReleaser<CFStringRef> linkName =
    CFStringCreateWithCString(nullptr, ("State:/Network/Interface/" + ifName + "/Link").c_str(),
                              kCFStringEncodingASCII);

  CFReleaser<CFDictionaryRef> dict = (CFDictionaryRef)SCDynamicStoreCopyValue(m_scStore.get(), linkName.get());
  if (dict.get() == nullptr) {
    return InterfaceState::UNKNOWN;
  }

  CFBooleanRef isActive = (CFBooleanRef)CFDictionaryGetValue(dict.get(), CFSTR("Active"));
  if (isActive == nullptr) {
    return InterfaceState::UNKNOWN;
  }

  return CFBooleanGetValue(isActive) ? InterfaceState::RUNNING : InterfaceState::DOWN;
}

template<typename AddressBytes>
static uint8_t
computePrefixLength(const AddressBytes& mask)
{
  uint8_t prefixLength = 0;
  for (auto byte : mask) {
    while (byte != 0) {
      ++prefixLength;
      byte <<= 1;
    }
  }
  return prefixLength;
}

void
NetworkMonitorImplOsx::updateInterfaceInfo(NetworkInterface& netif)
{
  ifaddrs* ifa_list = nullptr;
  if (::getifaddrs(&ifa_list) < 0) {
    BOOST_THROW_EXCEPTION(Error(std::string("getifaddrs() failed: ") + strerror(errno)));
  }

  for (ifaddrs* ifa = ifa_list; ifa != nullptr; ifa = ifa->ifa_next) {
    if (ifa->ifa_name != netif.getName())
      continue;

    netif.setFlags(ifa->ifa_flags);
    netif.setMtu(getInterfaceMtu(netif.getName()));

    if (ifa->ifa_addr == nullptr)
      continue;

    namespace ip = boost::asio::ip;
    AddressFamily addrFamily = AddressFamily::UNSPECIFIED;
    ip::address ipAddr, broadcastAddr;
    uint8_t prefixLength = 0;

    switch (ifa->ifa_addr->sa_family) {
      case AF_INET: {
        addrFamily = AddressFamily::V4;

        const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
        ip::address_v4::bytes_type bytes;
        std::copy_n(reinterpret_cast<const unsigned char*>(&sin->sin_addr), bytes.size(), bytes.begin());
        ipAddr = ip::address_v4(bytes);

        const sockaddr_in* sinMask = reinterpret_cast<sockaddr_in*>(ifa->ifa_netmask);
        std::copy_n(reinterpret_cast<const unsigned char*>(&sinMask->sin_addr), bytes.size(), bytes.begin());
        prefixLength = computePrefixLength(bytes);
        break;
      }

      case AF_INET6: {
        addrFamily = AddressFamily::V6;

        const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
        ip::address_v6::bytes_type bytes;
        std::copy_n(reinterpret_cast<const unsigned char*>(&sin6->sin6_addr), bytes.size(), bytes.begin());
        ipAddr = ip::address_v6(bytes);

        const sockaddr_in6* sinMask = reinterpret_cast<sockaddr_in6*>(ifa->ifa_netmask);
        std::copy_n(reinterpret_cast<const unsigned char*>(&sinMask->sin6_addr), bytes.size(), bytes.begin());
        prefixLength = computePrefixLength(bytes);
        break;
      }

      case AF_LINK: {
        const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
        netif.setIndex(sdl->sdl_index);

        if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ethernet::ADDR_LEN) {
          netif.setType(InterfaceType::ETHERNET);
          netif.setEthernetAddress(ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl))));
          NDN_LOG_TRACE(netif.getName() << ": set Ethernet address " << netif.getEthernetAddress());
        }
        else if (sdl->sdl_type == IFT_LOOP) {
          netif.setType(InterfaceType::LOOPBACK);
        }
        else {
          netif.setType(InterfaceType::UNKNOWN);
        }
        break;
      }
    }

    if (netif.canBroadcast()) {
      netif.setEthernetBroadcastAddress(ethernet::getBroadcastAddress());

      if (addrFamily == AddressFamily::V4 && ifa->ifa_broadaddr != nullptr) {
        const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
        ip::address_v4::bytes_type bytes;
        std::copy_n(reinterpret_cast<const unsigned char*>(&sin->sin_addr), bytes.size(), bytes.begin());
        broadcastAddr = ip::address_v4(bytes);
        NDN_LOG_TRACE(netif.getName() << ": set IPv4 broadcast address " << broadcastAddr);
      }
    }

    AddressScope scope = AddressScope::GLOBAL;
    if (ipAddr.is_loopback()) {
      scope = AddressScope::HOST;
    }
    else if ((ipAddr.is_v4() && (ipAddr.to_v4().to_ulong() & 0xFFFF0000) == 0xA9FE0000) ||
             (ipAddr.is_v6() && ipAddr.to_v6().is_link_local())) {
      scope = AddressScope::LINK;
    }

    netif.addNetworkAddress(NetworkAddress(addrFamily, ipAddr, broadcastAddr, prefixLength, scope, 0));
  }

  ::freeifaddrs(ifa_list);
}

size_t
NetworkMonitorImplOsx::getInterfaceMtu(const std::string& ifName)
{
  ifreq ifr{};
  std::strncpy(ifr.ifr_name, ifName.c_str(), sizeof(ifr.ifr_name) - 1);

  if (::ioctl(m_nullUdpSocket.native_handle(), SIOCGIFMTU, &ifr) == 0) {
    return static_cast<size_t>(ifr.ifr_mtu);
  }

  NDN_LOG_WARN("Failed to get interface MTU: " << std::strerror(errno));
  return ethernet::MAX_DATA_LEN;
}

void
NetworkMonitorImplOsx::onConfigChanged(SCDynamicStoreRef m_scStore, CFArrayRef changedKeys, void* context)
{
  static_cast<NetworkMonitorImplOsx*>(context)->onConfigChanged(changedKeys);
}

void
NetworkMonitorImplOsx::onConfigChanged(CFArrayRef changedKeys)
{
  size_t count = CFArrayGetCount(changedKeys);
  for (size_t i = 0; i != count; ++i) {
    std::string keyName = convertToStdString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i));
    Name key(keyName);
    std::string ifName = key.at(-2).toUri();

    auto ifIt = m_interfaces.find(ifName);
    if (ifIt == m_interfaces.end()) {
      addNewInterface(ifName);
      return;
    }

    NetworkInterface& netif = *ifIt->second;

    auto removeInterface = [&] {
      NDN_LOG_DEBUG("removing interface " << ifName);
      shared_ptr<NetworkInterface> removedInterface = ifIt->second;
      m_interfaces.erase(ifIt);
      this->emitSignal(onInterfaceRemoved, removedInterface);
    };

    if (key.at(-1).toUri() == "Link") {
      auto newState = getInterfaceState(ifName);

      if (newState == InterfaceState::UNKNOWN) {
        // check if it is really unknown or interface removed
        if (getInterfaceNames().count(ifName) == 0) {
          // newState = InterfaceState::DOWN;
          removeInterface();
          return;
        }
      }

      NDN_LOG_TRACE("Status of " << ifName << " changed from " << netif.getState() << " to " << newState);
      netif.setState(newState);
    }

    if (key.at(-1).toUri() == "IPv4" || key.at(-1).toUri() == "IPv6") {
      shared_ptr<NetworkInterface> updatedInterface = makeNetworkInterface();
      updatedInterface->setName(ifName);
      updateInterfaceInfo(*updatedInterface);
      if (updatedInterface->getType() == InterfaceType::UNKNOWN) {
        // somehow, type of interface changed to unknown
        NDN_LOG_DEBUG("Removing " << ifName << " because it changed to unhandled interface type");
        removeInterface();
        return;
      }

      const auto& newAddrs = updatedInterface->getNetworkAddresses();
      const auto& oldAddrs = netif.getNetworkAddresses();

      std::set<NetworkAddress> added;
      std::set<NetworkAddress> removed;

      std::set_difference(newAddrs.begin(), newAddrs.end(),
                          oldAddrs.begin(), oldAddrs.end(), std::inserter(added, added.end()));

      std::set_difference(oldAddrs.begin(), oldAddrs.end(),
                          newAddrs.begin(), newAddrs.end(), std::inserter(removed, removed.end()));

      for (const auto& addr : removed) {
        netif.removeNetworkAddress(addr);
      }

      for (const auto& addr : added) {
        netif.addNetworkAddress(addr);
      }
    }
  }
}

} // namespace net
} // namespace ndn
