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