mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-27 18:35:38 +08:00
73 lines
2.2 KiB
Go
73 lines
2.2 KiB
Go
|
package endpoint
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/sagernet/sing-box/adapter"
|
||
|
"github.com/sagernet/sing-box/log"
|
||
|
"github.com/sagernet/sing/common"
|
||
|
E "github.com/sagernet/sing/common/exceptions"
|
||
|
)
|
||
|
|
||
|
type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options T) (adapter.Endpoint, error)
|
||
|
|
||
|
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
|
||
|
registry.register(outboundType, func() any {
|
||
|
return new(Options)
|
||
|
}, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, rawOptions any) (adapter.Endpoint, error) {
|
||
|
var options *Options
|
||
|
if rawOptions != nil {
|
||
|
options = rawOptions.(*Options)
|
||
|
}
|
||
|
return constructor(ctx, router, logger, tag, common.PtrValueOrDefault(options))
|
||
|
})
|
||
|
}
|
||
|
|
||
|
var _ adapter.EndpointRegistry = (*Registry)(nil)
|
||
|
|
||
|
type (
|
||
|
optionsConstructorFunc func() any
|
||
|
constructorFunc func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options any) (adapter.Endpoint, error)
|
||
|
)
|
||
|
|
||
|
type Registry struct {
|
||
|
access sync.Mutex
|
||
|
optionsType map[string]optionsConstructorFunc
|
||
|
constructor map[string]constructorFunc
|
||
|
}
|
||
|
|
||
|
func NewRegistry() *Registry {
|
||
|
return &Registry{
|
||
|
optionsType: make(map[string]optionsConstructorFunc),
|
||
|
constructor: make(map[string]constructorFunc),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *Registry) CreateOptions(outboundType string) (any, bool) {
|
||
|
m.access.Lock()
|
||
|
defer m.access.Unlock()
|
||
|
optionsConstructor, loaded := m.optionsType[outboundType]
|
||
|
if !loaded {
|
||
|
return nil, false
|
||
|
}
|
||
|
return optionsConstructor(), true
|
||
|
}
|
||
|
|
||
|
func (m *Registry) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Endpoint, error) {
|
||
|
m.access.Lock()
|
||
|
defer m.access.Unlock()
|
||
|
constructor, loaded := m.constructor[outboundType]
|
||
|
if !loaded {
|
||
|
return nil, E.New("outbound type not found: " + outboundType)
|
||
|
}
|
||
|
return constructor(ctx, router, logger, tag, options)
|
||
|
}
|
||
|
|
||
|
func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
|
||
|
m.access.Lock()
|
||
|
defer m.access.Unlock()
|
||
|
m.optionsType[outboundType] = optionsConstructor
|
||
|
m.constructor[outboundType] = constructor
|
||
|
}
|