diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb index 4f826c4f09..47501a6824 100644 --- a/lib/net/ftp.rb +++ b/lib/net/ftp.rb @@ -111,6 +111,13 @@ module Net # Net::OpenTimeout exception. The default value is +nil+. attr_accessor :open_timeout + # Number of seconds to wait for the TLS handshake. Any number + # may be used, including Floats for fractional seconds. If the FTP + # object cannot complete the TLS handshake in this many seconds, it + # raises a Net::OpenTimeout exception. The default value is +nil+. + # If +ssl_handshake_timeout+ is +nil+, +open_timeout+ is used instead. + attr_accessor :ssl_handshake_timeout + # Number of seconds to wait for one block to be read (via one read(2) # call). Any number may be used, including Floats for fractional # seconds. If the FTP object cannot read data in this many seconds, @@ -194,6 +201,10 @@ module Net # See Net::FTP#open_timeout for details. Default: +nil+. # read_timeout:: Number of seconds to wait for one block to be read. # See Net::FTP#read_timeout for details. Default: +60+. + # ssl_handshake_timeout:: Number of seconds to wait for the TLS + # handshake. + # See Net::FTP#ssl_handshake_timeout for + # details. Default: +nil+. # debug_mode:: When +true+, all traffic to and from the server is # written to +$stdout+. Default: +false+. # @@ -247,6 +258,7 @@ module Net @bare_sock = @sock = NullSocket.new @logged_in = false @open_timeout = options[:open_timeout] + @ssl_handshake_timeout = options[:ssl_handshake_timeout] @read_timeout = options[:read_timeout] || 60 if host if options[:port] @@ -318,7 +330,7 @@ module Net # SOCKS_SERVER, then a SOCKSSocket is returned, else a Socket is # returned. def open_socket(host, port) # :nodoc: - return Timeout.timeout(@open_timeout, Net::OpenTimeout) { + return Timeout.timeout(@open_timeout, OpenTimeout) { if defined? SOCKSSocket and ENV["SOCKS_SERVER"] @passive = true sock = SOCKSSocket.open(host, port) @@ -338,7 +350,7 @@ module Net # ProFTPD returns 425 for data connections if session is not reused. ssl_sock.session = @ssl_session end - ssl_socket_connect(ssl_sock, @open_timeout) + ssl_socket_connect(ssl_sock, @ssl_handshake_timeout || @open_timeout) if @ssl_context.verify_mode != VERIFY_NONE ssl_sock.post_connection_check(@host) end diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb index d40e2d8283..fb9852e63d 100644 --- a/test/net/ftp/test_ftp.rb +++ b/test/net/ftp/test_ftp.rb @@ -2107,22 +2107,19 @@ EOF commands = [] sock = nil @thread = Thread.start do - begin - sock = server.accept - sock.print("220 (test_ftp).\r\n") - commands.push(sock.gets) - sock.print("234 AUTH success.\r\n") - rescue SystemCallError, IOError - # may be raised by broken connection - end + sock = server.accept + sock.print("220 (test_ftp).\r\n") + commands.push(sock.gets) + sock.print("234 AUTH success.\r\n") end begin assert_raise(Net::OpenTimeout) do Net::FTP.new("localhost", port: port, ssl: { ca_file: CA_FILE }, - open_timeout: 0.1) + ssl_handshake_timeout: 0.1) end + @thread.join ensure sock.close if sock server.close