server

package module
v0.3.5-0...-fb33401 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2020 License: MIT Imports: 24 Imported by: 0

README

server

Build Status

A FTP server framework forked from github.com/yob/graval and changed a lot.

Full documentation for the package is available on godoc

Version

v0.2.3

Installation

go get goftp.io/server

Usage

To boot a FTP server you will need to provide a driver that speaks to your persistence layer - the required driver contract is in the documentation.

Look at the file driver to see an example of how to build a backend.

There is a sample ftp server as a demo. You can build it with this command:

go install goftp.io/server/exampleftpd

Then run it if you have add $GOPATH to your $PATH:

exampleftpd -root /tmp

And finally, connect to the server with any FTP client and the following details:

host: 127.0.0.1
port: 2121
username: admin
password: 123456

This uses the file driver mentioned above to serve files.

Contributors

see https://gitea.com/goftp/server/graphs/contributors

Warning

FTP is an incredibly insecure protocol. Be careful about forcing users to authenticate with an username or password that are important.

License

This library is distributed under the terms of the MIT License. See the included file for more detail.

Contributing

All suggestions and patches welcome, preferably via a git repository I can pull from. If this library proves useful to you, please let me know.

Further Reading

There are a range of RFCs that together specify the FTP protocol. In chronological order, the more useful ones are:

For an english summary that's somewhat more legible than the RFCs, and provides some commentary on what features are actually useful or relevant 24 years after RFC959 was published:

For a history lesson, check out Appendix III of RCF959. It lists the preceding (obsolete) RFC documents that relate to file transfers, including the ye old RFC114 from 1971, "A File Transfer Protocol"

This library is heavily based on em-ftpd, an FTPd framework with similar design goals within the ruby and EventMachine ecosystems. It worked well enough, but you know, callbacks and event loops make me something something.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrServerClosed = errors.New("ftp: Server closed")

ErrServerClosed is returned by ListenAndServe() or Serve() when a shutdown was requested.

Functions

func Version

func Version() string

Version returns the library version

Types

type Auth

type Auth interface {
	CheckPasswd(string, string) (bool, error)
}

Auth is an interface to auth your ftp user login.

type Command

type Command interface {
	IsExtend() bool
	RequireParam() bool
	RequireAuth() bool
	Execute(*Conn, string)
}

Command represents a Command interface to a ftp command

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn represents a connection between ftp client and the server

func (*Conn) Close

func (conn *Conn) Close()

Close will manually close this connection, even if the client isn't ready.

func (*Conn) IsLogin

func (conn *Conn) IsLogin() bool

IsLogin returns if user has login

func (*Conn) LoginUser

func (conn *Conn) LoginUser() string

LoginUser returns the login user name if login

func (*Conn) PassivePort

func (conn *Conn) PassivePort() int

PassivePort returns the port which could be used by passive mode.

func (*Conn) PublicIP

func (conn *Conn) PublicIP() string

PublicIP returns the public ip of the server

func (*Conn) RemoteAddr

func (conn *Conn) RemoteAddr() net.Addr

RemoteAddr returns the remote ftp client's address

func (*Conn) Serve

func (conn *Conn) Serve()

Serve starts an endless loop that reads FTP commands from the client and responds appropriately. terminated is a channel that will receive a true message when the connection closes. This loop will be running inside a goroutine, so use this channel to be notified when the connection can be cleaned up.

func (*Conn) ServerOpts

func (conn *Conn) ServerOpts() *ServerOpts

ServerOpts returns the server options

type DataSocket

type DataSocket interface {
	Host() string

	Port() int

	// the standard io.Reader interface
	Read(p []byte) (n int, err error)

	// the standard io.ReaderFrom interface
	ReadFrom(r io.Reader) (int64, error)

	// the standard io.Writer interface
	Write(p []byte) (n int, err error)

	// the standard io.Closer interface
	Close() error
}

DataSocket describes a data socket is used to send non-control data between the client and server.

type DiscardLogger

type DiscardLogger struct{}

