// Copyright 2019 The Fuchsia 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 "src/lib/fidl_codec/message_decoder.h"

#include <lib/syslog/cpp/macros.h>

#include <ostream>
#include <sstream>

#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

#include "src/lib/fidl_codec/library_loader.h"
#include "src/lib/fidl_codec/status.h"
#include "src/lib/fidl_codec/wire_object.h"
#include "src/lib/fidl_codec/wire_parser.h"
#include "src/lib/fidl_codec/wire_types.h"

namespace fidl_codec {

std::string DocumentToString(rapidjson::Document* document);

bool DecodedMessage::DecodeMessage(MessageDecoderDispatcher* dispatcher, uint64_t process_koid,
                                   zx_handle_t handle, const uint8_t* bytes, uint32_t num_bytes,
                                   const zx_handle_disposition_t* handles, uint32_t num_handles,
                                   SyscallFidlType type, std::ostream& error_stream) {
  if ((bytes == nullptr) || (num_bytes < sizeof(fidl_message_header_t))) {
    error_stream << "not enough data for message\n";
    return false;
  }

  header_ = reinterpret_cast<const fidl_message_header_t*>(bytes);
  txid_ = header_->txid;
  ordinal_ = header_->ordinal;

  // Handle the epitaph header explicitly.
  if (ordinal_ == kFidlOrdinalEpitaph) {
    if (num_bytes < sizeof(fidl_epitaph)) {
      error_stream << "not enough data for epitaph\n";
      return false;
    }
    switch (type) {
      case SyscallFidlType::kOutputRequest:
      case SyscallFidlType::kOutputMessage:
        received_ = false;
        break;
      case SyscallFidlType::kInputResponse:
      case SyscallFidlType::kInputMessage:
        received_ = true;
        break;
    }
    auto epitaph = reinterpret_cast<const fidl_epitaph_t*>(header_);
    epitaph_error_ = epitaph->error;
    return true;
  }

  if ((dispatcher == nullptr) || (dispatcher->loader() == nullptr)) {
    return false;
  }

  const std::vector<const InterfaceMethod*>* methods = dispatcher->loader()->GetByOrdinal(ordinal_);
  if (methods == nullptr || methods->empty()) {
    error_stream << "Protocol method with ordinal 0x" << std::hex << header_->ordinal
                 << " not found\n";
    return false;
  }

  method_ = (*methods)[0];

  matched_request_ = DecodeRequest(method_, bytes, num_bytes, handles, num_handles,
                                   &decoded_request_, request_error_stream_);
  matched_response_ = DecodeResponse(method_, bytes, num_bytes, handles, num_handles,
                                     &decoded_response_, response_error_stream_);

  direction_ = dispatcher->ComputeDirection(process_koid, handle, type, method_,
                                            matched_request_ != matched_response_);
  switch (type) {
    case SyscallFidlType::kOutputMessage:
      if (direction_ == Direction::kClient) {
        is_request_ = true;
      }
      received_ = false;
      break;
    case SyscallFidlType::kInputMessage:
      if (direction_ == Direction::kServer) {
        is_request_ = true;
      }
      received_ = true;
      break;
    case SyscallFidlType::kOutputRequest:
      is_request_ = true;
      received_ = false;
      break;
    case SyscallFidlType::kInputResponse:
      received_ = true;
      break;
  }
  if (direction_ != Direction::kUnknown) {
    if ((is_request_ && !matched_request_) || (!is_request_ && !matched_response_)) {
      if ((is_request_ && matched_response_) || (!is_request_ && matched_request_)) {
        if ((type == SyscallFidlType::kOutputRequest) ||
            (type == SyscallFidlType::kInputResponse)) {
          // We know the direction: we can't be wrong => we haven't been able to decode the message.
          // However, we can still display something.
          return true;
        }
        // The first determination seems to be wrong. That is, we are expecting
        // a request but only a response has been successfully decoded or we are
        // expecting a response but only a request has been successfully
        // decoded.
        // Invert the deduction which should now be the right one.
        dispatcher->UpdateDirection(
            process_koid, handle,
            (direction_ == Direction::kClient) ? Direction::kServer : Direction::kClient);
        is_request_ = !is_request_;
      }
    }
  }
  return true;
}

Direction MessageDecoderDispatcher::ComputeDirection(uint64_t process_koid, zx_handle_t handle,
                                                     SyscallFidlType type,
                                                     const InterfaceMethod* method,
                                                     bool only_one_valid) {
  auto handle_direction = handle_directions_.find(std::make_tuple(handle, process_koid));
  if (handle_direction != handle_directions_.end()) {
    return handle_direction->second;
  }
  // This is the first read or write we intercept for this handle/koid. If we
  // launched the process, we suppose we intercepted the very first read or
  // write.
  // If this is not an event (which would mean method->request() is null), a
  // write means that we are watching a client (a client starts by writing a
  // request) and a read means that we are watching a server (a server starts
  // by reading the first client request).
  // If we attached to a running process, we can only determine correctly if
  // we are watching a client or a server if we have only one matched_request
  // or one matched_response.
  if (IsLaunchedProcess(process_koid) || only_one_valid) {
    // We launched the process or exactly one of request and response are
    // valid => we can determine the direction.
    switch (type) {
      case SyscallFidlType::kOutputMessage:
        handle_directions_[std::make_tuple(handle, process_koid)] =
            (method->request() != nullptr) ? Direction::kClient : Direction::kServer;
        break;
      case SyscallFidlType::kInputMessage:
        handle_directions_[std::make_tuple(handle, process_koid)] =
            (method->request() != nullptr) ? Direction::kServer : Direction::kClient;
        break;
      case SyscallFidlType::kOutputRequest:
      case SyscallFidlType::kInputResponse:
        handle_directions_[std::make_tuple(handle, process_koid)] = Direction::kClient;
    }
    return handle_directions_[std::make_tuple(handle, process_koid)];
  }
  return Direction::kUnknown;
}

MessageDecoder::MessageDecoder(const uint8_t* bytes, uint64_t num_bytes,
                               const zx_handle_disposition_t* handles, uint32_t num_handles,
                               std::ostream& error_stream)
    : num_bytes_(num_bytes),
      start_byte_pos_(bytes),
      end_handle_pos_(handles + num_handles),
      handle_pos_(handles),
      error_stream_(error_stream) {}

MessageDecoder::MessageDecoder(MessageDecoder* container, uint64_t offset, uint64_t num_bytes,
                               uint64_t num_handles)
    : absolute_offset_(container->absolute_offset() + offset),
      num_bytes_(num_bytes),
      start_byte_pos_(container->start_byte_pos_ + offset),
      end_handle_pos_(container->handle_pos_ + num_handles),
      handle_pos_(container->handle_pos_),
      error_stream_(container->error_stream_) {
  container->handle_pos_ += num_handles;
}

std::unique_ptr<StructValue> MessageDecoder::DecodeMessage(const Struct& message_format) {
  // Set the offset for the next object (just after this one).
  SkipObject(message_format.size());
  // Decode the message.
  std::unique_ptr<StructValue> message = DecodeStruct(message_format, 0);
  // It's an error if we didn't use all the bytes in the buffer.
  if (next_object_offset_ != num_bytes_) {
    AddError() << "Message not fully decoded (decoded=" << next_object_offset_
               << ", size=" << num_bytes_ << ")\n";
  }
  // It's an error if we didn't use all the handles in the buffer.
  if (GetRemainingHandles() != 0) {
    AddError() << "Message not fully decoded (remain " << GetRemainingHandles() << " handles)\n";
  }
  return message;
}

std::unique_ptr<Value> MessageDecoder::DecodeValue(const Type* type) {
  if (type == nullptr) {
    return nullptr;
  }
  // Set the offset for the next object (just after this one).
  SkipObject(type->InlineSize());
  // Decode the envelope.
  std::unique_ptr<Value> result = type->Decode(this, 0);
  // It's an error if we didn't use all the bytes in the buffer.
  if (next_object_offset_ != num_bytes_) {
    AddError() << "Message envelope not fully decoded (decoded=" << next_object_offset_
               << ", size=" << num_bytes_ << ")\n";
  }
  // It's an error if we didn't use all the handles in the buffer.
  if (GetRemainingHandles() != 0) {
    AddError() << "Message envelope not fully decoded (remain " << GetRemainingHandles()
               << " handles)\n";
  }
  return result;
}

std::unique_ptr<StructValue> MessageDecoder::DecodeStruct(const Struct& struct_definition,
                                                          uint64_t offset) {
  std::unique_ptr<StructValue> result = std::make_unique<StructValue>(struct_definition);
  for (const auto& member : struct_definition.members()) {
    std::unique_ptr<Value> value = member->type()->Decode(this, offset + member->offset());
    result->AddField(member.get(), std::move(value));
  }
  return result;
}

bool MessageDecoder::DecodeNullableHeader(uint64_t offset, uint64_t size, bool* is_null,
                                          uint64_t* nullable_offset) {
  uintptr_t data;
  if (!GetValueAt(offset, &data)) {
    return false;
  }

  if (data == FIDL_ALLOC_ABSENT) {
    *is_null = true;
    *nullable_offset = 0;
    return true;
  }
  if (data != FIDL_ALLOC_PRESENT) {
    AddError() << std::hex << (absolute_offset() + offset) << std::dec << ": Invalid value <"
               << std::hex << data << std::dec << "> for nullable\n";
    return false;
  }
  *is_null = false;
  *nullable_offset = next_object_offset();
  // Set the offset for the next object (just after this one).
  SkipObject(size);
  return true;
}

std::unique_ptr<Value> MessageDecoder::DecodeEnvelope(uint64_t offset, const Type* type) {
  FX_DCHECK(type != nullptr);
  uint32_t envelope_bytes;
  GetValueAt(offset, &envelope_bytes);
  offset += sizeof(envelope_bytes);
  uint32_t envelope_handles;
  GetValueAt(offset, &envelope_handles);
  offset += sizeof(envelope_handles);
  bool is_null;
  uint64_t nullable_offset;
  if (!DecodeNullableHeader(offset, envelope_bytes, &is_null, &nullable_offset)) {
    return std::make_unique<InvalidValue>();
  }
  if (is_null) {
    if (envelope_bytes != 0) {
      AddError() << std::hex << (absolute_offset() + offset) << std::dec
                 << ": Null envelope shouldn't have bytes\n";
    }
    if (envelope_handles != 0) {
      AddError() << std::hex << (absolute_offset() + offset) << std::dec
                 << ": Null envelope shouldn't have handles\n";
    }
    return std::make_unique<NullValue>();
  }
  if (envelope_bytes > num_bytes() - nullable_offset) {
    AddError() << std::hex << (absolute_offset() + nullable_offset) << std::dec
               << ": Not enough data to decode an envelope\n";
    return std::make_unique<InvalidValue>();
  }
  if (envelope_handles > GetRemainingHandles()) {
    AddError() << std::hex << (absolute_offset() + nullable_offset) << std::dec
               << ": Not enough handles to decode an envelope\n";
    return std::make_unique<InvalidValue>();
  }
  MessageDecoder envelope_decoder(this, nullable_offset, envelope_bytes, envelope_handles);
  return envelope_decoder.DecodeValue(type);
}

bool MessageDecoder::CheckNullEnvelope(uint64_t offset) {
  uint32_t envelope_bytes;
  GetValueAt(offset, &envelope_bytes);
  offset += sizeof(envelope_bytes);
  uint32_t envelope_handles;
  GetValueAt(offset, &envelope_handles);
  offset += sizeof(envelope_handles);
  bool is_null;
  uint64_t nullable_offset;
  if (!DecodeNullableHeader(offset, envelope_bytes, &is_null, &nullable_offset)) {
    return false;
  }
  if (!is_null) {
    AddError() << std::hex << (absolute_offset() + offset) << std::dec
               << ": Expecting null envelope\n";
    return false;
  }
  if (envelope_bytes != 0) {
    AddError() << std::hex << (absolute_offset() + offset) << std::dec
               << ": Null envelope shouldn't have bytes\n";
    return false;
  }
  if (envelope_handles != 0) {
    AddError() << std::hex << (absolute_offset() + offset) << std::dec
               << ": Null envelope shouldn't have handles\n";
    return false;
  }
  return true;
}

void MessageDecoder::SkipEnvelope(uint64_t offset) {
  uint32_t envelope_bytes;
  GetValueAt(offset, &envelope_bytes);
  offset += sizeof(envelope_bytes);
  uint32_t envelope_handles;
  GetValueAt(offset, &envelope_handles);
  offset += sizeof(envelope_handles);
  bool is_null;
  uint64_t nullable_offset;
  if (!DecodeNullableHeader(offset, envelope_bytes, &is_null, &nullable_offset)) {
    return;
  }
  if (is_null) {
    if (envelope_bytes != 0) {
      AddError() << std::hex << (absolute_offset() + offset) << std::dec
                 << ": Null envelope shouldn't have bytes\n";
    }
    if (envelope_handles != 0) {
      AddError() << std::hex << (absolute_offset() + offset) << std::dec
                 << ": Null envelope shouldn't have handles\n";
    }
    return;
  }
  if (envelope_bytes > num_bytes() - nullable_offset) {
    AddError() << std::hex << (absolute_offset() + nullable_offset) << std::dec
               << ": Not enough data to decode an envelope\n";
    return;
  }
  if (envelope_handles > GetRemainingHandles()) {
    AddError() << std::hex << (absolute_offset() + nullable_offset) << std::dec
               << ": Not enough handles to decode an envelope\n";
    return;
  }
}

}  // namespace fidl_codec
