Optionally connect with DialTimeout

This commit is contained in:
Philip Linde 2015-03-16 22:11:45 +01:00
parent 5807e676a3
commit 5ca8165a06

44
ftp.go
View File

@ -28,6 +28,7 @@ type ServerConn struct {
conn *textproto.Conn conn *textproto.Conn
host string host string
features map[string]string features map[string]string
timeout time.Duration
} }
// Entry describes a file and is returned by List(). // Entry describes a file and is returned by List().
@ -76,6 +77,42 @@ func Connect(addr string) (*ServerConn, error) {
return c, nil return c, nil
} }
// Connect initializes the connection to the specified ftp server address with
// the specified timeout setting.
//
// It is generally followed by a call to Login() as most FTP commands require
// an authenticated user.
func ConnectTimeout(addr string, timeout time.Duration) (*ServerConn, error) {
tconn, err := net.DialTimeout("tcp", addr, timeout)
if err != nil {
return nil, err
}
conn := textproto.NewConn(tconn)
a := strings.SplitN(addr, ":", 2)
c := &ServerConn{
conn: conn,
host: a[0],
features: make(map[string]string),
timeout: timeout,
}
_, _, err = c.conn.ReadResponse(StatusReady)
if err != nil {
c.Quit()
return nil, err
}
err = c.feat()
if err != nil {
c.Quit()
return nil, err
}
return c, nil
}
// Login authenticates the client with specified user and password. // Login authenticates the client with specified user and password.
// //
// "anonymous"/"anonymous" is a common user/password scheme for FTP servers // "anonymous"/"anonymous" is a common user/password scheme for FTP servers
@ -199,6 +236,7 @@ func (c *ServerConn) pasv() (port int, err error) {
func (c *ServerConn) openDataConn() (net.Conn, error) { func (c *ServerConn) openDataConn() (net.Conn, error) {
var port int var port int
var err error var err error
var conn net.Conn
// If features contains nat6 or EPSV => EPSV // If features contains nat6 or EPSV => EPSV
// else -> PASV // else -> PASV
@ -219,7 +257,11 @@ func (c *ServerConn) openDataConn() (net.Conn, error) {
// Build the new net address string // Build the new net address string
addr := fmt.Sprintf("%s:%d", c.host, port) addr := fmt.Sprintf("%s:%d", c.host, port)
conn, err := net.Dial("tcp", addr) if c.timeout == 0 {
conn, err = net.Dial("tcp", addr)
} else {
conn, err = net.DialTimeout("tcp", addr, c.timeout)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }