1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
require 'em/streamer'
# similar to EventMachine::FileStreamer, but for any IO object
module EventMachine
class IOStreamer
include Deferrable
CHUNK_SIZE = 16384
# @param [EventMachine::Connection] connection
# @param [IO] io Data source
# @param [Integer] Data size
#
# @option opts [Boolean] :http_chunks (false) Use HTTP 1.1 style chunked-encoding semantics.
def initialize(connection, io, opts = {})
@connection = connection
@io = io
@http_chunks = opts[:http_chunks]
@buff = String.new
@io.binmode if @io.respond_to?(:binmode)
stream_one_chunk
end
private
# Used internally to stream one chunk at a time over multiple reactor ticks
# @private
def stream_one_chunk
loop do
if @io.eof?
@connection.send_data "0\r\n\r\n" if @http_chunks
succeed
break
end
if @connection.respond_to?(:get_outbound_data_size) && (@connection.get_outbound_data_size > FileStreamer::BackpressureLevel)
EventMachine::next_tick { stream_one_chunk }
break
end
if @io.read(CHUNK_SIZE, @buff)
@connection.send_data("#{@buff.length.to_s(16)}\r\n") if @http_chunks
@connection.send_data(@buff)
@connection.send_data("\r\n") if @http_chunks
end
end
end
end
end
|