//===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "GDBRemoteCommunicationServerPlatform.h"

#include <errno.h>

#include <chrono>
#include <csignal>
#include <cstring>
#include <mutex>
#include <sstream>
#include <thread>

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Threading.h"

#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileAction.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "lldb/Utility/UriParser.h"

#include "lldb/Utility/StringExtractorGDBRemote.h"

using namespace lldb;
using namespace lldb_private::process_gdb_remote;
using namespace lldb_private;

GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
                                                       uint16_t max_port) {
  for (; min_port < max_port; ++min_port)
    m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
}

void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
  // Do not modify existing mappings
  m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
}

llvm::Expected<uint16_t>
GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
  if (m_port_map.empty())
    return 0; // Bind to port zero and get a port, we didn't have any
              // limitations

  for (auto &pair : m_port_map) {
    if (pair.second == LLDB_INVALID_PROCESS_ID) {
      pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
      return pair.first;
    }
  }
  return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                 "No free port found in port map");
}

bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
    uint16_t port, lldb::pid_t pid) {
  auto pos = m_port_map.find(port);
  if (pos != m_port_map.end()) {
    pos->second = pid;
    return true;
  }
  return false;
}

bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
  std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
  if (pos != m_port_map.end()) {
    pos->second = LLDB_INVALID_PROCESS_ID;
    return true;
  }
  return false;
}

bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
    lldb::pid_t pid) {
  if (!m_port_map.empty()) {
    for (auto &pair : m_port_map) {
      if (pair.second == pid) {
        pair.second = LLDB_INVALID_PROCESS_ID;
        return true;
      }
    }
  }
  return false;
}

bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
  return m_port_map.empty();
}

// GDBRemoteCommunicationServerPlatform constructor
GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
    const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
    : GDBRemoteCommunicationServerCommon("gdb-remote.server",
                                         "gdb-remote.server.rx_packet"),
      m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
      m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
  m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
  m_pending_gdb_server.port = 0;

  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qC,
      &GDBRemoteCommunicationServerPlatform::Handle_qC);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
      &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
      &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
      &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
      &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
      &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_qPathComplete,
      &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
      &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
  RegisterMemberFunctionHandler(
      StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
      &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);

  RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
                        [](StringExtractorGDBRemote packet, Status &error,
                           bool &interrupt, bool &quit) {
                          error.SetErrorString("interrupt received");
                          interrupt = true;
                          return PacketResult::Success;
                        });
}

// Destructor
GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}

Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
    const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
    llvm::Optional<uint16_t> &port, std::string &socket_name) {
  if (!port) {
    llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
    if (available_port)
      port = *available_port;
    else
      return Status(available_port.takeError());
  }

  // Spawn a new thread to accept the port that gets bound after binding to
  // port 0 (zero).

  // ignore the hostname send from the remote end, just use the ip address that
  // we're currently communicating with as the hostname

  // Spawn a debugserver and try to get the port it listens to.
  ProcessLaunchInfo debugserver_launch_info;
  if (hostname.empty())
    hostname = "127.0.0.1";

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
  LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
            *port);

  // Do not run in a new session so that it can not linger after the platform
  // closes.
  debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
  debugserver_launch_info.SetMonitorProcessCallback(
      std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
                this, std::placeholders::_1),
      false);

  std::ostringstream url;
// debugserver does not accept the URL scheme prefix.
#if !defined(__APPLE__)
  url << m_socket_scheme << "://";
