server.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package ssmapi
  2. import (
  3. "errors"
  4. "net"
  5. "net/http"
  6. "strings"
  7. "github.com/sagernet/sing-box/adapter"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/experimental"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing/common"
  13. E "github.com/sagernet/sing/common/exceptions"
  14. N "github.com/sagernet/sing/common/network"
  15. "github.com/go-chi/chi/v5"
  16. )
  17. func init() {
  18. experimental.RegisterSSMServerConstructor(NewServer)
  19. }
  20. var _ adapter.SSMServer = (*Server)(nil)
  21. type Server struct {
  22. router adapter.Router
  23. logger log.Logger
  24. httpServer *http.Server
  25. tcpListener net.Listener
  26. nodes []Node
  27. userManager *UserManager
  28. trafficManager *TrafficManager
  29. }
  30. type Node interface {
  31. Protocol() string
  32. ID() string
  33. Shadowsocks() ShadowsocksNodeObject
  34. Object() any
  35. Tag() string
  36. UpdateUsers(users []string, uPSKs []string) error
  37. }
  38. func NewServer(router adapter.Router, logger log.Logger, options option.SSMAPIOptions) (adapter.SSMServer, error) {
  39. chiRouter := chi.NewRouter()
  40. server := &Server{
  41. router: router,
  42. logger: logger,
  43. httpServer: &http.Server{
  44. Addr: options.Listen,
  45. Handler: chiRouter,
  46. },
  47. nodes: make([]Node, 0, len(options.Nodes)),
  48. }
  49. for i, nodeOptions := range options.Nodes {
  50. switch nodeOptions.Type {
  51. case C.TypeShadowsocks:
  52. ssOptions := nodeOptions.ShadowsocksOptions
  53. inbound, loaded := router.Inbound(ssOptions.Inbound)
  54. if !loaded {
  55. return nil, E.New("parse SSM node[", i, "]: inbound", ssOptions.Inbound, "not found")
  56. }
  57. ssInbound, isSS := inbound.(adapter.ManagedShadowsocksServer)
  58. if !isSS {
  59. return nil, E.New("parse SSM node[", i, "]: inbound", ssOptions.Inbound, "is not a shadowsocks inbound")
  60. }
  61. node := &ShadowsocksNode{
  62. ssOptions,
  63. ssInbound,
  64. }
  65. server.nodes = append(server.nodes, node)
  66. }
  67. }
  68. server.trafficManager = NewTrafficManager(server.nodes)
  69. server.userManager = NewUserManager(server.nodes, server.trafficManager)
  70. listenPrefix := options.ListenPrefix
  71. if !strings.HasPrefix(listenPrefix, "/") {
  72. listenPrefix = "/" + listenPrefix
  73. }
  74. chiRouter.Route(listenPrefix+"server/v1", server.setupRoutes)
  75. return server, nil
  76. }
  77. func (s *Server) Start() error {
  78. listener, err := net.Listen("tcp", s.httpServer.Addr)
  79. if err != nil {
  80. return err
  81. }
  82. s.logger.Info("ssm-api started at ", listener.Addr())
  83. s.tcpListener = listener
  84. go func() {
  85. err = s.httpServer.Serve(listener)
  86. if err != nil && !errors.Is(err, http.ErrServerClosed) {
  87. s.logger.Error("ssm-api serve error: ", err)
  88. }
  89. }()
  90. return nil
  91. }
  92. func (s *Server) Close() error {
  93. return common.Close(
  94. common.PtrOrNil(s.httpServer),
  95. s.tcpListener,
  96. s.trafficManager,
  97. )
  98. }
  99. func (s *Server) RoutedConnection(metadata adapter.InboundContext, conn net.Conn) net.Conn {
  100. return s.trafficManager.RoutedConnection(metadata, conn)
  101. }
  102. func (s *Server) RoutedPacketConnection(metadata adapter.InboundContext, conn N.PacketConn) N.PacketConn {
  103. return s.trafficManager.RoutedPacketConnection(metadata, conn)
  104. }