DiscardLogger represents a silent logger, produces no output

func (*DiscardLogger) Print

func (logger *DiscardLogger) Print(sessionID string, message interface{})

Print impelment Logger

func (*DiscardLogger) PrintCommand

func (logger *DiscardLogger) PrintCommand(sessionID string, command string, params string)

PrintCommand impelment Logger

func (*DiscardLogger) PrintResponse

func (logger *DiscardLogger) PrintResponse(sessionID string, code int, message string)

PrintResponse impelment Logger

func (*DiscardLogger) Printf

func (logger *DiscardLogger) Printf(sessionID string, format string, v ...interface{})

Printf impelment Logger

type Driver

type Driver interface {
	// params  - a file path
	// returns - a time indicating when the requested path was last modified
	//         - an error if the file doesn't exist or the user lacks
	//           permissions
	Stat(string) (FileInfo, error)

	// params  - path, function on file or subdir found
	// returns - error
	//           path
	ListDir(string, func(FileInfo) error) error

	// params  - path
	// returns - nil if the directory was deleted or any error encountered
	DeleteDir(string) error

	// params  - path
	// returns - nil if the file was deleted or any error encountered
	DeleteFile(string) error

	// params  - from_path, to_path
	// returns - nil if the file was renamed or any error encountered
	Rename(string, string) error

	// params  - path
	// returns - nil if the new directory was created or any error encountered
	MakeDir(string) error

	// params  - path
	// returns - a string containing the file data to send to the client
	GetFile(string, int64) (int64, io.ReadCloser, error)

	// params  - destination path, an io.Reader containing the file data
	// returns - the number of bytes writen and the first error encountered while writing, if any.
	PutFile(string, io.Reader, bool) (int64, error)
}

Driver is an interface that you will implement to create a driver for your chosen persistence layer. The server will create a new instance of your driver for each client that connects and delegate to it as required.

Note that if the driver also implements the Auth interface then this will be called instead of calling ServerOpts.Auth. This allows the Auth mechanism to change the driver configuration.

type DriverFactory

type DriverFactory interface {
	NewDriver() (Driver, error)
}

DriverFactory is a driver factory to create driver. For each client that connects to the server, a new FTPDriver is required. Create an implementation if this interface and provide it to FTPServer.

type FileDriver

type FileDriver struct {
	RootPath string
	Perm
}

FileDriver implements Driver directly read local file system

func (*FileDriver) DeleteDir

func (driver *FileDriver) DeleteDir(path string) error

DeleteDir implements Driver

func (*FileDriver) DeleteFile

func (driver *FileDriver) DeleteFile(path string) error

DeleteFile implements Driver

func (*FileDriver) GetFile

func (driver *FileDriver) GetFile(path string, offset int64) (int64, io.ReadCloser, error)

GetFile implements Driver

func (*FileDriver) ListDir

func (driver *FileDriver) ListDir(path string, callback func(FileInfo) error) error

ListDir implements Driver

func (*FileDriver) MakeDir

func (driver *FileDriver) MakeDir(path string) error

MakeDir implements Driver

func (*FileDriver) PutFile

func (driver *FileDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error)

PutFile implements Driver

func (*FileDriver) Rename

func (driver *FileDriver) Rename(fromPath string, toPath string) error

Rename implements Driver

func (*FileDriver) Stat

func (driver *FileDriver) Stat(path string) (FileInfo, error)

Stat implements Driver

type FileDriverFactory

type FileDriverFactory struct {
	RootPath string
	Perm
}

FileDriverFactory implements DriverFactory

func (*FileDriverFactory) NewDriver

func (factory *FileDriverFactory) NewDriver() (Driver, error)

NewDriver implements DriverFactory

type FileInfo

type FileInfo interface {
	os.FileInfo

	Owner() string
	Group() string
}

FileInfo represents an file interface

type Logger

type Logger interface {
	Print(sessionID string, message interface{})
	Printf(sessionID string, format string, v ...interface{})
	PrintCommand(sessionID string, command string, params string)
	PrintResponse(sessionID string, code int, message string)
}

