Receber por email
← Voltar para o catálogo

websocket

Habilidade especializada para implementação e teste do protocolo WebSocket. Gera implementações compatíveis com RFC 6455, valida handshake e framing, testa com Autobahn Test Suite, implementa compressão e depura problemas de conexão.

1.4kestrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add a5c-ai/babysitter

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/websocket/svg)](https://www.skillteca.com.br/skills/websocket)

Skills relacionadas

Ver todas de Automação →

Alerta por categoria

Receba novas skills de Automação toda segunda

1 email curto, só com as skills novas de Automação. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

websocket

You are websocket - a specialized skill for WebSocket protocol implementation and testing, providing deep expertise in RFC 6455 compliance, real-time messaging, and performance optimization.

Overview

This skill enables AI-powered WebSocket operations including:

  • Generating RFC 6455 compliant implementations
  • Validating WebSocket handshake and framing
  • Testing with Autobahn Test Suite
  • Implementing permessage-deflate compression
  • Debugging WebSocket connection issues
  • Generating subprotocol handlers
  • Analyzing WebSocket traffic

Prerequisites

  • WebSocket-capable runtime (Node.js, Python, Go, etc.)
  • Optional: wscat or websocat for CLI testing
  • Optional: Autobahn Test Suite for compliance testing

Capabilities

1. WebSocket Handshake

Implement RFC 6455 compliant handshake:

const crypto = require('crypto');
const http = require('http');

const WS_MAGIC_STRING = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';

function computeAcceptKey(secWebSocketKey) {
  return crypto
    .createHash('sha1')
    .update(secWebSocketKey + WS_MAGIC_STRING)
    .digest('base64');
}

function handleUpgrade(req, socket) {
  // Validate upgrade request
  if (req.headers['upgrade']?.toLowerCase() !== 'websocket') {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
    return false;
  }

  const key = req.headers['sec-websocket-key'];
  if (!key) {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
    return false;
  }

  // Validate key format (16 bytes base64 encoded)
  const keyBytes = Buffer.from(key, 'base64');
  if (keyBytes.length !== 16) {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
    return false;
  }

  const acceptKey = computeAcceptKey(key);

  // Optional: Handle subprotocol negotiation
  const requestedProtocols = req.headers['sec-websocket-protocol']?.split(',').map(p => p.trim()) || [];
  const selectedProtocol = negotiateProtocol(requestedProtocols);

  // Build response headers
  let response = [
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    `Sec-WebSocket-Accept: ${acceptKey}`
  ];

  if (selectedProtocol) {
    response.push(`Sec-WebSocket-Protocol: ${selectedProtocol}`);
  }

  // Optional: Handle extensions
  const extensions = negotiateExtensions(req.headers['sec-websocket-extensions']);
  if (extensions) {
    response.push(`Sec-WebSocket-Extensions: ${extensions}`);
  }

  socket.write(response.join('\r\n') + '\r\n\r\n');
  return true;
}

function negotiateProtocol(requested) {
  const supported = ['graphql-ws', 'wamp.2.json', 'mqtt'];
  return requested.find(p => supported.includes(p)) || null;
}

function negotiateExtensions(extensionHeader) {
  // Example: permessage-deflate negotiation
  if (extensionHeader?.includes('permessage-deflate')) {
    return 'permessage-deflate; server_no_context_takeover; client_no_context_takeover';
  }
  return null;
}

2. WebSocket Frame Parsing

Parse and create WebSocket frames:

const OPCODES = {
  CONTINUATION: 0x0,
  TEXT: 0x1,
  BINARY: 0x2,
  CLOSE: 0x8,
  PING: 0x9,
  PONG: 0xA
};

class WebSocketFrame {
  constructor() {
    this.fin = true;
    this.rsv1 = false;
    this.rsv2 = false;
    this.rsv3 = false;
    this.opcode = OPCODES.TEXT;
    this.masked = false;
    this.maskingKey = null;
    this.payload = Buffer.alloc(0);
  }

  static parse(buffer) {
    if (buffer.length < 2) return { frame: null, consumed: 0 };

    const frame = new WebSocketFrame();
    let offset = 0;

    // First byte: FIN, RSV1-3, Opcode
    const byte0 = buffer[offset++];
    frame.fin = (byte0 & 0x80) !== 0;
    frame.rsv1 = (byte0 & 0x40) !== 0;
    frame.rsv2 = (byte0 & 0x20) !== 0;
    frame.rsv3 = (byte0 & 0x10) !== 0;
    frame.opcode = byte0 & 0x0F;

    // Second byte: MASK, Payload length
    const byte1 = buffer[offset++];
    frame.masked = (byte1 & 0x80) !== 0;
    let payloadLength = byte1 & 0x7F;

    // Extended payload length
    if (payloadLength === 126) {
      if (buffer.length < offset + 2) return { frame: null, consumed: 0 };
      payloadLength = buffer.readUInt16BE(offset);
      offset += 2;
    } else if (payloadLength === 127) {
      if (buffer.length < offset + 8) return { frame: null, consumed: 0 };
      // JavaScript can't handle 64-bit integers precisely
      const high = buffer.readUInt32BE(offset);
      const low = buffer.readUInt32BE(offset + 4);
      payloadLength = high * 0x100000000 + low;
      offset += 8;
    }

    // Masking key (if masked)
    if (frame.masked) {
      if (buffer.length < offset + 4) return { frame: null, consumed: 0 };
      frame.maskingKey = buffer.slice(offset, offset + 4);
      offset += 4;
    }

    // Payload
    if (buffer.length < offset + payloadLength) {
      return { frame: null, consumed: 0 };
    }

    frame.payload = buffer.slice(offset, offset + payloadLength);
    offset += payloadLength;

    // Unmask payload if needed
    if (frame.masked) {
      frame.payload = Buffer.from(frame.payload); // Create copy
      for (let i = 0; i < frame.payload.length; i++) {
        frame.payload[i] ^= frame.maskingKey[i % 4];
      }
    }

    return { frame, consumed: offset };
  }

  serialize(mask = false) {
    const payloadLength = this.payload.length;
    let headerLength = 2;

    if (payloadLength > 65535) headerLength += 8;
    else if (payloadLength > 125) headerLength += 2;

    if (mask) headerLength += 4;

    const buffer = Buffer.alloc(headerLength + payloadLength);
    let offset = 0;

    // First byte
    buffer[offset++] = (this.fin ? 0x80 : 0) |
                       (this.rsv1 ? 0x40 : 0) |
                       (this.rsv2 ? 0x20 : 0) |
                       (this.rsv3 ? 0x10 : 0) |
                       this.opcode;

    // Second byte and extended length
    let lengthByte = mask ? 0x80 : 0;

    if (payloadLength > 65535) {
      lengthByte |= 127;
      buffer[offset++] = lengthByte;
      buffer.writeUInt32BE(Math.floor(payloadLength / 0x100000000), offset);
      buffer.writeUInt32BE(payloadLength % 0x100000000, offset + 4);
      offset += 8;
    } else if (payloadLength > 125) {
      lengthByte |= 126;
      buffer[offset++] = lengthByte;
      buffer.writeUInt16BE(payloadLength, offset);
      offset += 2;
    } else {
      lengthByte |= payloadLength;
      buffer[offset++] = lengthByte;
    }

    // Masking key
    if (mask) {
      const maskingKey = crypto.randomBytes(4);
      maskingKey.copy(buffer, offset);
      offset += 4;

      // Copy and mask payload
      for (let i = 0; i < payloadLength; i++) {
        buffer[offset + i] = this.payload[i] ^ maskingKey[i % 4];
      }
    } else {
      this.payload.copy(buffer, offset);
    }

    return buffer;
  }
}

3. WebSocket Server Implementation

Complete WebSocket server:

const http = require('http');
const crypto = require('crypto');
const EventEmitter = require('events');

class WebSocketServer extends EventEmitter {
  constructor(options = {}) {
    super();
    this.port = options.port || 8080;
    this.maxPayload = options.maxPayload || 100 * 1024 * 1024; // 100MB
    this.clients = new Set();

    this.server = http.createServer((req, res) => {
      res.writeHead(426, { 'Content-Type': 'text/plain' });
      res.end('WebSocket server - upgrade required');
    });

    this.server.on('upgrade', (req, socket, head) => {
      this.handleUpgrade(req, socket, head);
    });
  }

  handleUpgrade(req, socket, head) {
    const key = req.headers['sec-websocket-key'];
    if (!key) {
      socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
      return;
    }

    const acceptKey = crypto
      .createHash('sha1')
      .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
      .digest('base64');

    socket.write([
      'HTTP/1.1 101 Switching Protocols',
      'Upgrade: websocket',
      'Connection: Upgrade',
      `Sec-WebSocket-Accept: ${acceptKey}`,
      '',
      ''
    ].join('\r\n'));

Compartilhar X LinkedIn