Projects STRLCPY sing-box Commits e5f3bb63
🤬
  • ■ ■ ■ ■ ■
    adapter/experimental.go
    skipped 9 lines
    10 10   
    11 11  type ClashServer interface {
    12 12   Service
     13 + PreStarter
    13 14   Mode() string
    14 15   StoreSelected() bool
    15 16   CacheFile() ClashCacheFile
    skipped 36 lines
  • ■ ■ ■ ■ ■ ■
    adapter/prestart.go
     1 +package adapter
     2 + 
     3 +type PreStarter interface {
     4 + PreStart() error
     5 +}
     6 + 
     7 +func PreStart(starter any) error {
     8 + if preService, ok := starter.(PreStarter); ok {
     9 + err := preService.PreStart()
     10 + if err != nil {
     11 + return err
     12 + }
     13 + }
     14 + return nil
     15 +}
     16 + 
  • ■ ■ ■ ■ ■ ■
    box.go
    skipped 24 lines
    25 25  var _ adapter.Service = (*Box)(nil)
    26 26   
    27 27  type Box struct {
    28  - createdAt time.Time
    29  - router adapter.Router
    30  - inbounds []adapter.Inbound
    31  - outbounds []adapter.Outbound
    32  - logFactory log.Factory
    33  - logger log.ContextLogger
    34  - logFile *os.File
    35  - clashServer adapter.ClashServer
    36  - v2rayServer adapter.V2RayServer
    37  - done chan struct{}
     28 + createdAt time.Time
     29 + router adapter.Router
     30 + inbounds []adapter.Inbound
     31 + outbounds []adapter.Outbound
     32 + logFactory log.Factory
     33 + logger log.ContextLogger
     34 + logFile *os.File
     35 + preServices map[string]adapter.Service
     36 + postServices map[string]adapter.Service
     37 + done chan struct{}
    38 38  }
    39 39   
    40 40  func New(ctx context.Context, options option.Options, platformInterface platform.Interface) (*Box, error) {
    skipped 125 lines
    166 166   if err != nil {
    167 167   return nil, err
    168 168   }
    169  - 
    170  - var clashServer adapter.ClashServer
    171  - var v2rayServer adapter.V2RayServer
     169 + preServices := make(map[string]adapter.Service)
     170 + postServices := make(map[string]adapter.Service)
    172 171   if needClashAPI {
    173  - clashServer, err = experimental.NewClashServer(router, observableLogFactory, common.PtrValueOrDefault(options.Experimental.ClashAPI))
     172 + clashServer, err := experimental.NewClashServer(router, observableLogFactory, common.PtrValueOrDefault(options.Experimental.ClashAPI))
    174 173   if err != nil {
    175 174   return nil, E.Cause(err, "create clash api server")
    176 175   }
    177 176   router.SetClashServer(clashServer)
     177 + preServices["clash api"] = clashServer
    178 178   }
    179 179   if needV2RayAPI {
    180  - v2rayServer, err = experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(options.Experimental.V2RayAPI))
     180 + v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(options.Experimental.V2RayAPI))
    181 181   if err != nil {
    182 182   return nil, E.Cause(err, "create v2ray api server")
    183 183   }
    184 184   router.SetV2RayServer(v2rayServer)
     185 + preServices["v2ray api"] = v2rayServer
    185 186   }
    186 187   return &Box{
    187  - router: router,
    188  - inbounds: inbounds,
    189  - outbounds: outbounds,
    190  - createdAt: createdAt,
    191  - logFactory: logFactory,
    192  - logger: logFactory.Logger(),
    193  - logFile: logFile,
    194  - clashServer: clashServer,
    195  - v2rayServer: v2rayServer,
    196  - done: make(chan struct{}),
     188 + router: router,
     189 + inbounds: inbounds,
     190 + outbounds: outbounds,
     191 + createdAt: createdAt,
     192 + logFactory: logFactory,
     193 + logger: logFactory.Logger(),
     194 + logFile: logFile,
     195 + preServices: preServices,
     196 + postServices: postServices,
     197 + done: make(chan struct{}),
    197 198   }, nil
    198 199  }
    199 200   
     201 +func (s *Box) PreStart() error {
     202 + err := s.preStart()
     203 + if err != nil {
     204 + // TODO: remove catch error
     205 + defer func() {
     206 + v := recover()
     207 + if v != nil {
     208 + log.Error(E.Cause(err, "origin error"))
     209 + debug.PrintStack()
     210 + panic("panic on early close: " + fmt.Sprint(v))
     211 + }
     212 + }()
     213 + s.Close()
     214 + return err
     215 + }
     216 + s.logger.Info("sing-box pre-started (", F.Seconds(time.Since(s.createdAt).Seconds()), "s)")
     217 + return nil
     218 +}
     219 + 
    200 220  func (s *Box) Start() error {
    201 221   err := s.start()
    202 222   if err != nil {
    skipped 7 lines
    210 230   }
    211 231   }()
    212 232   s.Close()
     233 + return err
    213 234   }
    214  - return err
     235 + s.logger.Info("sing-box started (", F.Seconds(time.Since(s.createdAt).Seconds()), "s)")
     236 + return nil
    215 237  }
    216 238   
    217  -func (s *Box) start() error {
    218  - if s.clashServer != nil {
    219  - err := s.clashServer.Start()
    220  - if err != nil {
    221  - return E.Cause(err, "start clash api server")
    222  - }
    223  - }
    224  - if s.v2rayServer != nil {
    225  - err := s.v2rayServer.Start()
     239 +func (s *Box) preStart() error {
     240 + for serviceName, service := range s.preServices {
     241 + err := adapter.PreStart(service)
    226 242   if err != nil {
    227  - return E.Cause(err, "start v2ray api server")
     243 + return E.Cause(err, "pre-start ", serviceName)
    228 244   }
    229 245   }
    230 246   for i, out := range s.outbounds {
    skipped 10 lines
    241 257   }
    242 258   }
    243 259   }
    244  - err := s.router.Start()
     260 + return s.router.Start()
     261 +}
     262 + 
     263 +func (s *Box) start() error {
     264 + err := s.preStart()
    245 265   if err != nil {
    246 266   return err
    247 267   }
     268 + for serviceName, service := range s.preServices {
     269 + err = service.Start()
     270 + if err != nil {
     271 + return E.Cause(err, "start ", serviceName)
     272 + }
     273 + }
    248 274   for i, in := range s.inbounds {
    249 275   err = in.Start()
    250 276   if err != nil {
    skipped 6 lines
    257 283   return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
    258 284   }
    259 285   }
    260  - 
    261  - s.logger.Info("sing-box started (", F.Seconds(time.Since(s.createdAt).Seconds()), "s)")
     286 + for serviceName, service := range s.postServices {
     287 + err = service.Start()
     288 + if err != nil {
     289 + return E.Cause(err, "start ", serviceName)
     290 + }
     291 + }
    262 292   return nil
    263 293  }
    264 294   
    skipped 5 lines
    270 300   close(s.done)
    271 301   }
    272 302   var errors error
     303 + for serviceName, service := range s.postServices {
     304 + errors = E.Append(errors, service.Close(), func(err error) error {
     305 + return E.Cause(err, "close ", serviceName)
     306 + })
     307 + }
    273 308   for i, in := range s.inbounds {
    274 309   errors = E.Append(errors, in.Close(), func(err error) error {
    275 310   return E.Cause(err, "close inbound/", in.Type(), "[", i, "]")
    skipped 9 lines
    285 320   return E.Cause(err, "close router")
    286 321   })
    287 322   }
     323 + for serviceName, service := range s.preServices {
     324 + errors = E.Append(errors, service.Close(), func(err error) error {
     325 + return E.Cause(err, "close ", serviceName)
     326 + })
     327 + }
    288 328   if err := common.Close(s.logFactory); err != nil {
    289 329   errors = E.Append(errors, err, func(err error) error {
    290 330   return E.Cause(err, "close log factory")
    291  - })
    292  - }
    293  - if err := common.Close(s.clashServer); err != nil {
    294  - errors = E.Append(errors, err, func(err error) error {
    295  - return E.Cause(err, "close clash api server")
    296  - })
    297  - }
    298  - if err := common.Close(s.v2rayServer); err != nil {
    299  - errors = E.Append(errors, err, func(err error) error {
    300  - return E.Cause(err, "close v2ray api server")
    301 331   })
    302 332   }
    303 333   if s.logFile != nil {
    skipped 11 lines
  • ■ ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools.go
     1 +package main
     2 + 
     3 +import (
     4 + "context"
     5 + 
     6 + box "github.com/sagernet/sing-box"
     7 + E "github.com/sagernet/sing/common/exceptions"
     8 + 
     9 + "github.com/spf13/cobra"
     10 +)
     11 + 
     12 +var commandTools = &cobra.Command{
     13 + Use: "tools",
     14 + Short: "experimental tools",
     15 +}
     16 + 
     17 +func init() {
     18 + mainCommand.AddCommand(commandTools)
     19 +}
     20 + 
     21 +func createPreStartedClient() (*box.Box, error) {
     22 + options, err := readConfigAndMerge()
     23 + if err != nil {
     24 + return nil, err
     25 + }
     26 + instance, err := box.New(context.Background(), options, nil)
     27 + if err != nil {
     28 + return nil, E.Cause(err, "create service")
     29 + }
     30 + err = instance.PreStart()
     31 + if err != nil {
     32 + return nil, E.Cause(err, "start service")
     33 + }
     34 + return instance, nil
     35 +}
     36 + 
  • ■ ■ ■ ■ ■ ■
    cmd/sing-box/cmd_tools_connect.go
     1 +package main
     2 + 
     3 +import (
     4 + "context"
     5 + "os"
     6 + 
     7 + "github.com/sagernet/sing-box/log"
     8 + "github.com/sagernet/sing/common"
     9 + "github.com/sagernet/sing/common/bufio"
     10 + E "github.com/sagernet/sing/common/exceptions"
     11 + M "github.com/sagernet/sing/common/metadata"
     12 + N "github.com/sagernet/sing/common/network"
     13 + "github.com/sagernet/sing/common/task"
     14 + 
     15 + "github.com/spf13/cobra"
     16 +)
     17 + 
     18 +var commandFlagNetwork string
     19 + 
     20 +var commandConnect = &cobra.Command{
     21 + Use: "connect [address]",
     22 + Short: "connect to a address through default outbound",
     23 + Args: cobra.ExactArgs(1),
     24 + Run: func(cmd *cobra.Command, args []string) {
     25 + err := connect(args[0])
     26 + if err != nil {
     27 + log.Fatal(err)
     28 + }
     29 + },
     30 +}
     31 + 
     32 +func init() {
     33 + commandConnect.Flags().StringVar(&commandFlagNetwork, "network", "tcp", "network type")
     34 + commandTools.AddCommand(commandConnect)
     35 +}
     36 + 
     37 +func connect(address string) error {
     38 + switch N.NetworkName(commandFlagNetwork) {
     39 + case N.NetworkTCP, N.NetworkUDP:
     40 + default:
     41 + return E.Cause(N.ErrUnknownNetwork, commandFlagNetwork)
     42 + }
     43 + instance, err := createPreStartedClient()
     44 + if err != nil {
     45 + return err
     46 + }
     47 + outbound := instance.Router().DefaultOutbound(commandFlagNetwork)
     48 + if outbound == nil {
     49 + return E.New("missing default outbound")
     50 + }
     51 + conn, err := outbound.DialContext(context.Background(), commandFlagNetwork, M.ParseSocksaddr(address))
     52 + if err != nil {
     53 + return E.Cause(err, "connect to server")
     54 + }
     55 + var group task.Group
     56 + group.Append("upload", func(ctx context.Context) error {
     57 + return common.Error(bufio.Copy(conn, os.Stdin))
     58 + })
     59 + group.Append("download", func(ctx context.Context) error {
     60 + return common.Error(bufio.Copy(os.Stdout, conn))
     61 + })
     62 + err = group.Run(context.Background())
     63 + if E.IsClosed(err) {
     64 + log.Info(err)
     65 + } else {
     66 + log.Error(err)
     67 + }
     68 + return nil
     69 +}
     70 + 
  • ■ ■ ■ ■ ■
    experimental/clashapi/server.go
    skipped 113 lines
    114 114   return server, nil
    115 115  }
    116 116   
    117  -func (s *Server) Start() error {
     117 +func (s *Server) PreStart() error {
    118 118   if s.cacheFilePath != "" {
    119 119   cacheFile, err := cachefile.Open(s.cacheFilePath)
    120 120   if err != nil {
    skipped 1 lines
    122 122   }
    123 123   s.cacheFile = cacheFile
    124 124   }
     125 + return nil
     126 +}
     127 + 
     128 +func (s *Server) Start() error {
    125 129   listener, err := net.Listen("tcp", s.httpServer.Addr)
    126 130   if err != nil {
    127 131   return E.Cause(err, "external controller listen error")
    skipped 266 lines
Please wait...
Page is in error, reload to recover