// Copyright (c) 2012 The Chromium OS 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 "vpn-manager/service_manager.h"

#include <cstring>
#include <vector>

#include <arpa/inet.h>  // for inet_ntop and inet_pton
#include <netdb.h>      // for getaddrinfo

#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>

using base::FilePath;

namespace vpn_manager {

ServiceManager::ServiceManager(const std::string& service_name,
                               const base::FilePath& temp_path)
    : is_running_(false),
      was_stopped_(false),
      inner_service_(nullptr),
      outer_service_(nullptr),
      service_name_(service_name),
      error_(kServiceErrorNoError),
      temp_path_(temp_path) {}

void ServiceManager::OnStarted() {
  CHECK(!is_running_ && !was_stopped_);
  CHECK(outer_service_ == nullptr || outer_service_->is_running_);
  is_running_ = true;
  if (inner_service_ == nullptr)
    return;

  DLOG(INFO) << "Starting inner " << inner_service_->service_name();
  if (!inner_service_->Start()) {
    // Inner service could not be started, stop this layer.
    LOG(ERROR) << "Inner service " << inner_service_->service_name()
               << " failed.  Stopping " << service_name();
    Stop();
  }
}

void ServiceManager::OnStopped(bool was_error) {
  CHECK(inner_service_ == nullptr || !inner_service_->is_running_);
  is_running_ = false;
  was_stopped_ = true;
  if (outer_service_ != nullptr) {
    outer_service_->Stop();
  }
}

void ServiceManager::OnSyslogOutput(const std::string& prefix,
                                    const std::string& line) {}

void ServiceManager::RegisterError(ServiceError error) {
  // Register a given error only if it has a higher value than the one
  // currently registered as error identifiers are ordered from less
  // specific to more specific.
  if (error_ < error)
    error_ = error;
}

ServiceError ServiceManager::GetError() const {
  if (inner_service_ != nullptr) {
    ServiceError inner_service_error = inner_service_->GetError();
    if (inner_service_error != kServiceErrorNoError)
      return inner_service_error;
  }
  return error_;
}

void ServiceManager::WriteFdToSyslog(int fd,
                                     const std::string& prefix,
                                     std::string* partial_line) {
  char buffer[256];
  ssize_t written = HANDLE_EINTR(read(fd, &buffer, sizeof(buffer) - 1));
  if (written < 0) {
    PLOG(WARNING) << "Error condition on " << prefix << " pipe";
    return;
  }
  buffer[written] = '\0';
  partial_line->append(buffer);
  std::vector<std::string> lines = base::SplitString(
      *partial_line, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  if (lines.empty()) {
    partial_line->clear();
  } else {
    *partial_line = lines.back();
    lines.pop_back();
  }
  for (const auto& line : lines) {
    LOG(INFO) << prefix << line;
    OnSyslogOutput(prefix, line);
  }
}

bool ServiceManager::ResolveNameToSockAddr(const std::string& name,
                                           sockaddr_storage* address) {
  addrinfo* address_info;
  int s = getaddrinfo(name.c_str(), nullptr, nullptr, &address_info);
  if (s != 0) {
    LOG(ERROR) << "getaddrinfo failed: " << gai_strerror(s);
    return false;
  }
  memcpy(address, address_info->ai_addr, address_info->ai_addrlen);
  freeaddrinfo(address_info);
  return true;
}

bool ServiceManager::ConvertIPStringToSockAddr(const std::string& address_text,
                                               sockaddr_storage* address) {
  addrinfo hint_info = {};
  addrinfo* address_info;
  hint_info.ai_flags = AI_NUMERICHOST;
  int s = getaddrinfo(address_text.c_str(), nullptr, &hint_info, &address_info);
  if (s != 0) {
    LOG(ERROR) << "getaddrinfo failed: " << gai_strerror(s);
    return false;
  }
  memcpy(address, address_info->ai_addr, address_info->ai_addrlen);
  freeaddrinfo(address_info);
  return true;
}

bool ServiceManager::ConvertSockAddrToIPString(const sockaddr_storage& address,
                                               std::string* address_text) {
  char str[INET6_ADDRSTRLEN] = {0};
  switch (address.ss_family) {
    case AF_INET:
      if (!inet_ntop(
              AF_INET,
              &(reinterpret_cast<const sockaddr_in*>(&address)->sin_addr), str,
              sizeof(str))) {
        PLOG(ERROR) << "inet_ntop failed";
        return false;
      }
      break;
    case AF_INET6:
      if (!inet_ntop(
              AF_INET6,
              &(reinterpret_cast<const sockaddr_in6*>(&address)->sin6_addr),
              str, sizeof(str))) {
        PLOG(ERROR) << "inet_ntop failed";
        return false;
      }
      break;
    default:
      LOG(ERROR) << "Unknown address family: " << address.ss_family;
      return false;
  }
  *address_text = str;
  return true;
}

bool ServiceManager::GetLocalAddressFromRemote(
    const sockaddr_storage& remote_address, sockaddr_storage* local_address) {
  base::ScopedFD socket_fd(socket(remote_address.ss_family, SOCK_DGRAM, 0));
  if (!socket_fd.is_valid()) {
    PLOG(ERROR) << "Unable to create socket";
    return false;
  }
  socklen_t addr_len = sizeof(sockaddr_storage);
  if (HANDLE_EINTR(connect(socket_fd.get(),
                           reinterpret_cast<const sockaddr*>(&remote_address),
                           addr_len)) != 0) {
    PLOG(ERROR) << "Unable to connect";
    return false;
  }
  if (getsockname(socket_fd.get(), reinterpret_cast<sockaddr*>(local_address),
                  &addr_len) != 0) {
    PLOG(ERROR) << "getsockname failed on socket";
    return false;
  }
  return true;
}

}  // namespace vpn_manager
