class WebSocket::Driver::Draft76

Constants

BODY_SIZE

Public Class Methods

new(socket, options = {}) click to toggle source
Calls superclass method WebSocket::Driver::Draft75::new
# File lib/websocket/driver/draft76.rb, line 7
def initialize(socket, options = {})
  super
  input  = (@socket.env['rack.input'] || StringIO.new('')).read
  input  = input.dup if input.frozen?
  @stage = -1
  @body  = input.force_encoding(Encoding::BINARY)

  @headers.clear
  @headers['Upgrade'] = 'WebSocket'
  @headers['Connection'] = 'Upgrade'
  @headers['Sec-WebSocket-Origin'] = @socket.env['HTTP_ORIGIN']
  @headers['Sec-WebSocket-Location'] = @socket.url
end

Public Instance Methods

close(reason = nil, code = nil) click to toggle source
# File lib/websocket/driver/draft76.rb, line 31
def close(reason = nil, code = nil)
  return false if @ready_state == 3
  @socket.write([0xFF, 0x00].pack('C*')) if @ready_state == 1
  @ready_state = 3
  emit(:close, CloseEvent.new(nil, nil))
  true
end
start() click to toggle source
Calls superclass method WebSocket::Driver#start
# File lib/websocket/driver/draft76.rb, line 25
def start
  return false unless super
  send_handshake_body
  true
end
version() click to toggle source
# File lib/websocket/driver/draft76.rb, line 21
def version
  'hixie-76'
end

Private Instance Methods

handshake_response() click to toggle source
# File lib/websocket/driver/draft76.rb, line 41
def handshake_response
  env     = @socket.env
  key1    = env['HTTP_SEC_WEBSOCKET_KEY1']
  key2    = env['HTTP_SEC_WEBSOCKET_KEY2']

  raise ProtocolError.new('Missing required header: Sec-WebSocket-Key1') unless key1
  raise ProtocolError.new('Missing required header: Sec-WebSocket-Key2') unless key2

  number1 = number_from_key(key1)
  spaces1 = spaces_in_key(key1)

  number2 = number_from_key(key2)
  spaces2 = spaces_in_key(key2)

  if number1 % spaces1 != 0 or number2 % spaces2 != 0
    raise ProtocolError.new('Client sent invalid Sec-WebSocket-Key headers')
  end

  @key_values = [number1 / spaces1, number2 / spaces2]

  start   = 'HTTP/1.1 101 WebSocket Protocol Handshake'
  headers = [start, @headers.to_s, '']
  headers.join("\r\n")
end
handshake_signature() click to toggle source
# File lib/websocket/driver/draft76.rb, line 66
def handshake_signature
  return nil unless @body.bytesize >= BODY_SIZE

  head = @body[0...BODY_SIZE]
  Digest::MD5.digest((@key_values + [head]).pack('N2A*'))
end
number_from_key(key) click to toggle source
# File lib/websocket/driver/draft76.rb, line 88
def number_from_key(key)
  number = key.scan(/[0-9]/).join('')
  number == '' ? Float::NAN : number.to_i(10)
end
parse_leading_byte(octet) click to toggle source
# File lib/websocket/driver/draft76.rb, line 81
def parse_leading_byte(octet)
  return super unless octet == 0xFF
  @closing = true
  @length  = 0
  @stage   = 1
end
send_handshake_body() click to toggle source
# File lib/websocket/driver/draft76.rb, line 73
def send_handshake_body
  return unless signature = handshake_signature
  @socket.write(signature)
  @stage = 0
  open
  parse(@body[BODY_SIZE..-1]) if @body.bytesize > BODY_SIZE
end
spaces_in_key(key) click to toggle source
# File lib/websocket/driver/draft76.rb, line 93
def spaces_in_key(key)
  key.scan(/ /).size
end