mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Fix start lifecycle
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
@@ -43,6 +44,8 @@ var _ adapter.SimpleLifecycle = (*Box)(nil)
|
|||||||
|
|
||||||
type Box struct {
|
type Box struct {
|
||||||
createdAt time.Time
|
createdAt time.Time
|
||||||
|
debugOptions option.DebugOptions
|
||||||
|
debugHTTPServer *http.Server
|
||||||
logFactory log.Factory
|
logFactory log.Factory
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
network *route.NetworkManager
|
network *route.NetworkManager
|
||||||
@@ -142,7 +145,8 @@ func New(options Options) (*Box, error) {
|
|||||||
|
|
||||||
ctx = pause.WithDefaultManager(ctx)
|
ctx = pause.WithDefaultManager(ctx)
|
||||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||||
err := applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
|
debugOptions := common.PtrValueOrDefault(experimentalOptions.Debug)
|
||||||
|
err := checkDebugOptions(debugOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -470,6 +474,7 @@ func New(options Options) (*Box, error) {
|
|||||||
router: router,
|
router: router,
|
||||||
httpClientService: httpClientService,
|
httpClientService: httpClientService,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
|
debugOptions: debugOptions,
|
||||||
logFactory: logFactory,
|
logFactory: logFactory,
|
||||||
logger: logFactory.Logger(),
|
logger: logFactory.Logger(),
|
||||||
internalService: internalServices,
|
internalService: internalServices,
|
||||||
@@ -523,6 +528,11 @@ func (s *Box) preStart() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "start logger")
|
return E.Cause(err, "start logger")
|
||||||
}
|
}
|
||||||
|
applyDebugOptions(s.debugOptions)
|
||||||
|
s.debugHTTPServer, err = startDebugHTTPServer(s.debugOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = adapter.StartNamed(s.logger, adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api
|
err = adapter.StartNamed(s.logger, adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -594,6 +604,12 @@ func (s *Box) Close() error {
|
|||||||
close(s.done)
|
close(s.done)
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
if s.debugHTTPServer != nil {
|
||||||
|
err = E.Append(err, s.debugHTTPServer.Close(), func(err error) error {
|
||||||
|
return E.Cause(err, "close debug HTTP server")
|
||||||
|
})
|
||||||
|
s.debugHTTPServer = nil
|
||||||
|
}
|
||||||
for _, closeItem := range []struct {
|
for _, closeItem := range []struct {
|
||||||
name string
|
name string
|
||||||
service adapter.Lifecycle
|
service adapter.Lifecycle
|
||||||
|
|||||||
@@ -96,6 +96,15 @@ type appleTransport struct {
|
|||||||
closed bool
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateAppleTransport(ctx context.Context, options option.HTTPClientOptions) error {
|
||||||
|
sessionConfig, err := newAppleSessionConfig(ctx, options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sessionConfig.close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func newAppleTransport(ctx context.Context, logger logger.ContextLogger, rawDialer N.Dialer, options option.HTTPClientOptions) (innerTransport, error) {
|
func newAppleTransport(ctx context.Context, logger logger.ContextLogger, rawDialer N.Dialer, options option.HTTPClientOptions) (innerTransport, error) {
|
||||||
sessionConfig, err := newAppleSessionConfig(ctx, options)
|
sessionConfig, err := newAppleSessionConfig(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -111,6 +120,10 @@ func newAppleTransport(ctx context.Context, logger logger.ContextLogger, rawDial
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = bridge.Start()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
shared := &appleTransportShared{
|
shared := &appleTransportShared{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
bridge: bridge,
|
bridge: bridge,
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import (
|
|||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func validateAppleTransport(ctx context.Context, options option.HTTPClientOptions) error {
|
||||||
|
return E.New("Apple HTTP engine is not available on non-Apple platforms")
|
||||||
|
}
|
||||||
|
|
||||||
func newAppleTransport(ctx context.Context, logger logger.ContextLogger, rawDialer N.Dialer, options option.HTTPClientOptions) (innerTransport, error) {
|
func newAppleTransport(ctx context.Context, logger logger.ContextLogger, rawDialer N.Dialer, options option.HTTPClientOptions) (innerTransport, error) {
|
||||||
return nil, E.New("Apple HTTP engine is not available on non-Apple platforms")
|
return nil, E.New("Apple HTTP engine is not available on non-Apple platforms")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ func NewTransport(ctx context.Context, logger logger.ContextLogger, tag string,
|
|||||||
var cheapRebuild bool
|
var cheapRebuild bool
|
||||||
switch options.Engine {
|
switch options.Engine {
|
||||||
case C.TLSEngineApple:
|
case C.TLSEngineApple:
|
||||||
inner, transportErr := newAppleTransport(ctx, logger, rawDialer, options)
|
err = validateAppleTransport(ctx, options)
|
||||||
if transportErr != nil {
|
if err != nil {
|
||||||
return nil, transportErr
|
return nil, err
|
||||||
}
|
}
|
||||||
managedTransport := &ManagedTransport{
|
return &ManagedTransport{
|
||||||
dialer: rawDialer,
|
dialer: rawDialer,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
host: host,
|
host: host,
|
||||||
@@ -47,9 +47,7 @@ func NewTransport(ctx context.Context, logger logger.ContextLogger, tag string,
|
|||||||
factory: func() (innerTransport, error) {
|
factory: func() (innerTransport, error) {
|
||||||
return newAppleTransport(ctx, logger, rawDialer, options)
|
return newAppleTransport(ctx, logger, rawDialer, options)
|
||||||
},
|
},
|
||||||
}
|
}, nil
|
||||||
managedTransport.epoch.Store(&transportEpoch{transport: inner})
|
|
||||||
return managedTransport, nil
|
|
||||||
case "", C.TLSEngineGo:
|
case "", C.TLSEngineGo:
|
||||||
cheapRebuild = true
|
cheapRebuild = true
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -34,23 +34,26 @@ type Bridge struct {
|
|||||||
func New(ctx context.Context, logger logger.ContextLogger, tag string, dialer N.Dialer) (*Bridge, error) {
|
func New(ctx context.Context, logger logger.ContextLogger, tag string, dialer N.Dialer) (*Bridge, error) {
|
||||||
username := randomHex(16)
|
username := randomHex(16)
|
||||||
password := randomHex(16)
|
password := randomHex(16)
|
||||||
tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)})
|
return &Bridge{
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
bridge := &Bridge{
|
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
connection: service.FromContext[adapter.ConnectionManager](ctx),
|
connection: service.FromContext[adapter.ConnectionManager](ctx),
|
||||||
tcpListener: tcpListener,
|
|
||||||
username: username,
|
username: username,
|
||||||
password: password,
|
password: password,
|
||||||
authenticator: auth.NewAuthenticator([]auth.User{{Username: username, Password: password}}),
|
authenticator: auth.NewAuthenticator([]auth.User{{Username: username, Password: password}}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) Start() error {
|
||||||
|
tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
go bridge.acceptLoop()
|
b.tcpListener = tcpListener
|
||||||
return bridge, nil
|
go b.acceptLoop()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomHex(size int) string {
|
func randomHex(size int) string {
|
||||||
@@ -72,7 +75,7 @@ func (b *Bridge) Password() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bridge) Close() error {
|
func (b *Bridge) Close() error {
|
||||||
return common.Close(b.tcpListener)
|
return common.Close(common.PtrOrNil(b.tcpListener))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bridge) acceptLoop() {
|
func (b *Bridge) acceptLoop() {
|
||||||
|
|||||||
+39
-16
@@ -29,18 +29,42 @@ type acmeWrapper struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
cfg *certmagic.Config
|
cfg *certmagic.Config
|
||||||
cache *certmagic.Cache
|
cache *certmagic.Cache
|
||||||
|
zapLogger *zap.Logger
|
||||||
|
dataDirectory string
|
||||||
domain []string
|
domain []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *acmeWrapper) Start() error {
|
func (w *acmeWrapper) Start() error {
|
||||||
|
if w.dataDirectory != "" {
|
||||||
|
err := filemanager.MkdirAll(w.ctx, w.dataDirectory, 0o700)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "create ACME data directory")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config := w.cfg
|
||||||
|
cache := certmagic.NewCache(certmagic.CacheOptions{
|
||||||
|
GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) {
|
||||||
|
return config, nil
|
||||||
|
},
|
||||||
|
Logger: w.zapLogger,
|
||||||
|
})
|
||||||
|
config = certmagic.New(cache, *config)
|
||||||
|
w.cfg = config
|
||||||
|
w.cache = cache
|
||||||
return w.cfg.ManageSync(w.ctx, w.domain)
|
return w.cfg.ManageSync(w.ctx, w.domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *acmeWrapper) Close() error {
|
func (w *acmeWrapper) Close() error {
|
||||||
|
if w.cache != nil {
|
||||||
w.cache.Stop()
|
w.cache.Stop()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *acmeWrapper) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
return w.cfg.GetCertificate(hello)
|
||||||
|
}
|
||||||
|
|
||||||
func startACME(ctx context.Context, logger logger.Logger, options option.InboundACMEOptions) (*tls.Config, adapter.SimpleLifecycle, error) {
|
func startACME(ctx context.Context, logger logger.Logger, options option.InboundACMEOptions) (*tls.Config, adapter.SimpleLifecycle, error) {
|
||||||
var acmeServer string
|
var acmeServer string
|
||||||
switch options.Provider {
|
switch options.Provider {
|
||||||
@@ -54,13 +78,12 @@ func startACME(ctx context.Context, logger logger.Logger, options option.Inbound
|
|||||||
}
|
}
|
||||||
acmeServer = options.Provider
|
acmeServer = options.Provider
|
||||||
}
|
}
|
||||||
var storage certmagic.Storage
|
var (
|
||||||
|
storage certmagic.Storage
|
||||||
|
dataDirectory string
|
||||||
|
)
|
||||||
if options.DataDirectory != "" {
|
if options.DataDirectory != "" {
|
||||||
dataDirectory := filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
dataDirectory = filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
||||||
err := filemanager.MkdirAll(ctx, dataDirectory, 0o700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, E.Cause(err, "create ACME data directory")
|
|
||||||
}
|
|
||||||
storage = &certmagic.FileStorage{
|
storage = &certmagic.FileStorage{
|
||||||
Path: dataDirectory,
|
Path: dataDirectory,
|
||||||
}
|
}
|
||||||
@@ -126,23 +149,23 @@ func startACME(ctx context.Context, logger logger.Logger, options option.Inbound
|
|||||||
acmeConfig.ExternalAccount = (*acme.EAB)(options.ExternalAccount)
|
acmeConfig.ExternalAccount = (*acme.EAB)(options.ExternalAccount)
|
||||||
}
|
}
|
||||||
config.Issuers = []certmagic.Issuer{certmagic.NewACMEIssuer(config, acmeConfig)}
|
config.Issuers = []certmagic.Issuer{certmagic.NewACMEIssuer(config, acmeConfig)}
|
||||||
cache := certmagic.NewCache(certmagic.CacheOptions{
|
wrapper := &acmeWrapper{
|
||||||
GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) {
|
ctx: ctx,
|
||||||
return config, nil
|
cfg: config,
|
||||||
},
|
zapLogger: zapLogger,
|
||||||
Logger: zapLogger,
|
dataDirectory: dataDirectory,
|
||||||
})
|
domain: options.Domain,
|
||||||
config = certmagic.New(cache, *config)
|
}
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
if acmeConfig.DisableTLSALPNChallenge || acmeConfig.DNS01Solver != nil {
|
if acmeConfig.DisableTLSALPNChallenge || acmeConfig.DNS01Solver != nil {
|
||||||
tlsConfig = &tls.Config{
|
tlsConfig = &tls.Config{
|
||||||
GetCertificate: config.GetCertificate,
|
GetCertificate: wrapper.GetCertificate,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tlsConfig = &tls.Config{
|
tlsConfig = &tls.Config{
|
||||||
GetCertificate: config.GetCertificate,
|
GetCertificate: wrapper.GetCertificate,
|
||||||
NextProtos: []string{C.ACMETLS1Protocol},
|
NextProtos: []string{C.ACMETLS1Protocol},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tlsConfig, &acmeWrapper{ctx: ctx, cfg: config, cache: cache, domain: options.Domain}, nil
|
return tlsConfig, wrapper, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,13 +50,10 @@ type Manager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(outbound adapter.OutboundManager) *Manager {
|
func NewManager(outbound adapter.OutboundManager) *Manager {
|
||||||
manager := &Manager{
|
return &Manager{
|
||||||
outbound: outbound,
|
outbound: outbound,
|
||||||
eventSubscriber: observable.NewSubscriber[ConnectionEvent](256),
|
eventSubscriber: observable.NewSubscriber[ConnectionEvent](256),
|
||||||
}
|
}
|
||||||
manager.eventObserver = observable.NewObserver(manager.eventSubscriber, 64)
|
|
||||||
manager.cleaner = cleanup.Add(manager.Clear)
|
|
||||||
return manager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Name() string {
|
func (m *Manager) Name() string {
|
||||||
@@ -64,12 +61,21 @@ func (m *Manager) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Start(stage adapter.StartStage) error {
|
func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
|
if stage == adapter.StartStateInitialize {
|
||||||
|
m.eventObserver = observable.NewObserver(m.eventSubscriber, 64)
|
||||||
|
m.cleaner = cleanup.Add(m.Clear)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) Close() error {
|
func (m *Manager) Close() error {
|
||||||
|
if m.cleaner != nil {
|
||||||
m.cleaner.Close()
|
m.cleaner.Close()
|
||||||
|
}
|
||||||
|
if m.eventObserver != nil {
|
||||||
return m.eventObserver.Close()
|
return m.eventObserver.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) SubscribeEvents() (observable.Subscription[ConnectionEvent], <-chan struct{}, error) {
|
func (m *Manager) SubscribeEvents() (observable.Subscription[ConnectionEvent], <-chan struct{}, error) {
|
||||||
|
|||||||
@@ -7,8 +7,14 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func applyDebugOptions(options option.DebugOptions) error {
|
func checkDebugOptions(options option.DebugOptions) error {
|
||||||
applyDebugListenOption(options)
|
if options.OOMKiller != nil {
|
||||||
|
return E.New("legacy oom_killer in debug options is removed, use oom-killer service instead")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyDebugOptions(options option.DebugOptions) {
|
||||||
if options.GCPercent != nil {
|
if options.GCPercent != nil {
|
||||||
debug.SetGCPercent(*options.GCPercent)
|
debug.SetGCPercent(*options.GCPercent)
|
||||||
}
|
}
|
||||||
@@ -27,8 +33,4 @@ func applyDebugOptions(options option.DebugOptions) error {
|
|||||||
if options.MemoryLimit.Value() != 0 {
|
if options.MemoryLimit.Value() != 0 {
|
||||||
debug.SetMemoryLimit(int64(float64(options.MemoryLimit.Value()) / 1.5))
|
debug.SetMemoryLimit(int64(float64(options.MemoryLimit.Value()) / 1.5))
|
||||||
}
|
}
|
||||||
if options.OOMKiller != nil {
|
|
||||||
return E.New("legacy oom_killer in debug options is removed, use oom-killer service instead")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -1,6 +1,7 @@
|
|||||||
package box
|
package box
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -17,15 +18,9 @@ import (
|
|||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var debugHTTPServer *http.Server
|
func startDebugHTTPServer(options option.DebugOptions) (*http.Server, error) {
|
||||||
|
|
||||||
func applyDebugListenOption(options option.DebugOptions) {
|
|
||||||
if debugHTTPServer != nil {
|
|
||||||
debugHTTPServer.Close()
|
|
||||||
debugHTTPServer = nil
|
|
||||||
}
|
|
||||||
if options.Listen == "" {
|
if options.Listen == "" {
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
r := chi.NewMux()
|
r := chi.NewMux()
|
||||||
r.Route("/debug", func(r chi.Router) {
|
r.Route("/debug", func(r chi.Router) {
|
||||||
@@ -63,14 +58,19 @@ func applyDebugListenOption(options option.DebugOptions) {
|
|||||||
r.HandleFunc("/trace", pprof.Trace)
|
r.HandleFunc("/trace", pprof.Trace)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
debugHTTPServer = &http.Server{
|
server := &http.Server{
|
||||||
Addr: options.Listen,
|
Addr: options.Listen,
|
||||||
Handler: r,
|
Handler: r,
|
||||||
}
|
}
|
||||||
|
listener, err := net.Listen("tcp", options.Listen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "listen debug HTTP server")
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
err := debugHTTPServer.ListenAndServe()
|
err := server.Serve(listener)
|
||||||
if err != nil && !E.IsClosed(err) {
|
if err != nil && !E.IsClosed(err) {
|
||||||
log.Error(E.Cause(err, "serve debug HTTP server"))
|
log.Error(E.Cause(err, "serve debug HTTP server"))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/experimental/locale"
|
"github.com/sagernet/sing-box/experimental/locale"
|
||||||
|
|
||||||
@@ -14,11 +15,7 @@ func setLocaleFromContext(ctx context.Context) {
|
|||||||
if !loaded {
|
if !loaded {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, localeID := range requestMetadata.Get("accept-language") {
|
slices.ContainsFunc(requestMetadata.Get("accept-language"), locale.Set)
|
||||||
if locale.Set(localeID) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func unaryLocaleInterceptor(ctx context.Context, request any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
func unaryLocaleInterceptor(ctx context.Context, request any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ func init() {
|
|||||||
Locale: "fa",
|
Locale: "fa",
|
||||||
DeprecatedMessage: "%s از sing-box %s منسوخ شده است و در sing-box %s حذف خواهد شد؛ لطفاً راهنمای مهاجرت را ببینید.",
|
DeprecatedMessage: "%s از sing-box %s منسوخ شده است و در sing-box %s حذف خواهد شد؛ لطفاً راهنمای مهاجرت را ببینید.",
|
||||||
DeprecatedMessageNoLink: "%s از sing-box %s منسوخ شده است و در sing-box %s حذف خواهد شد.",
|
DeprecatedMessageNoLink: "%s از sing-box %s منسوخ شده است و در sing-box %s حذف خواهد شد.",
|
||||||
InsecureFeatureMessage: "%s در کلاینت گرافیکی sing-box برای Windows ناامن تلقی میشود. برای استفاده، `حالت ناامن` را در `تنظیمات - هسته - حالت ناامن` فعال کنید.",
|
InsecureFeatureMessage: "%s در کلاینت گرافیکی sing-box برای Windows ناامن تلقی می\u200cشود. برای استفاده، `حالت ناامن` را در `تنظیمات - هسته - حالت ناامن` فعال کنید.",
|
||||||
ExternalPathFeature: "دسترسی به %s (خارج از پوشهٔ کاری) در کلاینت گرافیکی sing-box برای Windows ناامن تلقی میشود. برای استفاده، `حالت ناامن` را در `تنظیمات - هسته - حالت ناامن` فعال کنید.",
|
ExternalPathFeature: "دسترسی به %s (خارج از پوشهٔ کاری) در کلاینت گرافیکی sing-box برای Windows ناامن تلقی می\u200cشود. برای استفاده، `حالت ناامن` را در `تنظیمات - هسته - حالت ناامن` فعال کنید.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -68,9 +68,6 @@ func NewDefaultFactory(
|
|||||||
/*if platformWriter != nil {
|
/*if platformWriter != nil {
|
||||||
factory.platformFormatter.DisableColors = platformWriter.DisableColors()
|
factory.platformFormatter.DisableColors = platformWriter.DisableColors()
|
||||||
}*/
|
}*/
|
||||||
if needObservable {
|
|
||||||
factory.observer = observable.NewObserver[Entry](factory.subscriber, 64)
|
|
||||||
}
|
|
||||||
return factory
|
return factory
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +82,9 @@ func (f *defaultFactory) Start() error {
|
|||||||
f.file = logFile
|
f.file = logFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if f.needObservable {
|
||||||
|
f.observer = observable.NewObserver[Entry](f.subscriber, 64)
|
||||||
|
}
|
||||||
f.startAccess.Lock()
|
f.startAccess.Lock()
|
||||||
pendingEntries := f.pendingEntries
|
pendingEntries := f.pendingEntries
|
||||||
f.pendingEntries = nil
|
f.pendingEntries = nil
|
||||||
|
|||||||
+20
-10
@@ -30,9 +30,11 @@ var _ adapter.OutboundWithMultiplex = (*Outbound)(nil)
|
|||||||
|
|
||||||
type Outbound struct {
|
type Outbound struct {
|
||||||
outbound.Adapter
|
outbound.Adapter
|
||||||
|
ctx context.Context
|
||||||
dialer tls.Dialer
|
dialer tls.Dialer
|
||||||
server M.Socksaddr
|
server M.Socksaddr
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
|
clientOptions anytls.ClientConfig
|
||||||
clientMetadata string
|
clientMetadata string
|
||||||
client *anytls.Client
|
client *anytls.Client
|
||||||
sessionClient *session.Client
|
sessionClient *session.Client
|
||||||
@@ -43,6 +45,7 @@ type Outbound struct {
|
|||||||
func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.AnyTLSOutboundOptions) (adapter.Outbound, error) {
|
func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.AnyTLSOutboundOptions) (adapter.Outbound, error) {
|
||||||
outbound := &Outbound{
|
outbound := &Outbound{
|
||||||
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeAnyTLS, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
|
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeAnyTLS, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
|
||||||
|
ctx: ctx,
|
||||||
server: options.ServerOptions.Build(),
|
server: options.ServerOptions.Build(),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
@@ -74,26 +77,33 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
|
|
||||||
outbound.dialer = tls.NewDialer(outboundDialer, tlsConfig)
|
outbound.dialer = tls.NewDialer(outboundDialer, tlsConfig)
|
||||||
|
|
||||||
client, err := anytls.NewClient(ctx, anytls.ClientConfig{
|
outbound.clientOptions = anytls.ClientConfig{
|
||||||
Password: options.Password,
|
Password: options.Password,
|
||||||
IdleSessionCheckInterval: options.IdleSessionCheckInterval.Build(),
|
IdleSessionCheckInterval: options.IdleSessionCheckInterval.Build(),
|
||||||
IdleSessionTimeout: options.IdleSessionTimeout.Build(),
|
IdleSessionTimeout: options.IdleSessionTimeout.Build(),
|
||||||
MinIdleSession: options.MinIdleSession,
|
MinIdleSession: options.MinIdleSession,
|
||||||
DialOut: outbound.dialOut,
|
DialOut: outbound.dialOut,
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
outbound.client = client
|
|
||||||
outbound.clientMetadata = options.ClientMetadata
|
outbound.clientMetadata = options.ClientMetadata
|
||||||
outbound.sessionClient = sessionClientOf(client)
|
return outbound, nil
|
||||||
|
}
|
||||||
|
|
||||||
outbound.uotClient = &uot.Client{
|
func (h *Outbound) Start(stage adapter.StartStage) error {
|
||||||
Dialer: (anytlsDialer)(outbound.createProxy),
|
if stage != adapter.StartStateInitialize {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
client, err := anytls.NewClient(h.ctx, h.clientOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h.client = client
|
||||||
|
h.sessionClient = sessionClientOf(client)
|
||||||
|
h.uotClient = &uot.Client{
|
||||||
|
Dialer: (anytlsDialer)(h.createProxy),
|
||||||
Version: uot.Version,
|
Version: uot.Version,
|
||||||
}
|
}
|
||||||
return outbound, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) createProxy(ctx context.Context, destination M.Socksaddr) (net.Conn, error) {
|
func (h *Outbound) createProxy(ctx context.Context, destination M.Socksaddr) (net.Conn, error) {
|
||||||
@@ -152,5 +162,5 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
return common.Close(h.client)
|
return common.Close(common.PtrOrNil(h.client))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,10 +153,6 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
}
|
}
|
||||||
stateDirectory = filemanager.BasePath(ctx, os.ExpandEnv(stateDirectory))
|
stateDirectory = filemanager.BasePath(ctx, os.ExpandEnv(stateDirectory))
|
||||||
stateDirectory, _ = filepath.Abs(stateDirectory)
|
stateDirectory, _ = filepath.Abs(stateDirectory)
|
||||||
mkdirErr := filemanager.MkdirAll(ctx, stateDirectory, 0o700)
|
|
||||||
if mkdirErr != nil {
|
|
||||||
return nil, E.Cause(mkdirErr, "create state directory")
|
|
||||||
}
|
|
||||||
if options.SSHServer != nil && options.SSHServer.Enabled {
|
if options.SSHServer != nil && options.SSHServer.Enabled {
|
||||||
err := adapter.CheckSecurityFeature(ctx, "Tailscale `ssh_server`")
|
err := adapter.CheckSecurityFeature(ctx, "Tailscale `ssh_server`")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -250,6 +246,10 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
func (t *Endpoint) Start(stage adapter.StartStage) error {
|
func (t *Endpoint) Start(stage adapter.StartStage) error {
|
||||||
switch stage {
|
switch stage {
|
||||||
case adapter.StartStateInitialize:
|
case adapter.StartStateInitialize:
|
||||||
|
mkdirErr := filemanager.MkdirAll(t.ctx, t.server.Dir, 0o700)
|
||||||
|
if mkdirErr != nil {
|
||||||
|
return E.Cause(mkdirErr, "create state directory")
|
||||||
|
}
|
||||||
t.server.PeerDNSQueryHandler = (*peerDNSQueryHandler)(t)
|
t.server.PeerDNSQueryHandler = (*peerDNSQueryHandler)(t)
|
||||||
case adapter.StartStateStart:
|
case adapter.StartStateStart:
|
||||||
return t.start()
|
return t.start()
|
||||||
|
|||||||
+39
-19
@@ -35,6 +35,7 @@ type Outbound struct {
|
|||||||
outbound.Adapter
|
outbound.Adapter
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
|
dialer N.Dialer
|
||||||
proxy *proxybridge.Bridge
|
proxy *proxybridge.Bridge
|
||||||
startConf *tor.StartConf
|
startConf *tor.StartConf
|
||||||
options map[string]string
|
options map[string]string
|
||||||
@@ -51,10 +52,6 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
}
|
}
|
||||||
startConf.TempDataDirBase = filemanager.TempPath(ctx)
|
startConf.TempDataDirBase = filemanager.TempPath(ctx)
|
||||||
if startConf.DataDir != "" {
|
if startConf.DataDir != "" {
|
||||||
err := filemanager.MkdirAll(ctx, startConf.DataDir, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dataDirAbs, _ := filepath.Abs(startConf.DataDir)
|
dataDirAbs, _ := filepath.Abs(startConf.DataDir)
|
||||||
geoIPPath := filepath.Join(dataDirAbs, "geoip")
|
geoIPPath := filepath.Join(dataDirAbs, "geoip")
|
||||||
geoIPInfo, err := filemanager.Stat(ctx, geoIPPath)
|
geoIPInfo, err := filemanager.Stat(ctx, geoIPPath)
|
||||||
@@ -68,14 +65,9 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
}
|
}
|
||||||
torrcFile := filepath.Join(startConf.DataDir, "torrc")
|
torrcFile := filepath.Join(startConf.DataDir, "torrc")
|
||||||
torrcInfo, err := filemanager.Stat(ctx, torrcFile)
|
torrcInfo, err := filemanager.Stat(ctx, torrcFile)
|
||||||
if os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
err = filemanager.WriteFile(ctx, torrcFile, []byte(""), 0o600)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
} else if err == nil && torrcInfo.IsDir() {
|
||||||
} else if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if torrcInfo.IsDir() {
|
|
||||||
return nil, E.New("Tor configuration path is a directory: ", torrcFile)
|
return nil, E.New("Tor configuration path is a directory: ", torrcFile)
|
||||||
}
|
}
|
||||||
startConf.TorrcFile = torrcFile
|
startConf.TorrcFile = torrcFile
|
||||||
@@ -94,26 +86,54 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
proxy, err := proxybridge.New(ctx, logger, "proxy", outboundDialer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Outbound{
|
return &Outbound{
|
||||||
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTor, tag, []string{N.NetworkTCP}, options.DialerOptions),
|
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTor, tag, []string{N.NetworkTCP}, options.DialerOptions),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
proxy: proxy,
|
dialer: outboundDialer,
|
||||||
startConf: &startConf,
|
startConf: &startConf,
|
||||||
options: options.Options,
|
options: options.Options,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Outbound) Start() error {
|
func (t *Outbound) Start(stage adapter.StartStage) error {
|
||||||
err := t.start()
|
switch stage {
|
||||||
|
case adapter.StartStateInitialize:
|
||||||
|
if t.startConf.DataDir == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := filemanager.MkdirAll(t.ctx, t.startConf.DataDir, 0o755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
torrcInfo, err := filemanager.Stat(t.ctx, t.startConf.TorrcFile)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = filemanager.WriteFile(t.ctx, t.startConf.TorrcFile, []byte(""), 0o600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
} else if torrcInfo.IsDir() {
|
||||||
|
return E.New("Tor configuration path is a directory: ", t.startConf.TorrcFile)
|
||||||
|
}
|
||||||
|
case adapter.StartStateStart:
|
||||||
|
proxy, err := proxybridge.New(t.ctx, t.logger, "proxy", t.dialer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.proxy = proxy
|
||||||
|
err = proxy.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = t.start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Close()
|
t.Close()
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var torLogEvents = []control.EventCode{
|
var torLogEvents = []control.EventCode{
|
||||||
|
|||||||
+29
-16
@@ -51,6 +51,8 @@ type Service struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
config *certmagic.Config
|
config *certmagic.Config
|
||||||
cache *certmagic.Cache
|
cache *certmagic.Cache
|
||||||
|
zapLogger *zap.Logger
|
||||||
|
dataDirectory string
|
||||||
domain []string
|
domain []string
|
||||||
nextProtos []string
|
nextProtos []string
|
||||||
}
|
}
|
||||||
@@ -78,13 +80,12 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
|||||||
return nil, E.New("email is required to use the ZeroSSL ACME endpoint without external_account or account_key")
|
return nil, E.New("email is required to use the ZeroSSL ACME endpoint without external_account or account_key")
|
||||||
}
|
}
|
||||||
|
|
||||||
var storage certmagic.Storage
|
var (
|
||||||
|
storage certmagic.Storage
|
||||||
|
dataDirectory string
|
||||||
|
)
|
||||||
if options.DataDirectory != "" {
|
if options.DataDirectory != "" {
|
||||||
dataDirectory := filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
dataDirectory = filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
||||||
err := filemanager.MkdirAll(ctx, dataDirectory, 0o700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, E.Cause(err, "create ACME data directory")
|
|
||||||
}
|
|
||||||
storage = &certmagic.FileStorage{Path: dataDirectory}
|
storage = &certmagic.FileStorage{Path: dataDirectory}
|
||||||
} else {
|
} else {
|
||||||
storage = certmagic.Default.Storage
|
storage = certmagic.Default.Storage
|
||||||
@@ -169,13 +170,6 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
|||||||
}
|
}
|
||||||
reflect.NewAt(httpClientField.Type(), unsafe.Pointer(httpClientField.UnsafeAddr())).Elem().Set(reflect.ValueOf(acmeHTTPClient))
|
reflect.NewAt(httpClientField.Type(), unsafe.Pointer(httpClientField.UnsafeAddr())).Elem().Set(reflect.ValueOf(acmeHTTPClient))
|
||||||
config.Issuers = []certmagic.Issuer{certmagicIssuer}
|
config.Issuers = []certmagic.Issuer{certmagicIssuer}
|
||||||
cache := certmagic.NewCache(certmagic.CacheOptions{
|
|
||||||
GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) {
|
|
||||||
return config, nil
|
|
||||||
},
|
|
||||||
Logger: zapLogger,
|
|
||||||
})
|
|
||||||
config = certmagic.New(cache, *config)
|
|
||||||
|
|
||||||
var nextProtos []string
|
var nextProtos []string
|
||||||
if !acmeIssuer.DisableTLSALPNChallenge && acmeIssuer.DNS01Solver == nil {
|
if !acmeIssuer.DisableTLSALPNChallenge && acmeIssuer.DNS01Solver == nil {
|
||||||
@@ -185,17 +179,36 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
|||||||
Adapter: certificate.NewAdapter(C.TypeACME, tag),
|
Adapter: certificate.NewAdapter(C.TypeACME, tag),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
config: config,
|
config: config,
|
||||||
cache: cache,
|
zapLogger: zapLogger,
|
||||||
|
dataDirectory: dataDirectory,
|
||||||
domain: options.Domain,
|
domain: options.Domain,
|
||||||
nextProtos: nextProtos,
|
nextProtos: nextProtos,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Start(stage adapter.StartStage) error {
|
func (s *Service) Start(stage adapter.StartStage) error {
|
||||||
if stage != adapter.StartStateStart {
|
switch stage {
|
||||||
return nil
|
case adapter.StartStateInitialize:
|
||||||
|
if s.dataDirectory != "" {
|
||||||
|
err := filemanager.MkdirAll(s.ctx, s.dataDirectory, 0o700)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "create ACME data directory")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
config := s.config
|
||||||
|
cache := certmagic.NewCache(certmagic.CacheOptions{
|
||||||
|
GetConfigForCert: func(certificate certmagic.Certificate) (*certmagic.Config, error) {
|
||||||
|
return config, nil
|
||||||
|
},
|
||||||
|
Logger: s.zapLogger,
|
||||||
|
})
|
||||||
|
config = certmagic.New(cache, *config)
|
||||||
|
s.config = config
|
||||||
|
s.cache = cache
|
||||||
|
case adapter.StartStateStart:
|
||||||
return s.config.ManageAsync(s.ctx, s.domain)
|
return s.config.ManageAsync(s.ctx, s.domain)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Close() error {
|
func (s *Service) Close() error {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ type Service struct {
|
|||||||
timeFunc func() time.Time
|
timeFunc func() time.Time
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
storage certmagic.Storage
|
storage certmagic.Storage
|
||||||
|
dataDirectory string
|
||||||
storageIssuerKey string
|
storageIssuerKey string
|
||||||
storageNamesKey string
|
storageNamesKey string
|
||||||
storageLockKey string
|
storageLockKey string
|
||||||
@@ -109,14 +110,12 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
|||||||
cancel()
|
cancel()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var storage certmagic.Storage
|
var (
|
||||||
|
storage certmagic.Storage
|
||||||
|
dataDirectory string
|
||||||
|
)
|
||||||
if options.DataDirectory != "" {
|
if options.DataDirectory != "" {
|
||||||
dataDirectory := filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
dataDirectory = filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
|
||||||
mkdirErr := filemanager.MkdirAll(ctx, dataDirectory, 0o700)
|
|
||||||
if mkdirErr != nil {
|
|
||||||
cancel()
|
|
||||||
return nil, E.Cause(mkdirErr, "create data directory")
|
|
||||||
}
|
|
||||||
storage = &certmagic.FileStorage{Path: dataDirectory}
|
storage = &certmagic.FileStorage{Path: dataDirectory}
|
||||||
} else {
|
} else {
|
||||||
storage = certmagic.Default.Storage
|
storage = certmagic.Default.Storage
|
||||||
@@ -140,6 +139,7 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
|||||||
timeFunc: timeFunc,
|
timeFunc: timeFunc,
|
||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
|
dataDirectory: dataDirectory,
|
||||||
storageIssuerKey: storageIssuerKey,
|
storageIssuerKey: storageIssuerKey,
|
||||||
storageNamesKey: storageNamesKey,
|
storageNamesKey: storageNamesKey,
|
||||||
storageLockKey: storageLockKey,
|
storageLockKey: storageLockKey,
|
||||||
@@ -162,7 +162,16 @@ func originCAHTTPClient(ctx context.Context, logger log.ContextLogger, options o
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Start(stage adapter.StartStage) error {
|
func (s *Service) Start(stage adapter.StartStage) error {
|
||||||
if stage != adapter.StartStateStart {
|
if stage == adapter.StartStateInitialize {
|
||||||
|
if s.dataDirectory == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := filemanager.MkdirAll(s.ctx, s.dataDirectory, 0o700)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "create data directory")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else if stage != adapter.StartStateStart {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cachedCertificate, cachedLeaf, err := s.loadCachedCertificate()
|
cachedCertificate, cachedLeaf, err := s.loadCachedCertificate()
|
||||||
|
|||||||
Reference in New Issue
Block a user