Browse Source

Disable EPSV for tests.

Also disable it for next attempts when it failed.
Julien Laffaye 9 years ago
parent
commit
988909ab28
2 changed files with 26 additions and 15 deletions
  1. 3 2
      client_test.go
  2. 23 13
      ftp.go

+ 3 - 2
client_test.go

@@ -21,7 +21,7 @@ func TestConnEPSV(t *testing.T) {
 	testConn(t, false)
 }
 
-func testConn(t *testing.T, passive bool) {
+func testConn(t *testing.T, disableEPSV bool) {
 	if testing.Short() {
 		t.Skip("skipping test in short mode.")
 	}
@@ -31,8 +31,9 @@ func testConn(t *testing.T, passive bool) {
 		t.Fatal(err)
 	}
 
-	if passive {
+	if disableEPSV {
 		delete(c.features, "EPSV")
+		c.disableEPSV = true
 	}
 
 	err = c.Login("anonymous", "anonymous")

+ 23 - 13
ftp.go

@@ -24,10 +24,11 @@ const (
 
 // ServerConn represents the connection to a remote FTP server.
 type ServerConn struct {
-	conn     *textproto.Conn
-	host     string
-	timeout  time.Duration
-	features map[string]string
+	conn        *textproto.Conn
+	host        string
+	timeout     time.Duration
+	features    map[string]string
+	disableEPSV bool
 }
 
 // Entry describes a file and is returned by List().
@@ -219,17 +220,26 @@ func (c *ServerConn) pasv() (port int, err error) {
 	return
 }
 
+// getDataConnPort returns a port for a new data connection
+// it uses the best available method to do so
+func (c *ServerConn) getDataConnPort() (int, error) {
+	if !c.disableEPSV {
+		if port, err := c.epsv(); err == nil {
+			return port, nil
+		}
+
+		// if there is an error, disable EPSV for the next attempts
+		c.disableEPSV = true
+	}
+
+	return c.pasv()
+}
+
 // openDataConn creates a new FTP data connection.
 func (c *ServerConn) openDataConn() (net.Conn, error) {
-	var (
-		port int
-		err  error
-	)
-
-	if port, err = c.epsv(); err != nil {
-		if port, err = c.pasv(); err != nil {
-			return nil, err
-		}
+	port, err := c.getDataConnPort()
+	if err != nil {
+		return nil, err
 	}
 
 	return net.DialTimeout("tcp", net.JoinHostPort(c.host, strconv.Itoa(port)), c.timeout)