diff options
Diffstat (limited to 'lib/net/protocol.rb')
-rw-r--r-- | lib/net/protocol.rb | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index cba92613c7..197ea09089 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -26,7 +26,7 @@ require 'io/wait' module Net # :nodoc: class Protocol #:nodoc: internal use only - VERSION = "0.1.0" + VERSION = "0.2.2" private def Protocol.protocol_param(name, val) @@ -120,6 +120,8 @@ module Net # :nodoc: @continue_timeout = continue_timeout @debug_output = debug_output @rbuf = ''.b + @rbuf_empty = true + @rbuf_offset = 0 end attr_reader :io @@ -154,14 +156,15 @@ module Net # :nodoc: LOG "reading #{len} bytes..." read_bytes = 0 begin - while read_bytes + @rbuf.size < len - s = rbuf_consume(@rbuf.size) - read_bytes += s.size - dest << s + while read_bytes + rbuf_size < len + if s = rbuf_consume_all + read_bytes += s.bytesize + dest << s + end rbuf_fill end s = rbuf_consume(len - read_bytes) - read_bytes += s.size + read_bytes += s.bytesize dest << s rescue EOFError raise unless ignore_eof @@ -175,9 +178,10 @@ module Net # :nodoc: read_bytes = 0 begin while true - s = rbuf_consume(@rbuf.size) - read_bytes += s.size - dest << s + if s = rbuf_consume_all + read_bytes += s.bytesize + dest << s + end rbuf_fill end rescue EOFError @@ -188,14 +192,16 @@ module Net # :nodoc: end def readuntil(terminator, ignore_eof = false) + offset = @rbuf_offset begin - until idx = @rbuf.index(terminator) + until idx = @rbuf.index(terminator, offset) + offset = @rbuf.bytesize rbuf_fill end - return rbuf_consume(idx + terminator.size) + return rbuf_consume(idx + terminator.bytesize - @rbuf_offset) rescue EOFError raise unless ignore_eof - return rbuf_consume(@rbuf.size) + return rbuf_consume end end @@ -208,12 +214,16 @@ module Net # :nodoc: BUFSIZE = 1024 * 16 def rbuf_fill - tmp = @rbuf.empty? ? @rbuf : nil + tmp = @rbuf_empty ? @rbuf : nil case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false) when String - return if rv.equal?(tmp) - @rbuf << rv - rv.clear + @rbuf_empty = false + if rv.equal?(tmp) + @rbuf_offset = 0 + else + @rbuf << rv + rv.clear + end return when :wait_readable (io = @io.to_io).wait_readable(@read_timeout) or raise Net::ReadTimeout.new(io) @@ -228,13 +238,40 @@ module Net # :nodoc: end while true end - def rbuf_consume(len) - if len == @rbuf.size + def rbuf_flush + if @rbuf_empty + @rbuf.clear + @rbuf_offset = 0 + end + nil + end + + def rbuf_size + @rbuf.bytesize - @rbuf_offset + end + + def rbuf_consume_all + rbuf_consume if rbuf_size > 0 + end + + def rbuf_consume(len = nil) + if @rbuf_offset == 0 && (len.nil? || len == @rbuf.bytesize) s = @rbuf @rbuf = ''.b + @rbuf_offset = 0 + @rbuf_empty = true + elsif len.nil? + s = @rbuf.byteslice(@rbuf_offset..-1) + @rbuf = ''.b + @rbuf_offset = 0 + @rbuf_empty = true else - s = @rbuf.slice!(0, len) + s = @rbuf.byteslice(@rbuf_offset, len) + @rbuf_offset += len + @rbuf_empty = @rbuf_offset == @rbuf.bytesize + rbuf_flush end + @debug_output << %Q[-> #{s.dump}\n] if @debug_output s end @@ -383,7 +420,7 @@ module Net # :nodoc: len = writing { using_each_crlf_line { begin - block.call(WriteAdapter.new(self, :write_message_0)) + block.call(WriteAdapter.new(self.method(:write_message_0))) rescue LocalJumpError # allow `break' from writer block end @@ -447,17 +484,16 @@ module Net # :nodoc: # The writer adapter class # class WriteAdapter - def initialize(socket, method) - @socket = socket - @method_id = method + def initialize(writer) + @writer = writer end def inspect - "#<#{self.class} socket=#{@socket.inspect}>" + "#<#{self.class} writer=#{@writer.inspect}>" end def write(str) - @socket.__send__(@method_id, str) + @writer.call(str) end alias print write |