1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
module WebSocket
class Driver
class Draft75 < Driver
def initialize(socket, options = {})
super
@stage = 0
@headers['Upgrade'] = 'WebSocket'
@headers['Connection'] = 'Upgrade'
@headers['WebSocket-Origin'] = @socket.env['HTTP_ORIGIN']
@headers['WebSocket-Location'] = @socket.url
end
def version
'hixie-75'
end
def close(reason = nil, code = nil)
return false if @ready_state == 3
@ready_state = 3
emit(:close, CloseEvent.new(nil, nil))
true
end
def parse(chunk)
return if @ready_state > 1
@reader.put(chunk)
@reader.each_byte do |octet|
case @stage
when -1 then
@body << octet
send_handshake_body
when 0 then
parse_leading_byte(octet)
when 1 then
@length = (octet & 0x7F) + 128 * @length
if @closing and @length.zero?
return close
elsif (octet & 0x80) != 0x80
if @length.zero?
@stage = 0
else
@skipped = 0
@stage = 2
end
end
when 2 then
if octet == 0xFF
@stage = 0
emit(:message, MessageEvent.new(Driver.encode(@buffer, :utf8)))
else
if @length
@skipped += 1
@stage = 0 if @skipped == @length
else
@buffer << octet
return close if @buffer.size > @max_length
end
end
end
end
end
def frame(buffer, type = nil, error_type = nil)
return queue([buffer, type, error_type]) if @ready_state == 0
frame = [0x00, buffer, 0xFF].pack('CA*C')
@socket.write(frame)
true
end
private
def handshake_response
start = 'HTTP/1.1 101 Web Socket Protocol Handshake'
headers = [start, @headers.to_s, '']
headers.join("\r\n")
end
def parse_leading_byte(octet)
if (octet & 0x80) == 0x80
@length = 0
@stage = 1
else
@length = nil
@skipped = nil
@buffer = []
@stage = 2
end
end
end
end
end
|