Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspector: report client-visible host and port #19664

Merged
merged 1 commit into from
Apr 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/inspector_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,12 @@ class HttpHandler : public ProtocolHandler {
CancelHandshake();
return;
} else if (!event.upgrade) {
delegate()->OnHttpGet(event.path);
delegate()->OnHttpGet(event.host, event.path);
} else if (event.ws_key.empty()) {
CancelHandshake();
return;
} else {
delegate()->OnSocketUpgrade(event.path, event.ws_key);
delegate()->OnSocketUpgrade(event.host, event.path, event.ws_key);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/inspector_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ class InspectorSocket {
public:
class Delegate {
public:
virtual void OnHttpGet(const std::string& path) = 0;
virtual void OnSocketUpgrade(const std::string& path,
virtual void OnHttpGet(const std::string& host,
const std::string& path) = 0;
virtual void OnSocketUpgrade(const std::string& host,
const std::string& path,
const std::string& accept_key) = 0;
virtual void OnWsFrame(const std::vector<char>& frame) = 0;
virtual ~Delegate() {}
Expand Down
75 changes: 45 additions & 30 deletions src/inspector_socket_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,42 @@ namespace inspector {
// depend on inspector_socket_server.h
std::string FormatWsAddress(const std::string& host, int port,
const std::string& target_id,
bool include_protocol) {
bool include_protocol);
namespace {

static const uint8_t PROTOCOL_JSON[] = {
#include "v8_inspector_protocol_json.h" // NOLINT(build/include_order)
};

void Escape(std::string* string) {
for (char& c : *string) {
c = (c == '\"' || c == '\\') ? '_' : c;
}
}

std::string FormatHostPort(const std::string& host, int port) {
// Host is valid (socket was bound) so colon means it's a v6 IP address
bool v6 = host.find(':') != std::string::npos;
std::ostringstream url;
if (include_protocol)
url << "ws://";
if (v6) {
url << '[';
}
url << host;
if (v6) {
url << ']';
}
url << ':' << port << '/' << target_id;
url << ':' << port;
return url.str();
}

namespace {

static const uint8_t PROTOCOL_JSON[] = {
#include "v8_inspector_protocol_json.h" // NOLINT(build/include_order)
};

void Escape(std::string* string) {
for (char& c : *string) {
c = (c == '\"' || c == '\\') ? '_' : c;
}
std::string FormatAddress(const std::string& host,
const std::string& target_id,
bool include_protocol) {
std::ostringstream url;
if (include_protocol)
url << "ws://";
url << host << '/' << target_id;
return url.str();
}

std::string MapToString(const std::map<std::string, std::string>& object) {
Expand Down Expand Up @@ -141,6 +150,11 @@ void SendProtocolJson(InspectorSocket* socket) {
}
} // namespace

std::string FormatWsAddress(const std::string& host, int port,
const std::string& target_id,
bool include_protocol) {
return FormatAddress(FormatHostPort(host, port), target_id, include_protocol);
}

class Closer {
public:
Expand Down Expand Up @@ -213,8 +227,8 @@ class SocketSession {
~Delegate() {
server_->SessionTerminated(session_id_);
}
void OnHttpGet(const std::string& path) override;
void OnSocketUpgrade(const std::string& path,
void OnHttpGet(const std::string& host, const std::string& path) override;
void OnSocketUpgrade(const std::string& host, const std::string& path,
const std::string& ws_key) override;
void OnWsFrame(const std::vector<char>& data) override;

Expand Down Expand Up @@ -320,6 +334,7 @@ void InspectorSocketServer::SessionTerminated(int session_id) {
}

bool InspectorSocketServer::HandleGetRequest(int session_id,
const std::string& host,
const std::string& path) {
SocketSession* session = Session(session_id);
InspectorSocket* socket = session->ws_socket();
Expand All @@ -328,25 +343,20 @@ bool InspectorSocketServer::HandleGetRequest(int session_id,
return false;

if (MatchPathSegment(command, "list") || command[0] == '\0') {
SendListResponse(socket, session);
SendListResponse(socket, host, session);
return true;
} else if (MatchPathSegment(command, "protocol")) {
SendProtocolJson(socket);
return true;
} else if (MatchPathSegment(command, "version")) {
SendVersionResponse(socket);
return true;
} else if (const char* target_id = MatchPathSegment(command, "activate")) {
if (TargetExists(target_id)) {
SendHttpResponse(socket, "Target activated");
return true;
}
return false;
}
return false;
}

void InspectorSocketServer::SendListResponse(InspectorSocket* socket,
const std::string& host,
SocketSession* session) {
std::vector<std::map<std::string, std::string>> response;
for (const std::string& id : delegate_->GetTargetIds()) {
Expand All @@ -371,15 +381,18 @@ void InspectorSocketServer::SendListResponse(InspectorSocket* socket,
}
}
if (!connected) {
std::string host = socket->GetHost();
int port = session->server_port();
std::string detected_host = host;
if (detected_host.empty()) {
detected_host = FormatHostPort(socket->GetHost(),
session->server_port());
}
std::ostringstream frontend_url;
frontend_url << "chrome-devtools://devtools/bundled";
frontend_url << "/inspector.html?experiments=true&v8only=true&ws=";
frontend_url << FormatWsAddress(host, port, id, false);
frontend_url << FormatAddress(detected_host, id, false);
target_map["devtoolsFrontendUrl"] += frontend_url.str();
target_map["webSocketDebuggerUrl"] =
FormatWsAddress(host, port, id, true);
FormatAddress(detected_host, id, true);
}
}
SendHttpResponse(socket, MapsToString(response));
Expand Down Expand Up @@ -531,12 +544,14 @@ void SocketSession::Send(const std::string& message) {
ws_socket_->Write(message.data(), message.length());
}

void SocketSession::Delegate::OnHttpGet(const std::string& path) {
if (!server_->HandleGetRequest(session_id_, path))
void SocketSession::Delegate::OnHttpGet(const std::string& host,
const std::string& path) {
if (!server_->HandleGetRequest(session_id_, host, path))
Session()->ws_socket()->CancelHandshake();
}

void SocketSession::Delegate::OnSocketUpgrade(const std::string& path,
void SocketSession::Delegate::OnSocketUpgrade(const std::string& host,
const std::string& path,
const std::string& ws_key) {
std::string id = path.empty() ? path : path.substr(1);
server_->SessionStarted(session_id_, id, ws_key);
Expand Down
6 changes: 4 additions & 2 deletions src/inspector_socket_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class InspectorSocketServer {

// Session connection lifecycle
void Accept(int server_port, uv_stream_t* server_socket);
bool HandleGetRequest(int session_id, const std::string& path);
bool HandleGetRequest(int session_id, const std::string& host,
const std::string& path);
void SessionStarted(int session_id, const std::string& target_id,
const std::string& ws_id);
void SessionTerminated(int session_id);
Expand All @@ -77,7 +78,8 @@ class InspectorSocketServer {
SocketSession* Session(int session_id);

private:
void SendListResponse(InspectorSocket* socket, SocketSession* session);
void SendListResponse(InspectorSocket* socket, const std::string& host,
SocketSession* session);
bool TargetExists(const std::string& id);

enum class ServerState {kNew, kRunning, kStopping, kStopped};
Expand Down
4 changes: 2 additions & 2 deletions test/cctest/test_inspector_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ class TestInspectorDelegate : public InspectorSocket::Delegate {
delegate = nullptr;
}

void OnHttpGet(const std::string& path) override {
void OnHttpGet(const std::string& host, const std::string& path) override {
process(kInspectorHandshakeHttpGet, path);
}

void OnSocketUpgrade(const std::string& path,
void OnSocketUpgrade(const std::string& host, const std::string& path,
const std::string& ws_key) override {
ws_key_ = ws_key;
process(kInspectorHandshakeUpgraded, path);
Expand Down
5 changes: 3 additions & 2 deletions test/common/inspector-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,11 @@ class NodeInstance {
}
}

httpGet(host, path) {
httpGet(host, path, hostHeaderValue) {
console.log('[test]', `Testing ${path}`);
const headers = hostHeaderValue ? { 'Host': hostHeaderValue } : null;
return this.portPromise.then((port) => new Promise((resolve, reject) => {
const req = http.get({ host, port, path }, (res) => {
const req = http.get({ host, port, path, headers }, (res) => {
let response = '';
res.setEncoding('utf8');
res
Expand Down
22 changes: 22 additions & 0 deletions test/parallel/test-inspector-reported-host.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');

common.skipIfInspectorDisabled();

const assert = require('assert');
const { NodeInstance } = require('../common/inspector-helper.js');

common.crashOnUnhandledRejection();

async function test() {
const madeUpHost = '111.111.111.111:11111';
const child = new NodeInstance(undefined, 'var a = 1');
const response = await child.httpGet(null, '/json', madeUpHost);
assert.ok(
response[0].webSocketDebuggerUrl.startsWith(`ws://${madeUpHost}`),
response[0].webSocketDebuggerUrl);
child.kill();
}

test();
5 changes: 3 additions & 2 deletions test/sequential/test-inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ function checkListResponse(response) {
assert.strictEqual(1, response.length);
assert.ok(response[0].devtoolsFrontendUrl);
assert.ok(
/ws:\/\/127\.0\.0\.1:\d+\/[0-9A-Fa-f]{8}-/
.test(response[0].webSocketDebuggerUrl));
/ws:\/\/localhost:\d+\/[0-9A-Fa-f]{8}-/
.test(response[0].webSocketDebuggerUrl),
response[0].webSocketDebuggerUrl);
}

function checkVersion(response) {
Expand Down