/*
 * Copyright 2016, 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <array>
#include <deque>
#include <unordered_map>

#include <event2/event.h>
#include <event2/listener.h>
#include <event2/thread.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>

#include "debuggerd/handler.h"
#include "debuggerd/protocol.h"
#include "debuggerd/util.h"

#include "intercept_manager.h"

using android::base::StringPrintf;
using android::base::unique_fd;

static InterceptManager* intercept_manager;

enum CrashStatus {
  kCrashStatusRunning,
  kCrashStatusQueued,
};

// Ownership of Crash is a bit messy.
// It's either owned by an active event that must have a timeout, or owned by
// queued_requests, in the case that multiple crashes come in at the same time.
struct Crash {
  ~Crash() {
    event_free(crash_event);
  }

  unique_fd crash_fd;
  pid_t crash_pid;
  event* crash_event = nullptr;
  std::string crash_path;
};

static constexpr char kTombstoneDirectory[] = "/data/tombstones/";
static constexpr size_t kTombstoneCount = 10;
static int tombstone_directory_fd = -1;
static int next_tombstone = 0;

static constexpr size_t kMaxConcurrentDumps = 1;
static size_t num_concurrent_dumps = 0;

static std::deque<Crash*> queued_requests;

// Forward declare the callbacks so they can be placed in a sensible order.
static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);

static void find_oldest_tombstone() {
  size_t oldest_tombstone = 0;
  time_t oldest_time = std::numeric_limits<time_t>::max();

  for (size_t i = 0; i < kTombstoneCount; ++i) {
    std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
    struct stat st;
    if (stat(path.c_str(), &st) != 0) {
      if (errno == ENOENT) {
        oldest_tombstone = i;
        break;
      } else {
        PLOG(ERROR) << "failed to stat " << path;
        continue;
      }
    }

    if (st.st_mtime < oldest_time) {
      oldest_tombstone = i;
      oldest_time = st.st_mtime;
    }
  }

  next_tombstone = oldest_tombstone;
}

static std::pair<unique_fd, std::string> get_tombstone() {
  // If kMaxConcurrentDumps is greater than 1, then theoretically the same
  // filename could be handed out to multiple processes. Unlink and create the
  // file, instead of using O_TRUNC, to avoid two processes interleaving their
  // output.
  unique_fd result;
  std::string file_name = StringPrintf("tombstone_%02d", next_tombstone);
  if (unlinkat(tombstone_directory_fd, file_name.c_str(), 0) != 0 && errno != ENOENT) {
    PLOG(FATAL) << "failed to unlink tombstone at " << kTombstoneDirectory << "/" << file_name;
  }

  result.reset(openat(tombstone_directory_fd, file_name.c_str(),
                      O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
  if (result == -1) {
    PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << "/" << file_name;
  }

  next_tombstone = (next_tombstone + 1) % kTombstoneCount;
  return {std::move(result), std::string(kTombstoneDirectory) + "/" + file_name};
}

static void perform_request(Crash* crash) {
  unique_fd output_fd;
  if (!intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
    std::tie(output_fd, crash->crash_path) = get_tombstone();
  }

  TombstonedCrashPacket response = {
    .packet_type = CrashPacketType::kPerformDump
  };
  ssize_t rc = send_fd(crash->crash_fd, &response, sizeof(response), std::move(output_fd));
  if (rc == -1) {
    PLOG(WARNING) << "failed to send response to CrashRequest";
    goto fail;
  } else if (rc != sizeof(response)) {
    PLOG(WARNING) << "crash socket write returned short";
    goto fail;
  } else {
    // TODO: Make this configurable by the interceptor?
    struct timeval timeout = { 10, 0 };

    event_base* base = event_get_base(crash->crash_event);
    event_assign(crash->crash_event, base, crash->crash_fd, EV_TIMEOUT | EV_READ,
                 crash_completed_cb, crash);
    event_add(crash->crash_event, &timeout);
  }

  ++num_concurrent_dumps;
  return;

fail:
  delete crash;
}

static void dequeue_requests() {
  while (!queued_requests.empty() && num_concurrent_dumps < kMaxConcurrentDumps) {
    Crash* next_crash = queued_requests.front();
    queued_requests.pop_front();
    perform_request(next_crash);
  }
}

static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
                            void*) {
  event_base* base = evconnlistener_get_base(listener);
  Crash* crash = new Crash();

  struct timeval timeout = { 1, 0 };
  event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
  crash->crash_fd.reset(sockfd);
  crash->crash_event = crash_event;
  event_add(crash_event, &timeout);
}

static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
  ssize_t rc;
  Crash* crash = static_cast<Crash*>(arg);
  TombstonedCrashPacket request = {};

  if ((ev & EV_TIMEOUT) != 0) {
    LOG(WARNING) << "crash request timed out";
    goto fail;
  } else if ((ev & EV_READ) == 0) {
    LOG(WARNING) << "tombstoned received unexpected event from crash socket";
    goto fail;
  }

  rc = TEMP_FAILURE_RETRY(read(sockfd, &request, sizeof(request)));
  if (rc == -1) {
    PLOG(WARNING) << "failed to read from crash socket";
    goto fail;
  } else if (rc != sizeof(request)) {
    LOG(WARNING) << "crash socket received short read of length " << rc << " (expected "
                 << sizeof(request) << ")";
    goto fail;
  }

  if (request.packet_type != CrashPacketType::kDumpRequest) {
    LOG(WARNING) << "unexpected crash packet type, expected kDumpRequest, received  "
                 << StringPrintf("%#2hhX", request.packet_type);
    goto fail;
  }

  crash->crash_pid = request.packet.dump_request.pid;
  LOG(INFO) << "received crash request for pid " << crash->crash_pid;

  if (num_concurrent_dumps == kMaxConcurrentDumps) {
    LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
    queued_requests.push_back(crash);
  } else {
    perform_request(crash);
  }

  return;

fail:
  delete crash;
}

static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
  ssize_t rc;
  Crash* crash = static_cast<Crash*>(arg);
  TombstonedCrashPacket request = {};

  --num_concurrent_dumps;

  if ((ev & EV_READ) == 0) {
    goto fail;
  }

  rc = TEMP_FAILURE_RETRY(read(sockfd, &request, sizeof(request)));
  if (rc == -1) {
    PLOG(WARNING) << "failed to read from crash socket";
    goto fail;
  } else if (rc != sizeof(request)) {
    LOG(WARNING) << "crash socket received short read of length " << rc << " (expected "
                 << sizeof(request) << ")";
    goto fail;
  }

  if (request.packet_type != CrashPacketType::kCompletedDump) {
    LOG(WARNING) << "unexpected crash packet type, expected kCompletedDump, received "
                 << uint32_t(request.packet_type);
    goto fail;
  }

  if (!crash->crash_path.empty()) {
    LOG(ERROR) << "Tombstone written to: " << crash->crash_path;
  }

fail:
  delete crash;

  // If there's something queued up, let them proceed.
  dequeue_requests();
}

int main(int, char* []) {
  umask(0137);

  // Don't try to connect to ourselves if we crash.
  struct sigaction action = {};
  action.sa_handler = [](int signal) {
    LOG(ERROR) << "received fatal signal " << signal;
    _exit(1);
  };
  debuggerd_register_handlers(&action);

  tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
  if (tombstone_directory_fd == -1) {
    PLOG(FATAL) << "failed to open tombstone directory";
  }

  find_oldest_tombstone();

  int intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName);
  int crash_socket = android_get_control_socket(kTombstonedCrashSocketName);

  if (intercept_socket == -1 || crash_socket == -1) {
    PLOG(FATAL) << "failed to get socket from init";
  }

  evutil_make_socket_nonblocking(intercept_socket);
  evutil_make_socket_nonblocking(crash_socket);

  event_base* base = event_base_new();
  if (!base) {
    LOG(FATAL) << "failed to create event_base";
  }

  intercept_manager = new InterceptManager(base, intercept_socket);

  evconnlistener* listener =
    evconnlistener_new(base, crash_accept_cb, nullptr, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
  if (!listener) {
    LOG(FATAL) << "failed to create evconnlistener";
  }

  LOG(INFO) << "tombstoned successfully initialized";
  event_base_dispatch(base);
}
