aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable/lib/action_cable/connection/stream.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-01-21 14:59:11 +1030
committerMatthew Draper <matthew@trebex.net>2016-01-24 22:52:40 +1030
commit322dca293b3716ccaa09e7e82046e539b0d2ffda (patch)
tree512383f2375ff948a085183c74c3da2848f58069 /actioncable/lib/action_cable/connection/stream.rb
parent68a9060d02b1eb35c12843c0f1653809b776b35b (diff)
downloadrails-322dca293b3716ccaa09e7e82046e539b0d2ffda.tar.gz
rails-322dca293b3716ccaa09e7e82046e539b0d2ffda.tar.bz2
rails-322dca293b3716ccaa09e7e82046e539b0d2ffda.zip
Import the relevant portions of faye-websocket
(as adapted to use concurrent-ruby / nio4r instead of eventmachine)
Diffstat (limited to 'actioncable/lib/action_cable/connection/stream.rb')
-rw-r--r--actioncable/lib/action_cable/connection/stream.rb59
1 files changed, 59 insertions, 0 deletions
diff --git a/actioncable/lib/action_cable/connection/stream.rb b/actioncable/lib/action_cable/connection/stream.rb
new file mode 100644
index 0000000000..ace250cd16
--- /dev/null
+++ b/actioncable/lib/action_cable/connection/stream.rb
@@ -0,0 +1,59 @@
+module ActionCable
+ module Connection
+ #--
+ # This class is heavily based on faye-websocket-ruby
+ #
+ # Copyright (c) 2010-2015 James Coglan
+ class Stream
+ def initialize(event_loop, socket)
+ @event_loop = event_loop
+ @socket_object = socket
+ @stream_send = socket.env['stream.send']
+
+ @rack_hijack_io = nil
+
+ hijack_rack_socket
+ end
+
+ def each(&callback)
+ @stream_send ||= callback
+ end
+
+ def close
+ shutdown
+ @socket_object.client_gone
+ end
+
+ def shutdown
+ clean_rack_hijack
+ end
+
+ def write(data)
+ return @rack_hijack_io.write(data) if @rack_hijack_io
+ return @stream_send.call(data) if @stream_send
+ rescue EOFError
+ @socket_object.client_gone
+ end
+
+ def receive(data)
+ @socket_object.parse(data)
+ end
+
+ private
+ def hijack_rack_socket
+ return unless @socket_object.env['rack.hijack']
+
+ @socket_object.env['rack.hijack'].call
+ @rack_hijack_io = @socket_object.env['rack.hijack_io']
+
+ @event_loop.attach(@rack_hijack_io, self)
+ end
+
+ def clean_rack_hijack
+ return unless @rack_hijack_io
+ @event_loop.detach(@rack_hijack_io, self)
+ @rack_hijack_io = nil
+ end
+ end
+ end
+end