box.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. package box
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "os"
  7. "runtime/debug"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. boxCertificate "github.com/sagernet/sing-box/adapter/certificate"
  11. "github.com/sagernet/sing-box/adapter/endpoint"
  12. "github.com/sagernet/sing-box/adapter/inbound"
  13. "github.com/sagernet/sing-box/adapter/outbound"
  14. boxService "github.com/sagernet/sing-box/adapter/service"
  15. "github.com/sagernet/sing-box/common/certificate"
  16. "github.com/sagernet/sing-box/common/dialer"
  17. "github.com/sagernet/sing-box/common/httpclient"
  18. "github.com/sagernet/sing-box/common/taskmonitor"
  19. "github.com/sagernet/sing-box/common/tls"
  20. C "github.com/sagernet/sing-box/constant"
  21. "github.com/sagernet/sing-box/dns"
  22. "github.com/sagernet/sing-box/experimental"
  23. "github.com/sagernet/sing-box/experimental/cachefile"
  24. "github.com/sagernet/sing-box/experimental/deprecated"
  25. "github.com/sagernet/sing-box/log"
  26. "github.com/sagernet/sing-box/option"
  27. "github.com/sagernet/sing-box/protocol/direct"
  28. "github.com/sagernet/sing-box/route"
  29. "github.com/sagernet/sing/common"
  30. E "github.com/sagernet/sing/common/exceptions"
  31. F "github.com/sagernet/sing/common/format"
  32. "github.com/sagernet/sing/common/ntp"
  33. "github.com/sagernet/sing/service"
  34. "github.com/sagernet/sing/service/pause"
  35. )
  36. var _ adapter.SimpleLifecycle = (*Box)(nil)
  37. type Box struct {
  38. createdAt time.Time
  39. logFactory log.Factory
  40. logger log.ContextLogger
  41. network *route.NetworkManager
  42. endpoint *endpoint.Manager
  43. inbound *inbound.Manager
  44. outbound *outbound.Manager
  45. service *boxService.Manager
  46. certificateProvider *boxCertificate.Manager
  47. dnsTransport *dns.TransportManager
  48. dnsRouter *dns.Router
  49. connection *route.ConnectionManager
  50. router *route.Router
  51. httpClientService adapter.LifecycleService
  52. internalService []adapter.LifecycleService
  53. done chan struct{}
  54. }
  55. type Options struct {
  56. option.Options
  57. Context context.Context
  58. PlatformLogWriter log.PlatformWriter
  59. }
  60. func Context(
  61. ctx context.Context,
  62. inboundRegistry adapter.InboundRegistry,
  63. outboundRegistry adapter.OutboundRegistry,
  64. endpointRegistry adapter.EndpointRegistry,
  65. dnsTransportRegistry adapter.DNSTransportRegistry,
  66. serviceRegistry adapter.ServiceRegistry,
  67. certificateProviderRegistry adapter.CertificateProviderRegistry,
  68. ) context.Context {
  69. if service.FromContext[option.InboundOptionsRegistry](ctx) == nil ||
  70. service.FromContext[adapter.InboundRegistry](ctx) == nil {
  71. ctx = service.ContextWith[option.InboundOptionsRegistry](ctx, inboundRegistry)
  72. ctx = service.ContextWith[adapter.InboundRegistry](ctx, inboundRegistry)
  73. }
  74. if service.FromContext[option.OutboundOptionsRegistry](ctx) == nil ||
  75. service.FromContext[adapter.OutboundRegistry](ctx) == nil {
  76. ctx = service.ContextWith[option.OutboundOptionsRegistry](ctx, outboundRegistry)
  77. ctx = service.ContextWith[adapter.OutboundRegistry](ctx, outboundRegistry)
  78. }
  79. if service.FromContext[option.EndpointOptionsRegistry](ctx) == nil ||
  80. service.FromContext[adapter.EndpointRegistry](ctx) == nil {
  81. ctx = service.ContextWith[option.EndpointOptionsRegistry](ctx, endpointRegistry)
  82. ctx = service.ContextWith[adapter.EndpointRegistry](ctx, endpointRegistry)
  83. }
  84. if service.FromContext[adapter.DNSTransportRegistry](ctx) == nil {
  85. ctx = service.ContextWith[option.DNSTransportOptionsRegistry](ctx, dnsTransportRegistry)
  86. ctx = service.ContextWith[adapter.DNSTransportRegistry](ctx, dnsTransportRegistry)
  87. }
  88. if service.FromContext[adapter.ServiceRegistry](ctx) == nil {
  89. ctx = service.ContextWith[option.ServiceOptionsRegistry](ctx, serviceRegistry)
  90. ctx = service.ContextWith[adapter.ServiceRegistry](ctx, serviceRegistry)
  91. }
  92. if service.FromContext[adapter.CertificateProviderRegistry](ctx) == nil {
  93. ctx = service.ContextWith[option.CertificateProviderOptionsRegistry](ctx, certificateProviderRegistry)
  94. ctx = service.ContextWith[adapter.CertificateProviderRegistry](ctx, certificateProviderRegistry)
  95. }
  96. return ctx
  97. }
  98. func New(options Options) (*Box, error) {
  99. createdAt := time.Now()
  100. ctx := options.Context
  101. if ctx == nil {
  102. ctx = context.Background()
  103. }
  104. ctx = service.ContextWithDefaultRegistry(ctx)
  105. endpointRegistry := service.FromContext[adapter.EndpointRegistry](ctx)
  106. inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
  107. outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
  108. dnsTransportRegistry := service.FromContext[adapter.DNSTransportRegistry](ctx)
  109. serviceRegistry := service.FromContext[adapter.ServiceRegistry](ctx)
  110. certificateProviderRegistry := service.FromContext[adapter.CertificateProviderRegistry](ctx)
  111. if endpointRegistry == nil {
  112. return nil, E.New("missing endpoint registry in context")
  113. }
  114. if inboundRegistry == nil {
  115. return nil, E.New("missing inbound registry in context")
  116. }
  117. if outboundRegistry == nil {
  118. return nil, E.New("missing outbound registry in context")
  119. }
  120. if dnsTransportRegistry == nil {
  121. return nil, E.New("missing DNS transport registry in context")
  122. }
  123. if serviceRegistry == nil {
  124. return nil, E.New("missing service registry in context")
  125. }
  126. if certificateProviderRegistry == nil {
  127. return nil, E.New("missing certificate provider registry in context")
  128. }
  129. ctx = pause.WithDefaultManager(ctx)
  130. experimentalOptions := common.PtrValueOrDefault(options.Experimental)
  131. err := applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
  132. if err != nil {
  133. return nil, err
  134. }
  135. var needCacheFile bool
  136. var needClashAPI bool
  137. var needV2RayAPI bool
  138. if experimentalOptions.CacheFile != nil && experimentalOptions.CacheFile.Enabled || options.PlatformLogWriter != nil {
  139. needCacheFile = true
  140. }
  141. if experimentalOptions.ClashAPI != nil || options.PlatformLogWriter != nil {
  142. needClashAPI = true
  143. }
  144. if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" {
  145. needV2RayAPI = true
  146. }
  147. platformInterface := service.FromContext[adapter.PlatformInterface](ctx)
  148. var defaultLogWriter io.Writer
  149. if platformInterface != nil {
  150. defaultLogWriter = io.Discard
  151. }
  152. logFactory, err := log.New(log.Options{
  153. Context: ctx,
  154. Options: common.PtrValueOrDefault(options.Log),
  155. Observable: needClashAPI,
  156. DefaultWriter: defaultLogWriter,
  157. BaseTime: createdAt,
  158. PlatformWriter: options.PlatformLogWriter,
  159. })
  160. if err != nil {
  161. return nil, E.Cause(err, "create log factory")
  162. }
  163. var internalServices []adapter.LifecycleService
  164. routeOptions := common.PtrValueOrDefault(options.Route)
  165. certificateOptions := common.PtrValueOrDefault(options.Certificate)
  166. if C.IsAndroid || certificateOptions.Store != "" && certificateOptions.Store != C.CertificateStoreSystem ||
  167. len(certificateOptions.Certificate) > 0 ||
  168. len(certificateOptions.CertificatePath) > 0 ||
  169. len(certificateOptions.CertificateDirectoryPath) > 0 {
  170. certificateStore, err := certificate.NewStore(ctx, logFactory.NewLogger("certificate"), certificateOptions)
  171. if err != nil {
  172. return nil, err
  173. }
  174. service.MustRegister[adapter.CertificateStore](ctx, certificateStore)
  175. internalServices = append(internalServices, certificateStore)
  176. }
  177. dnsOptions := common.PtrValueOrDefault(options.DNS)
  178. endpointManager := endpoint.NewManager(logFactory.NewLogger("endpoint"), endpointRegistry)
  179. inboundManager := inbound.NewManager(logFactory.NewLogger("inbound"), inboundRegistry, endpointManager)
  180. outboundManager := outbound.NewManager(logFactory.NewLogger("outbound"), outboundRegistry, endpointManager, routeOptions.Final)
  181. dnsTransportManager := dns.NewTransportManager(logFactory.NewLogger("dns/transport"), dnsTransportRegistry, outboundManager, dnsOptions.Final)
  182. serviceManager := boxService.NewManager(logFactory.NewLogger("service"), serviceRegistry)
  183. certificateProviderManager := boxCertificate.NewManager(logFactory.NewLogger("certificate-provider"), certificateProviderRegistry)
  184. service.MustRegister[adapter.EndpointManager](ctx, endpointManager)
  185. service.MustRegister[adapter.InboundManager](ctx, inboundManager)
  186. service.MustRegister[adapter.OutboundManager](ctx, outboundManager)
  187. service.MustRegister[adapter.DNSTransportManager](ctx, dnsTransportManager)
  188. service.MustRegister[adapter.ServiceManager](ctx, serviceManager)
  189. service.MustRegister[adapter.CertificateProviderManager](ctx, certificateProviderManager)
  190. dnsRouter, err := dns.NewRouter(ctx, logFactory, dnsOptions)
  191. if err != nil {
  192. return nil, E.Cause(err, "initialize DNS router")
  193. }
  194. service.MustRegister[adapter.DNSRouter](ctx, dnsRouter)
  195. service.MustRegister[adapter.DNSRuleSetUpdateValidator](ctx, dnsRouter)
  196. networkManager, err := route.NewNetworkManager(ctx, logFactory.NewLogger("network"), routeOptions, dnsOptions)
  197. if err != nil {
  198. return nil, E.Cause(err, "initialize network manager")
  199. }
  200. service.MustRegister[adapter.NetworkManager](ctx, networkManager)
  201. connectionManager := route.NewConnectionManager(logFactory.NewLogger("connection"))
  202. service.MustRegister[adapter.ConnectionManager](ctx, connectionManager)
  203. // Must register after ConnectionManager: the Apple HTTP engine's proxy bridge reads it from the context when Manager.Start resolves the default client.
  204. httpClientManager := httpclient.NewManager(ctx, logFactory.NewLogger("httpclient"), options.HTTPClients, routeOptions.DefaultHTTPClient)
  205. service.MustRegister[adapter.HTTPClientManager](ctx, httpClientManager)
  206. httpClientService := adapter.LifecycleService(httpClientManager)
  207. router := route.NewRouter(ctx, logFactory, routeOptions, dnsOptions)
  208. service.MustRegister[adapter.Router](ctx, router)
  209. err = router.Initialize(routeOptions.Rules, routeOptions.RuleSet)
  210. if err != nil {
  211. return nil, E.Cause(err, "initialize router")
  212. }
  213. ntpOptions := common.PtrValueOrDefault(options.NTP)
  214. var timeService *tls.TimeServiceWrapper
  215. if ntpOptions.Enabled {
  216. timeService = new(tls.TimeServiceWrapper)
  217. service.MustRegister[ntp.TimeService](ctx, timeService)
  218. }
  219. for i, transportOptions := range dnsOptions.Servers {
  220. var tag string
  221. if transportOptions.Tag != "" {
  222. tag = transportOptions.Tag
  223. } else {
  224. tag = F.ToString(i)
  225. }
  226. err = dnsTransportManager.Create(
  227. ctx,
  228. logFactory.NewLogger(F.ToString("dns/", transportOptions.Type, "[", tag, "]")),
  229. tag,
  230. transportOptions.Type,
  231. transportOptions.Options,
  232. )
  233. if err != nil {
  234. return nil, E.Cause(err, "initialize DNS server[", i, "]")
  235. }
  236. }
  237. err = dnsRouter.Initialize(dnsOptions.Rules)
  238. if err != nil {
  239. return nil, E.Cause(err, "initialize dns router")
  240. }
  241. for i, endpointOptions := range options.Endpoints {
  242. var tag string
  243. if endpointOptions.Tag != "" {
  244. tag = endpointOptions.Tag
  245. } else {
  246. tag = F.ToString(i)
  247. }
  248. endpointCtx := ctx
  249. if tag != "" {
  250. // TODO: remove this
  251. endpointCtx = adapter.WithContext(endpointCtx, &adapter.InboundContext{
  252. Outbound: tag,
  253. })
  254. }
  255. err = endpointManager.Create(
  256. endpointCtx,
  257. router,
  258. logFactory.NewLogger(F.ToString("endpoint/", endpointOptions.Type, "[", tag, "]")),
  259. tag,
  260. endpointOptions.Type,
  261. endpointOptions.Options,
  262. )
  263. if err != nil {
  264. return nil, E.Cause(err, "initialize endpoint[", i, "]")
  265. }
  266. }
  267. for i, inboundOptions := range options.Inbounds {
  268. var tag string
  269. if inboundOptions.Tag != "" {
  270. tag = inboundOptions.Tag
  271. } else {
  272. tag = F.ToString(i)
  273. }
  274. err = inboundManager.Create(
  275. ctx,
  276. router,
  277. logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
  278. tag,
  279. inboundOptions.Type,
  280. inboundOptions.Options,
  281. )
  282. if err != nil {
  283. return nil, E.Cause(err, "initialize inbound[", i, "]")
  284. }
  285. }
  286. for i, serviceOptions := range options.Services {
  287. var tag string
  288. if serviceOptions.Tag != "" {
  289. tag = serviceOptions.Tag
  290. } else {
  291. tag = F.ToString(i)
  292. }
  293. err = serviceManager.Create(
  294. ctx,
  295. logFactory.NewLogger(F.ToString("service/", serviceOptions.Type, "[", tag, "]")),
  296. tag,
  297. serviceOptions.Type,
  298. serviceOptions.Options,
  299. )
  300. if err != nil {
  301. return nil, E.Cause(err, "initialize service[", i, "]")
  302. }
  303. }
  304. for i, outboundOptions := range options.Outbounds {
  305. var tag string
  306. if outboundOptions.Tag != "" {
  307. tag = outboundOptions.Tag
  308. } else {
  309. tag = F.ToString(i)
  310. }
  311. outboundCtx := ctx
  312. if tag != "" {
  313. // TODO: remove this
  314. outboundCtx = adapter.WithContext(outboundCtx, &adapter.InboundContext{
  315. Outbound: tag,
  316. })
  317. }
  318. err = outboundManager.Create(
  319. outboundCtx,
  320. router,
  321. logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
  322. tag,
  323. outboundOptions.Type,
  324. outboundOptions.Options,
  325. )
  326. if err != nil {
  327. return nil, E.Cause(err, "initialize outbound[", i, "]")
  328. }
  329. }
  330. for i, certificateProviderOptions := range options.CertificateProviders {
  331. var tag string
  332. if certificateProviderOptions.Tag != "" {
  333. tag = certificateProviderOptions.Tag
  334. } else {
  335. tag = F.ToString(i)
  336. }
  337. err = certificateProviderManager.Create(
  338. ctx,
  339. logFactory.NewLogger(F.ToString("certificate-provider/", certificateProviderOptions.Type, "[", tag, "]")),
  340. tag,
  341. certificateProviderOptions.Type,
  342. certificateProviderOptions.Options,
  343. )
  344. if err != nil {
  345. return nil, E.Cause(err, "initialize certificate provider[", i, "]")
  346. }
  347. }
  348. outboundManager.Initialize(func() (adapter.Outbound, error) {
  349. return direct.NewOutbound(
  350. ctx,
  351. router,
  352. logFactory.NewLogger("outbound/direct"),
  353. "direct",
  354. option.DirectOutboundOptions{},
  355. )
  356. })
  357. dnsTransportManager.Initialize(func() (adapter.DNSTransport, error) {
  358. return dnsTransportRegistry.CreateDNSTransport(
  359. ctx,
  360. logFactory.NewLogger("dns/local"),
  361. "local",
  362. C.DNSTypeLocal,
  363. &option.LocalDNSServerOptions{},
  364. )
  365. })
  366. httpClientManager.Initialize(func() (*httpclient.ManagedTransport, error) {
  367. deprecated.Report(ctx, deprecated.OptionImplicitDefaultHTTPClient)
  368. var httpClientOptions option.HTTPClientOptions
  369. httpClientOptions.DefaultOutbound = true
  370. return httpclient.NewTransport(ctx, logFactory.NewLogger("httpclient"), "", httpClientOptions)
  371. })
  372. if platformInterface != nil {
  373. err = platformInterface.Initialize(networkManager)
  374. if err != nil {
  375. return nil, E.Cause(err, "initialize platform interface")
  376. }
  377. }
  378. if needCacheFile {
  379. cacheFile := cachefile.New(ctx, logFactory.NewLogger("cache-file"), common.PtrValueOrDefault(experimentalOptions.CacheFile))
  380. service.MustRegister[adapter.CacheFile](ctx, cacheFile)
  381. internalServices = append(internalServices, cacheFile)
  382. }
  383. if needClashAPI {
  384. clashAPIOptions := common.PtrValueOrDefault(experimentalOptions.ClashAPI)
  385. clashAPIOptions.ModeList = experimental.CalculateClashModeList(options.Options)
  386. clashServer, err := experimental.NewClashServer(ctx, logFactory.(log.ObservableFactory), clashAPIOptions)
  387. if err != nil {
  388. return nil, E.Cause(err, "create clash-server")
  389. }
  390. router.AppendTracker(clashServer)
  391. service.MustRegister[adapter.ClashServer](ctx, clashServer)
  392. internalServices = append(internalServices, clashServer)
  393. }
  394. if needV2RayAPI {
  395. v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
  396. if err != nil {
  397. return nil, E.Cause(err, "create v2ray-server")
  398. }
  399. if v2rayServer.StatsService() != nil {
  400. router.AppendTracker(v2rayServer.StatsService())
  401. internalServices = append(internalServices, v2rayServer)
  402. service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
  403. }
  404. }
  405. if ntpOptions.Enabled {
  406. ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions, ntpOptions.ServerIsDomain())
  407. if err != nil {
  408. return nil, E.Cause(err, "create NTP service")
  409. }
  410. ntpService := ntp.NewService(ntp.Options{
  411. Context: ctx,
  412. Dialer: ntpDialer,
  413. Logger: logFactory.NewLogger("ntp"),
  414. Server: ntpOptions.ServerOptions.Build(),
  415. Interval: time.Duration(ntpOptions.Interval),
  416. WriteToSystem: ntpOptions.WriteToSystem,
  417. })
  418. timeService.TimeService = ntpService
  419. internalServices = append(internalServices, adapter.NewLifecycleService(ntpService, "ntp service"))
  420. }
  421. return &Box{
  422. network: networkManager,
  423. endpoint: endpointManager,
  424. inbound: inboundManager,
  425. outbound: outboundManager,
  426. dnsTransport: dnsTransportManager,
  427. service: serviceManager,
  428. certificateProvider: certificateProviderManager,
  429. dnsRouter: dnsRouter,
  430. connection: connectionManager,
  431. router: router,
  432. httpClientService: httpClientService,
  433. createdAt: createdAt,
  434. logFactory: logFactory,
  435. logger: logFactory.Logger(),
  436. internalService: internalServices,
  437. done: make(chan struct{}),
  438. }, nil
  439. }
  440. func (s *Box) PreStart() error {
  441. err := s.preStart()
  442. if err != nil {
  443. // TODO: remove catch error
  444. defer func() {
  445. v := recover()
  446. if v != nil {
  447. println(err.Error())
  448. debug.PrintStack()
  449. panic("panic on early close: " + fmt.Sprint(v))
  450. }
  451. }()
  452. s.Close()
  453. return err
  454. }
  455. s.logger.Info("sing-box pre-started (", F.Seconds(time.Since(s.createdAt).Seconds()), "s)")
  456. return nil
  457. }
  458. func (s *Box) Start() error {
  459. err := s.start()
  460. if err != nil {
  461. // TODO: remove catch error
  462. defer func() {
  463. v := recover()
  464. if v != nil {
  465. println(err.Error())
  466. debug.PrintStack()
  467. println("panic on early start: " + fmt.Sprint(v))
  468. }
  469. }()
  470. s.Close()
  471. return err
  472. }
  473. s.logger.Info("sing-box started (", F.Seconds(time.Since(s.createdAt).Seconds()), "s)")
  474. return nil
  475. }
  476. func (s *Box) preStart() error {
  477. monitor := taskmonitor.New(s.logger, C.StartTimeout)
  478. monitor.Start("start logger")
  479. err := s.logFactory.Start()
  480. monitor.Finish()
  481. if err != nil {
  482. return E.Cause(err, "start logger")
  483. }
  484. err = adapter.StartNamed(s.logger, adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api
  485. if err != nil {
  486. return err
  487. }
  488. err = adapter.Start(s.logger, adapter.StartStateInitialize, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint, s.service, s.certificateProvider)
  489. if err != nil {
  490. return err
  491. }
  492. err = adapter.Start(s.logger, adapter.StartStateStart, s.outbound, s.dnsTransport, s.network, s.connection)
  493. if err != nil {
  494. return err
  495. }
  496. err = adapter.StartNamed(s.logger, adapter.StartStateStart, []adapter.LifecycleService{s.httpClientService})
  497. if err != nil {
  498. return err
  499. }
  500. err = adapter.Start(s.logger, adapter.StartStateStart, s.router, s.dnsRouter)
  501. if err != nil {
  502. return err
  503. }
  504. return nil
  505. }
  506. func (s *Box) start() error {
  507. err := s.preStart()
  508. if err != nil {
  509. return err
  510. }
  511. err = adapter.StartNamed(s.logger, adapter.StartStateStart, s.internalService)
  512. if err != nil {
  513. return err
  514. }
  515. err = adapter.Start(s.logger, adapter.StartStateStart, s.endpoint)
  516. if err != nil {
  517. return err
  518. }
  519. err = adapter.Start(s.logger, adapter.StartStateStart, s.certificateProvider)
  520. if err != nil {
  521. return err
  522. }
  523. err = adapter.Start(s.logger, adapter.StartStateStart, s.inbound, s.service)
  524. if err != nil {
  525. return err
  526. }
  527. err = adapter.Start(s.logger, adapter.StartStatePostStart, s.outbound, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.endpoint, s.certificateProvider, s.inbound, s.service)
  528. if err != nil {
  529. return err
  530. }
  531. err = adapter.StartNamed(s.logger, adapter.StartStatePostStart, s.internalService)
  532. if err != nil {
  533. return err
  534. }
  535. err = adapter.Start(s.logger, adapter.StartStateStarted, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.endpoint, s.certificateProvider, s.inbound, s.service)
  536. if err != nil {
  537. return err
  538. }
  539. err = adapter.StartNamed(s.logger, adapter.StartStateStarted, s.internalService)
  540. if err != nil {
  541. return err
  542. }
  543. return nil
  544. }
  545. func (s *Box) Close() error {
  546. select {
  547. case <-s.done:
  548. return os.ErrClosed
  549. default:
  550. close(s.done)
  551. }
  552. var err error
  553. for _, closeItem := range []struct {
  554. name string
  555. service adapter.Lifecycle
  556. }{
  557. {"service", s.service},
  558. {"inbound", s.inbound},
  559. {"certificate-provider", s.certificateProvider},
  560. {"endpoint", s.endpoint},
  561. {"outbound", s.outbound},
  562. {"router", s.router},
  563. {"connection", s.connection},
  564. {"dns-router", s.dnsRouter},
  565. {"dns-transport", s.dnsTransport},
  566. {"network", s.network},
  567. } {
  568. s.logger.Trace("close ", closeItem.name)
  569. startTime := time.Now()
  570. err = E.Append(err, closeItem.service.Close(), func(err error) error {
  571. return E.Cause(err, "close ", closeItem.name)
  572. })
  573. s.logger.Trace("close ", closeItem.name, " completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
  574. }
  575. if s.httpClientService != nil {
  576. s.logger.Trace("close ", s.httpClientService.Name())
  577. startTime := time.Now()
  578. err = E.Append(err, s.httpClientService.Close(), func(err error) error {
  579. return E.Cause(err, "close ", s.httpClientService.Name())
  580. })
  581. s.logger.Trace("close ", s.httpClientService.Name(), " completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
  582. }
  583. for _, lifecycleService := range s.internalService {
  584. s.logger.Trace("close ", lifecycleService.Name())
  585. startTime := time.Now()
  586. err = E.Append(err, lifecycleService.Close(), func(err error) error {
  587. return E.Cause(err, "close ", lifecycleService.Name())
  588. })
  589. s.logger.Trace("close ", lifecycleService.Name(), " completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
  590. }
  591. s.logger.Trace("close logger")
  592. startTime := time.Now()
  593. err = E.Append(err, s.logFactory.Close(), func(err error) error {
  594. return E.Cause(err, "close logger")
  595. })
  596. s.logger.Trace("close logger completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
  597. return err
  598. }
  599. func (s *Box) Network() adapter.NetworkManager {
  600. return s.network
  601. }
  602. func (s *Box) Router() adapter.Router {
  603. return s.router
  604. }
  605. func (s *Box) Inbound() adapter.InboundManager {
  606. return s.inbound
  607. }
  608. func (s *Box) Outbound() adapter.OutboundManager {
  609. return s.outbound
  610. }
  611. func (s *Box) Endpoint() adapter.EndpointManager {
  612. return s.endpoint
  613. }
  614. func (s *Box) LogFactory() log.Factory {
  615. return s.logFactory
  616. }