// Copyright 2020 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 "crash-reporter/crash_serializer.h"

#include <stdio.h>

#include <string>
#include <utility>

#include <base/big_endian.h>
#include <base/check_op.h>
#include <base/compiler_specific.h>  // FALLTHROUGH
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/optional.h>
#include <base/strings/string_util.h>
#include <base/threading/platform_thread.h>
#include <base/time/default_clock.h>
#include <base/time/time.h>

#include "crash-reporter/crash_sender_base.h"
#include "crash-reporter/crash_sender_util.h"
#include "crash-reporter/paths.h"
#include "crash-reporter/util.h"

namespace crash_serializer {

namespace {
void AddMetaField(crash::CrashInfo* info,
                  const std::string& key,
                  const std::string& value) {
  if (!base::IsStringUTF8(key)) {
    LOG(ERROR) << "key was not UTF8: " << key;
    return;
  }
  if (!base::IsStringUTF8(value)) {
    LOG(ERROR) << "value for key '" << key << "' was not UTF8";
    return;
  }
  crash::CrashMetadata* meta = info->add_fields();
  meta->set_key(key);
  meta->set_text(value);
}

base::Optional<crash::CrashBlob> MakeBlob(const std::string& name,
                                          const base::FilePath& file) {
  if (!base::IsStringUTF8(name)) {
    LOG(ERROR) << "key was not UTF8: " << name;
    return base::nullopt;
  }
  std::string contents;
  if (!base::ReadFileToString(file, &contents)) {
    return base::nullopt;
  }
  crash::CrashBlob b;
  b.set_key(name);
  b.set_blob(contents);
  b.set_filename(file.BaseName().value());
  return b;
}

}  // namespace

Serializer::Serializer(std::unique_ptr<base::Clock> clock,
                       const Options& options)
    : util::SenderBase(std::move(clock), options),
      out_("/dev/stdout"),
      fetch_cores_(options.fetch_coredumps),
      max_message_size_bytes_(options.max_proto_bytes) {}

// The serializer doesn't remove crashes, so do nothing.
void Serializer::RecordCrashRemoveReason(CrashRemoveReason reason) {}

void Serializer::PickCrashFiles(const base::FilePath& crash_dir,
                                std::vector<util::MetaFile>* to_send) {
  std::vector<base::FilePath> meta_files = util::GetMetaFiles(crash_dir);

  for (const auto& meta_file : meta_files) {
    LOG(INFO) << "Checking metadata: " << meta_file.value();

    std::string reason;
    util::CrashInfo info;
    switch (EvaluateMetaFileMinimal(meta_file, /*allow_old_os_timestamps=*/true,
                                    &reason, &info,
                                    /*processing_file=*/nullptr)) {
      case kRemove:
        FALLTHROUGH;  // Don't remove; rather, ignore the report.
      case kIgnore:
        LOG(INFO) << "Ignoring: " << reason;
        break;
      case kSend:
        to_send->push_back(std::make_pair(meta_file, std::move(info)));
        break;
      default:
        NOTREACHED();
    }
  }
}

void Serializer::SerializeCrashes(
    const std::vector<util::MetaFile>& crash_meta_files) {
  if (crash_meta_files.empty()) {
    return;
  }

  std::string client_id = util::GetClientId();

  base::File lock(AcquireLockFileOrDie());
  int64_t crash_id = -1;
  for (const auto& pair : crash_meta_files) {
    crash_id++;
    const base::FilePath& meta_file = pair.first;
    const util::CrashInfo& info = pair.second;
    LOG(INFO) << "Evaluating crash report: " << meta_file.value();

    base::TimeDelta sleep_time;
    if (!util::GetSleepTime(meta_file, /*max_spread_time=*/base::TimeDelta(),
                            hold_off_time_, &sleep_time)) {
      LOG(WARNING) << "Failed to compute sleep time for " << meta_file.value();
      continue;
    }

    LOG(INFO) << "Scheduled to send in " << sleep_time.InSeconds() << "s";
    lock.Close();  // Don't hold lock during sleep.
    if (!util::IsMock()) {
      base::PlatformThread::Sleep(sleep_time);
    } else if (!sleep_function_.is_null()) {
      sleep_function_.Run(sleep_time);
    }
    lock = AcquireLockFileOrDie();

    // Mark the crash as being processed so that if we crash, we don't try to
    // send the crash again.
    util::ScopedProcessingFile processing(meta_file);

    // User-specific crash reports become inaccessible if the user signs out
    // while sleeping, thus we need to check if the metadata is still
    // accessible.
    if (!base::PathExists(meta_file)) {
      LOG(INFO) << "Metadata is no longer accessible: " << meta_file.value();
      continue;
    }

    const util::CrashDetails details = {
        .meta_file = meta_file,
        .payload_file = info.payload_file,
        .payload_kind = info.payload_kind,
        .client_id = client_id,
        .metadata = info.metadata,
    };

    crash::FetchCrashesResponse resp;
    resp.set_crash_id(crash_id);
    std::vector<crash::CrashBlob> blobs;
    base::FilePath core_path;
    if (!SerializeCrash(details, resp.mutable_crash(), &blobs, &core_path)) {
      // If we cannot serialize the crash, give up -- there won't be anything to
      // write.
      LOG(ERROR) << "Failed to serialize " << meta_file.value();
      continue;
    }

    // Write the CrashInfo to output.
    if (!WriteFetchCrashesResponse(resp)) {
      // If we cannot write the CrashInfo, give up on the crash -- callers won't
      // be able to reconstruct anything useful from the report.
      LOG(ERROR) << "Failed to write CrashInfo proto for: " << meta_file.value()
                 << ". Giving up on this crash";
      continue;
    }

    if (!WriteBlobs(crash_id, blobs)) {
      // If this fails, keep trying to process the crash -- the coredump could
      // still be useful.
      LOG(ERROR) << "Failed to write blobs for " << meta_file.value();
    }

    if (!core_path.empty() && !WriteCoredump(crash_id, core_path)) {
      LOG(ERROR) << "Failed to write core for " << meta_file.value();
    }
  }
}

bool Serializer::SerializeCrash(const util::CrashDetails& details,
                                crash::CrashInfo* info,
                                std::vector<crash::CrashBlob>* blobs,
                                base::FilePath* core_path) {
  util::FullCrash crash = ReadMetaFile(details);

  // Add fields that are present directly in the FullCrash struct
  info->set_exec_name(crash.exec_name);
  AddMetaField(info, "board", crash.board);
  AddMetaField(info, "hwclass", crash.hwclass);
  info->set_prod(crash.prod);
  info->set_ver(crash.ver);
  info->set_sig(crash.sig);
  AddMetaField(info, "sig2", crash.sig);
  AddMetaField(info, "image_type", crash.image_type);
  AddMetaField(info, "boot_mode", crash.boot_mode);
  AddMetaField(info, "error_type", crash.error_type);
  AddMetaField(info, "guid", crash.guid);

  // Add fields from key_vals
  for (const auto& kv : crash.key_vals) {
    const std::string& key = kv.first;
    const std::string& val = kv.second;
    if (key == "in_progress_integration_test") {
      info->set_in_progress_integration_test(val);
    } else if (key == "collector") {
      info->set_collector(val);
    } else {
      AddMetaField(info, key, val);
    }
  }

  // Add payload file
  base::Optional<crash::CrashBlob> payload =
      MakeBlob(crash.payload.first, crash.payload.second);
  if (!payload) {
    return false;
  }
  blobs->push_back(*payload);

  // Add files
  for (const auto& kv : crash.files) {
    base::Optional<crash::CrashBlob> blob = MakeBlob(kv.first, kv.second);
    if (blob) {
      blobs->push_back(*blob);
    }
  }

  if (fetch_cores_) {
    base::FilePath maybe_core = details.meta_file.ReplaceExtension(".core");
    if (base::PathExists(maybe_core)) {
      *core_path = maybe_core;
    }
  }

  return true;
}

bool Serializer::WriteFetchCrashesResponse(
    const crash::FetchCrashesResponse& crash_data) {
  // Initialize string with the size and then append the proto to that so that
  // we get the data in a single buffer with no extra copies.
  size_t size = crash_data.ByteSizeLong();
  // Convert to a fixed size to ensure a consistent serialization format.
  static_assert(sizeof(size_t) <= sizeof(uint64_t),
                "size_t is too big to fit in 8 bytes");
  uint64_t size_uint64 = size;

  char size_bytes[sizeof(size_uint64)];
  base::WriteBigEndian(size_bytes, size_uint64);

  std::string buf(size_bytes, size_bytes + sizeof(size_uint64));
  if (!crash_data.AppendToString(&buf)) {
    LOG(ERROR) << "Failed to serialize proto to string";
    return false;
  }

  if (!base::AppendToFile(out_, buf)) {
    PLOG(ERROR) << "Failed to append";
    return false;
  }
  CHECK_EQ(buf.size(), size + sizeof(size_uint64));
  return true;
}

bool Serializer::WriteBlobs(int64_t crash_id,
                            const std::vector<crash::CrashBlob>& blobs) {
  crash::FetchCrashesResponse resp;
  resp.set_crash_id(crash_id);
  bool success = true;
  for (const auto& blob : blobs) {
    size_t actual_size = blob.blob().size();
    // Divide and round up to calculate the number of protos to split this
    // blob into.
    int proto_count =
        (actual_size + max_message_size_bytes_ - 1) / max_message_size_bytes_;

    crash::CrashBlob* send_blob = resp.mutable_blob();
    send_blob->set_key(blob.key());
    send_blob->set_filename(blob.filename());
    size_t offset = 0;
    for (int i = 0; i < proto_count; i++) {
      // Re-retrieve the pointer here because WriteFetchCrashesResponse might
      // invalidate it; see
      // https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#fields
      send_blob = resp.mutable_blob();
      CHECK_LE(offset, blob.blob().size());
      send_blob->set_blob(blob.blob().substr(offset, max_message_size_bytes_));

      if (!WriteFetchCrashesResponse(resp)) {
        LOG(ERROR) << "Failed to write blob: " << blob.key()
                   << " starting at offset: " << offset;
        // Don't continue with this blob -- even if we succeed at sending a
        // later chunk, callers won't be able to correctly reassemble the
        // data.
        success = false;
        break;
      }
      offset += max_message_size_bytes_;
    }
  }
  return success;
}

bool Serializer::WriteCoredump(int64_t crash_id, base::FilePath core_path) {
  crash::FetchCrashesResponse resp;
  resp.set_crash_id(crash_id);

  base::File core_file(core_path,
                       base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!core_file.IsValid()) {
    LOG(ERROR) << "Failed to open " << core_path.value() << " for reading: "
               << base::File::ErrorToString(core_file.error_details());
    return false;
  }

  int64_t size = core_file.GetLength();
  if (size < 0) {
    LOG(ERROR) << "Failed to get size for core file: " << core_path.value()
               << ": " << base::File::ErrorToString(core_file.error_details());
    return false;
  } else if (size == 0) {
    LOG(WARNING) << "Coredump " << core_path.value()
                 << " is empty. Proceeding anyway.";
  }

  int64_t total_read = 0;
  while (total_read < size) {
    std::vector<char> buf(max_message_size_bytes_);
    // Don't read the entire core into memory at once, as it could be multiple
    // GBs.
    int read = core_file.Read(total_read, buf.data(), max_message_size_bytes_);
    if (read < 0) {
      LOG(ERROR) << "Failed to read: " << core_path.value()
                 << "at offset: " << total_read << ": "
                 << base::File::ErrorToString(core_file.error_details());
      // Don't continue reading the core -- even if later calls succeed, the
      // caller won't be able to correctly reassemble the coredump.
      return false;
    }

    resp.set_core(buf.data(), read);
    if (!WriteFetchCrashesResponse(resp)) {
      LOG(ERROR) << "Failed to write core dump at offset " << total_read;
      // Don't continue reading the core -- even if later calls succeed, the
      // caller won't be able to correctly reassemble the coredump.
      return false;
    }

    total_read += read;
  }
  return true;
}

}  // namespace crash_serializer
