From 569481fc3b8c334b804905e81b12c4ae902920bb Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Sat, 15 Apr 2017 11:53:19 +0200 Subject: [PATCH] Add SetDeadline to Response closes #70 --- client_test.go | 18 ++++++++++++++++++ ftp.go | 23 ++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/client_test.go b/client_test.go index 94fb341..0409da0 100644 --- a/client_test.go +++ b/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) diff --git a/ftp.go b/ftp.go index f7ae157..567e2fd 100644 --- a/ftp.go +++ b/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) +}