/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "host/libs/allocd/resource_manager.h"

#include <android-base/logging.h>
#include <pwd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <atomic>
#include <cstdint>
#include <cstdlib>
#include <iomanip>
#include <memory>
#include <optional>
#include <sstream>
#include <string>

#include "common/libs/fs/shared_fd.h"
#include "host/libs/allocd/alloc_utils.h"
#include "host/libs/allocd/request.h"
#include "host/libs/allocd/utils.h"
#include "json/forwards.h"
#include "json/value.h"
#include "json/writer.h"

namespace cuttlefish {

uid_t GetUserIDFromSock(SharedFD client_socket);

ResourceManager::~ResourceManager() {
  bool success = true;
  for (auto& res : managed_sessions_) {
    success &= res.second->ReleaseAllResources();
  }

  Json::Value resp;
  resp["request_type"] = "shutdown";
  auto status = success ? RequestStatus::Success : RequestStatus::Failure;
  resp["request_status"] = StatusToStr(status);
  SendJsonMsg(shutdown_socket_, resp);
  LOG(INFO) << "Daemon Shutdown complete";
  unlink(location.c_str());
}

void ResourceManager::SetSocketLocation(const std::string& sock_name) {
  location = sock_name;
}

void ResourceManager::SetUseEbtablesLegacy(bool use_legacy) {
  use_ebtables_legacy_ = use_legacy;
}

uint32_t ResourceManager::AllocateResourceID() {
  return global_resource_id_.fetch_add(1, std::memory_order_relaxed);
}

uint32_t ResourceManager::AllocateSessionID() {
  return session_id_.fetch_add(1, std::memory_order_relaxed);
}

bool ResourceManager::AddInterface(const std::string& iface, IfaceType ty,
                                   uint32_t resource_id, uid_t uid) {
  bool allocatedIface = false;
  std::shared_ptr<StaticResource> res = nullptr;

  bool didInsert = active_interfaces_.insert(iface).second;
  if (didInsert) {
    const char* idp = iface.c_str() + (iface.size() - 3);
    int small_id = atoi(idp);
    switch (ty) {
      case IfaceType::mtap:
        res = std::make_shared<MobileIface>(iface, uid, small_id, resource_id,
                                            kMobileIp);
        allocatedIface = res->AcquireResource();
        pending_add_.insert({resource_id, res});
        break;
      case IfaceType::wtap: {
        // TODO (paulkirth): change this to cvd-wbr, to test w/ today's
        // debian package, this is required since the number of wireless
        // bridges provided by the debian package has gone from 10 down to
        // 1, but our debian packages in cloudtop are not up to date
        auto w = std::make_shared<EthernetIface>(iface, uid, small_id,
                                                 resource_id, "cvd-wbr-01",
                                                 kWirelessIp);
        w->SetUseEbtablesLegacy(use_ebtables_legacy_);
        w->SetHasIpv4(use_ipv4_bridge_);
        w->SetHasIpv6(use_ipv6_bridge_);
        res = w;
        allocatedIface = res->AcquireResource();
        pending_add_.insert({resource_id, res});
        break;
      }
      case IfaceType::etap: {
        auto w = std::make_shared<EthernetIface>(iface, uid, small_id,
                                                 resource_id, "cvd-ebr",
                                                 kEthernetIp);
        w->SetUseEbtablesLegacy(use_ebtables_legacy_);
        w->SetHasIpv4(use_ipv4_bridge_);
        w->SetHasIpv6(use_ipv6_bridge_);
        res = w;
        allocatedIface = res->AcquireResource();
        pending_add_.insert({resource_id, res});
        break;
      }
      case IfaceType::wbr:
      case IfaceType::ebr:
        allocatedIface = CreateBridge(iface);
        break;
      case IfaceType::Invalid:
        break;
    }
  } else {
    LOG(WARNING) << "Interface already in use: " << iface;
  }

  if (didInsert && !allocatedIface) {
    LOG(WARNING) << "Failed to allocate interface: " << iface;
    active_interfaces_.erase(iface);
    auto it = pending_add_.find(resource_id);
    it->second->ReleaseResource();
    pending_add_.erase(it);
  }

  LOG(INFO) << "Finish CreateInterface Request";

  return allocatedIface;
}

bool ResourceManager::RemoveInterface(const std::string& iface, IfaceType ty) {
  bool isManagedIface = active_interfaces_.erase(iface) > 0;
  bool removedIface = false;
  if (isManagedIface) {
    switch (ty) {
      case IfaceType::mtap: {
        const char* idp = iface.c_str() + (iface.size() - 3);
        int id = atoi(idp);
        removedIface = DestroyMobileIface(iface, id, kMobileIp);
        break;
      }
      case IfaceType::wtap:
      case IfaceType::etap:
        removedIface = DestroyEthernetIface(
            iface, use_ipv4_bridge_, use_ipv6_bridge_, use_ebtables_legacy_);
        break;
      case IfaceType::wbr:
      case IfaceType::ebr:
        removedIface = DestroyBridge(iface);
        break;
      case IfaceType::Invalid:
        break;
    }

  } else {
    LOG(WARNING) << "Interface not managed: " << iface;
  }

  if (isManagedIface) {
    LOG(INFO) << "Removed interface: " << iface;
  } else {
    LOG(WARNING) << "Could not remove interface: " << iface;
  }

  return isManagedIface;
}

bool ResourceManager::ValidateRequestList(const Json::Value& config) {
  if (!config.isMember("request_list") || !config["request_list"].isArray()) {
    LOG(WARNING) << "Request has invalid 'request_list' field";
    return false;
  }

  auto request_list = config["request_list"];

  Json::ArrayIndex size = request_list.size();
  if (size == 0) {
    LOG(WARNING) << "Request has empty 'request_list' field";
    return false;
  }

  for (Json::ArrayIndex i = 0; i < size; ++i) {
    if (!ValidateRequest(request_list[i])) {
      return false;
    }
  }

  return true;
}

bool ResourceManager::ValidateConfigRequest(const Json::Value& config) {
  if (!config.isMember("config_request") ||
      !config["config_request"].isObject()) {
    LOG(WARNING) << "Request has invalid 'config_request' field";
    return false;
  }

  Json::Value config_request = config["config_request"];

  return ValidateRequestList(config_request);
}

bool ResourceManager::ValidateRequest(const Json::Value& request) {
  if (!request.isMember("request_type") ||
      !request["request_type"].isString() ||
      StrToReqTy(request["request_type"].asString()) == RequestType::Invalid) {
    LOG(WARNING) << "Request has invalid 'request_type' field";
    return false;
  }
  return true;
}

void ResourceManager::JsonServer() {
  LOG(INFO) << "Starting server on " << kDefaultLocation;
  auto server = SharedFD::SocketLocalServer(kDefaultLocation, false,
                                            SOCK_STREAM, kSocketMode);
  CHECK(server->IsOpen()) << "Could not start server at " << kDefaultLocation;
  LOG(INFO) << "Accepting client connections";

  while (true) {
    auto client_socket = SharedFD::Accept(*server);
    CHECK(client_socket->IsOpen()) << "Error creating client socket";

    struct timeval timeout;
    timeout.tv_sec = 10;
    timeout.tv_usec = 0;

    int err = client_socket->SetSockOpt(SOL_SOCKET, SO_RCVTIMEO, &timeout,
                                        sizeof(timeout));
    if (err < 0) {
      LOG(WARNING) << "Could not set socket timeout";
      continue;
    }

    auto req_opt = RecvJsonMsg(client_socket);

    if (!req_opt) {
      LOG(WARNING) << "Invalid JSON Request, closing connection";
      continue;
    }

    Json::Value req = req_opt.value();

    if (!ValidateConfigRequest(req)) {
      continue;
    }

    Json::Value req_list = req["config_request"]["request_list"];

    Json::Value config_response;
    Json::Value response_list;
    Json::ArrayIndex req_list_size = req_list.size();

    // sentinel value, so we can populate the list of responses correctly
    // without trying to satisfy requests that will be aborted
    bool transaction_failed = false;

    for (Json::ArrayIndex i = 0; i < req_list_size; ++i) {
      LOG(INFO) << "Processing Request: " << i;
      auto req = req_list[i];
      auto req_ty_str = req["request_type"].asString();
      auto req_ty = StrToReqTy(req_ty_str);

      Json::Value response;
      if (transaction_failed) {
        response["request_type"] = req_ty_str;
        response["request_status"] = "pending";
        response["error"] = "";
        response_list.append(response);
        continue;
      }

      switch (req_ty) {
        case RequestType::ID: {
          response = JsonHandleIdRequest();
          break;
        }
        case RequestType::Shutdown: {
          if (i != 0 || req_list_size != 1) {
            response["request_type"] = req_ty_str;
            response["request_status"] = "failed";
            response["error"] =
                "Shutdown requests cannot be processed with other "
                "configuration requests";
            response_list.append(response);
            break;
          } else {
            response = JsonHandleShutdownRequest(client_socket);
            response_list.append(response);
            return;
          }
        }
        case RequestType::CreateInterface: {
          response = JsonHandleCreateInterfaceRequest(client_socket, req);
          break;
        }
        case RequestType::DestroyInterface: {
          response = JsonHandleDestroyInterfaceRequest(req);
          break;
        }
        case RequestType::StopSession: {
          response = JsonHandleStopSessionRequest(
              req, GetUserIDFromSock(client_socket));
          break;
        }
        case RequestType::Invalid: {
          LOG(WARNING) << "Invalid Request Type: " << req["request_type"];
          break;
        }
      }

      response_list.append(response);
      if (!(response["request_status"].asString() ==
            StatusToStr(RequestStatus::Success))) {
        LOG(INFO) << "Request failed:" << req;
        transaction_failed = true;
        continue;
      }
    }

    config_response["response_list"] = response_list;

    auto status =
        transaction_failed ? RequestStatus::Failure : RequestStatus::Success;
    config_response["config_status"] = StatusToStr(status);

    if (!transaction_failed) {
      auto session_id = AllocateSessionID();
      config_response["session_id"] = session_id;
      auto s = std::make_shared<Session>(session_id,
                                         GetUserIDFromSock(client_socket));

      // commit the resources
      s->Insert(pending_add_);
      pending_add_.clear();
      managed_sessions_.insert({session_id, s});
    } else {
      // be sure to release anything we've acquired if the transaction failed
      for (auto& droped_resource : pending_add_) {
        droped_resource.second->ReleaseResource();
      }
    }

    SendJsonMsg(client_socket, config_response);
    LOG(INFO) << "Closing connection to client";
    client_socket->Close();
  }
  server->Close();
}

uid_t GetUserIDFromSock(SharedFD client_socket) {
  struct ucred ucred {};
  socklen_t len = sizeof(struct ucred);

  if (-1 == client_socket->GetSockOpt(SOL_SOCKET, SO_PEERCRED, &ucred, &len)) {
    LOG(WARNING) << "Failed to get Socket Credentials";
    return -1;
  }

  return ucred.uid;
}

bool ResourceManager::CheckCredentials(SharedFD client_socket, uid_t uid) {
  uid_t sock_uid = GetUserIDFromSock(client_socket);

  if (sock_uid == -1) {
    LOG(WARNING) << "Invalid Socket UID: " << uid;
    return false;
  }

  if (uid != sock_uid) {
    LOG(WARNING) << "Message UID: " << uid
                 << " does not match socket's EUID: " << sock_uid;
    return false;
  }

  return true;
}

Json::Value ResourceManager::JsonHandleIdRequest() {
  Json::Value resp;
  resp["request_type"] = "allocate_id";
  resp["request_status"] = StatusToStr(RequestStatus::Success);
  resp["id"] = AllocateSessionID();
  return resp;
}

Json::Value ResourceManager::JsonHandleShutdownRequest(SharedFD client_socket) {
  LOG(INFO) << "Received Shutdown Request";
  shutdown_socket_ = client_socket;

  Json::Value resp;
  resp["request_type"] = "shutdown";
  resp["request_status"] = "pending";
  resp["error"] = "";

  return resp;
}

Json::Value ResourceManager::JsonHandleCreateInterfaceRequest(
    SharedFD client_socket, const Json::Value& request) {
  LOG(INFO) << "Received CreateInterface Request";

  Json::Value resp;
  resp["request_type"] = "create_interface";
  resp["iface_name"] = "";
  resp["request_status"] = StatusToStr(RequestStatus::Failure);
  resp["error"] = "unknown";

  if (!request.isMember("uid") || !request["uid"].isUInt()) {
    auto err_msg = "Input event doesn't have a valid 'uid' field";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  if (!request.isMember("iface_type") || !request["iface_type"].isString()) {
    auto err_msg = "Input event doesn't have a valid 'iface_type' field";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  auto uid = request["uid"].asUInt();

  if (!CheckCredentials(client_socket, uid)) {
    auto err_msg = "Credential check failed";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  auto user_opt = GetUserName(uid);

  bool addedIface = false;
  std::stringstream ss;
  if (!user_opt) {
    auto err_msg = "UserName could not be matched to UID";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  } else {
    auto iface_ty_name = request["iface_type"].asString();
    resp["iface_type"] = iface_ty_name;
    auto iface_type = StrToIfaceTy(iface_ty_name);
    auto attempts = kMaxIfaceNameId;
    do {
      auto id = AllocateResourceID();
      resp["resource_id"] = id;
      ss << "cvd-" << iface_ty_name << "-" << user_opt.value().substr(0, 4)
         << std::setfill('0') << std::setw(2) << (id % kMaxIfaceNameId);
      addedIface = AddInterface(ss.str(), iface_type, id, uid);
      --attempts;
    } while (!addedIface && (attempts > 0));
  }

  if (addedIface) {
    resp["request_status"] = StatusToStr(RequestStatus::Success);
    resp["iface_name"] = ss.str();
    resp["error"] = "";
  }

  return resp;
}

Json::Value ResourceManager::JsonHandleDestroyInterfaceRequest(
    const Json::Value& request) {
  Json::Value resp;
  resp["request_type"] = "destroy_interface";
  resp["request_status"] = StatusToStr(RequestStatus::Failure);
  if (!request.isMember("iface_name") || !request["iface_name"].isString()) {
    auto err_msg = "Input event doesn't have a valid 'iface_name' field";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  auto iface_name = request["iface_name"].asString();

  bool isManagedIface = active_interfaces_.erase(iface_name) > 0;

  if (!isManagedIface) {
    auto msg = "Interface not managed: " + iface_name;
    LOG(WARNING) << msg;
    resp["error"] = msg;
    return resp;
  }

  if (!request.isMember("session_id") || !request["session_id"].isUInt()) {
    auto err_msg = "Input event doesn't have a valid 'session_id' field";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  auto session_id = request["session_id"].asUInt();

  auto resource_id = request["resource_id"].asUInt();

  LOG(INFO) << "Received DestroyInterface Request for " << iface_name
            << " in session: " << session_id
            << ", resource_id: " << resource_id;

  auto sess_opt = FindSession(session_id);
  if (!sess_opt) {
    auto msg = "Interface " + iface_name +
               " was not managed in session: " + std::to_string(session_id) +
               " with resource_id: " + std::to_string(resource_id);
    LOG(WARNING) << msg;
    resp["error"] = msg;
    return resp;
  }

  auto s = sess_opt.value();

  // while we could wait to see if any acquisitions fail and delay releasing
  // resources until they are all finished, this operation is inherently
  // destructive, so should a release operation fail, there is no satisfactory
  // method for aborting the transaction. Instead, we try to release the
  // resource and then can signal to the rest of the transaction the failure
  // state, which can then just stop the transaction, and revert any newly
  // acquired resources, but any successful drop requests will persist
  auto did_drop_resource = s->ReleaseResource(resource_id);

  if (did_drop_resource) {
    resp["request_status"] = StatusToStr(RequestStatus::Success);
  } else {
    auto msg = "Interface " + iface_name +
               " was not managed in session: " + std::to_string(session_id) +
               " with resource_id: " + std::to_string(resource_id);
    LOG(WARNING) << msg;
    resp["error"] = msg;
  }

  return resp;
}

Json::Value ResourceManager::JsonHandleStopSessionRequest(
    const Json::Value& request, uid_t uid) {
  Json::Value resp;
  resp["request_type"] = ReqTyToStr(RequestType::StopSession);
  resp["request_status"] = StatusToStr(RequestStatus::Failure);
  if (!request.isMember("session_id") || !request["session_id"].isUInt()) {
    auto err_msg = "Input event doesn't have a valid 'session_id' field";
    LOG(WARNING) << err_msg;
    resp["error"] = err_msg;
    return resp;
  }

  auto session_id = request["session_id"].asUInt();
  LOG(INFO) << "Received StopSession Request for Session ID: " << session_id;

  auto it = managed_sessions_.find(session_id);
  if (it == managed_sessions_.end()) {
    auto msg = "Session not managed: " + std::to_string(session_id);
    LOG(WARNING) << msg;
    resp["error"] = msg;
    return resp;
  }

  if (it->second->GetUID() != uid) {
    auto msg = "Effective user ID does not match session owner. socket uid: " +
               std::to_string(uid);
    LOG(WARNING) << msg;
    resp["error"] = msg;
    return resp;
  }

  // while we could wait to see if any acquisitions fail and delay releasing
  // resources until they are all finished, this operation is inherently
  // destructive, so should a release operation fail, there is no satisfactory
  // method for aborting the transaction. Instead, we try to release the
  // resource and then can signal to the rest of the transaction the failure
  // state
  auto success = it->second->ReleaseAllResources();

  // release the names from the global list for reuse in future requests
  for (auto& iface : it->second->GetActiveInterfaces()) {
    active_interfaces_.erase(iface);
  }

  if (success) {
    managed_sessions_.erase(it);
    resp["request_status"] = StatusToStr(RequestStatus::Success);
  } else {
    resp["error"] =
        "unknown, allocd experienced an error ending the session id: " +
        std::to_string(session_id);
  }

  return resp;
}

std::optional<std::shared_ptr<Session>> ResourceManager::FindSession(
    uint32_t id) {
  auto it = managed_sessions_.find(id);
  if (it == managed_sessions_.end()) {
    return std::nullopt;
  } else {
    return it->second;
  }
}

}  // namespace cuttlefish
