// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/bootstrap_natives.h"
#include "vm/dart_api_impl.h"
#include "vm/datastream.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/kernel_isolate.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/port.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/symbols.h"

namespace dart {

DECLARE_FLAG(bool, trace_service);

#ifndef PRODUCT
class RegisterRunningIsolatesVisitor : public IsolateVisitor {
 public:
  explicit RegisterRunningIsolatesVisitor(Thread* thread)
      : IsolateVisitor(),
        register_function_(Function::Handle(thread->zone())),
        service_isolate_(thread->isolate()) {
    ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
    // Get library.
    const String& library_url = Symbols::DartVMService();
    ASSERT(!library_url.IsNull());
    const Library& library =
        Library::Handle(Library::LookupLibrary(thread, library_url));
    ASSERT(!library.IsNull());
    // Get function.
    const String& function_name =
        String::Handle(String::New("_registerIsolate"));
    ASSERT(!function_name.IsNull());
    register_function_ = library.LookupFunctionAllowPrivate(function_name);
    ASSERT(!register_function_.IsNull());
  }

  virtual void VisitIsolate(Isolate* isolate) {
    ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
    if (IsVMInternalIsolate(isolate)) {
      // We do not register the service (and descendants), the vm-isolate, or
      // the kernel isolate.
      return;
    }
    // Setup arguments for call.
    Dart_Port port_id = isolate->main_port();
    const Integer& port_int = Integer::Handle(Integer::New(port_id));
    ASSERT(!port_int.IsNull());
    const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
    const String& name = String::Handle(String::New(isolate->name()));
    ASSERT(!name.IsNull());
    const Array& args = Array::Handle(Array::New(3));
    ASSERT(!args.IsNull());
    args.SetAt(0, port_int);
    args.SetAt(1, send_port);
    args.SetAt(2, name);
    const Object& r =
        Object::Handle(DartEntry::InvokeFunction(register_function_, args));
    if (FLAG_trace_service) {
      OS::PrintErr("vm-service: Isolate %s %" Pd64 " registered.\n",
                   name.ToCString(), port_id);
    }
    ASSERT(!r.IsError());
  }

 private:
  Function& register_function_;
  Isolate* service_isolate_;
};
#endif  // !PRODUCT

DEFINE_NATIVE_ENTRY(VMService_SendIsolateServiceMessage, 2) {
  if (!FLAG_support_service) {
    return Bool::Get(false).raw();
  }
  GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1));

  // Set the type of the OOB message.
  message.SetAt(0,
                Smi::Handle(thread->zone(), Smi::New(Message::kServiceOOBMsg)));

  // Serialize message.
  MessageWriter writer(false);
  // TODO(turnidge): Throw an exception when the return value is false?
  bool result = PortMap::PostMessage(
      writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
  return Bool::Get(result).raw();
}

DEFINE_NATIVE_ENTRY(VMService_SendRootServiceMessage, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
  if (FLAG_support_service) {
    return Service::HandleRootMessage(message);
  }
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_SendObjectRootServiceMessage, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
  if (FLAG_support_service) {
    return Service::HandleObjectRootMessage(message);
  }
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_OnStart, 0) {
  if (FLAG_trace_service) {
    OS::PrintErr("vm-service: Booting dart:vmservice library.\n");
  }
  // Boot the dart:vmservice library.
  ServiceIsolate::BootVmServiceLibrary();
  if (!FLAG_support_service) {
    return Object::null();
  }
#ifndef PRODUCT
  // Register running isolates with service.
  RegisterRunningIsolatesVisitor register_isolates(thread);
  if (FLAG_trace_service) {
    OS::PrintErr("vm-service: Registering running isolates.\n");
  }
  Isolate::VisitIsolates(&register_isolates);
#endif
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_OnExit, 0) {
  if (FLAG_trace_service) {
    OS::PrintErr("vm-service: processed exit message.\n");
    MessageHandler* message_handler = isolate->message_handler();
    OS::PrintErr("vm-service: live ports = %" Pd "\n",
                 message_handler->live_ports());
  }
  Isolate::KillIfExists(isolate, Isolate::kInternalKillMsg);
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_OnServerAddressChange, 1) {
  if (!FLAG_support_service) {
    return Object::null();
  }
  GET_NATIVE_ARGUMENT(String, address, arguments->NativeArgAt(0));
  if (address.IsNull()) {
    ServiceIsolate::SetServerAddress(NULL);
  } else {
    ServiceIsolate::SetServerAddress(address.ToCString());
  }
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_ListenStream, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
  bool result = false;
  if (FLAG_support_service) {
    result = Service::ListenStream(stream_id.ToCString());
  }
  return Bool::Get(result).raw();
}