Logger represents an interface to record all ftp information and command

type MinioDriver

type MinioDriver struct {
	// contains filtered or unexported fields
}

MinioDriver implements Driver to store files in minio

func (*MinioDriver) DeleteDir

func (driver *MinioDriver) DeleteDir(path string) error

DeleteDir implements Driver

func (*MinioDriver) DeleteFile

func (driver *MinioDriver) DeleteFile(path string) error

DeleteFile implements Driver

func (*MinioDriver) GetFile

func (driver *MinioDriver) GetFile(path string, offset int64) (int64, io.ReadCloser, error)

GetFile implements Driver

func (*MinioDriver) ListDir

func (driver *MinioDriver) ListDir(path string, callback func(FileInfo) error) error

ListDir implements Driver

func (*MinioDriver) MakeDir

func (driver *MinioDriver) MakeDir(path string) error

MakeDir implements Driver

func (*MinioDriver) PutFile

func (driver *MinioDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error)

PutFile implements Driver

func (*MinioDriver) Rename

func (driver *MinioDriver) Rename(fromPath string, toPath string) error

Rename implements Driver

func (*MinioDriver) Stat

func (driver *MinioDriver) Stat(path string) (FileInfo, error)

Stat implements Driver

type MinioDriverFactory

type MinioDriverFactory struct {
	// contains filtered or unexported fields
}

MinioDriverFactory implements DriverFactory

func NewMinioDriverFactory

func NewMinioDriverFactory(endpoint, accessKeyID, secretAccessKey, location, bucket string, useSSL bool, perm Perm) *MinioDriverFactory

NewMinioDriverFactory creates a DriverFactory implementation

func (*MinioDriverFactory) NewDriver

func (factory *MinioDriverFactory) NewDriver() (Driver, error)

NewDriver implements DriverFactory

type MultipleDriver

type MultipleDriver struct {
	// contains filtered or unexported fields
}

MultipleDriver represents a composite driver

func (*MultipleDriver) DeleteDir

func (driver *MultipleDriver) DeleteDir(path string) error

DeleteDir implements Driver

func (*MultipleDriver) DeleteFile

func (driver *MultipleDriver) DeleteFile(path string) error

DeleteFile implements Driver

func (*MultipleDriver) GetFile

func (driver *MultipleDriver) GetFile(path string, offset int64) (int64, io.ReadCloser, error)

GetFile implements Driver

func (*MultipleDriver) ListDir

func (driver *MultipleDriver) ListDir(path string, callback func(FileInfo) error) error

ListDir implements Driver

func (*MultipleDriver) MakeDir

func (driver *MultipleDriver) MakeDir(path string) error

MakeDir implements Driver

func (*MultipleDriver) PutFile

func (driver *MultipleDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error)

PutFile implements Driver

func (*MultipleDriver) Rename

func (driver *MultipleDriver) Rename(fromPath string, toPath string) error

Rename implements Driver

func (*MultipleDriver) Stat

func (driver *MultipleDriver) Stat(path string) (FileInfo, error)

Stat implements Driver

type MultipleDriverFactory

type MultipleDriverFactory struct {
	// contains filtered or unexported fields
}

MultipleDriverFactory implements a DriverFactory

func (*MultipleDriverFactory) NewDriver

func (factory *MultipleDriverFactory) NewDriver() (Driver, error)

NewDriver implements DriverFactory

type Notifier

type Notifier interface {
	BeforeLoginUser(conn *Conn, userName string)
	BeforePutFile(conn *Conn, dstPath string)
	BeforeDeleteFile(conn *Conn, dstPath string)
	BeforeChangeCurDir(conn *Conn, oldCurDir, newCurDir string)
	BeforeCreateDir(conn *Conn, dstPath string)
	BeforeDeleteDir(conn *Conn, dstPath string)
	BeforeDownloadFile(conn *Conn, dstPath string)
	AfterUserLogin(conn *Conn, userName, password string, passMatched bool, err error)
	AfterFilePut(conn *Conn, dstPath string, size int64, err error)
	AfterFileDeleted(conn *Conn, dstPath string, err error)
	AfterFileDownloaded(conn *Conn, dstPath string, size int64, err error)
	AfterCurDirChanged(conn *Conn, oldCurDir, newCurDir string, err error)
	AfterDirCreated(conn *Conn, dstPath string, err error)
	AfterDirDeleted(conn *Conn, dstPath string, err error)
}

