server.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package smb
  2. import (
  3. "bufio"
  4. "encoding/hex"
  5. "fmt"
  6. "net"
  7. "os"
  8. "runtime"
  9. "sync/atomic"
  10. "time"
  11. "github.com/izouxv/logx"
  12. "golang.org/x/net/webdav"
  13. )
  14. var treeIdX = uint32(0)
  15. func NewAnchor(name, rootpath string) *Anchor {
  16. return &Anchor{Name: name, RootPath: rootpath, tid: atomic.AddUint32(&treeId, 1)}
  17. }
  18. type Handler struct {
  19. *webdav.Handler
  20. // symlink WIP
  21. }
  22. type Anchor struct {
  23. Name string
  24. RootPath string
  25. tid uint32
  26. Handle *Handler
  27. }
  28. type GetPwdFunc func(name string) (password string, err error)
  29. type GetAnchorFun func(userName string) (anchors []*Anchor, err error)
  30. type Config struct {
  31. // Port int
  32. Pwd GetPwdFunc
  33. Tree GetAnchorFun
  34. Handle func(string) *Handler
  35. }
  36. type ServerI interface {
  37. Start(PORT int)
  38. }
  39. func NewServer(config *Config) ServerI {
  40. return &server{config: config, sessions: make(map[uint64]SessionS)}
  41. }
  42. type server struct {
  43. config *Config
  44. sessions map[uint64]SessionS
  45. }
  46. func (s *server) Start(PORT int) {
  47. // PORT := s.config.Port
  48. getPwd := s.config.Pwd
  49. getTree := s.config.Tree
  50. l, err := net.Listen("tcp", fmt.Sprintf(":%d", PORT))
  51. if err != nil {
  52. fmt.Println("Error listening:", err.Error())
  53. os.Exit(1)
  54. }
  55. // Close the listener when the application closes.
  56. defer l.Close()
  57. fmt.Printf("Listening on %v port\n", PORT)
  58. for {
  59. // Listen for an incoming connection.
  60. conn, err := l.Accept()
  61. if err != nil {
  62. fmt.Println("Error accepting: ", err.Error())
  63. os.Exit(1)
  64. }
  65. fmt.Printf("IP: %v", conn.RemoteAddr().String())
  66. // Handle connections in a new goroutine.
  67. go s.HandleConnection(conn, getPwd, getTree)
  68. }
  69. }
  70. func (s *server) HandleConnection(conn net.Conn, getPwd GetPwdFunc, getTree GetAnchorFun) {
  71. remoteAddr := conn.RemoteAddr()
  72. defer func() {
  73. if err := recover(); err != nil {
  74. b := make([]byte, 4000, 4000)
  75. n := runtime.Stack(b, false)
  76. fmt.Printf("%s\n", b[:n])
  77. fmt.Printf("Error(%v): %s\n\n", remoteAddr, err)
  78. }
  79. }()
  80. defer conn.Close()
  81. session := NewSessionServer(true, conn, getPwd, getTree)
  82. if err := session.NegotiateProtocolServer(); err != nil {
  83. logx.Infof("login failed, %v, err: %v", session.IsAuthenticated, err)
  84. // time.Sleep(time.Second)
  85. // conn.Close()
  86. return
  87. }
  88. if !session.IsAuthenticated {
  89. logx.Infof("login failed, %v", session.IsAuthenticated)
  90. time.Sleep(time.Second)
  91. conn.Close()
  92. return
  93. }
  94. logx.Infof("login suc, %v", session.IsAuthenticated)
  95. rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
  96. for {
  97. reqMsg, _, err := session.Recv(rw)
  98. if err != nil {
  99. return
  100. }
  101. respBuf, cmd, stat := ActionFunc(NewDataCtx(session, conn, s.config.Handle), reqMsg)
  102. if stat != StatusOk {
  103. return
  104. }
  105. if false {
  106. fmt.Printf("\n\n\ncmd: %v req:\n%vresp:\n%v", cmd.String(), hex.Dump(reqMsg), hex.Dump(respBuf))
  107. }
  108. session.Send(respBuf, rw)
  109. }
  110. }