DEFINE_NATIVE_ENTRY(VMService_CancelStream, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
  if (FLAG_support_service) {
    Service::CancelStream(stream_id.ToCString());
  }
  return Object::null();
}

DEFINE_NATIVE_ENTRY(VMService_RequestAssets, 0) {
  if (!FLAG_support_service) {
    return Object::null();
  }
  return Service::RequestAssets();
}

#ifndef PRODUCT
// TODO(25041): When reading, this class copies out the filenames and contents
// into new buffers. It does this because the lifetime of |bytes| is uncertain.
// If |bytes| is pinned in memory, then we could instead load up
// |filenames_| and |contents_| with pointers into |bytes| without making
// copies.
class TarArchive {
 public:
  TarArchive(uint8_t* bytes, intptr_t bytes_length)
      : rs_(bytes, bytes_length) {}

  void Read() {
    while (HasNext()) {
      char* filename;
      uint8_t* data;
      intptr_t data_length;
      if (Next(&filename, &data, &data_length)) {
        filenames_.Add(filename);
        contents_.Add(data);
        content_lengths_.Add(data_length);
      }
    }
  }

  char* NextFilename() { return filenames_.RemoveLast(); }

  uint8_t* NextContent() { return contents_.RemoveLast(); }

  intptr_t NextContentLength() { return content_lengths_.RemoveLast(); }

  bool HasMore() const { return filenames_.length() > 0; }

  intptr_t Length() const { return filenames_.length(); }

 private:
  enum TarHeaderFields {
    kTarHeaderFilenameOffset = 0,
    kTarHeaderFilenameSize = 100,
    kTarHeaderSizeOffset = 124,
    kTarHeaderSizeSize = 12,
    kTarHeaderTypeOffset = 156,
    kTarHeaderTypeSize = 1,
    kTarHeaderSize = 512,
  };

  enum TarType {
    kTarAregType = '\0',
    kTarRegType = '0',
    kTarLnkType = '1',
    kTarSymType = '2',
    kTarChrType = '3',
    kTarBlkType = '4',
    kTarDirType = '5',
    kTarFifoType = '6',
    kTarContType = '7',
    kTarXhdType = 'x',
    kTarXglType = 'g',
  };

  bool HasNext() const { return !EndOfArchive(); }

  bool Next(char** filename, uint8_t** data, intptr_t* data_length) {
    intptr_t startOfBlock = rs_.Position();
    *filename = ReadFilename();
    rs_.SetPosition(startOfBlock + kTarHeaderSizeOffset);
    intptr_t size = ReadSize();
    rs_.SetPosition(startOfBlock + kTarHeaderTypeOffset);
    TarType type = ReadType();
    SeekToNextBlock(kTarHeaderSize);
    if ((type != kTarRegType) && (type != kTarAregType)) {
      SkipContents(size);
      return false;
    }
    ReadContents(data, size);
    *data_length = size;
    return true;
  }

  void SeekToNextBlock(intptr_t blockSize) {
    intptr_t remainder = blockSize - (rs_.Position() % blockSize);
    rs_.Advance(remainder);
  }

  uint8_t PeekByte(intptr_t i) const {
    return *(rs_.AddressOfCurrentPosition() + i);
  }

  bool EndOfArchive() const {
    if (rs_.PendingBytes() < (kTarHeaderSize * 2)) {
      return true;
    }
    for (intptr_t i = 0; i < (kTarHeaderSize * 2); i++) {
      if (PeekByte(i) != 0) {
        return false;
      }
    }
    return true;
  }

  TarType ReadType() {
    return static_cast<TarType>(ReadStream::Raw<1, uint8_t>::Read(&rs_));
  }

  void SkipContents(intptr_t size) {
    rs_.Advance(size);
    SeekToNextBlock(kTarHeaderSize);
  }

  intptr_t ReadCString(char** s, intptr_t length) {
    intptr_t to_read = Utils::Minimum(length, rs_.PendingBytes());
    char* result = new char[to_read + 1];
    strncpy(result,
            reinterpret_cast<const char*>(rs_.AddressOfCurrentPosition()),
            to_read);
    result[to_read] = '\0';
    rs_.SetPosition(rs_.Position() + to_read);
    *s = result;
    return to_read;
  }

  intptr_t ReadSize() {
    char* octalSize;
    unsigned int size;

    ReadCString(&octalSize, kTarHeaderSizeSize);
    int result = sscanf(octalSize, "%o", &size);
    delete[] octalSize;

    if (result != 1) {
      return 0;
    }
    return size;
  }

  char* ReadFilename() {
    char* result;
    intptr_t result_length = ReadCString(&result, kTarHeaderFilenameSize);
    if (result[0] == '/') {
      return result;
    }
    char* fixed_result = new char[result_length + 2];  // '/' + '\0'.
    fixed_result[0] = '/';
    strncpy(&fixed_result[1], result, result_length);
    fixed_result[result_length + 1] = '\0';
    delete[] result;
    return fixed_result;
  }

