initial import
Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
parent
5d9081f0e4
commit
0b1f88c1aa
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ _testmain.go
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
go-ftp
|
||||
|
195
main.go
Normal file
195
main.go
Normal file
@ -0,0 +1,195 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l, err := net.Listen("tcp", ":8021")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
continue
|
||||
}
|
||||
go handle(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handle(c net.Conn) {
|
||||
defer c.Close()
|
||||
s, err := NewServer(c)
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
}
|
||||
s.ctrl.PrintfLine("220 %s [%s]", "go-ftp", c.LocalAddr())
|
||||
for {
|
||||
line, err := s.ctrl.ReadLine()
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
return
|
||||
}
|
||||
parts := strings.Fields(line)
|
||||
cmd := parts[0]
|
||||
params := parts[1:]
|
||||
switch cmd {
|
||||
case "USER":
|
||||
s.cmdServerUser(params)
|
||||
case "PASS":
|
||||
s.cmdServerPass(params)
|
||||
case "PWD":
|
||||
s.cmdServerPwd(params)
|
||||
case "EPSV":
|
||||
s.cmdServerEpsv(params)
|
||||
case "PASV":
|
||||
s.cmdServerPasv(params)
|
||||
case "TYPE":
|
||||
s.cmdServerType(params)
|
||||
case "LIST":
|
||||
s.cmdServerList(params)
|
||||
case "SYST":
|
||||
s.cmdServerSyst(params)
|
||||
case "QUIT":
|
||||
s.cmdServerQuit(params)
|
||||
s.Close()
|
||||
return
|
||||
case "SIZE":
|
||||
s.cmdServerSize(params)
|
||||
case "CWD":
|
||||
s.cmdServerCwd(params)
|
||||
case "RETR":
|
||||
s.cmdServerRetr(params)
|
||||
default:
|
||||
fmt.Printf("%s\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerUser(args []string) {
|
||||
fmt.Printf("cmdServerUser: %s\n", args)
|
||||
s.ctrl.PrintfLine("331 Password required for %s", args[0])
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerPass(args []string) {
|
||||
fmt.Printf("cmdServerPass: %s\n", args)
|
||||
s.ctrl.PrintfLine("230 Logged on")
|
||||
//530 Login incorrect.
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerPwd(args []string) {
|
||||
fmt.Printf("cmdServerPwd: %s\n", args)
|
||||
s.ctrl.PrintfLine(`257 "/" is current directory.`)
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerEpsv(args []string) {
|
||||
fmt.Printf("cmdServerEpsv: %s\n", args)
|
||||
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
s.ln = ln
|
||||
_, port, _ := net.SplitHostPort(ln.Addr().String())
|
||||
s.ctrl.PrintfLine("229 Entering Extended Passive Mode (|||%s|)", port)
|
||||
go func() {
|
||||
for {
|
||||
conn, err := s.ln.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.data = conn
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerType(args []string) {
|
||||
fmt.Printf("cmdServerType: %s\n", args)
|
||||
switch args[0] {
|
||||
default:
|
||||
s.ctrl.PrintfLine("200 Type set to %s", args[0])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerList(args []string) {
|
||||
fmt.Printf("cmdServerList: %s\n", args)
|
||||
s.ctrl.PrintfLine(`150 Opening data channel for directory listing of "%s"`, args[0])
|
||||
n, err := s.data.Write([]byte("-rw-r--r-- 1 ftp ftp 4 Apr 16 2008 TEST\n"))
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
}
|
||||
s.data.Close()
|
||||
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||
s.ctrl.PrintfLine("226 Transfer complete.")
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerSyst(args []string) {
|
||||
fmt.Printf("cmdServerSyst: %s\n", args)
|
||||
s.ctrl.PrintfLine("215 UNIX Type: L8")
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerQuit(args []string) {
|
||||
if s.data != nil {
|
||||
s.data.Close()
|
||||
}
|
||||
if s.ln != nil {
|
||||
s.ln.Close()
|
||||
}
|
||||
if s.ctrl != nil {
|
||||
s.ctrl.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerPasv(args []string) {
|
||||
fmt.Printf("cmdServerPasv: %s\n", args)
|
||||
|
||||
ln, err := net.Listen("tcp4", "37.139.40.30:0")
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
s.ln = ln
|
||||
host, port, _ := net.SplitHostPort(ln.Addr().String())
|
||||
p0, _ := strconv.Atoi(port)
|
||||
p1 := p0 / 256
|
||||
p2 := p0 - p1*256
|
||||
s.ctrl.PrintfLine("227 Entering Passive Mode (%s,%d,%d)", strings.Replace(host, ".", ",", -1), p1, p2)
|
||||
go func() {
|
||||
for {
|
||||
conn, err := s.ln.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.data = conn
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerSize(args []string) {
|
||||
fmt.Printf("cmdServerSize: %s\n", args)
|
||||
s.ctrl.PrintfLine("213 %d", len([]byte("test\n")))
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerCwd(args []string) {
|
||||
fmt.Printf("cmdServerCwd: %s\n", args)
|
||||
s.ctrl.PrintfLine("250 Okay")
|
||||
}
|
||||
|
||||
func (s *Conn) cmdServerRetr(args []string) {
|
||||
fmt.Printf("cmdServerRetr: %s\n", args)
|
||||
s.ctrl.PrintfLine(`150 Opening data channel for file contents "%s"`, args[0])
|
||||
n, err := s.data.Write([]byte("test\n"))
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
}
|
||||
s.data.Close()
|
||||
s.ctrl.PrintfLine(`226 Closing data connection, sent %d bytes`, n)
|
||||
s.ctrl.PrintfLine("226 Transfer complete.")
|
||||
|
||||
}
|
20
server.go
Normal file
20
server.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/textproto"
|
||||
)
|
||||
|
||||
type Conn struct {
|
||||
ctrl *textproto.Conn
|
||||
data net.Conn
|
||||
ln net.Listener
|
||||
}
|
||||
|
||||
func (c *Conn) Close() error {
|
||||
return c.ctrl.Close()
|
||||
}
|
||||
|
||||
func NewServer(c net.Conn) (*Conn, error) {
|
||||
return &Conn{ctrl: textproto.NewConn(c)}, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user