class WebSocket::Driver::Client

def self.generate_key

def self.generate_key
  Base64.strict_encode64(SecureRandom.random_bytes(16))
end

def fail_handshake(message)

def fail_handshake(message)
  message = "Error during WebSocket handshake: #{ message }"
  @ready_state = 3
  emit(:error, ProtocolError.new(message))
  emit(:close, CloseEvent.new(ERRORS[:protocol_error], message))
end

def handshake_request

def handshake_request
  extensions = @extensions.generate_offer
  @headers['Sec-WebSocket-Extensions'] = extensions if extensions
  start   = "GET #{ @pathname } HTTP/1.1"
  headers = [start, @headers.to_s, '']
  headers.join("\r\n")
end

def initialize(socket, options = {})

def initialize(socket, options = {})
  super
  @ready_state = -1
  @key         = Client.generate_key
  @accept      = Hybi.generate_accept(@key)
  @http        = HTTP::Response.new
  uri = URI.parse(@socket.url)
  unless VALID_SCHEMES.include?(uri.scheme)
    raise URIError, "#{ socket.url } is not a valid WebSocket URL"
  end
  path      = (uri.path == '') ? '/' : uri.path
  @pathname = path + (uri.query ? '?' + uri.query : '')
  @headers['Host']                  = Driver.host_header(uri)
  @headers['Upgrade']               = 'websocket'
  @headers['Connection']            = 'Upgrade'
  @headers['Sec-WebSocket-Key']     = @key
  @headers['Sec-WebSocket-Version'] = VERSION
  if @protocols.size > 0
    @headers['Sec-WebSocket-Protocol'] = @protocols * ', '
  end
  if uri.user
    auth = Base64.strict_encode64([uri.user, uri.password] * ':')
    @headers['Authorization'] = 'Basic ' + auth
  end
end

def parse(chunk)

def parse(chunk)
  return if @ready_state == 3
  return super if @ready_state > 0
  @http.parse(chunk)
  return fail_handshake('Invalid HTTP response') if @http.error?
  return unless @http.complete?
  validate_handshake
  return if @ready_state == 3
  open
  parse(@http.body)
end

def proxy(origin, options = {})

def proxy(origin, options = {})
  Proxy.new(self, origin, options)
end

def start

def start
  return false unless @ready_state == -1
  @socket.write(handshake_request)
  @ready_state = 0
  true
end

def validate_handshake

def validate_handshake
  @status  = @http.code
  @headers = Headers.new(@http.headers)
  unless @http.code == 101
    return fail_handshake("Unexpected response code: #{ @http.code }")
  end
  upgrade    = @http['Upgrade'] || ''
  connection = @http['Connection'] || ''
  accept     = @http['Sec-WebSocket-Accept'] || ''
  protocol   = @http['Sec-WebSocket-Protocol'] || ''
  if upgrade == ''
    return fail_handshake("'Upgrade' header is missing")
  elsif upgrade.downcase != 'websocket'
    return fail_handshake("'Upgrade' header value is not 'WebSocket'")
  end
  if connection == ''
    return fail_handshake("'Connection' header is missing")
  elsif connection.downcase != 'upgrade'
    return fail_handshake("'Connection' header value is not 'Upgrade'")
  end
  unless accept == @accept
    return fail_handshake('Sec-WebSocket-Accept mismatch')
  end
  unless protocol == ''
    if @protocols.include?(protocol)
      @protocol = protocol
    else
      return fail_handshake('Sec-WebSocket-Protocol mismatch')
    end
  end
  begin
    @extensions.activate(@headers['Sec-WebSocket-Extensions'])
  rescue ::WebSocket::Extensions::ExtensionError => error
    return fail_handshake(error.message)
  end
end

def version

def version
  "hybi-#{ VERSION }"
end