浏览代码

Merge pull request #83 from digineo/deadline

Add SetDeadline to Response
Julien Laffaye 8 年之前
父节点
当前提交
0895dc7f07
共有 2 个文件被更改,包括 32 次插入9 次删除
  1. 18 0
      client_test.go
  2. 14 9
      ftp.go

+ 18 - 0
client_test.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"io/ioutil"
 	"net/textproto"
+	"strings"
 	"testing"
 	"time"
 )
@@ -67,6 +68,7 @@ func testConn(t *testing.T, disableEPSV bool) {
 		t.Error(err)
 	}
 
+	// Read without deadline
 	r, err := c.Retr("tset")
 	if err != nil {
 		t.Error(err)
@@ -81,6 +83,22 @@ func testConn(t *testing.T, disableEPSV bool) {
 		r.Close()
 	}
 
+	// Read with deadline
+	r, err = c.Retr("tset")
+	if err != nil {
+		t.Error(err)
+	} else {
+		r.SetDeadline(time.Now())
+		_, err := ioutil.ReadAll(r)
+		if err == nil {
+			t.Error("deadline should have caused error")
+		} else if !strings.HasSuffix(err.Error(), "i/o timeout") {
+			t.Error(err)
+		}
+		r.Close()
+	}
+
+	// Read with offset
 	r, err = c.RetrFrom("tset", 5)
 	if err != nil {
 		t.Error(err)

+ 14 - 9
ftp.go

@@ -45,8 +45,8 @@ type Entry struct {
 	Time time.Time
 }
 
-// response represent a data-connection
-type response struct {
+// Response represents a data-connection
+type Response struct {
 	conn net.Conn
 	c    *ServerConn
 }
@@ -337,7 +337,7 @@ func (c *ServerConn) NameList(path string) (entries []string, err error) {
 		return
 	}
 
-	r := &response{conn, c}
+	r := &Response{conn, c}
 	defer r.Close()
 
 	scanner := bufio.NewScanner(r)
@@ -368,7 +368,7 @@ func (c *ServerConn) List(path string) (entries []*Entry, err error) {
 		return
 	}
 
-	r := &response{conn, c}
+	r := &Response{conn, c}
 	defer r.Close()
 
 	scanner := bufio.NewScanner(r)
@@ -431,7 +431,7 @@ func (c *ServerConn) FileSize(path string) (int64, error) {
 // FTP server.
 //
 // The returned ReadCloser must be closed to cleanup the FTP data connection.
-func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
+func (c *ServerConn) Retr(path string) (*Response, error) {
 	return c.RetrFrom(path, 0)
 }
 
@@ -439,13 +439,13 @@ func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
 // FTP server, the server will not send the offset first bytes of the file.
 //
 // The returned ReadCloser must be closed to cleanup the FTP data connection.
-func (c *ServerConn) RetrFrom(path string, offset uint64) (io.ReadCloser, error) {
+func (c *ServerConn) RetrFrom(path string, offset uint64) (*Response, error) {
 	conn, err := c.cmdDataConnFrom(offset, "RETR %s", path)
 	if err != nil {
 		return nil, err
 	}
 
-	return &response{conn, c}, nil
+	return &Response{conn, c}, nil
 }
 
 // Stor issues a STOR FTP command to store a file to the remote FTP server.
@@ -531,12 +531,12 @@ func (c *ServerConn) Quit() error {
 }
 
 // Read implements the io.Reader interface on a FTP data connection.
-func (r *response) Read(buf []byte) (int, error) {
+func (r *Response) Read(buf []byte) (int, error) {
 	return r.conn.Read(buf)
 }
 
 // Close implements the io.Closer interface on a FTP data connection.
-func (r *response) Close() error {
+func (r *Response) Close() error {
 	err := r.conn.Close()
 	_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
 	if err2 != nil {
@@ -544,3 +544,8 @@ func (r *response) Close() error {
 	}
 	return err
 }
+
+// SetDeadline sets the deadlines associated with the connection.
+func (r *Response) SetDeadline(t time.Time) error {
+	return r.conn.SetDeadline(t)
+}