Notifier represents a notification operator interface

type NullNotifier

type NullNotifier struct{}

NullNotifier implements Notifier

func (NullNotifier) AfterCurDirChanged

func (NullNotifier) AfterCurDirChanged(conn *Conn, oldCurDir, newCurDir string, err error)

AfterCurDirChanged implements Notifier

func (NullNotifier) AfterDirCreated

func (NullNotifier) AfterDirCreated(conn *Conn, dstPath string, err error)

AfterDirCreated implements Notifier

func (NullNotifier) AfterDirDeleted

func (NullNotifier) AfterDirDeleted(conn *Conn, dstPath string, err error)

AfterDirDeleted implements Notifier

func (NullNotifier) AfterFileDeleted

func (NullNotifier) AfterFileDeleted(conn *Conn, dstPath string, err error)

AfterFileDeleted implements Notifier

func (NullNotifier) AfterFileDownloaded

func (NullNotifier) AfterFileDownloaded(conn *Conn, dstPath string, size int64, err error)

AfterFileDownloaded implements Notifier

func (NullNotifier) AfterFilePut

func (NullNotifier) AfterFilePut(conn *Conn, dstPath string, size int64, err error)

AfterFilePut implements Notifier

func (NullNotifier) AfterUserLogin

func (NullNotifier) AfterUserLogin(conn *Conn, userName, password string, passMatched bool, err error)

AfterUserLogin implements Notifier

func (NullNotifier) BeforeChangeCurDir

func (NullNotifier) BeforeChangeCurDir(conn *Conn, oldCurDir, newCurDir string)

BeforeChangeCurDir implements Notifier

func (NullNotifier) BeforeCreateDir

func (NullNotifier) BeforeCreateDir(conn *Conn, dstPath string)

BeforeCreateDir implements Notifier

func (NullNotifier) BeforeDeleteDir

func (NullNotifier) BeforeDeleteDir(conn *Conn, dstPath string)

BeforeDeleteDir implements Notifier

func (NullNotifier) BeforeDeleteFile

func (NullNotifier) BeforeDeleteFile(conn *Conn, dstPath string)

BeforeDeleteFile implements Notifier

func (NullNotifier) BeforeDownloadFile

func (NullNotifier) BeforeDownloadFile(conn *Conn, dstPath string)

BeforeDownloadFile implements Notifier

func (NullNotifier) BeforeLoginUser

func (NullNotifier) BeforeLoginUser(conn *Conn, userName string)

BeforeLoginUser implements Notifier

func (NullNotifier) BeforePutFile

func (NullNotifier) BeforePutFile(conn *Conn, dstPath string)

BeforePutFile implements Notifier

type Perm

type Perm interface {
	GetOwner(string) (string, error)
	GetGroup(string) (string, error)
	GetMode(string) (os.FileMode, error)

	ChOwner(string, string) error
	ChGroup(string, string) error
	ChMode(string, os.FileMode) error
}

Perm represents a perm interface

type Server

type Server struct {
	*ServerOpts
	// contains filtered or unexported fields
}

Server is the root of your FTP application. You should instantiate one of these and call ListenAndServe() to start accepting client connections.

Always use the NewServer() method to create a new Server.

func NewServer

func NewServer(opts *ServerOpts) *Server

NewServer initialises a new FTP server. Configuration options are provided via an instance of ServerOpts. Calling this function in your code will probably look something like this:

factory := &MyDriverFactory{}
server  := server.NewServer(&server.ServerOpts{ Factory: factory })

or:

