// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SRC_NODE_INTERNALS_H_
#define SRC_NODE_INTERNALS_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "env.h"
#include "node.h"
#include "node_binding.h"
#include "node_mutex.h"
#include "tracing/trace_event.h"
#include "util.h"
#include "uv.h"
#include "v8.h"

#include <cstdint>
#include <cstdlib>

#include <string>
#include <vector>

struct sockaddr;

namespace node {

namespace native_module {
class NativeModuleLoader;
}

namespace per_process {
extern Mutex env_var_mutex;
extern uint64_t node_start_time;
}  // namespace per_process

// Forward declaration
class Environment;

// Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object.
// Sets address and port properties on the info object and returns it.
// If |info| is omitted, a new object is returned.
v8::MaybeLocal<v8::Object> AddressToJS(
    Environment* env,
    const sockaddr* addr,
    v8::Local<v8::Object> info = v8::Local<v8::Object>());

template <typename T, int (*F)(const typename T::HandleType*, sockaddr*, int*)>
void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>& args) {
  T* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap,
                          args.Holder(),
                          args.GetReturnValue().Set(UV_EBADF));
  CHECK(args[0]->IsObject());
  sockaddr_storage storage;
  int addrlen = sizeof(storage);
  sockaddr* const addr = reinterpret_cast<sockaddr*>(&storage);
  const int err = F(&wrap->handle_, addr, &addrlen);
  if (err == 0)
    AddressToJS(wrap->env(), addr, args[0].As<v8::Object>());
  args.GetReturnValue().Set(err);
}

void PrintStackTrace(v8::Isolate* isolate, v8::Local<v8::StackTrace> stack);
void PrintCaughtException(v8::Isolate* isolate,
                          v8::Local<v8::Context> context,
                          const v8::TryCatch& try_catch);

void ResetStdio();  // Safe to call more than once and from signal handlers.
#ifdef __POSIX__
void SignalExit(int signal, siginfo_t* info, void* ucontext);
#endif

std::string GetProcessTitle(const char* default_title);
std::string GetHumanReadableProcessName();

v8::Maybe<bool> InitializeContextRuntime(v8::Local<v8::Context> context);
v8::Maybe<bool> InitializePrimordials(v8::Local<v8::Context> context);

class NodeArrayBufferAllocator : public ArrayBufferAllocator {
 public:
  inline uint32_t* zero_fill_field() { return &zero_fill_field_; }

  void* Allocate(size_t size) override;  // Defined in src/node.cc
  void* AllocateUninitialized(size_t size) override;
  void Free(void* data, size_t size) override;
  void* Reallocate(void* data, size_t old_size, size_t size) override;
  virtual void RegisterPointer(void* data, size_t size) {
    total_mem_usage_.fetch_add(size, std::memory_order_relaxed);
  }
  virtual void UnregisterPointer(void* data, size_t size) {
    total_mem_usage_.fetch_sub(size, std::memory_order_relaxed);
  }

  NodeArrayBufferAllocator* GetImpl() final { return this; }
  inline uint64_t total_mem_usage() const {
    return total_mem_usage_.load(std::memory_order_relaxed);
  }

 private:
  uint32_t zero_fill_field_ = 1;  // Boolean but exposed as uint32 to JS land.
  std::atomic<size_t> total_mem_usage_ {0};

  // Delegate to V8's allocator for compatibility with the V8 memory cage.
  std::unique_ptr<v8::ArrayBuffer::Allocator> allocator_{
      v8::ArrayBuffer::Allocator::NewDefaultAllocator()};
};

class DebuggingArrayBufferAllocator final : public NodeArrayBufferAllocator {
 public:
  ~DebuggingArrayBufferAllocator() override;
  void* Allocate(size_t size) override;
  void* AllocateUninitialized(size_t size) override;
  void Free(void* data, size_t size) override;
  void* Reallocate(void* data, size_t old_size, size_t size) override;
  void RegisterPointer(void* data, size_t size) override;
  void UnregisterPointer(void* data, size_t size) override;

 private:
  void RegisterPointerInternal(void* data, size_t size);
  void UnregisterPointerInternal(void* data, size_t size);
  Mutex mutex_;
  std::unordered_map<void*, size_t> allocations_;
};

