Class: Faye::WebSocket

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
API
Defined in:
lib/faye/websocket.rb,
lib/faye/websocket/api.rb,
lib/faye/websocket/client.rb,
lib/faye/adapters/rainbows.rb,
lib/faye/websocket/adapter.rb,
lib/faye/websocket/hybi_parser.rb,
lib/faye/adapters/rainbows_client.rb,
lib/faye/websocket/draft75_parser.rb,
lib/faye/websocket/draft76_parser.rb,
lib/faye/websocket/hybi_parser/handshake.rb,
lib/faye/websocket/hybi_parser/stream_reader.rb

Defined Under Namespace

Modules: API, Adapter Classes: Client, Draft75Parser, Draft76Parser, HybiParser, RainbowsClient, Stream

Constant Summary collapse

ADAPTERS =
{
  'thin'     => :Thin,
  'rainbows' => :Rainbows,
  'goliath'  => :Goliath
}

Constants included from API::ReadyStates

API::ReadyStates::CLOSED, API::ReadyStates::CLOSING, API::ReadyStates::CONNECTING, API::ReadyStates::OPEN

Instance Attribute Summary collapse

Attributes included from API

#buffered_amount, #ready_state, #url

Attributes included from API::EventTarget

#onclose, #onerror, #onmessage, #onopen

Class Method Summary collapse

Instance Method Summary collapse

Methods included from API

#close, #receive, #send

Methods included from API::EventTarget

#add_event_listener, #dispatch_event, #remove_event_listener

Constructor Details

#initialize(env, supported_protos = nil, options = {}) ⇒ WebSocket

Returns a new instance of WebSocket.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/faye/websocket.rb', line 127

def initialize(env, supported_protos = nil, options = {})
  @env     = env
  @stream  = Stream.new(self)
  @ping    = options[:ping]
  @ping_id = 0
  
  @url = WebSocket.determine_url(@env)
  @ready_state = CONNECTING
  @buffered_amount = 0
  
  @parser = WebSocket.parser(@env).new(self, :protocols => supported_protos)
  
  @send_buffer = []
  EventMachine.next_tick { open }
  
  @callback = @env['async.callback']
  @callback.call([101, {}, @stream])
  @stream.write(@parser.handshake_response)
  
  @ready_state = OPEN if @parser.open?
  
  if @ping
    @ping_timer = EventMachine.add_periodic_timer(@ping) do
      @ping_id += 1
      ping(@ping_id.to_s)
    end
  end
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



124
125
126
# File 'lib/faye/websocket.rb', line 124

def env
  @env
end

Class Method Details

.determine_url(env) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/faye/websocket.rb', line 110

def self.determine_url(env)
  secure = if env.has_key?('HTTP_X_FORWARDED_PROTO')
             env['HTTP_X_FORWARDED_PROTO'] == 'https'
           else
             env['HTTP_ORIGIN'] =~ /^https:/i
           end
  
  scheme = secure ? 'wss:' : 'ws:'
  "#{ scheme }//#{ env['HTTP_HOST'] }#{ env['REQUEST_URI'] }"
end

.encode(string, validate_encoding = false) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/faye/websocket.rb', line 76

def self.encode(string, validate_encoding = false)
  if Array === string
    string = utf8_string(string)
    return nil if validate_encoding and !valid_utf8?(string)
  end
  utf8_string(string)
end

.jruby?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/faye/websocket.rb', line 26

def self.jruby?
  defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
end

.load_adapter(backend) ⇒ Object



63
64
65
66
67
# File 'lib/faye/websocket.rb', line 63

def self.load_adapter(backend)
  const = Kernel.const_get(ADAPTERS[backend]) rescue nil
  require(backend) unless const
  require File.expand_path("../adapters/#{backend}", __FILE__)
end

.parser(env) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/faye/websocket.rb', line 100

def self.parser(env)
  if env['HTTP_SEC_WEBSOCKET_VERSION']
    HybiParser
  elsif env['HTTP_SEC_WEBSOCKET_KEY1']
    Draft76Parser
  else
    Draft75Parser
  end
end

.rbx?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/faye/websocket.rb', line 30

def self.rbx?
  defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
end

.utf8_string(string) ⇒ Object



69
70
71
72
73
74
# File 'lib/faye/websocket.rb', line 69

def self.utf8_string(string)
  string = string.pack('C*') if Array === string
  string.respond_to?(:force_encoding) ?
      string.force_encoding('UTF-8') :
      string
end

.valid_utf8?(byte_array) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
87
88
89
90
91
# File 'lib/faye/websocket.rb', line 84

def self.valid_utf8?(byte_array)
  string = utf8_string(byte_array)
  if defined?(UTF8_MATCH)
    UTF8_MATCH =~ string ? true : false
  else
    string.valid_encoding?
  end
end

.websocket?(env) ⇒ Boolean

Returns:

  • (Boolean)


93
94
95
96
97
98
# File 'lib/faye/websocket.rb', line 93

def self.websocket?(env)
  env['REQUEST_METHOD'] == 'GET' and
  env['HTTP_CONNECTION'] and
  env['HTTP_CONNECTION'].split(/\s*,\s*/).include?('Upgrade') and
  ['WebSocket', 'websocket'].include?(env['HTTP_UPGRADE'])
end

Instance Method Details

#ping(message = '', &callback) ⇒ Object



156
157
158
159
# File 'lib/faye/websocket.rb', line 156

def ping(message = '', &callback)
  return false unless @parser.respond_to?(:ping)
  @parser.ping(message, &callback)
end

#protocolObject



161
162
163
# File 'lib/faye/websocket.rb', line 161

def protocol
  @parser.protocol || ''
end

#rack_responseObject



165
166
167
# File 'lib/faye/websocket.rb', line 165

def rack_response
  [ -1, {}, [] ]
end