/*
 * Copyright (C) 2007 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 "minadbd_services.h"

#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_set>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/memory.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "adb.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "fdevent.h"
#include "fuse_adb_provider.h"
#include "fuse_sideload.h"
#include "minadbd_types.h"
#include "services.h"
#include "sysdeps.h"

static int minadbd_socket = -1;
static bool rescue_mode = false;

void SetMinadbdSocketFd(int socket_fd) {
  minadbd_socket = socket_fd;
}

void SetMinadbdRescueMode(bool rescue) {
  rescue_mode = rescue;
}

static bool WriteCommandToFd(MinadbdCommands cmd, int fd) {
  char message[kMinadbdMessageSize];
  memcpy(message, kMinadbdCommandPrefix, strlen(kMinadbdStatusPrefix));
  android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), cmd);

  if (!android::base::WriteFully(fd, message, kMinadbdMessageSize)) {
    PLOG(ERROR) << "Failed to write message " << message;
    return false;
  }
  return true;
}

// Blocks and reads the command status from |fd|. Returns false if the received message has a
// format error.
static bool WaitForCommandStatus(int fd, MinadbdCommandStatus* status) {
  char buffer[kMinadbdMessageSize];
  if (!android::base::ReadFully(fd, buffer, kMinadbdMessageSize)) {
    PLOG(ERROR) << "Failed to response status from socket";
    exit(kMinadbdSocketIOError);
  }

  std::string message(buffer, buffer + kMinadbdMessageSize);
  if (!android::base::StartsWith(message, kMinadbdStatusPrefix)) {
    LOG(ERROR) << "Failed to parse status in " << message;
    return false;
  }

  *status = android::base::get_unaligned<MinadbdCommandStatus>(
      message.substr(strlen(kMinadbdStatusPrefix)).c_str());
  return true;
}

static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args,
                                           MinadbdCommandStatus* status) {
  auto pieces = android::base::Split(args, ":");
  int64_t file_size;
  int block_size;
  if (pieces.size() != 2 || !android::base::ParseInt(pieces[0], &file_size) || file_size <= 0 ||
      !android::base::ParseInt(pieces[1], &block_size) || block_size <= 0) {
    LOG(ERROR) << "bad sideload-host arguments: " << args;
    return kMinadbdPackageSizeError;
  }

  LOG(INFO) << "sideload-host file size " << file_size << ", block size " << block_size;

  if (!WriteCommandToFd(MinadbdCommands::kInstall, minadbd_socket)) {
    return kMinadbdSocketIOError;
  }

  auto adb_data_reader = std::make_unique<FuseAdbDataProvider>(sfd, file_size, block_size);
  if (int result = run_fuse_sideload(std::move(adb_data_reader)); result != 0) {
    LOG(ERROR) << "Failed to start fuse";
    return kMinadbdFuseStartError;
  }

  if (!WaitForCommandStatus(minadbd_socket, status)) {
    return kMinadbdMessageFormatError;
  }

  // Signal host-side adb to stop. For sideload mode, we always send kSideloadServiceExitSuccess
  // (i.e. "DONEDONE") regardless of the install result. For rescue mode, we send failure message on
  // install error.
  if (!rescue_mode || *status == MinadbdCommandStatus::kSuccess) {
    if (!android::base::WriteFully(sfd, kSideloadServiceExitSuccess,
                                   strlen(kSideloadServiceExitSuccess))) {
      return kMinadbdHostSocketIOError;
    }
  } else {
    if (!android::base::WriteFully(sfd, kSideloadServiceExitFailure,
                                   strlen(kSideloadServiceExitFailure))) {
      return kMinadbdHostSocketIOError;
    }
  }

  return kMinadbdSuccess;
}

// Sideload service always exits after serving an install command.
static void SideloadHostService(unique_fd sfd, const std::string& args) {
  MinadbdCommandStatus status;
  exit(RunAdbFuseSideload(sfd.get(), args, &status));
}

// Rescue service waits for the next command after an install command.
static void RescueInstallHostService(unique_fd sfd, const std::string& args) {
  MinadbdCommandStatus status;
  if (auto result = RunAdbFuseSideload(sfd.get(), args, &status); result != kMinadbdSuccess) {
    exit(result);
  }
}

static void RescueGetpropHostService(unique_fd sfd, const std::string& prop) {
  static const std::unordered_set<std::string> kGetpropAllowedProps = {
    "ro.build.fingerprint",
    "ro.build.date.utc",
  };
  auto allowed = kGetpropAllowedProps.find(prop) != kGetpropAllowedProps.end();
  if (!allowed) {
    return;
  }

  auto result = android::base::GetProperty(prop, "");
  if (result.empty()) {
    return;
  }
  if (!android::base::WriteFully(sfd, result.data(), result.size())) {
    exit(kMinadbdHostSocketIOError);
  }
}

unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport */) {
  if (rescue_mode) {
    if (ConsumePrefix(&name, "rescue-install:")) {
      // rescue-install:<file-size>:<block-size>
      std::string args(name);
      return create_service_thread(
          "rescue-install", std::bind(RescueInstallHostService, std::placeholders::_1, args));
    } else if (ConsumePrefix(&name, "rescue-getprop:")) {
      // rescue-getprop:<prop>
      std::string args(name);
      return create_service_thread(
          "rescue-getprop", std::bind(RescueGetpropHostService, std::placeholders::_1, args));
    }
    return unique_fd{};
  }

  if (name.starts_with("sideload:")) {
    // This exit status causes recovery to print a special error message saying to use a newer adb
    // (that supports sideload-host).
    exit(kMinadbdAdbVersionError);
  } else if (ConsumePrefix(&name, "sideload-host:")) {
    // sideload-host:<file-size>:<block-size>
    std::string args(name);
    return create_service_thread("sideload-host",
                                 std::bind(SideloadHostService, std::placeholders::_1, args));
  }
  return unique_fd{};
}
