// Copyright 2015 The Weave 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 "examples/ubuntu/network_manager.h"

#include <arpa/inet.h>
#include <linux/wireless.h>
#include <sys/ioctl.h>
#include <sys/wait.h>

#include <fstream>

#include <base/bind.h>
#include <weave/provider/task_runner.h>

#include "examples/ubuntu/ssl_stream.h"

namespace weave {
namespace examples {

namespace {

int ForkCmd(const std::string& path, const std::vector<std::string>& args) {
  int pid = fork();
  if (pid != 0)
    return pid;

  std::vector<const char*> args_vector;
  args_vector.push_back(path.c_str());
  for (auto& i : args)
    args_vector.push_back(i.c_str());
  args_vector.push_back(nullptr);

  execvp(path.c_str(), const_cast<char**>(args_vector.data()));
  NOTREACHED();
  return 0;
}

}  // namespace

NetworkImpl::NetworkImpl(provider::TaskRunner* task_runner,
                         bool force_bootstrapping)
    : force_bootstrapping_{force_bootstrapping}, task_runner_{task_runner} {
  SSL_load_error_strings();
  SSL_library_init();

  StopAccessPoint();
  UpdateNetworkState();
}
NetworkImpl::~NetworkImpl() {
  StopAccessPoint();
}

void NetworkImpl::AddConnectionChangedCallback(
    const ConnectionChangedCallback& callback) {
  callbacks_.push_back(callback);
}

void NetworkImpl::TryToConnect(const std::string& ssid,
                               const std::string& passphrase,
                               int pid,
                               base::Time until,
                               const DoneCallback& callback) {
  if (pid) {
    int status = 0;
    if (pid == waitpid(pid, &status, WNOWAIT)) {
      int sockf_d = socket(AF_INET, SOCK_DGRAM, 0);
      CHECK_GE(sockf_d, 0) << strerror(errno);

      iwreq wreq = {};
      snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "wlan0");
      std::string essid(' ', IW_ESSID_MAX_SIZE + 1);
      wreq.u.essid.pointer = &essid[0];
      wreq.u.essid.length = essid.size();
      CHECK_GE(ioctl(sockf_d, SIOCGIWESSID, &wreq), 0) << strerror(errno);
      essid.resize(wreq.u.essid.length);
      close(sockf_d);

      if (ssid == essid)
        return task_runner_->PostDelayedTask(FROM_HERE,
                                             base::Bind(callback, nullptr), {});
      pid = 0;  // Try again.
    }
  }

  if (pid == 0) {
    pid = ForkCmd("nmcli",
                  {"dev", "wifi", "connect", ssid, "password", passphrase});
  }

  if (base::Time::Now() >= until) {
    ErrorPtr error;
    Error::AddTo(&error, FROM_HERE, "wifi", "timeout",
                 "Timeout connecting to WiFI network.");
    task_runner_->PostDelayedTask(
        FROM_HERE, base::Bind(callback, base::Passed(&error)), {});
    return;
  }

  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&NetworkImpl::TryToConnect, weak_ptr_factory_.GetWeakPtr(),
                 ssid, passphrase, pid, until, callback),
      base::TimeDelta::FromSeconds(1));
}

void NetworkImpl::Connect(const std::string& ssid,
                          const std::string& passphrase,
                          const DoneCallback& callback) {
  force_bootstrapping_ = false;
  CHECK(!hostapd_started_);
  if (hostapd_started_) {
    ErrorPtr error;
    Error::AddTo(&error, FROM_HERE, "wifi", "busy", "Running Access Point.");
    task_runner_->PostDelayedTask(
        FROM_HERE, base::Bind(callback, base::Passed(&error)), {});
    return;
  }

  TryToConnect(ssid, passphrase, 0,
               base::Time::Now() + base::TimeDelta::FromMinutes(1), callback);
}

void NetworkImpl::UpdateNetworkState() {
  network_state_ = Network::State::kOffline;
  if (force_bootstrapping_)
    return;
  if (std::system("ping talk.google.com -c 1") == 0)
    network_state_ = State::kOnline;
  else if (std::system("nmcli dev"))
    network_state_ = State::kError;
  else if (std::system("nmcli dev | grep connecting") == 0)
    network_state_ = State::kConnecting;

  task_runner_->PostDelayedTask(FROM_HERE,
                                base::Bind(&NetworkImpl::UpdateNetworkState,
                                           weak_ptr_factory_.GetWeakPtr()),
                                base::TimeDelta::FromSeconds(10));
  for (const auto& cb : callbacks_)
    cb.Run();
}

provider::Network::State NetworkImpl::GetConnectionState() const {
  return network_state_;
}

void NetworkImpl::StartAccessPoint(const std::string& ssid) {
  if (hostapd_started_)
    return;

  network_state_ = State::kOffline;

  // Release wlan0 interface.
  CHECK_EQ(0, std::system("nmcli nm wifi off"));
  CHECK_EQ(0, std::system("rfkill unblock wlan"));
  sleep(1);

  std::string hostapd_conf = "/tmp/weave_hostapd.conf";
  {
    std::ofstream ofs(hostapd_conf);
    ofs << "interface=wlan0" << std::endl;
    ofs << "channel=1" << std::endl;
    ofs << "ssid=" << ssid << std::endl;
  }

  CHECK_EQ(0, std::system(("hostapd -B -K " + hostapd_conf).c_str()));
  hostapd_started_ = true;

  for (size_t i = 0; i < 10; ++i) {
    if (0 == std::system("ifconfig wlan0 192.168.76.1/24"))
      break;
    sleep(1);
  }

  std::string dnsmasq_conf = "/tmp/weave_dnsmasq.conf";
  {
    std::ofstream ofs(dnsmasq_conf.c_str());
    ofs << "port=0" << std::endl;
    ofs << "bind-interfaces" << std::endl;
    ofs << "log-dhcp" << std::endl;
    ofs << "dhcp-range=192.168.76.10,192.168.76.100" << std::endl;
    ofs << "interface=wlan0" << std::endl;
    ofs << "dhcp-leasefile=" << dnsmasq_conf << ".leases" << std::endl;
  }

  CHECK_EQ(0, std::system(("dnsmasq --conf-file=" + dnsmasq_conf).c_str()));
}

void NetworkImpl::StopAccessPoint() {
  base::IgnoreResult(std::system("pkill -f dnsmasq.*/tmp/weave"));
  base::IgnoreResult(std::system("pkill -f hostapd.*/tmp/weave"));
  CHECK_EQ(0, std::system("nmcli nm wifi on"));
  hostapd_started_ = false;
}

bool NetworkImpl::HasWifiCapability() {
  return std::system("nmcli dev | grep ^wlan0") == 0;
}

void NetworkImpl::OpenSslSocket(const std::string& host,
                                uint16_t port,
                                const OpenSslSocketCallback& callback) {
  // Connect to SSL port instead of upgrading to TLS.
  std::unique_ptr<SSLStream> tls_stream{new SSLStream{task_runner_}};

  if (tls_stream->Init(host, port)) {
    task_runner_->PostDelayedTask(
        FROM_HERE, base::Bind(callback, base::Passed(&tls_stream), nullptr),
        {});
  } else {
    ErrorPtr error;
    Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed",
                 "Failed to initialize TLS stream.");
    task_runner_->PostDelayedTask(
        FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {});
  }
}

}  // namespace examples
}  // namespace weave
