registry.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package inbound
  2. import (
  3. "context"
  4. "sync"
  5. "github.com/sagernet/sing-box/adapter"
  6. "github.com/sagernet/sing-box/log"
  7. "github.com/sagernet/sing/common"
  8. E "github.com/sagernet/sing/common/exceptions"
  9. )
  10. type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options T) (adapter.Inbound, error)
  11. func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
  12. registry.register(outboundType, func() any {
  13. return new(Options)
  14. }, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, rawOptions any) (adapter.Inbound, error) {
  15. var options *Options
  16. if rawOptions != nil {
  17. options = rawOptions.(*Options)
  18. }
  19. return constructor(ctx, router, logger, tag, common.PtrValueOrDefault(options))
  20. })
  21. }
  22. var _ adapter.InboundRegistry = (*Registry)(nil)
  23. type (
  24. optionsConstructorFunc func() any
  25. constructorFunc func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options any) (adapter.Inbound, error)
  26. )
  27. type Registry struct {
  28. access sync.Mutex
  29. optionsType map[string]optionsConstructorFunc
  30. constructor map[string]constructorFunc
  31. }
  32. func NewRegistry() *Registry {
  33. return &Registry{
  34. optionsType: make(map[string]optionsConstructorFunc),
  35. constructor: make(map[string]constructorFunc),
  36. }
  37. }
  38. func (m *Registry) CreateOptions(outboundType string) (any, bool) {
  39. m.access.Lock()
  40. defer m.access.Unlock()
  41. optionsConstructor, loaded := m.optionsType[outboundType]
  42. if !loaded {
  43. return nil, false
  44. }
  45. return optionsConstructor(), true
  46. }
  47. func (m *Registry) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Inbound, error) {
  48. m.access.Lock()
  49. defer m.access.Unlock()
  50. constructor, loaded := m.constructor[outboundType]
  51. if !loaded {
  52. return nil, E.New("outbound type not found: " + outboundType)
  53. }
  54. return constructor(ctx, router, logger, tag, options)
  55. }
  56. func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
  57. m.access.Lock()
  58. defer m.access.Unlock()
  59. m.optionsType[outboundType] = optionsConstructor
  60. m.constructor[outboundType] = constructor
  61. }