11cb0ef41Sopenharmony_ci#include "inspector_socket_server.h"
21cb0ef41Sopenharmony_ci#include <unistd.h>
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci#include "node.h"
51cb0ef41Sopenharmony_ci#include "util-inl.h"
61cb0ef41Sopenharmony_ci#include "uv.h"
71cb0ef41Sopenharmony_ci#include "zlib.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include <algorithm>
101cb0ef41Sopenharmony_ci#include <cstdio>
111cb0ef41Sopenharmony_ci#include <iostream>
121cb0ef41Sopenharmony_ci#include <map>
131cb0ef41Sopenharmony_ci#include <set>
141cb0ef41Sopenharmony_ci#include <sstream>
151cb0ef41Sopenharmony_ci#include <string>
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace node {
181cb0ef41Sopenharmony_cinamespace inspector {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Function is declared in inspector_io.h so the rest of the node does not
211cb0ef41Sopenharmony_ci// depend on inspector_socket_server.h
221cb0ef41Sopenharmony_cistd::string FormatWsAddress(const std::string& host, int port,
231cb0ef41Sopenharmony_ci                            const std::string& target_id,
241cb0ef41Sopenharmony_ci                            bool include_protocol);
251cb0ef41Sopenharmony_cinamespace {
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cistatic const uint8_t PROTOCOL_JSON[] = {
281cb0ef41Sopenharmony_ci  #include "v8_inspector_protocol_json.h"  // NOLINT(build/include_order)
291cb0ef41Sopenharmony_ci};
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_civoid Escape(std::string* string) {
321cb0ef41Sopenharmony_ci  for (char& c : *string) {
331cb0ef41Sopenharmony_ci    c = (c == '\"' || c == '\\') ? '_' : c;
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cistd::string FormatHostPort(const std::string& host, int port) {
381cb0ef41Sopenharmony_ci  // Host is valid (socket was bound) so colon means it's a v6 IP address
391cb0ef41Sopenharmony_ci  bool v6 = host.find(':') != std::string::npos;
401cb0ef41Sopenharmony_ci  std::ostringstream url;
411cb0ef41Sopenharmony_ci  if (v6) {
421cb0ef41Sopenharmony_ci    url << '[';
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci  url << host;
451cb0ef41Sopenharmony_ci  if (v6) {
461cb0ef41Sopenharmony_ci    url << ']';
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci  url << ':' << port;
491cb0ef41Sopenharmony_ci  return url.str();
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cistd::string FormatAddress(const std::string& host,
531cb0ef41Sopenharmony_ci                          const std::string& target_id,
541cb0ef41Sopenharmony_ci                          bool include_protocol) {
551cb0ef41Sopenharmony_ci  std::ostringstream url;
561cb0ef41Sopenharmony_ci  if (include_protocol)
571cb0ef41Sopenharmony_ci    url << "ws://";
581cb0ef41Sopenharmony_ci  url << host << '/' << target_id;
591cb0ef41Sopenharmony_ci  return url.str();
601cb0ef41Sopenharmony_ci}
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_cistd::string MapToString(const std::map<std::string, std::string>& object) {
631cb0ef41Sopenharmony_ci  bool first = true;
641cb0ef41Sopenharmony_ci  std::ostringstream json;
651cb0ef41Sopenharmony_ci  json << "{\n";
661cb0ef41Sopenharmony_ci  for (const auto& name_value : object) {
671cb0ef41Sopenharmony_ci    if (!first)
681cb0ef41Sopenharmony_ci      json << ",\n";
691cb0ef41Sopenharmony_ci    first = false;
701cb0ef41Sopenharmony_ci    json << "  \"" << name_value.first << "\": \"";
711cb0ef41Sopenharmony_ci    json << name_value.second << "\"";
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci  json << "\n} ";
741cb0ef41Sopenharmony_ci  return json.str();
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_cistd::string MapsToString(
781cb0ef41Sopenharmony_ci    const std::vector<std::map<std::string, std::string>>& array) {
791cb0ef41Sopenharmony_ci  bool first = true;
801cb0ef41Sopenharmony_ci  std::ostringstream json;
811cb0ef41Sopenharmony_ci  json << "[ ";
821cb0ef41Sopenharmony_ci  for (const auto& object : array) {
831cb0ef41Sopenharmony_ci    if (!first)
841cb0ef41Sopenharmony_ci      json << ", ";
851cb0ef41Sopenharmony_ci    first = false;
861cb0ef41Sopenharmony_ci    json << MapToString(object);
871cb0ef41Sopenharmony_ci  }
881cb0ef41Sopenharmony_ci  json << "]\n\n";
891cb0ef41Sopenharmony_ci  return json.str();
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ciconst char* MatchPathSegment(const char* path, const char* expected) {
931cb0ef41Sopenharmony_ci  size_t len = strlen(expected);
941cb0ef41Sopenharmony_ci  if (StringEqualNoCaseN(path, expected, len)) {
951cb0ef41Sopenharmony_ci    if (path[len] == '/') return path + len + 1;
961cb0ef41Sopenharmony_ci    if (path[len] == '\0') return path + len;
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  return nullptr;
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_civoid SendHttpResponse(InspectorSocket* socket,
1021cb0ef41Sopenharmony_ci                      const std::string& response,
1031cb0ef41Sopenharmony_ci                      int code) {
1041cb0ef41Sopenharmony_ci  const char HEADERS[] = "HTTP/1.0 %d OK\r\n"
1051cb0ef41Sopenharmony_ci                         "Content-Type: application/json; charset=UTF-8\r\n"
1061cb0ef41Sopenharmony_ci                         "Cache-Control: no-cache\r\n"
1071cb0ef41Sopenharmony_ci                         "Content-Length: %zu\r\n"
1081cb0ef41Sopenharmony_ci                         "\r\n";
1091cb0ef41Sopenharmony_ci  char header[sizeof(HEADERS) + 20];
1101cb0ef41Sopenharmony_ci  int header_len = snprintf(header,
1111cb0ef41Sopenharmony_ci                            sizeof(header),
1121cb0ef41Sopenharmony_ci                            HEADERS,
1131cb0ef41Sopenharmony_ci                            code,
1141cb0ef41Sopenharmony_ci                            response.size());
1151cb0ef41Sopenharmony_ci  socket->Write(header, header_len);
1161cb0ef41Sopenharmony_ci  socket->Write(response.data(), response.size());
1171cb0ef41Sopenharmony_ci}
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_civoid SendVersionResponse(InspectorSocket* socket) {
1201cb0ef41Sopenharmony_ci  std::map<std::string, std::string> response;
1211cb0ef41Sopenharmony_ci  response["Browser"] = "node.js/" NODE_VERSION;
1221cb0ef41Sopenharmony_ci  response["Protocol-Version"] = "1.1";
1231cb0ef41Sopenharmony_ci  SendHttpResponse(socket, MapToString(response), 200);
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_civoid SendHttpNotFound(InspectorSocket* socket) {
1271cb0ef41Sopenharmony_ci  SendHttpResponse(socket, "", 404);
1281cb0ef41Sopenharmony_ci}
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_civoid SendProtocolJson(InspectorSocket* socket) {
1311cb0ef41Sopenharmony_ci  z_stream strm;
1321cb0ef41Sopenharmony_ci  strm.zalloc = Z_NULL;
1331cb0ef41Sopenharmony_ci  strm.zfree = Z_NULL;
1341cb0ef41Sopenharmony_ci  strm.opaque = Z_NULL;
1351cb0ef41Sopenharmony_ci  CHECK_EQ(Z_OK, inflateInit(&strm));
1361cb0ef41Sopenharmony_ci  static const size_t kDecompressedSize =
1371cb0ef41Sopenharmony_ci      PROTOCOL_JSON[0] * 0x10000u +
1381cb0ef41Sopenharmony_ci      PROTOCOL_JSON[1] * 0x100u +
1391cb0ef41Sopenharmony_ci      PROTOCOL_JSON[2];
1401cb0ef41Sopenharmony_ci  strm.next_in = const_cast<uint8_t*>(PROTOCOL_JSON + 3);
1411cb0ef41Sopenharmony_ci  strm.avail_in = sizeof(PROTOCOL_JSON) - 3;
1421cb0ef41Sopenharmony_ci  std::string data(kDecompressedSize, '\0');
1431cb0ef41Sopenharmony_ci  strm.next_out = reinterpret_cast<Byte*>(data.data());
1441cb0ef41Sopenharmony_ci  strm.avail_out = data.size();
1451cb0ef41Sopenharmony_ci  CHECK_EQ(Z_STREAM_END, inflate(&strm, Z_FINISH));
1461cb0ef41Sopenharmony_ci  CHECK_EQ(0, strm.avail_out);
1471cb0ef41Sopenharmony_ci  CHECK_EQ(Z_OK, inflateEnd(&strm));
1481cb0ef41Sopenharmony_ci  SendHttpResponse(socket, data, 200);
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci}  // namespace
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cistd::string FormatWsAddress(const std::string& host, int port,
1531cb0ef41Sopenharmony_ci                            const std::string& target_id,
1541cb0ef41Sopenharmony_ci                            bool include_protocol) {
1551cb0ef41Sopenharmony_ci  return FormatAddress(FormatHostPort(host, port), target_id, include_protocol);
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciclass SocketSession {
1591cb0ef41Sopenharmony_ci public:
1601cb0ef41Sopenharmony_ci  SocketSession(InspectorSocketServer* server, int id, int server_port);
1611cb0ef41Sopenharmony_ci  void Close() {
1621cb0ef41Sopenharmony_ci    ws_socket_.reset();
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci  void Send(const std::string& message);
1651cb0ef41Sopenharmony_ci  void Own(InspectorSocket::Pointer ws_socket) {
1661cb0ef41Sopenharmony_ci    ws_socket_ = std::move(ws_socket);
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci  int id() const { return id_; }
1691cb0ef41Sopenharmony_ci  int server_port() {
1701cb0ef41Sopenharmony_ci    return server_port_;
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci  InspectorSocket* ws_socket() {
1731cb0ef41Sopenharmony_ci    return ws_socket_.get();
1741cb0ef41Sopenharmony_ci  }
1751cb0ef41Sopenharmony_ci  void Accept(const std::string& ws_key) {
1761cb0ef41Sopenharmony_ci    ws_socket_->AcceptUpgrade(ws_key);
1771cb0ef41Sopenharmony_ci  }
1781cb0ef41Sopenharmony_ci  void Decline() {
1791cb0ef41Sopenharmony_ci    ws_socket_->CancelHandshake();
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  class Delegate : public InspectorSocket::Delegate {
1831cb0ef41Sopenharmony_ci   public:
1841cb0ef41Sopenharmony_ci    Delegate(InspectorSocketServer* server, int session_id)
1851cb0ef41Sopenharmony_ci             : server_(server), session_id_(session_id) { }
1861cb0ef41Sopenharmony_ci    ~Delegate() override {
1871cb0ef41Sopenharmony_ci      server_->SessionTerminated(session_id_);
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci    void OnHttpGet(const std::string& host, const std::string& path) override;
1901cb0ef41Sopenharmony_ci    void OnSocketUpgrade(const std::string& host, const std::string& path,
1911cb0ef41Sopenharmony_ci                         const std::string& ws_key) override;
1921cb0ef41Sopenharmony_ci    void OnWsFrame(const std::vector<char>& data) override;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci   private:
1951cb0ef41Sopenharmony_ci    SocketSession* Session() {
1961cb0ef41Sopenharmony_ci      return server_->Session(session_id_);
1971cb0ef41Sopenharmony_ci    }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    InspectorSocketServer* server_;
2001cb0ef41Sopenharmony_ci    int session_id_;
2011cb0ef41Sopenharmony_ci  };
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci private:
2041cb0ef41Sopenharmony_ci  const int id_;
2051cb0ef41Sopenharmony_ci  InspectorSocket::Pointer ws_socket_;
2061cb0ef41Sopenharmony_ci  const int server_port_;
2071cb0ef41Sopenharmony_ci};
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ciclass ServerSocket {
2101cb0ef41Sopenharmony_ci public:
2111cb0ef41Sopenharmony_ci  explicit ServerSocket(InspectorSocketServer* server)
2121cb0ef41Sopenharmony_ci                        : tcp_socket_(uv_tcp_t()), server_(server), unix_socket_(uv_pipe_t()) {}
2131cb0ef41Sopenharmony_ci  int Listen(sockaddr* addr, uv_loop_t* loop, int pid = -1);
2141cb0ef41Sopenharmony_ci  void Close() {
2151cb0ef41Sopenharmony_ci    uv_close(reinterpret_cast<uv_handle_t*>(&tcp_socket_), FreeOnCloseCallback);
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci  void CloseUnix() {
2181cb0ef41Sopenharmony_ci    if (unix_socket_on) {
2191cb0ef41Sopenharmony_ci      uv_close(reinterpret_cast<uv_handle_t*>(&unix_socket_), nullptr);
2201cb0ef41Sopenharmony_ci      unix_socket_on = false;
2211cb0ef41Sopenharmony_ci    }
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci  int port() const { return port_; }
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci private:
2261cb0ef41Sopenharmony_ci  template <typename UvHandle>
2271cb0ef41Sopenharmony_ci  static ServerSocket* FromTcpSocket(UvHandle* socket) {
2281cb0ef41Sopenharmony_ci    return node::ContainerOf(&ServerSocket::tcp_socket_,
2291cb0ef41Sopenharmony_ci                             reinterpret_cast<uv_tcp_t*>(socket));
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci  static void SocketConnectedCallback(uv_stream_t* tcp_socket, int status);
2321cb0ef41Sopenharmony_ci  static void UnixSocketConnectedCallback(uv_stream_t* unix_socket, int status);
2331cb0ef41Sopenharmony_ci  static void FreeOnCloseCallback(uv_handle_t* tcp_socket_) {
2341cb0ef41Sopenharmony_ci    delete FromTcpSocket(tcp_socket_);
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci  int DetectPort(uv_loop_t *loop, int pid);
2371cb0ef41Sopenharmony_ci  ~ServerSocket() = default;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  uv_tcp_t tcp_socket_;
2401cb0ef41Sopenharmony_ci  InspectorSocketServer* server_;
2411cb0ef41Sopenharmony_ci  uv_pipe_t unix_socket_;
2421cb0ef41Sopenharmony_ci  int port_ = -1;
2431cb0ef41Sopenharmony_ci  bool unix_socket_on = false;
2441cb0ef41Sopenharmony_ci};
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_civoid PrintDebuggerReadyMessage(
2471cb0ef41Sopenharmony_ci    const std::string& host,
2481cb0ef41Sopenharmony_ci    const std::vector<InspectorSocketServer::ServerSocketPtr>& server_sockets,
2491cb0ef41Sopenharmony_ci    const std::vector<std::string>& ids,
2501cb0ef41Sopenharmony_ci    const char* verb,
2511cb0ef41Sopenharmony_ci    bool publish_uid_stderr,
2521cb0ef41Sopenharmony_ci    FILE* out) {
2531cb0ef41Sopenharmony_ci  if (!publish_uid_stderr || out == nullptr) {
2541cb0ef41Sopenharmony_ci    return;
2551cb0ef41Sopenharmony_ci  }
2561cb0ef41Sopenharmony_ci  for (const auto& server_socket : server_sockets) {
2571cb0ef41Sopenharmony_ci    for (const std::string& id : ids) {
2581cb0ef41Sopenharmony_ci      fprintf(out, "Debugger %s on %s\n",
2591cb0ef41Sopenharmony_ci              verb,
2601cb0ef41Sopenharmony_ci              FormatWsAddress(host, server_socket->port(), id, true).c_str());
2611cb0ef41Sopenharmony_ci    }
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci  fprintf(out, "For help, see: %s\n",
2641cb0ef41Sopenharmony_ci          "https://nodejs.org/en/docs/inspector");
2651cb0ef41Sopenharmony_ci  fflush(out);
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ciInspectorSocketServer::InspectorSocketServer(
2691cb0ef41Sopenharmony_ci    std::unique_ptr<SocketServerDelegate> delegate, uv_loop_t* loop,
2701cb0ef41Sopenharmony_ci    const std::string& host, int port,
2711cb0ef41Sopenharmony_ci    const InspectPublishUid& inspect_publish_uid, FILE* out, int pid)
2721cb0ef41Sopenharmony_ci    : loop_(loop),
2731cb0ef41Sopenharmony_ci      delegate_(std::move(delegate)),
2741cb0ef41Sopenharmony_ci      host_(host),
2751cb0ef41Sopenharmony_ci      port_(port),
2761cb0ef41Sopenharmony_ci      inspect_publish_uid_(inspect_publish_uid),
2771cb0ef41Sopenharmony_ci      next_session_id_(0),
2781cb0ef41Sopenharmony_ci      out_(out),
2791cb0ef41Sopenharmony_ci      pid_(pid) {
2801cb0ef41Sopenharmony_ci  delegate_->AssignServer(this);
2811cb0ef41Sopenharmony_ci  state_ = ServerState::kNew;
2821cb0ef41Sopenharmony_ci}
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ciInspectorSocketServer::~InspectorSocketServer() = default;
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciSocketSession* InspectorSocketServer::Session(int session_id) {
2871cb0ef41Sopenharmony_ci  auto it = connected_sessions_.find(session_id);
2881cb0ef41Sopenharmony_ci  return it == connected_sessions_.end() ? nullptr : it->second.second.get();
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_civoid InspectorSocketServer::SessionStarted(int session_id,
2921cb0ef41Sopenharmony_ci                                           const std::string& id,
2931cb0ef41Sopenharmony_ci                                           const std::string& ws_key) {
2941cb0ef41Sopenharmony_ci  SocketSession* session = Session(session_id);
2951cb0ef41Sopenharmony_ci  if (!TargetExists(id)) {
2961cb0ef41Sopenharmony_ci    session->Decline();
2971cb0ef41Sopenharmony_ci    return;
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci  connected_sessions_[session_id].first = id;
3001cb0ef41Sopenharmony_ci  session->Accept(ws_key);
3011cb0ef41Sopenharmony_ci  delegate_->StartSession(session_id, id);
3021cb0ef41Sopenharmony_ci}
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_civoid InspectorSocketServer::SessionTerminated(int session_id) {
3051cb0ef41Sopenharmony_ci  if (Session(session_id) == nullptr) {
3061cb0ef41Sopenharmony_ci    return;
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci  bool was_attached = connected_sessions_[session_id].first != "";
3091cb0ef41Sopenharmony_ci  if (was_attached) {
3101cb0ef41Sopenharmony_ci    delegate_->EndSession(session_id);
3111cb0ef41Sopenharmony_ci  }
3121cb0ef41Sopenharmony_ci  connected_sessions_.erase(session_id);
3131cb0ef41Sopenharmony_ci  if (connected_sessions_.empty()) {
3141cb0ef41Sopenharmony_ci    if (was_attached && state_ == ServerState::kRunning
3151cb0ef41Sopenharmony_ci        && !server_sockets_.empty()) {
3161cb0ef41Sopenharmony_ci      PrintDebuggerReadyMessage(host_,
3171cb0ef41Sopenharmony_ci                                server_sockets_,
3181cb0ef41Sopenharmony_ci                                delegate_->GetTargetIds(),
3191cb0ef41Sopenharmony_ci                                "ending",
3201cb0ef41Sopenharmony_ci                                inspect_publish_uid_.console,
3211cb0ef41Sopenharmony_ci                                out_);
3221cb0ef41Sopenharmony_ci    }
3231cb0ef41Sopenharmony_ci    if (state_ == ServerState::kStopped) {
3241cb0ef41Sopenharmony_ci      delegate_.reset();
3251cb0ef41Sopenharmony_ci    }
3261cb0ef41Sopenharmony_ci  }
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_cibool InspectorSocketServer::HandleGetRequest(int session_id,
3301cb0ef41Sopenharmony_ci                                             const std::string& host,
3311cb0ef41Sopenharmony_ci                                             const std::string& path) {
3321cb0ef41Sopenharmony_ci  SocketSession* session = Session(session_id);
3331cb0ef41Sopenharmony_ci  InspectorSocket* socket = session->ws_socket();
3341cb0ef41Sopenharmony_ci  if (!inspect_publish_uid_.http) {
3351cb0ef41Sopenharmony_ci    SendHttpNotFound(socket);
3361cb0ef41Sopenharmony_ci    return true;
3371cb0ef41Sopenharmony_ci  }
3381cb0ef41Sopenharmony_ci  const char* command = MatchPathSegment(path.c_str(), "/json");
3391cb0ef41Sopenharmony_ci  if (command == nullptr)
3401cb0ef41Sopenharmony_ci    return false;
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci  if (MatchPathSegment(command, "list") || command[0] == '\0') {
3431cb0ef41Sopenharmony_ci    SendListResponse(socket, host, session);
3441cb0ef41Sopenharmony_ci    return true;
3451cb0ef41Sopenharmony_ci  } else if (MatchPathSegment(command, "protocol")) {
3461cb0ef41Sopenharmony_ci    SendProtocolJson(socket);
3471cb0ef41Sopenharmony_ci    return true;
3481cb0ef41Sopenharmony_ci  } else if (MatchPathSegment(command, "version")) {
3491cb0ef41Sopenharmony_ci    SendVersionResponse(socket);
3501cb0ef41Sopenharmony_ci    return true;
3511cb0ef41Sopenharmony_ci  }
3521cb0ef41Sopenharmony_ci  return false;
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_civoid InspectorSocketServer::SendListResponse(InspectorSocket* socket,
3561cb0ef41Sopenharmony_ci                                             const std::string& host,
3571cb0ef41Sopenharmony_ci                                             SocketSession* session) {
3581cb0ef41Sopenharmony_ci  std::vector<std::map<std::string, std::string>> response;
3591cb0ef41Sopenharmony_ci  for (const std::string& id : delegate_->GetTargetIds()) {
3601cb0ef41Sopenharmony_ci    response.push_back(std::map<std::string, std::string>());
3611cb0ef41Sopenharmony_ci    std::map<std::string, std::string>& target_map = response.back();
3621cb0ef41Sopenharmony_ci    target_map["description"] = "node.js instance";
3631cb0ef41Sopenharmony_ci    target_map["faviconUrl"] =
3641cb0ef41Sopenharmony_ci                        "https://nodejs.org/static/images/favicons/favicon.ico";
3651cb0ef41Sopenharmony_ci    target_map["id"] = id;
3661cb0ef41Sopenharmony_ci    target_map["title"] = delegate_->GetTargetTitle(id);
3671cb0ef41Sopenharmony_ci    Escape(&target_map["title"]);
3681cb0ef41Sopenharmony_ci    target_map["type"] = "node";
3691cb0ef41Sopenharmony_ci    // This attribute value is a "best effort" URL that is passed as a JSON
3701cb0ef41Sopenharmony_ci    // string. It is not guaranteed to resolve to a valid resource.
3711cb0ef41Sopenharmony_ci    target_map["url"] = delegate_->GetTargetUrl(id);
3721cb0ef41Sopenharmony_ci    Escape(&target_map["url"]);
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci    std::string detected_host = host;
3751cb0ef41Sopenharmony_ci    if (detected_host.empty()) {
3761cb0ef41Sopenharmony_ci      detected_host = FormatHostPort(socket->GetHost(),
3771cb0ef41Sopenharmony_ci                                     session->server_port());
3781cb0ef41Sopenharmony_ci    }
3791cb0ef41Sopenharmony_ci    std::string formatted_address = FormatAddress(detected_host, id, false);
3801cb0ef41Sopenharmony_ci    target_map["devtoolsFrontendUrl"] = GetFrontendURL(false,
3811cb0ef41Sopenharmony_ci                                                       formatted_address);
3821cb0ef41Sopenharmony_ci    // The compat URL is for Chrome browsers older than 66.0.3345.0
3831cb0ef41Sopenharmony_ci    target_map["devtoolsFrontendUrlCompat"] = GetFrontendURL(true,
3841cb0ef41Sopenharmony_ci                                                             formatted_address);
3851cb0ef41Sopenharmony_ci    target_map["webSocketDebuggerUrl"] = FormatAddress(detected_host, id, true);
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci  SendHttpResponse(socket, MapsToString(response), 200);
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_cistd::string InspectorSocketServer::GetFrontendURL(bool is_compat,
3911cb0ef41Sopenharmony_ci    const std::string &formatted_address) {
3921cb0ef41Sopenharmony_ci  std::ostringstream frontend_url;
3931cb0ef41Sopenharmony_ci  frontend_url << "devtools://devtools/bundled/";
3941cb0ef41Sopenharmony_ci  frontend_url << (is_compat ? "inspector" : "js_app");
3951cb0ef41Sopenharmony_ci  frontend_url << ".html?v8only=true&ws=";
3961cb0ef41Sopenharmony_ci  frontend_url << formatted_address;
3971cb0ef41Sopenharmony_ci  return frontend_url.str();
3981cb0ef41Sopenharmony_ci}
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_cibool InspectorSocketServer::Start() {
4011cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(delegate_);
4021cb0ef41Sopenharmony_ci  CHECK_EQ(state_, ServerState::kNew);
4031cb0ef41Sopenharmony_ci  std::unique_ptr<SocketServerDelegate> delegate_holder;
4041cb0ef41Sopenharmony_ci  // We will return it if startup is successful
4051cb0ef41Sopenharmony_ci  delegate_.swap(delegate_holder);
4061cb0ef41Sopenharmony_ci  struct addrinfo hints;
4071cb0ef41Sopenharmony_ci  memset(&hints, 0, sizeof(hints));
4081cb0ef41Sopenharmony_ci  hints.ai_flags = AI_NUMERICSERV;
4091cb0ef41Sopenharmony_ci  hints.ai_socktype = SOCK_STREAM;
4101cb0ef41Sopenharmony_ci  uv_getaddrinfo_t req;
4111cb0ef41Sopenharmony_ci  const std::string port_string = std::to_string(port_);
4121cb0ef41Sopenharmony_ci  int err = uv_getaddrinfo(loop_, &req, nullptr, host_.c_str(),
4131cb0ef41Sopenharmony_ci                           port_string.c_str(), &hints);
4141cb0ef41Sopenharmony_ci  if (err < 0) {
4151cb0ef41Sopenharmony_ci    if (out_ != nullptr) {
4161cb0ef41Sopenharmony_ci      fprintf(out_, "Unable to resolve \"%s\": %s\n", host_.c_str(),
4171cb0ef41Sopenharmony_ci              uv_strerror(err));
4181cb0ef41Sopenharmony_ci    }
4191cb0ef41Sopenharmony_ci    return false;
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci  for (addrinfo* address = req.addrinfo; address != nullptr;
4221cb0ef41Sopenharmony_ci       address = address->ai_next) {
4231cb0ef41Sopenharmony_ci    auto server_socket = ServerSocketPtr(new ServerSocket(this));
4241cb0ef41Sopenharmony_ci    err = server_socket->Listen(address->ai_addr, loop_, pid_);
4251cb0ef41Sopenharmony_ci    if (err == 0)
4261cb0ef41Sopenharmony_ci      server_sockets_.push_back(std::move(server_socket));
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci  uv_freeaddrinfo(req.addrinfo);
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  // We only show error if we failed to start server on all addresses. We only
4311cb0ef41Sopenharmony_ci  // show one error, for the last address.
4321cb0ef41Sopenharmony_ci  if (server_sockets_.empty()) {
4331cb0ef41Sopenharmony_ci    if (out_ != nullptr) {
4341cb0ef41Sopenharmony_ci      fprintf(out_, "Starting inspector on %s:%d failed: %s\n",
4351cb0ef41Sopenharmony_ci              host_.c_str(), port_, uv_strerror(err));
4361cb0ef41Sopenharmony_ci      fflush(out_);
4371cb0ef41Sopenharmony_ci    }
4381cb0ef41Sopenharmony_ci    return false;
4391cb0ef41Sopenharmony_ci  }
4401cb0ef41Sopenharmony_ci  delegate_.swap(delegate_holder);
4411cb0ef41Sopenharmony_ci  state_ = ServerState::kRunning;
4421cb0ef41Sopenharmony_ci  PrintDebuggerReadyMessage(host_,
4431cb0ef41Sopenharmony_ci                            server_sockets_,
4441cb0ef41Sopenharmony_ci                            delegate_->GetTargetIds(),
4451cb0ef41Sopenharmony_ci                            "listening",
4461cb0ef41Sopenharmony_ci                            inspect_publish_uid_.console,
4471cb0ef41Sopenharmony_ci                            out_);
4481cb0ef41Sopenharmony_ci  return true;
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_civoid InspectorSocketServer::Stop() {
4521cb0ef41Sopenharmony_ci  if (state_ == ServerState::kStopped)
4531cb0ef41Sopenharmony_ci    return;
4541cb0ef41Sopenharmony_ci  CHECK_EQ(state_, ServerState::kRunning);
4551cb0ef41Sopenharmony_ci  state_ = ServerState::kStopped;
4561cb0ef41Sopenharmony_ci  server_sockets_.clear();
4571cb0ef41Sopenharmony_ci  if (done())
4581cb0ef41Sopenharmony_ci    delegate_.reset();
4591cb0ef41Sopenharmony_ci}
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_civoid InspectorSocketServer::TerminateConnections() {
4621cb0ef41Sopenharmony_ci  for (const auto& key_value : connected_sessions_)
4631cb0ef41Sopenharmony_ci    key_value.second.second->Close();
4641cb0ef41Sopenharmony_ci}
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_cibool InspectorSocketServer::TargetExists(const std::string& id) {
4671cb0ef41Sopenharmony_ci  const std::vector<std::string>& target_ids = delegate_->GetTargetIds();
4681cb0ef41Sopenharmony_ci  const auto& found = std::find(target_ids.begin(), target_ids.end(), id);
4691cb0ef41Sopenharmony_ci  return found != target_ids.end();
4701cb0ef41Sopenharmony_ci}
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ciint InspectorSocketServer::Port() const {
4731cb0ef41Sopenharmony_ci  if (!server_sockets_.empty()) {
4741cb0ef41Sopenharmony_ci    return server_sockets_[0]->port();
4751cb0ef41Sopenharmony_ci  }
4761cb0ef41Sopenharmony_ci  return port_;
4771cb0ef41Sopenharmony_ci}
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_civoid InspectorSocketServer::Accept(int server_port,
4801cb0ef41Sopenharmony_ci                                   uv_stream_t* server_socket) {
4811cb0ef41Sopenharmony_ci  std::unique_ptr<SocketSession> session(
4821cb0ef41Sopenharmony_ci      new SocketSession(this, next_session_id_++, server_port));
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  InspectorSocket::DelegatePointer delegate =
4851cb0ef41Sopenharmony_ci      InspectorSocket::DelegatePointer(
4861cb0ef41Sopenharmony_ci          new SocketSession::Delegate(this, session->id()));
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  InspectorSocket::Pointer inspector =
4891cb0ef41Sopenharmony_ci      InspectorSocket::Accept(server_socket, std::move(delegate));
4901cb0ef41Sopenharmony_ci  if (inspector) {
4911cb0ef41Sopenharmony_ci    session->Own(std::move(inspector));
4921cb0ef41Sopenharmony_ci    connected_sessions_[session->id()].second = std::move(session);
4931cb0ef41Sopenharmony_ci  }
4941cb0ef41Sopenharmony_ci}
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_civoid InspectorSocketServer::Send(int session_id, const std::string& message) {
4971cb0ef41Sopenharmony_ci  SocketSession* session = Session(session_id);
4981cb0ef41Sopenharmony_ci  if (session != nullptr) {
4991cb0ef41Sopenharmony_ci    session->Send(message);
5001cb0ef41Sopenharmony_ci  }
5011cb0ef41Sopenharmony_ci}
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_civoid InspectorSocketServer::CloseServerSocket(ServerSocket* server) {
5041cb0ef41Sopenharmony_ci  server->Close();
5051cb0ef41Sopenharmony_ci  server->CloseUnix();
5061cb0ef41Sopenharmony_ci}
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci// InspectorSession tracking
5091cb0ef41Sopenharmony_ciSocketSession::SocketSession(InspectorSocketServer* server, int id,
5101cb0ef41Sopenharmony_ci                             int server_port)
5111cb0ef41Sopenharmony_ci    : id_(id), server_port_(server_port) {}
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_civoid SocketSession::Send(const std::string& message) {
5141cb0ef41Sopenharmony_ci  ws_socket_->Write(message.data(), message.length());
5151cb0ef41Sopenharmony_ci}
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_civoid SocketSession::Delegate::OnHttpGet(const std::string& host,
5181cb0ef41Sopenharmony_ci                                        const std::string& path) {
5191cb0ef41Sopenharmony_ci  if (!server_->HandleGetRequest(session_id_, host, path))
5201cb0ef41Sopenharmony_ci    Session()->ws_socket()->CancelHandshake();
5211cb0ef41Sopenharmony_ci}
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_civoid SocketSession::Delegate::OnSocketUpgrade(const std::string& host,
5241cb0ef41Sopenharmony_ci                                              const std::string& path,
5251cb0ef41Sopenharmony_ci                                              const std::string& ws_key) {
5261cb0ef41Sopenharmony_ci  std::string id = path.empty() ? path : path.substr(1);
5271cb0ef41Sopenharmony_ci  server_->SessionStarted(session_id_, id, ws_key);
5281cb0ef41Sopenharmony_ci}
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_civoid SocketSession::Delegate::OnWsFrame(const std::vector<char>& data) {
5311cb0ef41Sopenharmony_ci  server_->MessageReceived(session_id_,
5321cb0ef41Sopenharmony_ci                           std::string(data.data(), data.size()));
5331cb0ef41Sopenharmony_ci}
5341cb0ef41Sopenharmony_ci
5351cb0ef41Sopenharmony_ci// ServerSocket implementation
5361cb0ef41Sopenharmony_ciint ServerSocket::DetectPort(uv_loop_t *loop, int pid) {
5371cb0ef41Sopenharmony_ci  sockaddr_storage addr;
5381cb0ef41Sopenharmony_ci  int len = sizeof(addr);
5391cb0ef41Sopenharmony_ci  int err = uv_tcp_getsockname(&tcp_socket_,
5401cb0ef41Sopenharmony_ci                               reinterpret_cast<struct sockaddr*>(&addr), &len);
5411cb0ef41Sopenharmony_ci  if (err != 0)
5421cb0ef41Sopenharmony_ci    return err;
5431cb0ef41Sopenharmony_ci  int port;
5441cb0ef41Sopenharmony_ci  if (addr.ss_family == AF_INET6)
5451cb0ef41Sopenharmony_ci    port = reinterpret_cast<const sockaddr_in6*>(&addr)->sin6_port;
5461cb0ef41Sopenharmony_ci  else
5471cb0ef41Sopenharmony_ci    port = reinterpret_cast<const sockaddr_in*>(&addr)->sin_port;
5481cb0ef41Sopenharmony_ci  port_ = ntohs(port);
5491cb0ef41Sopenharmony_ci  if (!unix_socket_on && pid != -1) {
5501cb0ef41Sopenharmony_ci    auto unixDomainSocketPath = "jsvm_devtools_remote_" +
5511cb0ef41Sopenharmony_ci      std::to_string(port_) + "_" + std::to_string(pid);
5521cb0ef41Sopenharmony_ci    auto *abstract = new char[unixDomainSocketPath.length() + 2];
5531cb0ef41Sopenharmony_ci    abstract[0] = '\0';
5541cb0ef41Sopenharmony_ci    strcpy(abstract + 1, unixDomainSocketPath.c_str());
5551cb0ef41Sopenharmony_ci    auto status = uv_pipe_init(loop, &unix_socket_, 0);
5561cb0ef41Sopenharmony_ci    if (status == 0) {
5571cb0ef41Sopenharmony_ci      status = uv_pipe_bind(&unix_socket_, abstract);
5581cb0ef41Sopenharmony_ci    }
5591cb0ef41Sopenharmony_ci    if (status == 0) {
5601cb0ef41Sopenharmony_ci      constexpr int unixBacklog = 128;
5611cb0ef41Sopenharmony_ci      status = uv_listen(reinterpret_cast<uv_stream_t*>(&unix_socket_), unixBacklog,
5621cb0ef41Sopenharmony_ci        ServerSocket::UnixSocketConnectedCallback);
5631cb0ef41Sopenharmony_ci    }
5641cb0ef41Sopenharmony_ci    unix_socket_on = status == 0;
5651cb0ef41Sopenharmony_ci    delete abstract;
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci  return err;
5681cb0ef41Sopenharmony_ci}
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ciint ServerSocket::Listen(sockaddr* addr, uv_loop_t* loop, int pid) {
5711cb0ef41Sopenharmony_ci  uv_tcp_t* server = &tcp_socket_;
5721cb0ef41Sopenharmony_ci  CHECK_EQ(0, uv_tcp_init(loop, server));
5731cb0ef41Sopenharmony_ci  int err = uv_tcp_bind(server, addr, 0);
5741cb0ef41Sopenharmony_ci  if (err == 0) {
5751cb0ef41Sopenharmony_ci    // 511 is the value used by a 'net' module by default
5761cb0ef41Sopenharmony_ci    err = uv_listen(reinterpret_cast<uv_stream_t*>(server), 511,
5771cb0ef41Sopenharmony_ci                    ServerSocket::SocketConnectedCallback);
5781cb0ef41Sopenharmony_ci  }
5791cb0ef41Sopenharmony_ci  if (err == 0) {
5801cb0ef41Sopenharmony_ci    err = DetectPort(loop, pid);
5811cb0ef41Sopenharmony_ci  }
5821cb0ef41Sopenharmony_ci  return err;
5831cb0ef41Sopenharmony_ci}
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci// static
5861cb0ef41Sopenharmony_civoid ServerSocket::SocketConnectedCallback(uv_stream_t* tcp_socket,
5871cb0ef41Sopenharmony_ci                                           int status) {
5881cb0ef41Sopenharmony_ci  if (status == 0) {
5891cb0ef41Sopenharmony_ci    ServerSocket* server_socket = ServerSocket::FromTcpSocket(tcp_socket);
5901cb0ef41Sopenharmony_ci    // Memory is freed when the socket closes.
5911cb0ef41Sopenharmony_ci    server_socket->server_->Accept(server_socket->port_, tcp_socket);
5921cb0ef41Sopenharmony_ci  }
5931cb0ef41Sopenharmony_ci}
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_civoid ServerSocket::UnixSocketConnectedCallback(uv_stream_t* unix_socket,
5961cb0ef41Sopenharmony_ci                                               int status) {
5971cb0ef41Sopenharmony_ci  if (status == 0) {
5981cb0ef41Sopenharmony_ci    (void)unix_socket;
5991cb0ef41Sopenharmony_ci  }
6001cb0ef41Sopenharmony_ci}
6011cb0ef41Sopenharmony_ci}  // namespace inspector
6021cb0ef41Sopenharmony_ci}  // namespace node
603