summaryrefslogtreecommitdiff
path: root/lib/net
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-03-31 04:44:36 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-03-31 04:44:36 +0000
commit5f81a53fd2939c8618b4ba3e01052333e584ba56 (patch)
treea4f4aafa9b5606f064ab371c0184e660e5785e6e /lib/net
parenta3626110d9d67cba3dea060821c453a218023c57 (diff)
* lib/net/ftp.rb (read_timeout=, open_timeout=): supported timeout.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35194 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/net')
-rw-r--r--lib/net/ftp.rb80
1 files changed, 72 insertions, 8 deletions
diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb
index 64de5aa35f..4ea36cac32 100644
--- a/lib/net/ftp.rb
+++ b/lib/net/ftp.rb
@@ -16,6 +16,7 @@
require "socket"
require "monitor"
+require "net/protocol"
module Net
@@ -76,7 +77,7 @@ module Net
# :stopdoc:
FTP_PORT = 21
CRLF = "\r\n"
- DEFAULT_BLOCKSIZE = 4096
+ DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE
# :startdoc:
# When +true+, transfers are performed in binary mode. Default: +true+.
@@ -93,6 +94,24 @@ module Net
# transfers are resumed or restarted. Default: +false+.
attr_accessor :resume
+ # Number of seconds to wait for the connection to open. Any number
+ # may be used, including Floats for fractional seconds. If the FTP
+ # object cannot open a connection in this many seconds, it raises a
+ # Net::OpenTimeout exception.
+ attr_accessor :open_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,
+ # it raises a TimeoutError exception.
+ attr_reader :read_timeout
+
+ # Setter for the read_timeout attribute.
+ def read_timeout=(sec)
+ @sock.read_timeout = sec
+ @read_timeout = sec
+ end
+
# The server's welcome message.
attr_reader :welcome
@@ -135,6 +154,8 @@ module Net
@resume = false
@sock = NullSocket.new
@logged_in = false
+ @open_timeout = nil
+ @read_timeout = 60
if host
connect(host)
if user
@@ -199,12 +220,17 @@ module Net
# SOCKS_SERVER, then a SOCKSSocket is returned, else a TCPSocket is
# returned.
def open_socket(host, port) # :nodoc:
- if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
- @passive = true
- return SOCKSSocket.open(host, port)
- else
- return TCPSocket.open(host, port)
- end
+ return Timeout.timeout(@open_timeout, Net::OpenTimeout) {
+ if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
+ @passive = true
+ sock = SOCKSSocket.open(host, port)
+ else
+ sock = TCPSocket.open(host, port)
+ end
+ io = BufferedSocket.new(sock)
+ io.read_timeout = @read_timeout
+ io
+ }
end
private :open_socket
@@ -405,7 +431,8 @@ module Net
if resp[0] != ?1
raise FTPReplyError, resp
end
- conn = sock.accept
+ conn = BufferedSocket.new(sock.accept)
+ conn.read_timeout = @read_timeout
sock.close
end
return conn
@@ -1016,10 +1043,47 @@ module Net
# :stopdoc:
class NullSocket
+ def read_timeout=(sec)
+ end
+
+ def close
+ end
+
def method_missing(mid, *args)
raise FTPConnectionError, "not connected"
end
end
+
+ class BufferedSocket < BufferedIO
+ [:addr, :peeraddr].each do |method|
+ define_method(method) { |*args|
+ @io.__send__(method, *args)
+ }
+ end
+
+ def read(len = nil)
+ if len
+ s = super(len, "", true)
+ return s.empty? ? nil : s
+ else
+ result = ""
+ while s = super(BUFSIZ, "", true)
+ result << s
+ end
+ return result
+ end
+ end
+
+ def gets
+ return readuntil("\n")
+ rescue EOFError
+ return nil
+ end
+
+ def readline
+ return readuntil("\n")
+ end
+ end
# :startdoc:
end
end