// 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/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);

static uint8_t* malloc_allocator(uint8_t* ptr,
                                 intptr_t old_size,
                                 intptr_t new_size) {
  void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
  return reinterpret_cast<uint8_t*>(new_ptr);
}

static void malloc_deallocator(uint8_t* ptr) {
  free(reinterpret_cast<void*>(ptr));
}


#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) or the vm-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::Print("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.
  uint8_t* data = NULL;
  MessageWriter writer(&data, &malloc_allocator, &malloc_deallocator, false);
  writer.WriteMessage(message);

  // TODO(turnidge): Throw an exception when the return value is false?
  bool result = PortMap::PostMessage(
      new Message(sp.Id(), data, writer.BytesWritten(), 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) {
    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) {
    Service::HandleObjectRootMessage(message);
  }
  return Object::null();
}


DEFINE_NATIVE_ENTRY(VMService_OnStart, 0) {
  if (FLAG_trace_service) {
    OS::Print("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::Print("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::Print("vm-service: processed exit message.\n");
    MessageHandler* message_handler = isolate->message_handler();
    OS::Print("vm-service: live ports = %" Pd "\n",
              message_handler->live_ports());
  }
  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* 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();
    uint8_t* contents = archive.NextContent();
    intptr_t contents_length = archive.NextContentLength();

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

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

    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
