inspector: zero out structure members
Ctor has to be added as memset to 0 is no longer an option, since the structure now has std::vector member. Attempt at fixing nodejs/node#8155 (so far I was not able to repro it) PR-URL: https://github.com/nodejs/node/pull/8536 Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
be07458b11
commit
bc1ebd67d8
@ -32,6 +32,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
namespace inspector {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char TAG_CONNECT[] = "#connect";
|
const char TAG_CONNECT[] = "#connect";
|
||||||
@ -51,7 +52,7 @@ void PrintDebuggerReadyMessage(int port) {
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AcceptsConnection(inspector_socket_t* socket, const std::string& path) {
|
bool AcceptsConnection(InspectorSocket* socket, const std::string& path) {
|
||||||
return StringEqualNoCaseN(path.c_str(), DEVTOOLS_PATH,
|
return StringEqualNoCaseN(path.c_str(), DEVTOOLS_PATH,
|
||||||
sizeof(DEVTOOLS_PATH) - 1);
|
sizeof(DEVTOOLS_PATH) - 1);
|
||||||
}
|
}
|
||||||
@ -62,11 +63,11 @@ void Escape(std::string* string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisposeInspector(inspector_socket_t* socket, int status) {
|
void DisposeInspector(InspectorSocket* socket, int status) {
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisconnectAndDisposeIO(inspector_socket_t* socket) {
|
void DisconnectAndDisposeIO(InspectorSocket* socket) {
|
||||||
if (socket) {
|
if (socket) {
|
||||||
inspector_close(socket, DisposeInspector);
|
inspector_close(socket, DisposeInspector);
|
||||||
}
|
}
|
||||||
@ -77,7 +78,7 @@ void OnBufferAlloc(uv_handle_t* handle, size_t len, uv_buf_t* buf) {
|
|||||||
buf->len = len;
|
buf->len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendHttpResponse(inspector_socket_t* socket, const char* response,
|
void SendHttpResponse(InspectorSocket* socket, const char* response,
|
||||||
size_t len) {
|
size_t len) {
|
||||||
const char HEADERS[] = "HTTP/1.0 200 OK\r\n"
|
const char HEADERS[] = "HTTP/1.0 200 OK\r\n"
|
||||||
"Content-Type: application/json; charset=UTF-8\r\n"
|
"Content-Type: application/json; charset=UTF-8\r\n"
|
||||||
@ -90,7 +91,7 @@ void SendHttpResponse(inspector_socket_t* socket, const char* response,
|
|||||||
inspector_write(socket, response, len);
|
inspector_write(socket, response, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendVersionResponse(inspector_socket_t* socket) {
|
void SendVersionResponse(InspectorSocket* socket) {
|
||||||
const char VERSION_RESPONSE_TEMPLATE[] =
|
const char VERSION_RESPONSE_TEMPLATE[] =
|
||||||
"[ {"
|
"[ {"
|
||||||
" \"Browser\": \"node.js/%s\","
|
" \"Browser\": \"node.js/%s\","
|
||||||
@ -117,7 +118,7 @@ std::string GetProcessTitle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendTargentsListResponse(inspector_socket_t* socket,
|
void SendTargentsListResponse(InspectorSocket* socket,
|
||||||
const std::string& script_name_,
|
const std::string& script_name_,
|
||||||
const std::string& script_path_,
|
const std::string& script_path_,
|
||||||
int port) {
|
int port) {
|
||||||
@ -169,7 +170,7 @@ const char* match_path_segment(const char* path, const char* expected) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RespondToGet(inspector_socket_t* socket, const std::string& script_name_,
|
bool RespondToGet(InspectorSocket* socket, const std::string& script_name_,
|
||||||
const std::string& script_path_, const std::string& path,
|
const std::string& script_path_, const std::string& path,
|
||||||
int port) {
|
int port) {
|
||||||
const char* command = match_path_segment(path.c_str(), "/json");
|
const char* command = match_path_segment(path.c_str(), "/json");
|
||||||
@ -192,8 +193,6 @@ bool RespondToGet(inspector_socket_t* socket, const std::string& script_name_,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace inspector {
|
|
||||||
|
|
||||||
|
|
||||||
class V8NodeInspector;
|
class V8NodeInspector;
|
||||||
|
|
||||||
@ -220,7 +219,7 @@ class AgentImpl {
|
|||||||
|
|
||||||
static void ThreadCbIO(void* agent);
|
static void ThreadCbIO(void* agent);
|
||||||
static void OnSocketConnectionIO(uv_stream_t* server, int status);
|
static void OnSocketConnectionIO(uv_stream_t* server, int status);
|
||||||
static bool OnInspectorHandshakeIO(inspector_socket_t* socket,
|
static bool OnInspectorHandshakeIO(InspectorSocket* socket,
|
||||||
enum inspector_handshake_event state,
|
enum inspector_handshake_event state,
|
||||||
const std::string& path);
|
const std::string& path);
|
||||||
static void WriteCbIO(uv_async_t* async);
|
static void WriteCbIO(uv_async_t* async);
|
||||||
@ -228,8 +227,8 @@ class AgentImpl {
|
|||||||
void InstallInspectorOnProcess();
|
void InstallInspectorOnProcess();
|
||||||
|
|
||||||
void WorkerRunIO();
|
void WorkerRunIO();
|
||||||
void OnInspectorConnectionIO(inspector_socket_t* socket);
|
void OnInspectorConnectionIO(InspectorSocket* socket);
|
||||||
void OnRemoteDataIO(inspector_socket_t* stream, ssize_t read,
|
void OnRemoteDataIO(InspectorSocket* stream, ssize_t read,
|
||||||
const uv_buf_t* b);
|
const uv_buf_t* b);
|
||||||
void SetConnected(bool connected);
|
void SetConnected(bool connected);
|
||||||
void DispatchMessages();
|
void DispatchMessages();
|
||||||
@ -255,7 +254,7 @@ class AgentImpl {
|
|||||||
|
|
||||||
uv_async_t* data_written_;
|
uv_async_t* data_written_;
|
||||||
uv_async_t io_thread_req_;
|
uv_async_t io_thread_req_;
|
||||||
inspector_socket_t* client_socket_;
|
InspectorSocket* client_socket_;
|
||||||
V8NodeInspector* inspector_;
|
V8NodeInspector* inspector_;
|
||||||
v8::Platform* platform_;
|
v8::Platform* platform_;
|
||||||
MessageQueue incoming_message_queue_;
|
MessageQueue incoming_message_queue_;
|
||||||
@ -281,7 +280,7 @@ void InterruptCallback(v8::Isolate*, void* agent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DataCallback(uv_stream_t* stream, ssize_t read, const uv_buf_t* buf) {
|
void DataCallback(uv_stream_t* stream, ssize_t read, const uv_buf_t* buf) {
|
||||||
inspector_socket_t* socket = inspector_from_stream(stream);
|
InspectorSocket* socket = inspector_from_stream(stream);
|
||||||
static_cast<AgentImpl*>(socket->data)->OnRemoteDataIO(socket, read, buf);
|
static_cast<AgentImpl*>(socket->data)->OnRemoteDataIO(socket, read, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +593,7 @@ void AgentImpl::ThreadCbIO(void* agent) {
|
|||||||
// static
|
// static
|
||||||
void AgentImpl::OnSocketConnectionIO(uv_stream_t* server, int status) {
|
void AgentImpl::OnSocketConnectionIO(uv_stream_t* server, int status) {
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
inspector_socket_t* socket = new inspector_socket_t();
|
InspectorSocket* socket = new InspectorSocket();
|
||||||
socket->data = server->data;
|
socket->data = server->data;
|
||||||
if (inspector_accept(server, socket,
|
if (inspector_accept(server, socket,
|
||||||
AgentImpl::OnInspectorHandshakeIO) != 0) {
|
AgentImpl::OnInspectorHandshakeIO) != 0) {
|
||||||
@ -604,7 +603,7 @@ void AgentImpl::OnSocketConnectionIO(uv_stream_t* server, int status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool AgentImpl::OnInspectorHandshakeIO(inspector_socket_t* socket,
|
bool AgentImpl::OnInspectorHandshakeIO(InspectorSocket* socket,
|
||||||
enum inspector_handshake_event state,
|
enum inspector_handshake_event state,
|
||||||
const std::string& path) {
|
const std::string& path) {
|
||||||
AgentImpl* agent = static_cast<AgentImpl*>(socket->data);
|
AgentImpl* agent = static_cast<AgentImpl*>(socket->data);
|
||||||
@ -626,7 +625,7 @@ bool AgentImpl::OnInspectorHandshakeIO(inspector_socket_t* socket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
|
void AgentImpl::OnRemoteDataIO(InspectorSocket* socket,
|
||||||
ssize_t read,
|
ssize_t read,
|
||||||
const uv_buf_t* buf) {
|
const uv_buf_t* buf) {
|
||||||
Mutex::ScopedLock scoped_lock(pause_lock_);
|
Mutex::ScopedLock scoped_lock(pause_lock_);
|
||||||
@ -660,7 +659,7 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
|
|||||||
// static
|
// static
|
||||||
void AgentImpl::WriteCbIO(uv_async_t* async) {
|
void AgentImpl::WriteCbIO(uv_async_t* async) {
|
||||||
AgentImpl* agent = static_cast<AgentImpl*>(async->data);
|
AgentImpl* agent = static_cast<AgentImpl*>(async->data);
|
||||||
inspector_socket_t* socket = agent->client_socket_;
|
InspectorSocket* socket = agent->client_socket_;
|
||||||
if (socket) {
|
if (socket) {
|
||||||
MessageQueue outgoing_messages;
|
MessageQueue outgoing_messages;
|
||||||
agent->SwapBehindLock(&agent->outgoing_message_queue_, &outgoing_messages);
|
agent->SwapBehindLock(&agent->outgoing_message_queue_, &outgoing_messages);
|
||||||
@ -741,7 +740,7 @@ void AgentImpl::PostIncomingMessage(const String16& message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentImpl::OnInspectorConnectionIO(inspector_socket_t* socket) {
|
void AgentImpl::OnInspectorConnectionIO(InspectorSocket* socket) {
|
||||||
if (client_socket_) {
|
if (client_socket_) {
|
||||||
DisconnectAndDisposeIO(socket);
|
DisconnectAndDisposeIO(socket);
|
||||||
return;
|
return;
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#define DUMP_READS 0
|
#define DUMP_READS 0
|
||||||
#define DUMP_WRITES 0
|
#define DUMP_WRITES 0
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
namespace inspector {
|
||||||
|
|
||||||
static const char CLOSE_FRAME[] = {'\x88', '\x00'};
|
static const char CLOSE_FRAME[] = {'\x88', '\x00'};
|
||||||
|
|
||||||
enum ws_decode_result {
|
enum ws_decode_result {
|
||||||
@ -53,7 +56,7 @@ static void remove_from_beginning(std::vector<char>* buffer, size_t count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dispose_inspector(uv_handle_t* handle) {
|
static void dispose_inspector(uv_handle_t* handle) {
|
||||||
inspector_socket_t* inspector = inspector_from_stream(handle);
|
InspectorSocket* inspector = inspector_from_stream(handle);
|
||||||
inspector_cb close =
|
inspector_cb close =
|
||||||
inspector->ws_mode ? inspector->ws_state->close_cb : nullptr;
|
inspector->ws_mode ? inspector->ws_state->close_cb : nullptr;
|
||||||
inspector->buffer.clear();
|
inspector->buffer.clear();
|
||||||
@ -64,7 +67,7 @@ static void dispose_inspector(uv_handle_t* handle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_connection(inspector_socket_t* inspector) {
|
static void close_connection(InspectorSocket* inspector) {
|
||||||
uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->client);
|
uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->client);
|
||||||
if (!uv_is_closing(socket)) {
|
if (!uv_is_closing(socket)) {
|
||||||
uv_read_stop(reinterpret_cast<uv_stream_t*>(socket));
|
uv_read_stop(reinterpret_cast<uv_stream_t*>(socket));
|
||||||
@ -73,7 +76,7 @@ static void close_connection(inspector_socket_t* inspector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WriteRequest {
|
struct WriteRequest {
|
||||||
WriteRequest(inspector_socket_t* inspector, const char* data, size_t size)
|
WriteRequest(InspectorSocket* inspector, const char* data, size_t size)
|
||||||
: inspector(inspector)
|
: inspector(inspector)
|
||||||
, storage(data, data + size)
|
, storage(data, data + size)
|
||||||
, buf(uv_buf_init(&storage[0], storage.size())) {}
|
, buf(uv_buf_init(&storage[0], storage.size())) {}
|
||||||
@ -82,7 +85,7 @@ struct WriteRequest {
|
|||||||
return node::ContainerOf(&WriteRequest::req, req);
|
return node::ContainerOf(&WriteRequest::req, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
inspector_socket_t* const inspector;
|
InspectorSocket* const inspector;
|
||||||
std::vector<char> storage;
|
std::vector<char> storage;
|
||||||
uv_write_t req;
|
uv_write_t req;
|
||||||
uv_buf_t buf;
|
uv_buf_t buf;
|
||||||
@ -93,7 +96,7 @@ static void write_request_cleanup(uv_write_t* req, int status) {
|
|||||||
delete WriteRequest::from_write_req(req);
|
delete WriteRequest::from_write_req(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_to_client(inspector_socket_t* inspector,
|
static int write_to_client(InspectorSocket* inspector,
|
||||||
const char* msg,
|
const char* msg,
|
||||||
size_t len,
|
size_t len,
|
||||||
uv_write_cb write_cb = write_request_cleanup) {
|
uv_write_cb write_cb = write_request_cleanup) {
|
||||||
@ -246,7 +249,7 @@ static ws_decode_result decode_frame_hybi17(const std::vector<char>& buffer,
|
|||||||
return closed ? FRAME_CLOSE : FRAME_OK;
|
return closed ? FRAME_CLOSE : FRAME_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invoke_read_callback(inspector_socket_t* inspector,
|
static void invoke_read_callback(InspectorSocket* inspector,
|
||||||
int status, const uv_buf_t* buf) {
|
int status, const uv_buf_t* buf) {
|
||||||
if (inspector->ws_state->read_cb) {
|
if (inspector->ws_state->read_cb) {
|
||||||
inspector->ws_state->read_cb(
|
inspector->ws_state->read_cb(
|
||||||
@ -254,13 +257,13 @@ static void invoke_read_callback(inspector_socket_t* inspector,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shutdown_complete(inspector_socket_t* inspector) {
|
static void shutdown_complete(InspectorSocket* inspector) {
|
||||||
close_connection(inspector);
|
close_connection(inspector);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_close_frame_written(uv_write_t* req, int status) {
|
static void on_close_frame_written(uv_write_t* req, int status) {
|
||||||
WriteRequest* wr = WriteRequest::from_write_req(req);
|
WriteRequest* wr = WriteRequest::from_write_req(req);
|
||||||
inspector_socket_t* inspector = wr->inspector;
|
InspectorSocket* inspector = wr->inspector;
|
||||||
delete wr;
|
delete wr;
|
||||||
inspector->ws_state->close_sent = true;
|
inspector->ws_state->close_sent = true;
|
||||||
if (inspector->ws_state->received_close) {
|
if (inspector->ws_state->received_close) {
|
||||||
@ -268,7 +271,7 @@ static void on_close_frame_written(uv_write_t* req, int status) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_frame_received(inspector_socket_t* inspector) {
|
static void close_frame_received(InspectorSocket* inspector) {
|
||||||
inspector->ws_state->received_close = true;
|
inspector->ws_state->received_close = true;
|
||||||
if (!inspector->ws_state->close_sent) {
|
if (!inspector->ws_state->close_sent) {
|
||||||
invoke_read_callback(inspector, 0, 0);
|
invoke_read_callback(inspector, 0, 0);
|
||||||
@ -279,7 +282,7 @@ static void close_frame_received(inspector_socket_t* inspector) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_ws_frames(inspector_socket_t* inspector) {
|
static int parse_ws_frames(InspectorSocket* inspector) {
|
||||||
int bytes_consumed = 0;
|
int bytes_consumed = 0;
|
||||||
std::vector<char> output;
|
std::vector<char> output;
|
||||||
bool compressed = false;
|
bool compressed = false;
|
||||||
@ -314,7 +317,7 @@ static void prepare_buffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) {
|
|||||||
*buf = uv_buf_init(new char[len], len);
|
*buf = uv_buf_init(new char[len], len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reclaim_uv_buf(inspector_socket_t* inspector, const uv_buf_t* buf,
|
static void reclaim_uv_buf(InspectorSocket* inspector, const uv_buf_t* buf,
|
||||||
ssize_t read) {
|
ssize_t read) {
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
std::vector<char>& buffer = inspector->buffer;
|
std::vector<char>& buffer = inspector->buffer;
|
||||||
@ -325,7 +328,7 @@ static void reclaim_uv_buf(inspector_socket_t* inspector, const uv_buf_t* buf,
|
|||||||
|
|
||||||
static void websockets_data_cb(uv_stream_t* stream, ssize_t nread,
|
static void websockets_data_cb(uv_stream_t* stream, ssize_t nread,
|
||||||
const uv_buf_t* buf) {
|
const uv_buf_t* buf) {
|
||||||
inspector_socket_t* inspector = inspector_from_stream(stream);
|
InspectorSocket* inspector = inspector_from_stream(stream);
|
||||||
reclaim_uv_buf(inspector, buf, nread);
|
reclaim_uv_buf(inspector, buf, nread);
|
||||||
if (nread < 0 || nread == UV_EOF) {
|
if (nread < 0 || nread == UV_EOF) {
|
||||||
inspector->connection_eof = true;
|
inspector->connection_eof = true;
|
||||||
@ -352,7 +355,7 @@ static void websockets_data_cb(uv_stream_t* stream, ssize_t nread,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int inspector_read_start(inspector_socket_t* inspector,
|
int inspector_read_start(InspectorSocket* inspector,
|
||||||
uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
|
uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
|
||||||
ASSERT(inspector->ws_mode);
|
ASSERT(inspector->ws_mode);
|
||||||
ASSERT(!inspector->shutting_down || read_cb == nullptr);
|
ASSERT(!inspector->shutting_down || read_cb == nullptr);
|
||||||
@ -369,7 +372,7 @@ int inspector_read_start(inspector_socket_t* inspector,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void inspector_read_stop(inspector_socket_t* inspector) {
|
void inspector_read_stop(InspectorSocket* inspector) {
|
||||||
uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->client));
|
uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->client));
|
||||||
inspector->ws_state->alloc_cb = nullptr;
|
inspector->ws_state->alloc_cb = nullptr;
|
||||||
inspector->ws_state->read_cb = nullptr;
|
inspector->ws_state->read_cb = nullptr;
|
||||||
@ -388,7 +391,7 @@ static void generate_accept_string(const std::string& client_key,
|
|||||||
|
|
||||||
static int header_value_cb(http_parser* parser, const char* at, size_t length) {
|
static int header_value_cb(http_parser* parser, const char* at, size_t length) {
|
||||||
static const char SEC_WEBSOCKET_KEY_HEADER[] = "Sec-WebSocket-Key";
|
static const char SEC_WEBSOCKET_KEY_HEADER[] = "Sec-WebSocket-Key";
|
||||||
auto inspector = static_cast<inspector_socket_t*>(parser->data);
|
auto inspector = static_cast<InspectorSocket*>(parser->data);
|
||||||
auto state = inspector->http_parsing_state;
|
auto state = inspector->http_parsing_state;
|
||||||
state->parsing_value = true;
|
state->parsing_value = true;
|
||||||
if (state->current_header.size() == sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1 &&
|
if (state->current_header.size() == sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1 &&
|
||||||
@ -401,7 +404,7 @@ static int header_value_cb(http_parser* parser, const char* at, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int header_field_cb(http_parser* parser, const char* at, size_t length) {
|
static int header_field_cb(http_parser* parser, const char* at, size_t length) {
|
||||||
auto inspector = static_cast<inspector_socket_t*>(parser->data);
|
auto inspector = static_cast<InspectorSocket*>(parser->data);
|
||||||
auto state = inspector->http_parsing_state;
|
auto state = inspector->http_parsing_state;
|
||||||
if (state->parsing_value) {
|
if (state->parsing_value) {
|
||||||
state->parsing_value = false;
|
state->parsing_value = false;
|
||||||
@ -412,13 +415,13 @@ static int header_field_cb(http_parser* parser, const char* at, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int path_cb(http_parser* parser, const char* at, size_t length) {
|
static int path_cb(http_parser* parser, const char* at, size_t length) {
|
||||||
auto inspector = static_cast<inspector_socket_t*>(parser->data);
|
auto inspector = static_cast<InspectorSocket*>(parser->data);
|
||||||
auto state = inspector->http_parsing_state;
|
auto state = inspector->http_parsing_state;
|
||||||
state->path.append(at, length);
|
state->path.append(at, length);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handshake_complete(inspector_socket_t* inspector) {
|
static void handshake_complete(InspectorSocket* inspector) {
|
||||||
uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->client));
|
uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->client));
|
||||||
handshake_cb callback = inspector->http_parsing_state->callback;
|
handshake_cb callback = inspector->http_parsing_state->callback;
|
||||||
inspector->ws_state = new ws_state_s();
|
inspector->ws_state = new ws_state_s();
|
||||||
@ -427,20 +430,20 @@ static void handshake_complete(inspector_socket_t* inspector) {
|
|||||||
inspector->http_parsing_state->path);
|
inspector->http_parsing_state->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup_http_parsing_state(inspector_socket_t* inspector) {
|
static void cleanup_http_parsing_state(InspectorSocket* inspector) {
|
||||||
delete inspector->http_parsing_state;
|
delete inspector->http_parsing_state;
|
||||||
inspector->http_parsing_state = nullptr;
|
inspector->http_parsing_state = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void report_handshake_failure_cb(uv_handle_t* handle) {
|
static void report_handshake_failure_cb(uv_handle_t* handle) {
|
||||||
dispose_inspector(handle);
|
dispose_inspector(handle);
|
||||||
inspector_socket_t* inspector = inspector_from_stream(handle);
|
InspectorSocket* inspector = inspector_from_stream(handle);
|
||||||
handshake_cb cb = inspector->http_parsing_state->callback;
|
handshake_cb cb = inspector->http_parsing_state->callback;
|
||||||
cleanup_http_parsing_state(inspector);
|
cleanup_http_parsing_state(inspector);
|
||||||
cb(inspector, kInspectorHandshakeFailed, std::string());
|
cb(inspector, kInspectorHandshakeFailed, std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_and_report_handshake_failure(inspector_socket_t* inspector) {
|
static void close_and_report_handshake_failure(InspectorSocket* inspector) {
|
||||||
uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->client);
|
uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->client);
|
||||||
if (uv_is_closing(socket)) {
|
if (uv_is_closing(socket)) {
|
||||||
report_handshake_failure_cb(socket);
|
report_handshake_failure_cb(socket);
|
||||||
@ -451,12 +454,12 @@ static void close_and_report_handshake_failure(inspector_socket_t* inspector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void then_close_and_report_failure(uv_write_t* req, int status) {
|
static void then_close_and_report_failure(uv_write_t* req, int status) {
|
||||||
inspector_socket_t* inspector = WriteRequest::from_write_req(req)->inspector;
|
InspectorSocket* inspector = WriteRequest::from_write_req(req)->inspector;
|
||||||
write_request_cleanup(req, status);
|
write_request_cleanup(req, status);
|
||||||
close_and_report_handshake_failure(inspector);
|
close_and_report_handshake_failure(inspector);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handshake_failed(inspector_socket_t* inspector) {
|
static void handshake_failed(InspectorSocket* inspector) {
|
||||||
const char HANDSHAKE_FAILED_RESPONSE[] =
|
const char HANDSHAKE_FAILED_RESPONSE[] =
|
||||||
"HTTP/1.0 400 Bad Request\r\n"
|
"HTTP/1.0 400 Bad Request\r\n"
|
||||||
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
|
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
|
||||||
@ -467,11 +470,10 @@ static void handshake_failed(inspector_socket_t* inspector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init_handshake references message_complete_cb
|
// init_handshake references message_complete_cb
|
||||||
static void init_handshake(inspector_socket_t* inspector);
|
static void init_handshake(InspectorSocket* inspector);
|
||||||
|
|
||||||
static int message_complete_cb(http_parser* parser) {
|
static int message_complete_cb(http_parser* parser) {
|
||||||
inspector_socket_t* inspector =
|
InspectorSocket* inspector = static_cast<InspectorSocket*>(parser->data);
|
||||||
reinterpret_cast<inspector_socket_t*>(parser->data);
|
|
||||||
struct http_parsing_state_s* state = inspector->http_parsing_state;
|
struct http_parsing_state_s* state = inspector->http_parsing_state;
|
||||||
if (parser->method != HTTP_GET) {
|
if (parser->method != HTTP_GET) {
|
||||||
handshake_failed(inspector);
|
handshake_failed(inspector);
|
||||||
@ -517,7 +519,7 @@ static void data_received_cb(uv_stream_s* client, ssize_t nread,
|
|||||||
printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
|
printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
inspector_socket_t* inspector = inspector_from_stream(client);
|
InspectorSocket* inspector = inspector_from_stream(client);
|
||||||
reclaim_uv_buf(inspector, buf, nread);
|
reclaim_uv_buf(inspector, buf, nread);
|
||||||
if (nread < 0 || nread == UV_EOF) {
|
if (nread < 0 || nread == UV_EOF) {
|
||||||
close_and_report_handshake_failure(inspector);
|
close_and_report_handshake_failure(inspector);
|
||||||
@ -536,7 +538,7 @@ static void data_received_cb(uv_stream_s* client, ssize_t nread,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_handshake(inspector_socket_t* inspector) {
|
static void init_handshake(InspectorSocket* inspector) {
|
||||||
http_parsing_state_s* state = inspector->http_parsing_state;
|
http_parsing_state_s* state = inspector->http_parsing_state;
|
||||||
CHECK_NE(state, nullptr);
|
CHECK_NE(state, nullptr);
|
||||||
state->current_header.clear();
|
state->current_header.clear();
|
||||||
@ -553,13 +555,13 @@ static void init_handshake(inspector_socket_t* inspector) {
|
|||||||
settings->on_url = path_cb;
|
settings->on_url = path_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
int inspector_accept(uv_stream_t* server, inspector_socket_t* inspector,
|
int inspector_accept(uv_stream_t* server, InspectorSocket* inspector,
|
||||||
handshake_cb callback) {
|
handshake_cb callback) {
|
||||||
ASSERT_NE(callback, nullptr);
|
ASSERT_NE(callback, nullptr);
|
||||||
CHECK_EQ(inspector->http_parsing_state, nullptr);
|
CHECK_EQ(inspector->http_parsing_state, nullptr);
|
||||||
|
|
||||||
inspector->http_parsing_state = new http_parsing_state_s();
|
inspector->http_parsing_state = new http_parsing_state_s();
|
||||||
uv_stream_t* client = reinterpret_cast<uv_stream_t*>(&inspector->client);
|
uv_stream_t* client = reinterpret_cast<uv_stream_t*>(&inspector->client);
|
||||||
CHECK_NE(client, nullptr);
|
|
||||||
int err = uv_tcp_init(server->loop, &inspector->client);
|
int err = uv_tcp_init(server->loop, &inspector->client);
|
||||||
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
@ -577,7 +579,7 @@ int inspector_accept(uv_stream_t* server, inspector_socket_t* inspector,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void inspector_write(inspector_socket_t* inspector, const char* data,
|
void inspector_write(InspectorSocket* inspector, const char* data,
|
||||||
size_t len) {
|
size_t len) {
|
||||||
if (inspector->ws_mode) {
|
if (inspector->ws_mode) {
|
||||||
std::vector<char> output = encode_frame_hybi17(data, len);
|
std::vector<char> output = encode_frame_hybi17(data, len);
|
||||||
@ -587,7 +589,7 @@ void inspector_write(inspector_socket_t* inspector, const char* data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void inspector_close(inspector_socket_t* inspector,
|
void inspector_close(InspectorSocket* inspector,
|
||||||
inspector_cb callback) {
|
inspector_cb callback) {
|
||||||
// libuv throws assertions when closing stream that's already closed - we
|
// libuv throws assertions when closing stream that's already closed - we
|
||||||
// need to do the same.
|
// need to do the same.
|
||||||
@ -605,8 +607,20 @@ void inspector_close(inspector_socket_t* inspector,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inspector_is_active(const struct inspector_socket_s* inspector) {
|
bool inspector_is_active(const InspectorSocket* inspector) {
|
||||||
const uv_handle_t* client =
|
const uv_handle_t* client =
|
||||||
reinterpret_cast<const uv_handle_t*>(&inspector->client);
|
reinterpret_cast<const uv_handle_t*>(&inspector->client);
|
||||||
return !inspector->shutting_down && !uv_is_closing(client);
|
return !inspector->shutting_down && !uv_is_closing(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InspectorSocket::reinit() {
|
||||||
|
http_parsing_state = nullptr;
|
||||||
|
ws_state = nullptr;
|
||||||
|
buffer.clear();
|
||||||
|
ws_mode = false;
|
||||||
|
shutting_down = false;
|
||||||
|
connection_eof = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace inspector
|
||||||
|
} // namespace node
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
namespace inspector {
|
||||||
|
|
||||||
enum inspector_handshake_event {
|
enum inspector_handshake_event {
|
||||||
kInspectorHandshakeUpgrading,
|
kInspectorHandshakeUpgrading,
|
||||||
kInspectorHandshakeUpgraded,
|
kInspectorHandshakeUpgraded,
|
||||||
@ -16,13 +19,13 @@ enum inspector_handshake_event {
|
|||||||
kInspectorHandshakeFailed
|
kInspectorHandshakeFailed
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inspector_socket_s;
|
class InspectorSocket;
|
||||||
|
|
||||||
typedef void (*inspector_cb)(struct inspector_socket_s*, int);
|
typedef void (*inspector_cb)(InspectorSocket*, int);
|
||||||
// Notifies as handshake is progressing. Returning false as a response to
|
// Notifies as handshake is progressing. Returning false as a response to
|
||||||
// kInspectorHandshakeUpgrading or kInspectorHandshakeHttpGet event will abort
|
// kInspectorHandshakeUpgrading or kInspectorHandshakeHttpGet event will abort
|
||||||
// the connection. inspector_write can be used from the callback.
|
// the connection. inspector_write can be used from the callback.
|
||||||
typedef bool (*handshake_cb)(struct inspector_socket_s*,
|
typedef bool (*handshake_cb)(InspectorSocket*,
|
||||||
enum inspector_handshake_event state,
|
enum inspector_handshake_event state,
|
||||||
const std::string& path);
|
const std::string& path);
|
||||||
|
|
||||||
@ -45,7 +48,12 @@ struct ws_state_s {
|
|||||||
bool received_close;
|
bool received_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inspector_socket_s {
|
class InspectorSocket {
|
||||||
|
public:
|
||||||
|
InspectorSocket() : data(nullptr), http_parsing_state(nullptr),
|
||||||
|
ws_state(nullptr), buffer(0), ws_mode(false),
|
||||||
|
shutting_down(false), connection_eof(false) { }
|
||||||
|
void reinit();
|
||||||
void* data;
|
void* data;
|
||||||
struct http_parsing_state_s* http_parsing_state;
|
struct http_parsing_state_s* http_parsing_state;
|
||||||
struct ws_state_s* ws_state;
|
struct ws_state_s* ws_state;
|
||||||
@ -54,35 +62,39 @@ struct inspector_socket_s {
|
|||||||
bool ws_mode;
|
bool ws_mode;
|
||||||
bool shutting_down;
|
bool shutting_down;
|
||||||
bool connection_eof;
|
bool connection_eof;
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(InspectorSocket);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct inspector_socket_s inspector_socket_t;
|
int inspector_accept(uv_stream_t* server, InspectorSocket* inspector,
|
||||||
|
|
||||||
int inspector_accept(uv_stream_t* server, struct inspector_socket_s* inspector,
|
|
||||||
handshake_cb callback);
|
handshake_cb callback);
|
||||||
|
|
||||||
void inspector_close(struct inspector_socket_s* inspector,
|
void inspector_close(InspectorSocket* inspector,
|
||||||
inspector_cb callback);
|
inspector_cb callback);
|
||||||
|
|
||||||
// Callbacks will receive stream handles. Use inspector_from_stream to get
|
// Callbacks will receive stream handles. Use inspector_from_stream to get
|
||||||
// inspector_socket_t* from the stream handle.
|
// InspectorSocket* from the stream handle.
|
||||||
int inspector_read_start(struct inspector_socket_s* inspector, uv_alloc_cb,
|
int inspector_read_start(InspectorSocket* inspector, uv_alloc_cb,
|
||||||
uv_read_cb);
|
uv_read_cb);
|
||||||
void inspector_read_stop(struct inspector_socket_s* inspector);
|
void inspector_read_stop(InspectorSocket* inspector);
|
||||||
void inspector_write(struct inspector_socket_s* inspector,
|
void inspector_write(InspectorSocket* inspector,
|
||||||
const char* data, size_t len);
|
const char* data, size_t len);
|
||||||
bool inspector_is_active(const struct inspector_socket_s* inspector);
|
bool inspector_is_active(const InspectorSocket* inspector);
|
||||||
|
|
||||||
inline inspector_socket_t* inspector_from_stream(uv_tcp_t* stream) {
|
inline InspectorSocket* inspector_from_stream(uv_tcp_t* stream) {
|
||||||
return node::ContainerOf(&inspector_socket_t::client, stream);
|
return node::ContainerOf(&InspectorSocket::client, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline inspector_socket_t* inspector_from_stream(uv_stream_t* stream) {
|
inline InspectorSocket* inspector_from_stream(uv_stream_t* stream) {
|
||||||
return inspector_from_stream(reinterpret_cast<uv_tcp_t*>(stream));
|
return inspector_from_stream(reinterpret_cast<uv_tcp_t*>(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline inspector_socket_t* inspector_from_stream(uv_handle_t* stream) {
|
inline InspectorSocket* inspector_from_stream(uv_handle_t* stream) {
|
||||||
return inspector_from_stream(reinterpret_cast<uv_tcp_t*>(stream));
|
return inspector_from_stream(reinterpret_cast<uv_tcp_t*>(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace inspector
|
||||||
|
} // namespace node
|
||||||
|
|
||||||
|
|
||||||
#endif // SRC_INSPECTOR_SOCKET_H_
|
#endif // SRC_INSPECTOR_SOCKET_H_
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#define PORT 9444
|
#define PORT 9444
|
||||||
|
|
||||||
|
using namespace node::inspector;
|
||||||
|
|
||||||
static const int MAX_LOOP_ITERATIONS = 10000;
|
static const int MAX_LOOP_ITERATIONS = 10000;
|
||||||
|
|
||||||
#define SPIN_WHILE(condition) \
|
#define SPIN_WHILE(condition) \
|
||||||
@ -23,7 +25,7 @@ static int handshake_events = 0;
|
|||||||
static enum inspector_handshake_event last_event = kInspectorHandshakeHttpGet;
|
static enum inspector_handshake_event last_event = kInspectorHandshakeHttpGet;
|
||||||
static uv_loop_t loop;
|
static uv_loop_t loop;
|
||||||
static uv_tcp_t server, client_socket;
|
static uv_tcp_t server, client_socket;
|
||||||
static inspector_socket_t inspector;
|
static InspectorSocket inspector;
|
||||||
static std::string last_path;
|
static std::string last_path;
|
||||||
static void (*handshake_delegate)(enum inspector_handshake_event state,
|
static void (*handshake_delegate)(enum inspector_handshake_event state,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
@ -76,7 +78,7 @@ static void stop_if_stop_path(enum inspector_handshake_event state,
|
|||||||
*cont = path.empty() || path != "/close";
|
*cont = path.empty() || path != "/close";
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool connected_cb(inspector_socket_t* socket,
|
static bool connected_cb(InspectorSocket* socket,
|
||||||
enum inspector_handshake_event state,
|
enum inspector_handshake_event state,
|
||||||
const std::string& path) {
|
const std::string& path) {
|
||||||
inspector_ready = state == kInspectorHandshakeUpgraded;
|
inspector_ready = state == kInspectorHandshakeUpgraded;
|
||||||
@ -95,7 +97,7 @@ static bool connected_cb(inspector_socket_t* socket,
|
|||||||
static void on_new_connection(uv_stream_t* server, int status) {
|
static void on_new_connection(uv_stream_t* server, int status) {
|
||||||
GTEST_ASSERT_EQ(0, status);
|
GTEST_ASSERT_EQ(0, status);
|
||||||
connected = true;
|
connected = true;
|
||||||
inspector_accept(server, reinterpret_cast<inspector_socket_t*>(server->data),
|
inspector_accept(server, static_cast<InspectorSocket*>(server->data),
|
||||||
connected_cb);
|
connected_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +278,7 @@ static void expect_on_server(const char* data, size_t len) {
|
|||||||
|
|
||||||
static void inspector_record_error_code(uv_stream_t* stream, ssize_t nread,
|
static void inspector_record_error_code(uv_stream_t* stream, ssize_t nread,
|
||||||
const uv_buf_t* buf) {
|
const uv_buf_t* buf) {
|
||||||
inspector_socket_t *inspector = inspector_from_stream(stream);
|
InspectorSocket *inspector = inspector_from_stream(stream);
|
||||||
// Increment instead of assign is to ensure the function is only called once
|
// Increment instead of assign is to ensure the function is only called once
|
||||||
*(static_cast<int*>(inspector->data)) += nread;
|
*(static_cast<int*>(inspector->data)) += nread;
|
||||||
}
|
}
|
||||||
@ -336,13 +338,13 @@ static void on_connection(uv_connect_t* connect, int status) {
|
|||||||
class InspectorSocketTest : public ::testing::Test {
|
class InspectorSocketTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
|
inspector.reinit();
|
||||||
handshake_delegate = stop_if_stop_path;
|
handshake_delegate = stop_if_stop_path;
|
||||||
handshake_events = 0;
|
handshake_events = 0;
|
||||||
connected = false;
|
connected = false;
|
||||||
inspector_ready = false;
|
inspector_ready = false;
|
||||||
last_event = kInspectorHandshakeHttpGet;
|
last_event = kInspectorHandshakeHttpGet;
|
||||||
uv_loop_init(&loop);
|
uv_loop_init(&loop);
|
||||||
inspector = inspector_socket_t();
|
|
||||||
server = uv_tcp_t();
|
server = uv_tcp_t();
|
||||||
client_socket = uv_tcp_t();
|
client_socket = uv_tcp_t();
|
||||||
server.data = &inspector;
|
server.data = &inspector;
|
||||||
@ -568,7 +570,7 @@ TEST_F(InspectorSocketTest, CanStopReadingFromInspector) {
|
|||||||
|
|
||||||
static int inspector_closed = 0;
|
static int inspector_closed = 0;
|
||||||
|
|
||||||
void inspector_closed_cb(inspector_socket_t *inspector, int code) {
|
void inspector_closed_cb(InspectorSocket *inspector, int code) {
|
||||||
inspector_closed++;
|
inspector_closed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +773,7 @@ TEST_F(InspectorSocketTest, WriteBeforeHandshake) {
|
|||||||
SPIN_WHILE(inspector_closed == 0);
|
SPIN_WHILE(inspector_closed == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CleanupSocketAfterEOF_close_cb(inspector_socket_t* inspector,
|
static void CleanupSocketAfterEOF_close_cb(InspectorSocket* inspector,
|
||||||
int status) {
|
int status) {
|
||||||
*(static_cast<bool*>(inspector->data)) = true;
|
*(static_cast<bool*>(inspector->data)) = true;
|
||||||
}
|
}
|
||||||
@ -779,7 +781,7 @@ static void CleanupSocketAfterEOF_close_cb(inspector_socket_t* inspector,
|
|||||||
static void CleanupSocketAfterEOF_read_cb(uv_stream_t* stream, ssize_t nread,
|
static void CleanupSocketAfterEOF_read_cb(uv_stream_t* stream, ssize_t nread,
|
||||||
const uv_buf_t* buf) {
|
const uv_buf_t* buf) {
|
||||||
EXPECT_EQ(UV_EOF, nread);
|
EXPECT_EQ(UV_EOF, nread);
|
||||||
inspector_socket_t* insp = inspector_from_stream(stream);
|
InspectorSocket* insp = inspector_from_stream(stream);
|
||||||
inspector_close(insp, CleanupSocketAfterEOF_close_cb);
|
inspector_close(insp, CleanupSocketAfterEOF_close_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user