github.com/sagernet/sing-box@v1.9.0-rc.20/experimental/v2rayapi/server.go (about) 1 package v2rayapi 2 3 import ( 4 "errors" 5 "net" 6 "net/http" 7 8 "github.com/sagernet/sing-box/adapter" 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 14 "google.golang.org/grpc" 15 "google.golang.org/grpc/credentials/insecure" 16 ) 17 18 func init() { 19 experimental.RegisterV2RayServerConstructor(NewServer) 20 } 21 22 var _ adapter.V2RayServer = (*Server)(nil) 23 24 type Server struct { 25 logger log.Logger 26 listen string 27 tcpListener net.Listener 28 grpcServer *grpc.Server 29 statsService *StatsService 30 } 31 32 func NewServer(logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) { 33 grpcServer := grpc.NewServer(grpc.Creds(insecure.NewCredentials())) 34 statsService := NewStatsService(common.PtrValueOrDefault(options.Stats)) 35 if statsService != nil { 36 RegisterStatsServiceServer(grpcServer, statsService) 37 } 38 server := &Server{ 39 logger: logger, 40 listen: options.Listen, 41 grpcServer: grpcServer, 42 statsService: statsService, 43 } 44 return server, nil 45 } 46 47 func (s *Server) Start() error { 48 listener, err := net.Listen("tcp", s.listen) 49 if err != nil { 50 return err 51 } 52 s.logger.Info("grpc server started at ", listener.Addr()) 53 s.tcpListener = listener 54 go func() { 55 err = s.grpcServer.Serve(listener) 56 if err != nil && !errors.Is(err, http.ErrServerClosed) { 57 s.logger.Error(err) 58 } 59 }() 60 return nil 61 } 62 63 func (s *Server) Close() error { 64 if s.grpcServer != nil { 65 s.grpcServer.Stop() 66 } 67 return common.Close( 68 common.PtrOrNil(s.grpcServer), 69 s.tcpListener, 70 ) 71 } 72 73 func (s *Server) StatsService() adapter.V2RayStatsService { 74 return s.statsService 75 }