123456789_123456789_123456789_123456789_123456789_

Class: DEBUGGER__::UI_CDP::WebSocketClient

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: lib/debug/server_cdp.rb

Class Method Summary

Instance Method Summary

Constructor Details

.new(s) ⇒ WebSocketClient

[ GitHub ]

  
# File 'lib/debug/server_cdp.rb', line 287

def initialize s
  @sock = s
end

Instance Method Details

#extract_data

[ GitHub ]

  
# File 'lib/debug/server_cdp.rb', line 344

def extract_data
  first_group = @sock.getbyte
  fin = first_group & 0b10000000 != 128
  raise 'Unsupported' if fin
  opcode = first_group & 0b00001111
  raise "Unsupported: #{opcode}" unless opcode == 1

  second_group = @sock.getbyte
  mask = second_group & 0b10000000 == 128
  raise 'The server must not mask any frames' if mask
  payload_len = second_group & 0b01111111
  # TODO: Support other payload_lengths
  if payload_len == 126
    payload_len = @sock.read(2).unpack('n*')[0]
  end

  msg = @sock.read payload_len
  show_protocol :<, msg
  JSON.parse msg
end

#handshake(port, path)

[ GitHub ]

  
# File 'lib/debug/server_cdp.rb', line 291

def handshake port, path
  key = SecureRandom.hex(11)
  req = "GET #{path} HTTP/1.1\r\nHost: 127.0.0.1:#{port}\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: #{key}==\r\n\r\n"
  show_protocol :>, req
  @sock.print req
  res = @sock.readpartial 4092
  show_protocol :<, res

  if res.match(/^Sec-WebSocket-Accept: (.*)\r\n/)
    correct_key = Digest::SHA1.base64digest "#{key}==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
    raise "The Sec-WebSocket-Accept value: #{$1} is not valid" unless $1 == correct_key
  else
    raise "Unknown response: #{res}"
  end
end

#send(**msg)

[ GitHub ]

  
# File 'lib/debug/server_cdp.rb', line 307

def send **msg
  msg = JSON.generate(msg)
  show_protocol :>, msg
  frame = Frame.new
  fin = 0b10000000
  opcode = 0b00000001
  frame.char fin + opcode

  mask = 0b10000000 # A client must mask all frames in a WebSocket Protocol.
  bytesize = msg.bytesize
  if bytesize < 126
    payload_len = bytesize
    frame.char mask + payload_len
  elsif bytesize < 2 ** 16
    payload_len = 0b01111110
    frame.char mask + payload_len
    frame.uint16 bytesize
  elsif bytesize < 2 ** 64
    payload_len = 0b01111111
    frame.char mask + payload_len
    frame.ulonglong bytesize
  else
    raise 'Bytesize is too big.'
  end

  masking_key = 4.times.map{
    key = rand(1..255)
    frame.char key
    key
  }
  msg.bytes.each_with_index do |b, i|
    frame.char(b ^ masking_key[i % 4])
  end

  @sock.print frame.b
end