From a9410e3e51e45887e38a0fb8da0bb22d90e63887 Mon Sep 17 00:00:00 2001 From: Julien Laffaye Date: Mon, 16 Mar 2015 23:45:56 +0100 Subject: [PATCH] Implements timeouts. Added DialTimeout and Dial functions. Fixes issue #27. --- client_test.go | 7 ++++--- ftp.go | 22 ++++++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/client_test.go b/client_test.go index d93d310..ba2f77d 100644 --- a/client_test.go +++ b/client_test.go @@ -4,6 +4,7 @@ import ( "bytes" "io/ioutil" "testing" + "time" ) const ( @@ -12,7 +13,7 @@ const ( ) func TestConn(t *testing.T) { - c, err := Connect("localhost:21") + c, err := DialTimeout("localhost:21", 5*time.Second) if err != nil { t.Fatal(err) } @@ -112,8 +113,8 @@ func TestConn(t *testing.T) { } // ftp.mozilla.org uses multiline 220 response -func TestConn2(t *testing.T) { - c, err := Connect("ftp.mozilla.org:21") +func TestMultiline(t *testing.T) { + c, err := DialTimeout("ftp.mozilla.org:21", 5*time.Second) if err != nil { t.Fatal(err) } diff --git a/ftp.go b/ftp.go index d6b4d43..ed94755 100644 --- a/ftp.go +++ b/ftp.go @@ -27,6 +27,7 @@ const ( type ServerConn struct { conn *textproto.Conn host string + timeout time.Duration features map[string]string } @@ -44,20 +45,33 @@ type response struct { c *ServerConn } -// Connect initializes the connection to the specified ftp server address. +// Connect is an alias to Dial, for backward compatibility +func Connect(addr string) (*ServerConn, error) { + return Dial(addr) +} + +// Dial is like DialTimeout with no timeout +func Dial(addr string) (*ServerConn, error) { + return DialTimeout(addr, 0) +} + +// DialTimeout initializes the connection to the specified ftp server address. // // It is generally followed by a call to Login() as most FTP commands require // an authenticated user. -func Connect(addr string) (*ServerConn, error) { - conn, err := textproto.Dial("tcp", addr) +func DialTimeout(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], + timeout: timeout, features: make(map[string]string), } @@ -219,7 +233,7 @@ func (c *ServerConn) openDataConn() (net.Conn, error) { // Build the new net address string addr := fmt.Sprintf("%s:%d", c.host, port) - conn, err := net.Dial("tcp", addr) + conn, err := net.DialTimeout("tcp", addr, c.timeout) if err != nil { return nil, err }