From aa063173f3d86d7b2a29e77e7ab7f99dc4ab053e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Rosick=C3=BD?= Date: Tue, 28 Mar 2017 23:58:47 +0200 Subject: [PATCH] net/imap: Replace TCPSocket.open with Socket.tcp and sock.gets, sock.read with sock.read_nonblock --- lib/net/imap.rb | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 7a4d4da301..ee878c8415 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -18,6 +18,7 @@ require "monitor" require "digest/md5" require "strscan" +require 'net/protocol' begin require "openssl" rescue LoadError @@ -221,6 +222,16 @@ class IMAP # Returns all response handlers. attr_reader :response_handlers + # Seconds to wait until a connection is opened. + # If the IMAP object cannot open a connection within this time, + # it raises a Net::OpenTimeout exception. The default value is 30 seconds. + attr_reader :open_timeout + + # Seconds to wait until reading one block (by one read(1) call). + # If the IMAP object cannot complete a read() within this time, + # it raises a Net::ReadTimeout exception. The default value is 60 seconds. + attr_reader :read_timeout + # The thread to receive exceptions. attr_accessor :client_thread @@ -1048,6 +1059,8 @@ def self.format_datetime(time) # be installed. # If options[:ssl] is a hash, it's passed to # OpenSSL::SSL::SSLContext#set_params as parameters. + # open_timeout:: Seconds to wait until a connection is opened + # read_timeout:: Seconds to wait until reading one block # # The most common errors are: # @@ -1076,8 +1089,10 @@ def initialize(host, port_or_options = {}, @port = options[:port] || (options[:ssl] ? SSL_PORT : PORT) @tag_prefix = "RUBY" @tagno = 0 + @open_timeout = options[:open_timeout] || 30 + @read_timeout = options[:read_timeout] || 60 @parser = ResponseParser.new - @sock = TCPSocket.open(@host, @port) + @sock = Socket.tcp(@host, @port, :connect_timeout => @open_timeout) begin if options[:ssl] start_tls_session(options[:ssl]) @@ -1199,14 +1214,35 @@ def get_tagged_response(tag, cmd) end end + def get_response_data(length, terminator = nil) + str = nil + buff = String.new + while true + str = @sock.read_nonblock(length, :exception => false) + case str + when :wait_readable + @sock.to_io.wait_readable(@read_timeout) or + raise Net::ReadTimeout, "#{@host}:#{@port} read timeout (exceeds #{@read_timeout} seconds)" + when nil + break + else + buff.concat(str) + if terminator ? buff.include?(terminator) : (buff.length >= length) + break + end + end + end + buff + end + def get_response buff = String.new while true - s = @sock.gets(CRLF) - break unless s + s = get_response_data(1, CRLF) + break if s.length == 0 buff.concat(s) if /\{(\d+)\}\r\n/n =~ s - s = @sock.read($1.to_i) + s = get_response_data($1.to_i) buff.concat(s) else break -- 2.11.0.windows.3