Module: EventMachine::Protocols::LineText2
- Included in:
- HeaderAndContentProtocol, HttpClient2, SmtpClient, SmtpServer, Stomp
- Defined in:
- lib/em/protocols/linetext2.rb
Overview
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.
Constant Summary collapse
- MaxBinaryLength =
TODO! We’re not enforcing the limits on header lengths and text-lengths. When we get around to that, call #receive_error if the user defined it, otherwise throw exceptions.
32*1024*1024
Instance Method Summary collapse
-
#receive_binary_data(data) ⇒ Object
Stub.
-
#receive_data(data) ⇒ Object
– Will loop internally until there’s no data left to read.
-
#receive_end_of_binary_data ⇒ Object
Stub.
-
#receive_line(ln) ⇒ Object
Stub.
-
#set_binary_mode(size = nil) ⇒ Object
Alias for #set_text_mode, added for back-compatibility with LineAndTextProtocol.
-
#set_delimiter(delim) ⇒ Object
The line delimiter may be a regular expression or a string.
-
#set_line_mode(data = "") ⇒ Object
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.
- #set_text_mode(size = nil) ⇒ Object
-
#unbind ⇒ Object
In case of a dropped connection, we’ll send a partial buffer to user code when in sized text mode.
Instance Method Details
#receive_binary_data(data) ⇒ Object
Stub. Should be subclassed by user code.
166 167 168 |
# File 'lib/em/protocols/linetext2.rb', line 166 def receive_binary_data data # no-op end |
#receive_data(data) ⇒ Object
– Will loop internally until there’s no data left to read. That way the user-defined handlers we call can modify the handling characteristics on a per-token basis.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/em/protocols/linetext2.rb', line 47 def receive_data data return unless (data and data.length > 0) # Do this stuff in lieu of a constructor. @lt2_mode ||= :lines @lt2_delimiter ||= "\n" @lt2_linebuffer ||= [] remaining_data = data while remaining_data.length > 0 if @lt2_mode == :lines delimiter_string = case @lt2_delimiter when Regexp remaining_data.slice(@lt2_delimiter) else @lt2_delimiter end ix = remaining_data.index(delimiter_string) if delimiter_string if ix @lt2_linebuffer << remaining_data[0...ix] ln = @lt2_linebuffer.join @lt2_linebuffer.clear if @lt2_delimiter == "\n" ln.chomp! end receive_line ln remaining_data = remaining_data[(ix+delimiter_string.length)..-1] else @lt2_linebuffer << remaining_data remaining_data = "" end elsif @lt2_mode == :text if @lt2_textsize needed = @lt2_textsize - @lt2_textpos will_take = if remaining_data.length > needed needed else remaining_data.length end @lt2_textbuffer << remaining_data[0...will_take] tail = remaining_data[will_take..-1] @lt2_textpos += will_take if @lt2_textpos >= @lt2_textsize # Reset line mode (the default behavior) BEFORE calling the # receive_binary_data. This makes it possible for user code # to call set_text_mode, enabling chains of text blocks # (which can possibly be of different sizes). set_line_mode receive_binary_data @lt2_textbuffer.join receive_end_of_binary_data end remaining_data = tail else receive_binary_data remaining_data remaining_data = "" end end end end |
#receive_end_of_binary_data ⇒ Object
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.
174 175 176 |
# File 'lib/em/protocols/linetext2.rb', line 174 def receive_end_of_binary_data # no-op end |
#receive_line(ln) ⇒ Object
Stub. Should be subclassed by user code.
161 162 163 |
# File 'lib/em/protocols/linetext2.rb', line 161 def receive_line ln # no-op end |
#set_binary_mode(size = nil) ⇒ Object
Alias for #set_text_mode, added for back-compatibility with LineAndTextProtocol.
146 147 148 |
# File 'lib/em/protocols/linetext2.rb', line 146 def set_binary_mode size=nil set_text_mode size end |
#set_delimiter(delim) ⇒ Object
The line delimiter may be a regular expression or a string. Anything passed to set_delimiter other than a regular expression will be converted to a string.
114 115 116 117 118 119 120 121 |
# File 'lib/em/protocols/linetext2.rb', line 114 def set_delimiter delim @lt2_delimiter = case delim when Regexp delim else delim.to_s end end |
#set_line_mode(data = "") ⇒ Object
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.
128 129 130 131 132 |
# File 'lib/em/protocols/linetext2.rb', line 128 def set_line_mode data="" @lt2_mode = :lines (@lt2_linebuffer ||= []).clear receive_data data.to_s end |
#set_text_mode(size = nil) ⇒ Object
134 135 136 137 138 139 140 141 142 143 |
# File 'lib/em/protocols/linetext2.rb', line 134 def set_text_mode size=nil if size == 0 set_line_mode else @lt2_mode = :text (@lt2_textbuffer ||= []).clear @lt2_textsize = size # which can be nil, signifying no limit @lt2_textpos = 0 end end |
#unbind ⇒ Object
In case of a dropped connection, we’ll send a partial buffer to user code when in sized text mode. User overrides of #receive_binary_data need to be aware that they may get a short buffer.
153 154 155 156 157 158 |
# File 'lib/em/protocols/linetext2.rb', line 153 def unbind @lt2_mode ||= nil if @lt2_mode == :text and @lt2_textpos > 0 receive_binary_data @lt2_textbuffer.join end end |