In the grand, time-honored tradition of re-inventing the wheel, we offer here YET ANOTHER protocol that handles line-oriented data with interspersed binary text. This one trades away some of the performance optimizations of EventMachine::Protocols::LineAndTextProtocol in order to get better correctness with regard to binary text blocks that can switch back to line mode. It also permits the line-delimiter to change in midstream. This was originally written to support Stomp.
TODO! We’re not enforcing the limits on header lengths and text-lengths. When we get around to that, call # if the user defined it, otherwise throw exceptions.
Stub. Should be subclassed by user code.
# File lib/em/protocols/linetext2.rb, line 147 147: def receive_binary_data data 148: # no-op 149: end
# File lib/em/protocols/linetext2.rb, line 48 48: def receive_data data 49: return unless (data and data.length > 0) 50: 51: # Do this stuff in lieu of a constructor. 52: @lt2_mode ||= :lines 53: @lt2_delimiter ||= "\n" 54: @lt2_linebuffer ||= [] 55: 56: if @lt2_mode == :lines 57: if ix = data.index( @lt2_delimiter ) 58: @lt2_linebuffer << data[0...ix] 59: ln = @lt2_linebuffer.join 60: @lt2_linebuffer.clear 61: if @lt2_delimiter == "\n" 62: ln.chomp! 63: end 64: receive_line ln 65: receive_data data[(ix+@lt2_delimiter.length)..1] 66: else 67: @lt2_linebuffer << data 68: end 69: elsif @lt2_mode == :text 70: if @lt2_textsize 71: needed = @lt2_textsize - @lt2_textpos 72: will_take = if data.length > needed 73: needed 74: else 75: data.length 76: end 77: 78: @lt2_textbuffer << data[0...will_take] 79: tail = data[will_take..1] 80: 81: @lt2_textpos += will_take 82: if @lt2_textpos >= @lt2_textsize 83: # Reset line mode (the default behavior) BEFORE calling the 84: # receive_binary_data. This makes it possible for user code 85: # to call set_text_mode, enabling chains of text blocks 86: # (which can possibly be of different sizes). 87: set_line_mode 88: receive_binary_data @lt2_textbuffer.join 89: receive_end_of_binary_data 90: end 91: 92: receive_data tail 93: else 94: receive_binary_data data 95: end 96: end 97: end
Stub. Should be subclassed by user code. This is called when transitioning internally from text mode back to line mode. Useful when client code doesn’t want to keep track of how much data it’s received.
# File lib/em/protocols/linetext2.rb, line 155 155: def receive_end_of_binary_data 156: # no-op 157: end
Stub. Should be subclassed by user code.
# File lib/em/protocols/linetext2.rb, line 142 142: def receive_line ln 143: # no-op 144: end
Alias for #, added for back-compatibility with LineAndTextProtocol.
# File lib/em/protocols/linetext2.rb, line 127 127: def set_binary_mode size=nil 128: set_text_mode size 129: end
# File lib/em/protocols/linetext2.rb, line 100 100: def set_delimiter delim 101: @lt2_delimiter = delim.to_s 102: end
Called internally but also exposed to user code, for the case in which processing of binary data creates a need to transition back to line mode. We support an optional parameter to “throw back” some data, which might be an umprocessed chunk of the transmitted binary data, or something else entirely.
# File lib/em/protocols/linetext2.rb, line 109 109: def set_line_mode data="" 110: @lt2_mode = :lines 111: (@lt2_linebuffer ||= []).clear 112: receive_data data.to_s 113: end
# File lib/em/protocols/linetext2.rb, line 115 115: def set_text_mode size=nil 116: if size == 0 117: set_line_mode 118: else 119: @lt2_mode = :text 120: (@lt2_textbuffer ||= []).clear 121: @lt2_textsize = size # which can be nil, signifying no limit 122: @lt2_textpos = 0 123: end 124: end
In case of a dropped connection, we’ll send a partial buffer to user code when in sized text mode. User overrides of # need to be aware that they may get a short buffer.
# File lib/em/protocols/linetext2.rb, line 134 134: def unbind 135: @lt2_mode ||= nil 136: if @lt2_mode == :text and @lt2_textpos > 0 137: receive_binary_data @lt2_textbuffer.join 138: end 139: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.