class EventMachine::Protocols::LineAndTextProtocol
that can switch back to line mode.
for a version which is optimized for correctness with regard to binary text blocks
This version is optimized for performance. See EventMachine::Protocols::LineText2
A protocol that handles line-oriented data with interspersed binary text.
def initialize *args
def initialize *args super lbp_init_line_state end
def lbp_init_line_state
--
def lbp_init_line_state @lpb_buffer = BufferedTokenizer.new("\n") @lbp_mode = :lines end
def receive_data data
def receive_data data if @lbp_mode == :lines begin @lpb_buffer.extract(data).each do |line| receive_line(line.chomp) if respond_to?(:receive_line) end rescue receive_error('overlength line') if respond_to?(:receive_error) close_connection return end else if @lbp_binary_limit > 0 wanted = @lbp_binary_limit - @lbp_binary_bytes_received chunk = nil if data.length > wanted chunk = data.slice!(0...wanted) else chunk = data data = "" end @lbp_binary_buffer[@lbp_binary_bytes_received...(@lbp_binary_bytes_received+chunk.length)] = chunk @lbp_binary_bytes_received += chunk.length if @lbp_binary_bytes_received == @lbp_binary_limit receive_binary_data(@lbp_binary_buffer) if respond_to?(:receive_binary_data) lbp_init_line_state end receive_data(data) if data.length > 0 else receive_binary_data(data) if respond_to?(:receive_binary_data) data = "" end end end
def set_binary_mode size = nil
Specifiyng zero for the limit will cause an immediate transition back to line mode.
Specifying nil for the limit (the default) means there is no limit.
(in which case we'll pass up a partial).
pass it upstream until we've seen it all, or until there is an unbind
If a limit is given, we'll hold the incoming binary data and not
data and passed to the upstream protocol handler as we receive it.
If the limit is nil, then ALL subsequent data will be treated as binary
This recycles all the data currently waiting in the line buffer, if any.
Set up to read the supplied number of binary bytes.
def set_binary_mode size = nil if @lbp_mode == :lines if size == 0 receive_binary_data("") if respond_to?(:receive_binary_data) # Do no more work here. Stay in line mode and keep consuming data. else @lbp_binary_limit = size.to_i # (nil will be stored as zero) if @lbp_binary_limit > 0 raise "Overlength" if @lbp_binary_limit > MaxBinaryLength # arbitrary sanity check @lbp_binary_buffer = "\0" * @lbp_binary_limit @lbp_binary_bytes_received = 0 end @lbp_mode = :binary receive_data @lpb_buffer.flush end else raise "invalid operation" end end
def unbind
def unbind if @lbp_mode == :binary and @lbp_binary_limit > 0 if respond_to?(:receive_binary_data) receive_binary_data( @lbp_binary_buffer[0...@lbp_binary_bytes_received] ) end end end