Skip to content
This repository has been archived by the owner on Jul 8, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:goftp/server
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Apr 16, 2016
2 parents b60255f + fa63b56 commit e8484ac
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 38 deletions.
31 changes: 28 additions & 3 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func (cmd commandList) Execute(conn *Conn, param string) {
for _, field := range fields {
if strings.HasPrefix(field, "-") {
//TODO: currently ignore all the flag
fpath = conn.namePrefix
//fpath = conn.namePrefix
} else {
fpath = field
}
Expand Down Expand Up @@ -398,9 +398,34 @@ func (cmd commandNlst) RequireAuth() bool {

func (cmd commandNlst) Execute(conn *Conn, param string) {
conn.writeMessage(150, "Opening ASCII mode data connection for file list")
path := conn.buildPath(param)
var fpath string
if len(param) == 0 {
fpath = param
} else {
fields := strings.Fields(param)
for _, field := range fields {
if strings.HasPrefix(field, "-") {
//TODO: currently ignore all the flag
//fpath = conn.namePrefix
} else {
fpath = field
}
}
}

path := conn.buildPath(fpath)
info, err := conn.driver.Stat(path)
if err != nil {
conn.writeMessage(550, err.Error())
return
}
if !info.IsDir() {
// TODO: should we show the file description?
return
}

var files []FileInfo
err := conn.driver.ListDir(path, func(f FileInfo) error {
err = conn.driver.ListDir(path, func(f FileInfo) error {
files = append(files, f)
return nil
})
Expand Down
8 changes: 5 additions & 3 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,11 @@ func (Conn *Conn) buildPath(filename string) (fullPath string) {
// data socket. Assumes the socket is open and ready to be used.
func (Conn *Conn) sendOutofbandData(data []byte) {
bytes := len(data)
Conn.dataConn.Write(data)
Conn.dataConn.Close()
Conn.dataConn = nil
if Conn.dataConn != nil {
Conn.dataConn.Write(data)
Conn.dataConn.Close()
Conn.dataConn = nil
}
message := "Closing data connection, sent " + strconv.Itoa(bytes) + " bytes"
Conn.writeMessage(226, message)
}
Expand Down
24 changes: 18 additions & 6 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Server struct {
listenTo string
driverFactory DriverFactory
logger *Logger
listener net.Listener
}

// serverOptsWithDefaults copies an ServerOpts struct into a new struct,
Expand Down Expand Up @@ -186,23 +187,34 @@ func (Server *Server) ListenAndServe() error {

Server.logger.Printf("%s listening on %d", Server.Name, Server.Port)

Server.listener = listener
for {
tcpConn, err := listener.Accept()
tcpConn, err := Server.listener.Accept()
if err != nil {
Server.logger.Print("listening error")
Server.logger.Printf("listening error: %v", err)
break
}
driver, err := Server.driverFactory.NewDriver()
if err != nil {
Server.logger.Print("Error creating driver, aborting client connection")
break
Server.logger.Printf("Error creating driver, aborting client connection: %v", err)
tcpConn.Close()
} else {
ftpConn := Server.newConn(tcpConn, driver, Server.Auth)
go ftpConn.Serve()
}
ftpConn := Server.newConn(tcpConn, driver, Server.Auth)
go ftpConn.Serve()
}
return nil
}

// Gracefully stops a server. Already connected clients will retain their connections
func (Server *Server) Shutdown() error {
if Server.listener != nil {
return Server.listener.Close()
}
// server wasnt even started
return nil
}

func buildTcpString(hostname string, port int) (result string) {
if strings.Contains(hostname, ":") {
// ipv6
Expand Down
46 changes: 20 additions & 26 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net"
"strconv"
"strings"
"time"
"sync"
)

// A data socket is used to send non-control data between the client and
Expand Down Expand Up @@ -80,6 +80,7 @@ type ftpPassiveSocket struct {
ingress chan []byte
egress chan []byte
logger *Logger
wg sync.WaitGroup
}

func newPassiveSocket(host string, logger *Logger) (DataSocket, error) {
Expand All @@ -88,12 +89,8 @@ func newPassiveSocket(host string, logger *Logger) (DataSocket, error) {
socket.egress = make(chan []byte)
socket.logger = logger
socket.host = host
go socket.ListenAndServe()
for {
if socket.Port() > 0 {
break
}
time.Sleep(100 * time.Millisecond)
if err := socket.GoListenAndServe(); err != nil {
return nil, err
}
return socket, nil
}
Expand Down Expand Up @@ -128,7 +125,7 @@ func (socket *ftpPassiveSocket) Close() error {
return nil
}

func (socket *ftpPassiveSocket) ListenAndServe() {
func (socket *ftpPassiveSocket) GoListenAndServe() (err error) {
laddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
if err != nil {
socket.logger.Print(err)
Expand All @@ -148,26 +145,23 @@ func (socket *ftpPassiveSocket) ListenAndServe() {
}

socket.port = port
tcpConn, err := listener.AcceptTCP()
if err != nil {
socket.logger.Print(err)
return
}
socket.conn = tcpConn
socket.wg.Add(1)
go func() {
tcpConn, err := listener.AcceptTCP()
socket.wg.Done()
if err != nil {
socket.logger.Print(err)
return
}
socket.conn = tcpConn
}()
return nil
}

func (socket *ftpPassiveSocket) waitForOpenSocket() bool {
retries := 0
for {
if socket.conn != nil {
break
}
if retries > 3 {
socket.logger.Print("socket isn't open")
return false
}
time.Sleep(500 * time.Millisecond)
retries += 1
if socket.conn != nil {
return true
}
return true
socket.wg.Wait()
return socket.conn != nil
}

0 comments on commit e8484ac

Please sign in to comment.