// 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/compiler_specific.h>  // FALLTHROUGH
#include <base/files/file_path.h>
#include <base/files/file_util.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.data(), buf.size())) {
    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