namespace Buffer {
v8::MaybeLocal<v8::Object> Copy(Environment* env, const char* data, size_t len);
v8::MaybeLocal<v8::Object> New(Environment* env, size_t size);
// Takes ownership of |data|.
v8::MaybeLocal<v8::Object> New(Environment* env,
                               char* data,
                               size_t length,
                               void (*callback)(char* data, void* hint),
                               void* hint);
// Takes ownership of |data|.  Must allocate |data| with the current Isolate's
// ArrayBuffer::Allocator().
v8::MaybeLocal<v8::Object> New(Environment* env,
                               char* data,
                               size_t length);
// Creates a Buffer instance over an existing ArrayBuffer.
v8::MaybeLocal<v8::Uint8Array> New(Environment* env,
                                   v8::Local<v8::ArrayBuffer> ab,
                                   size_t byte_offset,
                                   size_t length);
// Construct a Buffer from a MaybeStackBuffer (and also its subclasses like
// Utf8Value and TwoByteValue).
// If |buf| is invalidated, an empty MaybeLocal is returned, and nothing is
// changed.
// If |buf| contains actual data, this method takes ownership of |buf|'s
// underlying buffer. However, |buf| itself can be reused even after this call,
// but its capacity, if increased through AllocateSufficientStorage, is not
// guaranteed to stay the same.
template <typename T>
static v8::MaybeLocal<v8::Object> New(Environment* env,
                                      MaybeStackBuffer<T>* buf) {
  v8::MaybeLocal<v8::Object> ret;
  char* src = reinterpret_cast<char*>(buf->out());
  const size_t len_in_bytes = buf->length() * sizeof(buf->out()[0]);

  if (buf->IsAllocated())
    ret = New(env, src, len_in_bytes);
  else if (!buf->IsInvalidated())
    ret = Copy(env, src, len_in_bytes);

  if (ret.IsEmpty())
    return ret;

  if (buf->IsAllocated())
    buf->Release();

  return ret;
}
}  // namespace Buffer

v8::MaybeLocal<v8::Value> InternalMakeCallback(
    Environment* env,
    v8::Local<v8::Object> resource,
    v8::Local<v8::Object> recv,
    const v8::Local<v8::Function> callback,
    int argc,
    v8::Local<v8::Value> argv[],
    async_context asyncContext);

v8::MaybeLocal<v8::Value> MakeSyncCallback(v8::Isolate* isolate,
                                           v8::Local<v8::Object> recv,
                                           v8::Local<v8::Function> callback,
                                           int argc,
                                           v8::Local<v8::Value> argv[]);

class InternalCallbackScope {
 public:
  enum Flags {
    kNoFlags = 0,
    // Indicates whether 'before' and 'after' hooks should be skipped.
    kSkipAsyncHooks = 1,
    // Indicates whether nextTick and microtask queues should be skipped.
    // This should only be used when there is no call into JS in this scope.
    // (The HTTP parser also uses it for some weird backwards
    // compatibility issues, but it shouldn't.)
    kSkipTaskQueues = 2
  };
  InternalCallbackScope(Environment* env,
                        v8::Local<v8::Object> object,
                        const async_context& asyncContext,
                        int flags = kNoFlags);
  // Utility that can be used by AsyncWrap classes.
  explicit InternalCallbackScope(AsyncWrap* async_wrap, int flags = 0);
  ~InternalCallbackScope();
  void Close();

  inline bool Failed() const { return failed_; }
  inline void MarkAsFailed() { failed_ = true; }

 private:
  Environment* env_;
  async_context async_context_;
  v8::Local<v8::Object> object_;
  bool skip_hooks_;
  bool skip_task_queues_;
  bool failed_ = false;
  bool pushed_ids_ = false;
  bool closed_ = false;
};

class DebugSealHandleScope {
 public:
  explicit inline DebugSealHandleScope(v8::Isolate* isolate = nullptr)
#ifdef DEBUG
    : actual_scope_(isolate != nullptr ? isolate : v8::Isolate::GetCurrent())
#endif
  {}

 private:
#ifdef DEBUG
  v8::SealHandleScope actual_scope_;
#endif
};

class ThreadPoolWork {
 public:
  explicit inline ThreadPoolWork(Environment* env) : env_(env) {
    CHECK_NOT_NULL(env);
  }
  inline virtual ~ThreadPoolWork() = default;

  inline void ScheduleWork();
  inline int CancelWork();

  virtual void DoThreadPoolWork() = 0;
  virtual void AfterThreadPoolWork(int status) = 0;

  Environment* env() const { return env_; }

 private:
  Environment* env_;
  uv_work_t work_req_;
};

#define TRACING_CATEGORY_NODE "node"
#define TRACING_CATEGORY_NODE1(one)                                           \
    TRACING_CATEGORY_NODE ","                                                 \
    TRACING_CATEGORY_NODE "." #one
#define TRACING_CATEGORY_NODE2(one, two)                                      \
    TRACING_CATEGORY_NODE ","                                                 \
    TRACING_CATEGORY_NODE "." #one ","                                        \
    TRACING_CATEGORY_NODE "." #one "." #two

