# class WebSocket::Driver

### Constants

CloseEvent
ConfigurationError
ConnectEvent
MAX_LENGTH
MessageEvent
OpenEvent
PORTS
PingEvent
PongEvent
ProtocolError
STATES
URIError

### Attributes

protocol[R]
ready_state[R]

### Public Class Methods

client(socket, options = {}) click to toggle source

    # File lib/websocket/driver.rb, line 176
    def self.client(socket, options = {})
      Client.new(socket, options.merge(:masking => true))
    end

encode(data, encoding = nil) click to toggle source

    # File lib/websocket/driver.rb, line 200
    def self.encode(data, encoding = nil)
      if Array === data
        data = data.pack('C*')
        encoding ||= Encoding::BINARY
      end

      return data if encoding.nil? or data.encoding == encoding

      if data.encoding == Encoding::BINARY
        data = data.dup if data.frozen?
        data.force_encoding(encoding)
      else
        data.encode(encoding)
      end
    end

host_header(uri) click to toggle source

    # File lib/websocket/driver.rb, line 216
    def self.host_header(uri)
      host = uri.host
      if uri.port and uri.port != PORTS[uri.scheme]
        host += ":#{uri.port}"
      end
      host
    end

new(socket, options = {}) click to toggle source
Calls superclass method `WebSocket::Driver::EventEmitter::new`

    # File lib/websocket/driver.rb, line 72
    def initialize(socket, options = {})
      super()
      Driver.validate_options(options, [:max_length, :masking, :require_masking, :protocols, :binary_data_format])

      @socket      = socket
      @reader      = StreamReader.new
      @options     = options
      @max_length  = options[:max_length] || MAX_LENGTH
      @headers     = Headers.new
      @queue       = []
      @ready_state = 0

      @binary_data_format = options[:binary_data_format] || :string
    end

rack(socket, options = {}) click to toggle source

    # File lib/websocket/driver.rb, line 184
    def self.rack(socket, options = {})
      env     = socket.env
      version = env['HTTP_SEC_WEBSOCKET_VERSION']
      key     = env['HTTP_SEC_WEBSOCKET_KEY']
      key1    = env['HTTP_SEC_WEBSOCKET_KEY1']
      key2    = env['HTTP_SEC_WEBSOCKET_KEY2']

      if version or key
        Hybi.new(socket, options.merge(:require_masking => true))
      elsif key1 or key2
        Draft76.new(socket, options)
      else
        Draft75.new(socket, options)
      end
    end

server(socket, options = {}) click to toggle source

    # File lib/websocket/driver.rb, line 180
    def self.server(socket, options = {})
      Server.new(socket, options.merge(:require_masking => true))
    end

validate_options(options, valid_keys) click to toggle source

    # File lib/websocket/driver.rb, line 224
    def self.validate_options(options, valid_keys)
      options.keys.each do |key|
        unless valid_keys.include?(key)
          raise ConfigurationError, "Unrecognized option: #{ key.inspect }"
        end
      end

      if options[:binary_data_format]
        unless [:array, :string].include?(options[:binary_data_format])
          raise ConfigurationError, "Invalid :binary_data_format: #{options[:binary_data_format].inspect}"
        end
      end
    end

websocket?(env) click to toggle source

    # File lib/websocket/driver.rb, line 238
    def self.websocket?(env)
      connection = env['HTTP_CONNECTION'] || ''
      upgrade    = env['HTTP_UPGRADE']    || ''

      env['REQUEST_METHOD'] == 'GET' and
      connection.downcase.split(/ *, */).include?('upgrade') and
      upgrade.downcase == 'websocket'
    end

### Public Instance Methods

add_extension(extension) click to toggle source

    # File lib/websocket/driver.rb, line 92
    def add_extension(extension)
      false
    end

binary(message) click to toggle source

    # File lib/websocket/driver.rb, line 125
    def binary(message)
      false
    end

close(reason = nil, code = nil) click to toggle source

    # File lib/websocket/driver.rb, line 137
    def close(reason = nil, code = nil)
      return false unless @ready_state == 1
      @ready_state = 3
      emit(:close, CloseEvent.new(nil, nil))
      true
    end

ping(*args) click to toggle source

    # File lib/websocket/driver.rb, line 129
    def ping(*args)
      false
    end

pong(*args) click to toggle source

    # File lib/websocket/driver.rb, line 133
    def pong(*args)
      false
    end

set_header(name, value) click to toggle source

    # File lib/websocket/driver.rb, line 96
    def set_header(name, value)
      return false unless @ready_state <= 0
      @headers[name] = value
      true
    end

start() click to toggle source

    # File lib/websocket/driver.rb, line 102
    def start
      return false unless @ready_state == 0

      unless Driver.websocket?(@socket.env)
        return fail_handshake(ProtocolError.new('Not a WebSocket request'))
      end

      begin
        response = handshake_response
      rescue => error
        return fail_handshake(error)
      end

      @socket.write(response)
      open unless @stage == -1
      true
    end

state() click to toggle source

    # File lib/websocket/driver.rb, line 87
    def state
      return nil unless @ready_state >= 0
      STATES[@ready_state]
    end

text(message) click to toggle source

    # File lib/websocket/driver.rb, line 120
    def text(message)
      message = Driver.encode(message, Encoding::UTF_8)
      frame(message, :text)
    end

### Private Instance Methods

fail(type, message) click to toggle source

    # File lib/websocket/driver.rb, line 158
    def fail(type, message)
      @ready_state = 2
      emit(:error, ProtocolError.new(message))
      close
    end

fail_handshake(error) click to toggle source

    # File lib/websocket/driver.rb, line 146
    def fail_handshake(error)
      headers = Headers.new
      headers['Content-Type'] = 'text/plain'
      headers['Content-Length'] = error.message.bytesize

      headers = ['HTTP/1.1 400 Bad Request', headers.to_s, error.message]
      @socket.write(headers.join("\r\n"))
      fail(:protocol_error, error.message)

      false
    end

open() click to toggle source

    # File lib/websocket/driver.rb, line 164
    def open
      @ready_state = 1
      @queue.each { |message| frame(*message) }
      @queue = []
      emit(:open, OpenEvent.new)
    end

queue(message) click to toggle source

    # File lib/websocket/driver.rb, line 171
    def queue(message)
      @queue << message
      true
    end