#endif
  uint16_t *port_ptr = port.getPointer();
  if (m_socket_protocol == Socket::ProtocolTcp) {
    llvm::StringRef platform_scheme;
    llvm::StringRef platform_ip;
    int platform_port;
    llvm::StringRef platform_path;
    std::string platform_uri = GetConnection()->GetURI();
    bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
                               platform_port, platform_path);
    UNUSED_IF_ASSERT_DISABLED(ok);
    assert(ok);
    url << '[' << platform_ip.str() << "]:" << *port;
  } else {
    socket_name = GetDomainSocketPath("gdbserver").GetPath();
    url << socket_name;
    port_ptr = nullptr;
  }

  Status error = StartDebugserverProcess(
      url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);

  pid = debugserver_launch_info.GetProcessID();
  if (pid != LLDB_INVALID_PROCESS_ID) {
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    m_spawned_pids.insert(pid);
    if (*port > 0)
      m_port_map.AssociatePortWithProcess(*port, pid);
  } else {
    if (*port > 0)
      m_port_map.FreePort(*port);
  }
  return error;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
    StringExtractorGDBRemote &packet) {
  // Spawn a local debugserver as a platform so we can then attach or launch a
  // process...

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
  LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
            __FUNCTION__);

  ConnectionFileDescriptor file_conn;
  std::string hostname;
  packet.SetFilePos(::strlen("qLaunchGDBServer;"));
  llvm::StringRef name;
  llvm::StringRef value;
  llvm::Optional<uint16_t> port;
  while (packet.GetNameColonValue(name, value)) {
    if (name.equals("host"))
      hostname = std::string(value);
    else if (name.equals("port")) {
      // Make the Optional valid so we can use its value
      port = 0;
      value.getAsInteger(0, port.getValue());
    }
  }

  lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
  std::string socket_name;
  Status error =
      LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "GDBRemoteCommunicationServerPlatform::%s() debugserver "
              "launch failed: %s",
              __FUNCTION__, error.AsCString());
    return SendErrorResponse(9);
  }

  LLDB_LOGF(log,
            "GDBRemoteCommunicationServerPlatform::%s() debugserver "
            "launched successfully as pid %" PRIu64,
            __FUNCTION__, debugserver_pid);

  StreamGDBRemote response;
  assert(port);
  response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
                  *port + m_port_offset);
  if (!socket_name.empty()) {
    response.PutCString("socket_name:");
    response.PutStringAsRawHex8(socket_name);
    response.PutChar(';');
  }

  PacketResult packet_result = SendPacketNoLock(response.GetString());
  if (packet_result != PacketResult::Success) {
    if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
      Host::Kill(debugserver_pid, SIGINT);
  }
  return packet_result;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
    StringExtractorGDBRemote &packet) {
  namespace json = llvm::json;

  if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
    return SendErrorResponse(4);

  json::Object server{{"port", m_pending_gdb_server.port}};

  if (!m_pending_gdb_server.socket_name.empty())
    server.try_emplace("socket_name", m_pending_gdb_server.socket_name);

  json::Array server_list;
  server_list.push_back(std::move(server));

  StreamGDBRemote response;
  response.AsRawOstream() << std::move(server_list);

  StreamGDBRemote escaped_response;
  escaped_response.PutEscapedBytes(response.GetString().data(),
                                   response.GetSize());
  return SendPacketNoLock(escaped_response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("qKillSpawnedProcess:"));

  lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);

  // verify that we know anything about this pid. Scope for locker
  {
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
      // not a pid we know about
      return SendErrorResponse(10);
    }
  }

  // go ahead and attempt to kill the spawned process
  if (KillSpawnedProcess(pid))
    return SendOKResponse();
  else
    return SendErrorResponse(11);
}

bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
  // make sure we know about this process
  {
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
      return false;
  }

  // first try a SIGTERM (standard kill)
  Host::Kill(pid, SIGTERM);

  // check if that worked
  for (size_t i = 0; i < 10; ++i) {
    {
      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
        // it is now killed
        return true;
      }
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  {
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
      return true;
  }

  // the launched process still lives.  Now try killing it again, this time
  // with an unblockable signal.
  Host::Kill(pid, SIGKILL);

  for (size_t i = 0; i < 10; ++i) {
    {
      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
        // it is now killed
        return true;
      }
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  // check one more time after the final sleep
  {
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
      return true;
  }

  // no luck - the process still lives
  return false;
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
    StringExtractorGDBRemote &packet) {
  lldb::pid_t pid = m_process_launch_info.GetProcessID();
  m_process_launch_info.Clear();

  if (pid == LLDB_INVALID_PROCESS_ID)
    return SendErrorResponse(1);

  ProcessInstanceInfo proc_info;
  if (!Host::GetProcessInfo(pid, proc_info))
    return SendErrorResponse(1);

  StreamString response;
  CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("qPathComplete:"));
  const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
  if (packet.GetChar() != ',')
    return SendErrorResponse(85);
  std::string path;
  packet.GetHexByteString(path);

  StringList matches;
  StandardTildeExpressionResolver resolver;
  if (only_dir)
    CommandCompletions::DiskDirectories(path, matches, resolver);
  else
    CommandCompletions::DiskFiles(path, matches, resolver);

  StreamString response;
  response.PutChar('M');
  llvm::StringRef separator;
  std::sort(matches.begin(), matches.end());
  for (const auto &match : matches) {
    response << separator;
    separator = ",";
    // encode result strings into hex bytes to avoid unexpected error caused by
    // special characters like '$'.
    response.PutStringAsRawHex8(match.c_str());
  }

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
    StringExtractorGDBRemote &packet) {

  llvm::SmallString<64> cwd;
  if (std::error_code ec = llvm::sys::fs::current_path(cwd))
    return SendErrorResponse(ec.value());

  StreamString response;
  response.PutBytesAsRawHex8(cwd.data(), cwd.size());
  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
    StringExtractorGDBRemote &packet) {
  packet.SetFilePos(::strlen("QSetWorkingDir:"));
  std::string path;
  packet.GetHexByteString(path);

  if (std::error_code ec = llvm::sys::fs::set_current_path(path))
    return SendErrorResponse(ec.value());
  return SendOKResponse();
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qC(
    StringExtractorGDBRemote &packet) {
  // NOTE: lldb should now be using qProcessInfo for process IDs.  This path
  // here
  // should not be used.  It is reporting process id instead of thread id.  The
  // correct answer doesn't seem to make much sense for lldb-platform.
  // CONSIDER: flip to "unsupported".
  lldb::pid_t pid = m_process_launch_info.GetProcessID();

  StreamString response;
  response.Printf("QC%" PRIx64, pid);

  // If we launch a process and this GDB server is acting as a platform, then
  // we need to clear the process launch state so we can start launching
  // another process. In order to launch a process a bunch or packets need to
  // be sent: environment packets, working directory, disable ASLR, and many
  // more settings. When we launch a process we then need to know when to clear
  // this information. Currently we are selecting the 'qC' packet as that
  // packet which seems to make the most sense.
  if (pid != LLDB_INVALID_PROCESS_ID) {
    m_process_launch_info.Clear();
  }

  return SendPacketNoLock(response.GetString());
}

GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
    StringExtractorGDBRemote &packet) {
  StructuredData::Array signal_array;

  lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
  for (auto signo = signals->GetFirstSignalNumber();
       signo != LLDB_INVALID_SIGNAL_NUMBER;
       signo = signals->GetNextSignalNumber(signo)) {
    auto dictionary = std::make_shared<StructuredData::Dictionary>();

    dictionary->AddIntegerItem("signo", signo);
    dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));

    bool suppress, stop, notify;
    signals->GetSignalInfo(signo, suppress, stop, notify);
    dictionary->AddBooleanItem("suppress", suppress);
    dictionary->AddBooleanItem("stop", stop);
    dictionary->AddBooleanItem("notify", notify);

    signal_array.Push(dictionary);
  }

  StreamString response;
  signal_array.Dump(response);
  return SendPacketNoLock(response.GetString());
}

bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
    lldb::pid_t pid) {
  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
  m_port_map.FreePortForProcess(pid);
  m_spawned_pids.erase(pid);
  return true;
}

Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
  if (!m_process_launch_info.GetArguments().GetArgumentCount())
    return Status("%s: no process command line specified to launch",
                  __FUNCTION__);

  // specify the process monitor if not already set.  This should generally be
  // what happens since we need to reap started processes.
  if (!m_process_launch_info.GetMonitorProcessCallback())
    m_process_launch_info.SetMonitorProcessCallback(
        std::bind(
            &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
            this, std::placeholders::_1),
        false);

  Status error = Host::LaunchProcess(m_process_launch_info);
  if (!error.Success()) {
    fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
            m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
    return error;
  }

  printf("Launched '%s' as process %" PRIu64 "...\n",
         m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
         m_process_launch_info.GetProcessID());

  // add to list of spawned processes.  On an lldb-gdbserver, we would expect
  // there to be only one.
  const auto pid = m_process_launch_info.GetProcessID();
  if (pid != LLDB_INVALID_PROCESS_ID) {
    // add to spawned pids
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
    m_spawned_pids.insert(pid);
  }

  return error;
}

void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
  m_port_map = port_map;
}

const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
  static FileSpec g_domainsocket_dir;
  static llvm::once_flag g_once_flag;

  llvm::call_once(g_once_flag, []() {
    const char *domainsocket_dir_env =
        ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
    if (domainsocket_dir_env != nullptr)
      g_domainsocket_dir = FileSpec(domainsocket_dir_env);
    else
      g_domainsocket_dir = HostInfo::GetProcessTempDir();
  });

  return g_domainsocket_dir;
}

FileSpec
GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
  llvm::SmallString<128> socket_path;
  llvm::SmallString<128> socket_name(
      (llvm::StringRef(prefix) + ".%%%%%%").str());

  FileSpec socket_path_spec(GetDomainSocketDir());
  socket_path_spec.AppendPathComponent(socket_name.c_str());

  llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
  return FileSpec(socket_path.c_str());
}

void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
  m_port_offset = port_offset;
}

void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
    lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
  m_pending_gdb_server.pid = pid;
  m_pending_gdb_server.port = port;
  m_pending_gdb_server.socket_name = socket_name;
}