  void ReadContents(uint8_t** data, intptr_t size) {
    uint8_t* result = new uint8_t[size];
    rs_.ReadBytes(result, size);
    SeekToNextBlock(kTarHeaderSize);
    *data = result;
  }

  ReadStream rs_;
  GrowableArray<char*> filenames_;
  GrowableArray<uint8_t*> contents_;
  GrowableArray<intptr_t> content_lengths_;

  DISALLOW_COPY_AND_ASSIGN(TarArchive);
};

static void ContentsFinalizer(void* isolate_callback_data,
                              Dart_WeakPersistentHandle handle,
                              void* peer) {
  uint8_t* data = reinterpret_cast<uint8_t*>(peer);
  delete[] data;
}

static void FilenameFinalizer(void* isolate_callback_data,
                              Dart_WeakPersistentHandle handle,
                              void* peer) {
  char* filename = reinterpret_cast<char*>(peer);
  delete[] filename;
}

#endif

DEFINE_NATIVE_ENTRY(VMService_DecodeAssets, 1) {
#ifndef PRODUCT
  if (!FLAG_support_service) {
    return Object::null();
  }
  GET_NON_NULL_NATIVE_ARGUMENT(TypedData, data, arguments->NativeArgAt(0));
  TransitionVMToNative transition(thread);
  Api::Scope scope(thread);

  Dart_Handle data_handle = Api::NewHandle(thread, data.raw());

  Dart_TypedData_Type typ;
  void* bytes;
  intptr_t length;
  Dart_Handle err =
      Dart_TypedDataAcquireData(data_handle, &typ, &bytes, &length);
  ASSERT(!Dart_IsError(err));

  TarArchive archive(reinterpret_cast<uint8_t*>(bytes), length);
  archive.Read();

  err = Dart_TypedDataReleaseData(data_handle);
  ASSERT(!Dart_IsError(err));

  intptr_t archive_size = archive.Length();

  Dart_Handle result_list = Dart_NewList(2 * archive_size);
  ASSERT(!Dart_IsError(result_list));

  intptr_t idx = 0;
  while (archive.HasMore()) {
    char* filename = archive.NextFilename();
    intptr_t filename_length = strlen(filename);
    uint8_t* contents = archive.NextContent();
    intptr_t contents_length = archive.NextContentLength();

    Dart_Handle dart_filename = Dart_NewExternalLatin1String(
        reinterpret_cast<uint8_t*>(filename), filename_length, filename,
        filename_length, FilenameFinalizer);
    ASSERT(!Dart_IsError(dart_filename));

    Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
        Dart_TypedData_kUint8, contents, contents_length, contents,
        contents_length, ContentsFinalizer);
    ASSERT(!Dart_IsError(dart_contents));

    Dart_ListSetAt(result_list, idx, dart_filename);
    Dart_ListSetAt(result_list, (idx + 1), dart_contents);
    idx += 2;
  }
  return Api::UnwrapArrayHandle(thread->zone(), result_list).raw();
#else
  return Object::null();
#endif
}

DEFINE_NATIVE_ENTRY(VMService_spawnUriNotify, 2) {
#ifndef PRODUCT
  if (!FLAG_support_service) {
    return Object::null();
  }
  GET_NON_NULL_NATIVE_ARGUMENT(Instance, result, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(String, token, arguments->NativeArgAt(1));

  if (result.IsSendPort()) {
    Dart_Port id = SendPort::Cast(result).Id();
    Isolate* isolate = PortMap::GetIsolate(id);
    if (isolate != NULL) {
      ServiceEvent spawn_event(isolate, ServiceEvent::kIsolateSpawn);
      spawn_event.set_spawn_token(&token);
      Service::HandleEvent(&spawn_event);
    } else {
      // There is no isolate at the control port anymore.  Must have
      // died already.
      ServiceEvent spawn_event(NULL, ServiceEvent::kIsolateSpawn);
      const String& error = String::Handle(
          String::New("spawned isolate exited before notification completed"));
      spawn_event.set_spawn_token(&token);
      spawn_event.set_spawn_error(&error);
      Service::HandleEvent(&spawn_event);
    }
  } else {
    // The isolate failed to spawn.
    ASSERT(result.IsString());
    ServiceEvent spawn_event(NULL, ServiceEvent::kIsolateSpawn);
    spawn_event.set_spawn_token(&token);
    spawn_event.set_spawn_error(&String::Cast(result));
    Service::HandleEvent(&spawn_event);
  }
#endif  // PRODUCT
  return Object::null();
}

}  // namespace dart