// Functions defined in node.cc that are exposed via the bootstrapper object

#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
#define NODE_IMPLEMENTS_POSIX_CREDENTIALS 1
#endif  // defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)

namespace credentials {
bool SafeGetenv(const char* key,
                std::string* text,
                std::shared_ptr<KVStore> env_vars = nullptr,
                v8::Isolate* isolate = nullptr);
}  // namespace credentials

void DefineZlibConstants(v8::Local<v8::Object> target);
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
                        uv_loop_t* event_loop,
                        MultiIsolatePlatform* platform);
// This overload automatically picks the right 'main_script_id' if no callback
// was provided by the embedder.
v8::MaybeLocal<v8::Value> StartExecution(Environment* env,
                                         StartExecutionCallback cb = nullptr);
v8::MaybeLocal<v8::Object> GetPerContextExports(v8::Local<v8::Context> context);
v8::MaybeLocal<v8::Value> ExecuteBootstrapper(
    Environment* env,
    const char* id,
    std::vector<v8::Local<v8::Value>>* arguments);
void MarkBootstrapComplete(const v8::FunctionCallbackInfo<v8::Value>& args);

class InitializationResultImpl final : public InitializationResult {
 public:
  ~InitializationResultImpl();
  int exit_code() const { return exit_code_; }
  bool early_return() const { return early_return_; }
  const std::vector<std::string>& args() const { return args_; }
  const std::vector<std::string>& exec_args() const { return exec_args_; }
  const std::vector<std::string>& errors() const { return errors_; }
  MultiIsolatePlatform* platform() const { return platform_; }

  int exit_code_ = 0;
  std::vector<std::string> args_;
  std::vector<std::string> exec_args_;
  std::vector<std::string> errors_;
  bool early_return_ = false;
  MultiIsolatePlatform* platform_ = nullptr;
};

void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s);
void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s);
void SetIsolateCreateParamsForNode(v8::Isolate::CreateParams* params);

#if HAVE_INSPECTOR
namespace profiler {
void StartProfilers(Environment* env);
}
#endif  // HAVE_INSPECTOR

#ifdef __POSIX__
static constexpr unsigned kMaxSignal = 32;
#endif

bool HasSignalJSHandler(int signum);

#ifdef _WIN32
typedef SYSTEMTIME TIME_TYPE;
#else  // UNIX, OSX
typedef struct tm TIME_TYPE;
#endif

double GetCurrentTimeInMicroseconds();
int WriteFileSync(const char* path, uv_buf_t buf);
int WriteFileSync(v8::Isolate* isolate,
                  const char* path,
                  v8::Local<v8::String> string);

class DiagnosticFilename {
 public:
  static void LocalTime(TIME_TYPE* tm_struct);

  inline DiagnosticFilename(Environment* env,
                            const char* prefix,
                            const char* ext);

  inline DiagnosticFilename(uint64_t thread_id,
                            const char* prefix,
                            const char* ext);

  inline const char* operator*() const;

 private:
  static std::string MakeFilename(
      uint64_t thread_id,
      const char* prefix,
      const char* ext);

  std::string filename_;
};

namespace heap {
v8::Maybe<void> WriteSnapshot(Environment* env, const char* filename);
}

namespace heap {

void DeleteHeapSnapshot(const v8::HeapSnapshot* snapshot);
using HeapSnapshotPointer =
  DeleteFnPtr<const v8::HeapSnapshot, DeleteHeapSnapshot>;

BaseObjectPtr<AsyncWrap> CreateHeapSnapshotStream(
    Environment* env, HeapSnapshotPointer&& snapshot);
}  // namespace heap

namespace fs {
std::string Basename(const std::string& str, const std::string& extension);
}  // namespace fs

node_module napi_module_to_node_module(const napi_module* mod);

std::ostream& operator<<(std::ostream& output,
                         const std::vector<SnapshotIndex>& v);
std::ostream& operator<<(std::ostream& output,
                         const std::vector<std::string>& vec);
std::ostream& operator<<(std::ostream& output,
                         const std::vector<PropInfo>& vec);
std::ostream& operator<<(std::ostream& output, const PropInfo& d);
std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& d);
std::ostream& operator<<(std::ostream& output,
                         const ImmediateInfo::SerializeInfo& d);
std::ostream& operator<<(std::ostream& output,
                         const TickInfo::SerializeInfo& d);
std::ostream& operator<<(std::ostream& output,
                         const AsyncHooks::SerializeInfo& d);

namespace performance {
std::ostream& operator<<(std::ostream& output,
                         const PerformanceState::SerializeInfo& d);
}

bool linux_at_secure();
}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_INTERNALS_H_
