mirror of https://github.com/XTLS/Xray-core
Add OptionalFeatures injection
For example OptionalFeatures() is useful for fakedns modulepull/4206/head
parent
9c62017e96
commit
377a41844f
|
@ -106,7 +106,7 @@ func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
d := new(DefaultDispatcher)
|
d := new(DefaultDispatcher)
|
||||||
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
|
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
|
||||||
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
|
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
d.fdns = fdns
|
d.fdns = fdns
|
||||||
})
|
})
|
||||||
return d.Init(config.(*Config), om, router, pm, sm, dc)
|
return d.Init(config.(*Config), om, router, pm, sm, dc)
|
||||||
|
|
|
@ -56,7 +56,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
||||||
return NewTCPLocalNameServer(u, queryStrategy)
|
return NewTCPLocalNameServer(u, queryStrategy)
|
||||||
case strings.EqualFold(u.String(), "fakedns"):
|
case strings.EqualFold(u.String(), "fakedns"):
|
||||||
var fd dns.FakeDNSEngine
|
var fd dns.FakeDNSEngine
|
||||||
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
|
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
fd = fdns
|
fd = fdns
|
||||||
})
|
})
|
||||||
return NewFakeDNSServer(fd), nil
|
return NewFakeDNSServer(fd), nil
|
||||||
|
|
|
@ -38,7 +38,7 @@ func init() {
|
||||||
sv := &service{v: s}
|
sv := &service{v: s}
|
||||||
err := s.RequireFeatures(func(Observatory extension.Observatory) {
|
err := s.RequireFeatures(func(Observatory extension.Observatory) {
|
||||||
sv.observatory = Observatory
|
sv.observatory = Observatory
|
||||||
})
|
}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ func (s *service) Register(server *grpc.Server) {
|
||||||
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
|
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
|
||||||
hs.ihm = im
|
hs.ihm = im
|
||||||
hs.ohm = om
|
hs.ohm = om
|
||||||
}))
|
}, false))
|
||||||
RegisterHandlerServiceServer(server, hs)
|
RegisterHandlerServiceServer(server, hs)
|
||||||
|
|
||||||
// For compatibility purposes
|
// For compatibility purposes
|
||||||
|
|
|
@ -135,7 +135,7 @@ func (s *service) Register(server *grpc.Server) {
|
||||||
vCoreDesc := RoutingService_ServiceDesc
|
vCoreDesc := RoutingService_ServiceDesc
|
||||||
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
|
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
|
||||||
server.RegisterService(&vCoreDesc, rs)
|
server.RegisterService(&vCoreDesc, rs)
|
||||||
}))
|
}, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
41
core/xray.go
41
core/xray.go
|
@ -83,6 +83,7 @@ type Instance struct {
|
||||||
statusLock sync.Mutex
|
statusLock sync.Mutex
|
||||||
features []features.Feature
|
features []features.Feature
|
||||||
pendingResolutions []resolution
|
pendingResolutions []resolution
|
||||||
|
pendingOptionalResolutions []resolution
|
||||||
running bool
|
running bool
|
||||||
resolveLock sync.Mutex
|
resolveLock sync.Mutex
|
||||||
|
|
||||||
|
@ -145,7 +146,14 @@ func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) err
|
||||||
// See Instance.RequireFeatures for more information.
|
// See Instance.RequireFeatures for more information.
|
||||||
func RequireFeatures(ctx context.Context, callback interface{}) error {
|
func RequireFeatures(ctx context.Context, callback interface{}) error {
|
||||||
v := MustFromContext(ctx)
|
v := MustFromContext(ctx)
|
||||||
return v.RequireFeatures(callback)
|
return v.RequireFeatures(callback, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalFeatures is a helper function to aquire features from Instance in context.
|
||||||
|
// See Instance.RequireFeatures for more information.
|
||||||
|
func OptionalFeatures(ctx context.Context, callback interface{}) error {
|
||||||
|
v := MustFromContext(ctx)
|
||||||
|
return v.RequireFeatures(callback, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Xray instance based on given configuration.
|
// New returns a new Xray instance based on given configuration.
|
||||||
|
@ -263,7 +271,7 @@ func (s *Instance) Close() error {
|
||||||
|
|
||||||
// RequireFeatures registers a callback, which will be called when all dependent features are registered.
|
// RequireFeatures registers a callback, which will be called when all dependent features are registered.
|
||||||
// The callback must be a func(). All its parameters must be features.Feature.
|
// The callback must be a func(). All its parameters must be features.Feature.
|
||||||
func (s *Instance) RequireFeatures(callback interface{}) error {
|
func (s *Instance) RequireFeatures(callback interface{}, optional bool) error {
|
||||||
callbackType := reflect.TypeOf(callback)
|
callbackType := reflect.TypeOf(callback)
|
||||||
if callbackType.Kind() != reflect.Func {
|
if callbackType.Kind() != reflect.Func {
|
||||||
panic("not a function")
|
panic("not a function")
|
||||||
|
@ -291,8 +299,12 @@ func (s *Instance) RequireFeatures(callback interface{}) error {
|
||||||
if foundAll {
|
if foundAll {
|
||||||
s.resolveLock.Unlock()
|
s.resolveLock.Unlock()
|
||||||
return r.callbackResolution(s.features)
|
return r.callbackResolution(s.features)
|
||||||
|
} else {
|
||||||
|
if optional {
|
||||||
|
s.pendingOptionalResolutions = append(s.pendingOptionalResolutions, r)
|
||||||
} else {
|
} else {
|
||||||
s.pendingResolutions = append(s.pendingResolutions, r)
|
s.pendingResolutions = append(s.pendingResolutions, r)
|
||||||
|
}
|
||||||
s.resolveLock.Unlock()
|
s.resolveLock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -309,12 +321,9 @@ func (s *Instance) AddFeature(feature features.Feature) error {
|
||||||
|
|
||||||
s.resolveLock.Lock()
|
s.resolveLock.Lock()
|
||||||
s.features = append(s.features, feature)
|
s.features = append(s.features, feature)
|
||||||
if s.pendingResolutions == nil {
|
|
||||||
s.resolveLock.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var pending []resolution
|
|
||||||
var availableResolution []resolution
|
var availableResolution []resolution
|
||||||
|
var pending []resolution
|
||||||
for _, r := range s.pendingResolutions {
|
for _, r := range s.pendingResolutions {
|
||||||
foundAll := true
|
foundAll := true
|
||||||
for _, d := range r.deps {
|
for _, d := range r.deps {
|
||||||
|
@ -331,6 +340,24 @@ func (s *Instance) AddFeature(feature features.Feature) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.pendingResolutions = pending
|
s.pendingResolutions = pending
|
||||||
|
|
||||||
|
var pendingOptional []resolution
|
||||||
|
for _, r := range s.pendingOptionalResolutions {
|
||||||
|
foundAll := true
|
||||||
|
for _, d := range r.deps {
|
||||||
|
f := getFeature(s.features, d)
|
||||||
|
if f == nil {
|
||||||
|
foundAll = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if foundAll {
|
||||||
|
availableResolution = append(availableResolution, r)
|
||||||
|
} else {
|
||||||
|
pendingOptional = append(pendingOptional, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.pendingOptionalResolutions = pendingOptional
|
||||||
s.resolveLock.Unlock()
|
s.resolveLock.Unlock()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestXrayDependency(t *testing.T) {
|
||||||
t.Error("expected dns client fulfilled, but actually nil")
|
t.Error("expected dns client fulfilled, but actually nil")
|
||||||
}
|
}
|
||||||
wait <- true
|
wait <- true
|
||||||
})
|
}, false)
|
||||||
instance.AddFeature(localdns.New())
|
instance.AddFeature(localdns.New())
|
||||||
<-wait
|
<-wait
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
h := new(Handler)
|
h := new(Handler)
|
||||||
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
|
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
|
||||||
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
|
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
h.fdns = fdns
|
h.fdns = fdns
|
||||||
})
|
})
|
||||||
return h.Init(config.(*Config), dnsClient, policyManager)
|
return h.Init(config.(*Config), dnsClient, policyManager)
|
||||||
|
|
Loading…
Reference in New Issue