Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jul 18, 2025

This PR implements WebSocket support in the JSAR Inspector, enabling real-time debugging communication as the foundation for Chrome DevTools Protocol (CDP) integration.

Changes Made

Core WebSocket Implementation

  • Connection Upgrade: Added automatic detection and handling of HTTP to WebSocket upgrade requests
  • RFC 6455 Compliance: Implemented proper WebSocket handshake with SHA-1 + Base64 key generation
  • Frame Handling: Added WebSocket frame parsing for incoming messages and frame generation for outgoing messages
  • Connection Management: Added connection type tracking (HTTP vs WebSocket) with proper state transitions

Connection Limiting

  • Maximum Connections: Enforced limit of 5 concurrent WebSocket connections
  • Graceful Rejection: Additional connection attempts receive HTTP 503 Service Unavailable response
  • Connection Tracking: Added getWebSocketConnectionCount() method to monitor active connections

Enhanced Inspector Architecture

// New connection type tracking
enum class ConnectionType { HTTP, WEBSOCKET };

// WebSocket-specific methods
bool tryUpgradeToWebSocket();
void handleWebSocketFrame();
void sendWebSocketMessage(const std::string &message);
bool canAcceptWebSocketConnection();

Backward Compatibility

  • Preserved HTTP API: All existing /json/* endpoints continue to work unchanged
  • No Breaking Changes: HTTP functionality remains completely intact
  • Graceful Degradation: Invalid WebSocket upgrade requests are processed as normal HTTP requests

Usage Example

// Connect to JSAR Inspector via WebSocket
const ws = new WebSocket('ws://localhost:9423/devtools/inspector/1');

ws.onopen = () => {
    // Send CDP-style command
    ws.send(JSON.stringify({
        id: 1,
        method: 'Runtime.enable',
        params: {}
    }));
};

ws.onmessage = (event) => {
    const response = JSON.parse(event.data);
    console.log('Inspector response:', response);
};

Testing

  • Unit Tests: Comprehensive tests for WebSocket key generation and frame parsing
  • Integration Tests: Validation of HTTP endpoint compatibility and WebSocket upgrade process
  • Connection Limit Testing: Verification of 5-connection limit enforcement

Technical Details

  • WebSocket Handshake: Validates required headers (Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key)
  • Frame Format: Supports text frames (opcode 0x1) and close frames (opcode 0x8)
  • Message Handling: Currently implements echo functionality as placeholder for CDP implementation
  • Error Handling: Proper connection cleanup, frame validation, and timeout handling

This implementation provides the WebSocket transport layer needed for CDP, with the next phase being the replacement of echo functionality with actual CDP message routing and domain implementations.

Fixes #105.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmmirror.com
    • Triggering command: npm install (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits July 18, 2025 17:12
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title [WIP] inspector: supports accept connection as websocket inspector: Add WebSocket support for Chrome DevTools Protocol integration Jul 18, 2025
Copilot AI requested a review from yorkie July 18, 2025 17:19
Copy link
Member

@yorkie yorkie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Remove the build files which should not be committed
  2. Follow the clang-format style in your C/C++ files
  3. Does the SSL necessary?
  4. Add a sample to connect & send/recv from the inspector websocket

Copilot AI and others added 2 commits July 18, 2025 17:30
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 18, 2025

  1. Remove the build files which should not be committed
  2. Follow the clang-format style in your C/C++ files
  3. Does the SSL necessary?
    ...

All feedback addressed in commits a47862e and 79eaa34:

  1. ✅ Removed build files (build/cmake/*) that were incorrectly committed
  2. ✅ Applied clang-format to all C++ files for consistent formatting
  3. ✅ Replaced OpenSSL dependency with self-contained SHA-1 and Base64 implementation for WebSocket handshake (RFC 6455 compliant)
  4. ✅ Added comprehensive WebSocket examples: Node.js client, HTML test page, and documentation in /examples/

Copilot AI requested a review from yorkie July 18, 2025 17:34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the inspector example to the fixtures/inspector-client

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved inspector examples to fixtures/inspector-client/ directory as requested in commit af2033b.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use 2 spaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed HTML indentation to use 2 spaces instead of 4 spaces in commit af2033b.

for (const auto &client : clients_)
{
if (client->isWebSocket())
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
count++;

public:
void tryAccept();
void tick();
int getWebSocketConnectionCount() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int getWebSocketConnectionCount() const;
int coutWebSocketClients() const;


for (const auto &header : headers_)
{
std::string lowerKey = header.first;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

for (const auto &header : headers_)
{
std::string lowerKey = header.first;
std::transform(lowerKey.begin(), lowerKey.end(), lowerKey.begin(), ::tolower);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

DEBUG(LOG_TAG_INSPECTOR, "WebSocket connection limit reached, rejecting upgrade");
// Send 503 Service Unavailable
std::stringstream response;
response << "HTTP/1.1 503 Service Unavailable\r\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add a method for sending 400 or 500 response, which auto calucate the content-length.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added sendHttpErrorResponse() helper method that auto-calculates Content-Length header in commit af2033b.

auto hash = sha1(combined);

// Base64 encode the hash
auto base64Encode = [](const std::array<uint8_t, 20> &input) -> std::string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the base64 encoding to the src/common/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved base64 encoding to src/common/utility.hpp as Base64Encode template function in commit af2033b.

DEBUG(LOG_TAG_INSPECTOR, "Received WebSocket message: %s", message.c_str());

// For now, just echo the message back (placeholder for CDP implementation)
sendWebSocketMessage("Echo: " + message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved to TrInspector such as a lifetime onMessage(client), and you can does this echo logic there :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved echo logic to TrInspector::onMessage(client, message) method - the client now forwards WebSocket messages to the inspector for handling in commit af2033b.

…tility methods

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jul 18, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmmirror.com
    • Triggering command: npm install (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from yorkie July 18, 2025 18:24
…nlikely attribute, remove debug log

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI requested a review from yorkie July 18, 2025 18:55
@yorkie yorkie marked this pull request as ready for review July 18, 2025 19:33
@yorkie yorkie merged commit f17a093 into main Jul 18, 2025
2 checks passed
@yorkie yorkie deleted the copilot/fix-105 branch July 18, 2025 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

inspector: supports accept connection as websocket

2 participants