lib/faye/websocket/api.rb in faye-websocket-0.4.7-java vs lib/faye/websocket/api.rb in faye-websocket-0.5.0
- old
+ new
@@ -1,97 +1,107 @@
+require File.expand_path('../api/event_target', __FILE__)
+require File.expand_path('../api/event', __FILE__)
+
module Faye
class WebSocket
module API
- module ReadyStates
- CONNECTING = 0
- OPEN = 1
- CLOSING = 2
- CLOSED = 3
- end
+ CONNECTING = 0
+ OPEN = 1
+ CLOSING = 2
+ CLOSED = 3
- class IllegalStateError < StandardError
- end
-
- require File.expand_path('../api/event_target', __FILE__)
- require File.expand_path('../api/event', __FILE__)
include EventTarget
- include ReadyStates
+ extend Forwardable
+ def_delegators :@driver, :version
+
attr_reader :url, :ready_state, :buffered_amount
- private
+ def initialize
+ super
- def open
- return if @parser and not @parser.open?
- @ready_state = OPEN
+ @ready_state = CONNECTING
+ @buffered_amount = 0
- buffer = @send_buffer || []
- while message = buffer.shift
- send(*message)
+ @driver.on(:open) { |e| open }
+ @driver.on(:message) { |e| receive_message(e.data) }
+ @driver.on(:close) { |e| finalize(e.reason, e.code) }
+
+ @driver.on(:error) do |error|
+ event = Event.new('error')
+ event.init_event('error', false, false)
+ dispatch_event(event)
end
+ if @ping
+ @ping_timer = EventMachine.add_periodic_timer(@ping) do
+ @ping_id += 1
+ ping(@ping_id.to_s)
+ end
+ end
+ end
+
+ private
+
+ def open
+ return unless @ready_state == CONNECTING
+ @ready_state = OPEN
event = Event.new('open')
event.init_event('open', false, false)
dispatch_event(event)
end
- public
-
- def receive(data)
- return false unless @ready_state == OPEN
+ def receive_message(data)
+ return unless @ready_state == OPEN
event = Event.new('message')
event.init_event('message', false, false)
event.data = data
dispatch_event(event)
end
- def send(data, type = nil, error_type = nil)
- if @ready_state == CONNECTING
- if @send_buffer
- @send_buffer << [data, type, error_type]
- return true
- else
- raise IllegalStateError, 'Cannot call send(), socket is not open yet'
- end
- end
+ def finalize(reason = nil, code = nil)
+ return if @ready_state == CLOSED
+ @ready_state = CLOSED
+ EventMachine.cancel_timer(@ping_timer) if @ping_timer
+ @stream.close_connection_after_writing
+ event = Event.new('close', :code => code || 1000, :reason => reason || '')
+ event.init_event('close', false, false)
+ dispatch_event(event)
+ end
- return false if @ready_state == CLOSED
+ def parse(data)
+ @driver.parse(data)
+ end
- data = data.to_s unless Array === data
+ public
- data = WebSocket.encode(data) if String === data
- frame = @parser.frame(data, type, error_type)
- @stream.write(frame) if frame
+ def write(data)
+ @stream.write(data)
end
- def close(code = nil, reason = nil, ack = true)
- return if @ready_state == CLOSED
- return if @ready_state == CLOSING && ack
-
- finalize = lambda do
- @ready_state = CLOSED
- EventMachine.cancel_timer(@ping_timer) if @ping_timer
- @stream.close_connection_after_writing
- event = Event.new('close', :code => code || 1000, :reason => reason || '')
- event.init_event('close', false, false)
- dispatch_event(event)
+ def send(message)
+ return false if @ready_state > OPEN
+ case message
+ when Numeric then @driver.text(message.to_s)
+ when String then @driver.text(message)
+ when Array then @driver.binary(message)
+ else false
end
+ end
- return finalize.call if @ready_state == CONNECTING
+ def ping(message = '', &callback)
+ return false if @ready_state > OPEN
+ @driver.ping(message, &callback)
+ end
- @ready_state = CLOSING
+ def close
+ @ready_state = CLOSING if @ready_state == OPEN
+ @driver.close
+ end
- if ack
- if @parser.respond_to?(:close)
- @parser.close(code, reason, &finalize)
- else
- finalize.call
- end
- else
- @parser.close(code, reason) if @parser.respond_to?(:close)
- finalize.call
- end
+ def protocol
+ @driver.protocol || ''
end
end
end
end