Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
inspector_io.h
Go to the documentation of this file.
1 #ifndef SRC_INSPECTOR_IO_H_
2 #define SRC_INSPECTOR_IO_H_
3 
5 #include "node_debug_options.h"
6 #include "node_mutex.h"
7 #include "uv.h"
8 
9 #include <deque>
10 #include <memory>
11 #include <stddef.h>
12 
13 #if !HAVE_INSPECTOR
14 #error("This header can only be used when inspector is enabled")
15 #endif
16 
17 
18 // Forward declaration to break recursive dependency chain with src/env.h.
19 namespace node {
20 class Environment;
21 } // namespace node
22 
23 namespace v8_inspector {
24 class StringBuffer;
25 class StringView;
26 } // namespace v8_inspector
27 
28 namespace node {
29 namespace inspector {
30 
31 std::string FormatWsAddress(const std::string& host, int port,
32  const std::string& target_id,
33  bool include_protocol);
34 
35 class InspectorIoDelegate;
36 
37 enum class InspectorAction {
41 };
42 
43 // kKill closes connections and stops the server, kStop only stops the server
44 enum class TransportAction {
45  kKill,
46  kSendMessage,
47  kStop
48 };
49 
50 class InspectorIo {
51  public:
52  InspectorIo(node::Environment* env, v8::Platform* platform,
53  const std::string& path, const DebugOptions& options,
54  bool wait_for_connect);
55 
56  ~InspectorIo();
57  // Start the inspector agent thread, waiting for it to initialize,
58  // and waiting as well for a connection if wait_for_connect.
59  bool Start();
60  // Stop the inspector agent thread.
61  void Stop();
62 
63  bool IsStarted();
64  bool IsConnected();
65 
66  void WaitForDisconnect();
67  // Called from thread to queue an incoming message and trigger
68  // DispatchMessages() on the main thread.
69  void PostIncomingMessage(InspectorAction action, int session_id,
70  const std::string& message);
71  void ResumeStartup() {
72  uv_sem_post(&thread_start_sem_);
73  }
74  void ServerDone() {
75  uv_close(reinterpret_cast<uv_handle_t*>(&thread_req_), nullptr);
76  }
77 
78  int port() const { return port_; }
79  std::string host() const { return options_.host_name(); }
80  std::vector<std::string> GetTargetIds() const;
81 
82  private:
83  template <typename Action>
84  using MessageQueue =
85  std::deque<std::tuple<Action, int,
86  std::unique_ptr<v8_inspector::StringBuffer>>>;
87  enum class State {
88  kNew,
89  kAccepting,
90  kConnected,
91  kDone,
92  kError,
93  kShutDown
94  };
95 
96  // Callback for main_thread_req_'s uv_async_t
97  static void MainThreadReqAsyncCb(uv_async_t* req);
98 
99  // Wrapper for agent->ThreadMain()
100  static void ThreadMain(void* agent);
101 
102  // Runs a uv_loop_t
103  template <typename Transport> void ThreadMain();
104  // Called by ThreadMain's loop when triggered by thread_req_, writes
105  // messages from outgoing_message_queue to the InspectorSockerServer
106  template <typename Transport> static void IoThreadAsyncCb(uv_async_t* async);
107 
108  void SetConnected(bool connected);
109  void DispatchMessages();
110  // Write action to outgoing_message_queue, and wake the thread
111  void Write(TransportAction action, int session_id,
112  const v8_inspector::StringView& message);
113  // Thread-safe append of message to a queue. Return true if the queue
114  // used to be empty.
115  template <typename ActionType>
116  bool AppendMessage(MessageQueue<ActionType>* vector, ActionType action,
117  int session_id,
118  std::unique_ptr<v8_inspector::StringBuffer> buffer);
119  // Used as equivalent of a thread-safe "pop" of an entire queue's content.
120  template <typename ActionType>
121  void SwapBehindLock(MessageQueue<ActionType>* vector1,
122  MessageQueue<ActionType>* vector2);
123  // Wait on incoming_message_cond_
124  void WaitForFrontendMessageWhilePaused();
125  // Broadcast incoming_message_cond_
126  void NotifyMessageReceived();
127 
128  const DebugOptions options_;
129 
130  // The IO thread runs its own uv_loop to implement the TCP server off
131  // the main thread.
132  uv_thread_t thread_;
133  // Used by Start() to wait for thread to initialize, or for it to initialize
134  // and receive a connection if wait_for_connect was requested.
135  uv_sem_t thread_start_sem_;
136 
137  InspectorIoDelegate* delegate_;
138  State state_;
139  node::Environment* parent_env_;
140 
141  // Attached to the uv_loop in ThreadMain()
142  uv_async_t thread_req_;
143  // Note that this will live while the async is being closed - likely, past
144  // the parent object lifespan
145  std::pair<uv_async_t, Agent*>* main_thread_req_;
146  std::unique_ptr<InspectorSessionDelegate> session_delegate_;
147  v8::Platform* platform_;
148 
149  // Message queues
150  ConditionVariable incoming_message_cond_;
151  Mutex state_lock_; // Locked before mutating either queue.
152  MessageQueue<InspectorAction> incoming_message_queue_;
153  MessageQueue<TransportAction> outgoing_message_queue_;
154  MessageQueue<InspectorAction> dispatching_message_queue_;
155 
156  bool dispatching_messages_;
157  int session_id_;
158 
159  std::string script_name_;
160  std::string script_path_;
161  const bool wait_for_connect_;
162  int port_;
163 
164  friend class DispatchMessagesTask;
165  friend class IoSessionDelegate;
166  friend void InterruptCallback(v8::Isolate*, void* agent);
167 };
168 
169 std::unique_ptr<v8_inspector::StringBuffer> Utf8ToStringView(
170  const std::string& message);
171 
172 } // namespace inspector
173 } // namespace node
174 
175 #endif // SRC_INSPECTOR_IO_H_
std::unique_ptr< StringBuffer > Utf8ToStringView(const std::string &message)
void InterruptCallback(v8::Isolate *, void *agent)
hostent * host
Definition: cares_wrap.cc:482
std::string host() const
Definition: inspector_io.h:79
std::string FormatWsAddress(const std::string &host, int port, const std::string &target_id, bool include_protocol)
uv_fs_t req
Definition: node_file.cc:374
int Start(Isolate *isolate, IsolateData *isolate_data, int argc, const char *const *argv, int exec_argc, const char *const *exec_argv)
Definition: node.cc:4536