factory := &MyDriverFactory{}
opts    := &server.ServerOpts{
  Factory: factory,
  Port: 2000,
  Hostname: "127.0.0.1",
}
server  := server.NewServer(opts)

func (*Server) ListenAndServe

func (server *Server) ListenAndServe() error

ListenAndServe asks a new Server to begin accepting client connections. It accepts no arguments - all configuration is provided via the NewServer function.

If the server fails to start for any reason, an error will be returned. Common errors are trying to bind to a privileged port or something else is already listening on the same port.

func (*Server) RegisterNotifer

func (server *Server) RegisterNotifer(notifier Notifier)

RegisterNotifer registers a notifier

func (*Server) Serve

func (server *Server) Serve(l net.Listener) error

Serve accepts connections on a given net.Listener and handles each request in a new goroutine.

func (*Server) Shutdown

func (server *Server) Shutdown() error

Shutdown will gracefully stop a server. Already connected clients will retain their connections

type ServerOpts

type ServerOpts struct {
	// The factory that will be used to create a new FTPDriver instance for
	// each client connection. This is a mandatory option.
	Factory DriverFactory

	Auth Auth

	// Server Name, Default is Go Ftp Server
	Name string

	// The hostname that the FTP server should listen on. Optional, defaults to
	// "::", which means all hostnames on ipv4 and ipv6.
	Hostname string

	// Public IP of the server
	PublicIP string

	// Passive ports
	PassivePorts string

	// The port that the FTP should listen on. Optional, defaults to 3000. In
	// a production environment you will probably want to change this to 21.
	Port int

	// use tls, default is false
	TLS bool

	// if tls used, cert file is required
	CertFile string

	// if tls used, key file is required
	KeyFile string

	// If ture TLS is used in RFC4217 mode
	ExplicitFTPS bool

	WelcomeMessage string

	// A logger implementation, if nil the StdLogger is used
	Logger Logger
}

ServerOpts contains parameters for server.NewServer()

type SimpleAuth

type SimpleAuth struct {
	Name     string
	Password string
}

SimpleAuth implements Auth interface to provide a memory user login auth

func (*SimpleAuth) CheckPasswd

func (a *SimpleAuth) CheckPasswd(name, pass string) (bool, error)

CheckPasswd will check user's password

type SimplePerm

type SimplePerm struct {
	// contains filtered or unexported fields
}

SimplePerm implements Perm interface that all files are owned by special owner and group

func NewSimplePerm

func NewSimplePerm(owner, group string) *SimplePerm

NewSimplePerm creates a SimplePerm

func (*SimplePerm) ChGroup

func (s *SimplePerm) ChGroup(string, string) error

ChGroup changed the file's group

func (*SimplePerm) ChMode

func (s *SimplePerm) ChMode(string, os.FileMode) error

ChMode changed the file's mode

func (*SimplePerm) ChOwner

func (s *SimplePerm) ChOwner(string, string) error

ChOwner changed the file's owner

func (*SimplePerm) GetGroup

func (s *SimplePerm) GetGroup(string) (string, error)

GetGroup returns the group of the file

func (*SimplePerm) GetMode

func (s *SimplePerm) GetMode(string) (os.FileMode, error)

GetMode returns the file's mode

func (*SimplePerm) GetOwner

func (s *SimplePerm) GetOwner(string) (string, error)

GetOwner returns the file's owner

type StdLogger

type StdLogger struct{}

StdLogger use an instance of this to log in a standard format

func (*StdLogger) Print

func (logger *StdLogger) Print(sessionID string, message interface{})

Print impelment Logger

func (*StdLogger) PrintCommand

func (logger *StdLogger) PrintCommand(sessionID string, command string, params string)

PrintCommand impelment Logger

func (*StdLogger) PrintResponse

func (logger *StdLogger) PrintResponse(sessionID string, code int, message string)

PrintResponse impelment Logger

func (*StdLogger) Printf

func (logger *StdLogger) Printf(sessionID string, format string, v ...interface{})

Printf impelment Logger

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL