# File lib/websocket/driver/hybi.rb, line 10 def self.generate_accept(key) Base64.strict_encode64(Digest::SHA1.digest(key + GUID)) end
# File lib/websocket/driver/hybi.rb, line 56 def initialize(socket, options = {}) super @extensions = ::WebSocket::Extensions.new @stage = 0 @masking = options[:masking] @protocols = options[:protocols] || [] @protocols = @protocols.strip.split(/ *, */) if String === @protocols @require_masking = options[:require_masking] @ping_callbacks = {} @frame = @message = nil return unless @socket.respond_to?(:env) sec_key = @socket.env['HTTP_SEC_WEBSOCKET_KEY'] protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL'] @headers['Upgrade'] = 'websocket' @headers['Connection'] = 'Upgrade' @headers['Sec-WebSocket-Accept'] = Hybi.generate_accept(sec_key) if protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL'] protos = protos.split(/ *, */) if String === protos @protocol = protos.find { |p| @protocols.include?(p) } @headers['Sec-WebSocket-Protocol'] = @protocol if @protocol end end
# File lib/websocket/driver/hybi.rb, line 89 def add_extension(extension) @extensions.add(extension) true end
# File lib/websocket/driver/hybi.rb, line 132 def binary(message) frame(message, :binary) end
# File lib/websocket/driver/hybi.rb, line 145 def close(reason = nil, code = nil) reason ||= '' code ||= ERRORS[:normal_closure] if @ready_state <= 0 @ready_state = 3 emit(:close, CloseEvent.new(code, reason)) true elsif @ready_state == 1 frame(reason, :close, code) @ready_state = 2 true else false end end
# File lib/websocket/driver/hybi.rb, line 162 def frame(buffer, type = nil, code = nil) return queue([buffer, type, code]) if @ready_state <= 0 return false unless @ready_state == 1 message = Message.new frame = Frame.new is_text = String === buffer message.rsv1 = message.rsv2 = message.rsv3 = false message.opcode = OPCODES[type || (is_text ? :text : :binary)] payload = is_text ? buffer.bytes.to_a : buffer payload = [code].pack(PACK_FORMATS[2]).bytes.to_a + payload if code message.data = payload.pack('C*') if MESSAGE_OPCODES.include?(message.opcode) message = @extensions.process_outgoing_message(message) end frame.final = true frame.rsv1 = message.rsv1 frame.rsv2 = message.rsv2 frame.rsv3 = message.rsv3 frame.opcode = message.opcode frame.masked = !!@masking frame.masking_key = SecureRandom.random_bytes(4) if frame.masked frame.length = message.data.bytesize frame.payload = message.data send_frame(frame) true rescue ::WebSocket::Extensions::ExtensionError => error fail(:extension_error, error.message) end
# File lib/websocket/driver/hybi.rb, line 94 def parse(chunk) @reader.put(chunk) buffer = true while buffer case @stage when 0 then buffer = @reader.read(1) parse_opcode(buffer.getbyte(0)) if buffer when 1 then buffer = @reader.read(1) parse_length(buffer.getbyte(0)) if buffer when 2 then buffer = @reader.read(@frame.length_bytes) parse_extended_length(buffer) if buffer when 3 then buffer = @reader.read(4) if buffer @stage = 4 @frame.masking_key = buffer end when 4 then buffer = @reader.read(@frame.length) if buffer @stage = 0 emit_frame(buffer) end else buffer = nil end end end
# File lib/websocket/driver/hybi.rb, line 136 def ping(message = '', &callback) @ping_callbacks[message] = callback if callback frame(message, :ping) end
# File lib/websocket/driver/hybi.rb, line 141 def pong(message = '') frame(message, :pong) end
# File lib/websocket/driver/hybi.rb, line 85 def version "hybi-#{@socket.env['HTTP_SEC_WEBSOCKET_VERSION']}" end