mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.9 KiB
171 lines
4.9 KiB
#ifndef SRC_INSPECTOR_IO_H_
|
|
#define SRC_INSPECTOR_IO_H_
|
|
|
|
#include "inspector_socket_server.h"
|
|
#include "node_debug_options.h"
|
|
#include "node_mutex.h"
|
|
#include "uv.h"
|
|
|
|
#include <deque>
|
|
#include <memory>
|
|
#include <stddef.h>
|
|
|
|
#if !HAVE_INSPECTOR
|
|
#error("This header can only be used when inspector is enabled")
|
|
#endif
|
|
|
|
|
|
// Forward declaration to break recursive dependency chain with src/env.h.
|
|
namespace node {
|
|
class Environment;
|
|
} // namespace node
|
|
|
|
namespace v8_inspector {
|
|
class StringBuffer;
|
|
class StringView;
|
|
} // namespace v8_inspector
|
|
|
|
namespace node {
|
|
namespace inspector {
|
|
|
|
class InspectorIoDelegate;
|
|
|
|
enum class InspectorAction {
|
|
kStartSession,
|
|
kEndSession,
|
|
kSendMessage
|
|
};
|
|
|
|
// kKill closes connections and stops the server, kStop only stops the server
|
|
enum class TransportAction {
|
|
kKill,
|
|
kSendMessage,
|
|
kStop
|
|
};
|
|
|
|
class InspectorIo {
|
|
public:
|
|
InspectorIo(node::Environment* env, v8::Platform* platform,
|
|
const std::string& path, const DebugOptions& options,
|
|
bool wait_for_connect);
|
|
|
|
~InspectorIo();
|
|
// Start the inspector agent thread, waiting for it to initialize,
|
|
// and waiting as well for a connection if wait_for_connect.
|
|
bool Start();
|
|
// Stop the inspector agent thread.
|
|
void Stop();
|
|
|
|
bool IsStarted();
|
|
bool IsConnected();
|
|
|
|
void WaitForDisconnect();
|
|
// Called from thread to queue an incoming message and trigger
|
|
// DispatchMessages() on the main thread.
|
|
void PostIncomingMessage(InspectorAction action, int session_id,
|
|
const std::string& message);
|
|
void ResumeStartup() {
|
|
uv_sem_post(&thread_start_sem_);
|
|
}
|
|
void ServerDone() {
|
|
uv_close(reinterpret_cast<uv_handle_t*>(&thread_req_), nullptr);
|
|
}
|
|
|
|
int port() const { return port_; }
|
|
std::string host() const { return options_.host_name(); }
|
|
std::vector<std::string> GetTargetIds() const;
|
|
|
|
private:
|
|
template <typename Action>
|
|
using MessageQueue =
|
|
std::deque<std::tuple<Action, int,
|
|
std::unique_ptr<v8_inspector::StringBuffer>>>;
|
|
enum class State {
|
|
kNew,
|
|
kAccepting,
|
|
kConnected,
|
|
kDone,
|
|
kError,
|
|
kShutDown
|
|
};
|
|
|
|
// Callback for main_thread_req_'s uv_async_t
|
|
static void MainThreadReqAsyncCb(uv_async_t* req);
|
|
|
|
// Wrapper for agent->ThreadMain()
|
|
static void ThreadMain(void* agent);
|
|
|
|
// Runs a uv_loop_t
|
|
template <typename Transport> void ThreadMain();
|
|
// Called by ThreadMain's loop when triggered by thread_req_, writes
|
|
// messages from outgoing_message_queue to the InspectorSockerServer
|
|
template <typename Transport> static void IoThreadAsyncCb(uv_async_t* async);
|
|
|
|
void SetConnected(bool connected);
|
|
void DispatchMessages();
|
|
// Write action to outgoing_message_queue, and wake the thread
|
|
void Write(TransportAction action, int session_id,
|
|
const v8_inspector::StringView& message);
|
|
// Thread-safe append of message to a queue. Return true if the queue
|
|
// used to be empty.
|
|
template <typename ActionType>
|
|
bool AppendMessage(MessageQueue<ActionType>* vector, ActionType action,
|
|
int session_id,
|
|
std::unique_ptr<v8_inspector::StringBuffer> buffer);
|
|
// Used as equivalent of a thread-safe "pop" of an entire queue's content.
|
|
template <typename ActionType>
|
|
void SwapBehindLock(MessageQueue<ActionType>* vector1,
|
|
MessageQueue<ActionType>* vector2);
|
|
// Wait on incoming_message_cond_
|
|
void WaitForFrontendMessageWhilePaused();
|
|
// Broadcast incoming_message_cond_
|
|
void NotifyMessageReceived();
|
|
|
|
const DebugOptions options_;
|
|
|
|
// The IO thread runs its own uv_loop to implement the TCP server off
|
|
// the main thread.
|
|
uv_thread_t thread_;
|
|
// Used by Start() to wait for thread to initialize, or for it to initialize
|
|
// and receive a connection if wait_for_connect was requested.
|
|
uv_sem_t thread_start_sem_;
|
|
|
|
InspectorIoDelegate* delegate_;
|
|
State state_;
|
|
node::Environment* parent_env_;
|
|
|
|
// Attached to the uv_loop in ThreadMain()
|
|
uv_async_t thread_req_;
|
|
// Note that this will live while the async is being closed - likely, past
|
|
// the parent object lifespan
|
|
std::pair<uv_async_t, Agent*>* main_thread_req_;
|
|
std::unique_ptr<InspectorSessionDelegate> session_delegate_;
|
|
v8::Platform* platform_;
|
|
|
|
// Message queues
|
|
ConditionVariable incoming_message_cond_;
|
|
Mutex state_lock_; // Locked before mutating either queue.
|
|
MessageQueue<InspectorAction> incoming_message_queue_;
|
|
MessageQueue<TransportAction> outgoing_message_queue_;
|
|
MessageQueue<InspectorAction> dispatching_message_queue_;
|
|
|
|
bool dispatching_messages_;
|
|
int session_id_;
|
|
|
|
std::string script_name_;
|
|
std::string script_path_;
|
|
const bool wait_for_connect_;
|
|
int port_;
|
|
|
|
friend class DispatchMessagesTask;
|
|
friend class IoSessionDelegate;
|
|
friend void InterruptCallback(v8::Isolate*, void* agent);
|
|
};
|
|
|
|
std::unique_ptr<v8_inspector::StringBuffer> Utf8ToStringView(
|
|
const std::string& message);
|
|
|
|
} // namespace inspector
|
|
} // namespace node
|
|
|
|
#endif // SRC_INSPECTOR_IO_H_
|
|
|