mirror of https://github.com/v2ray/v2ray-core
refactor dependency resolution
parent
d9cdfffc69
commit
a5dcb0f13e
|
@ -12,29 +12,46 @@ import (
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/signal/done"
|
"v2ray.com/core/common/signal/done"
|
||||||
|
"v2ray.com/core/features"
|
||||||
"v2ray.com/core/features/outbound"
|
"v2ray.com/core/features/outbound"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commander is a V2Ray feature that provides gRPC methods to external clients.
|
// Commander is a V2Ray feature that provides gRPC methods to external clients.
|
||||||
type Commander struct {
|
type Commander struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
server *grpc.Server
|
server *grpc.Server
|
||||||
config Config
|
services []Service
|
||||||
v *core.Instance
|
ohm outbound.Manager
|
||||||
ohm outbound.Manager
|
tag string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommander creates a new Commander based on the given config.
|
// NewCommander creates a new Commander based on the given config.
|
||||||
func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
|
func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
c := &Commander{
|
c := &Commander{
|
||||||
config: *config,
|
tag: config.Tag,
|
||||||
ohm: v.OutboundHandlerManager(),
|
|
||||||
v: v,
|
|
||||||
}
|
}
|
||||||
if err := v.RegisterFeature(c); err != nil {
|
|
||||||
return nil, err
|
v := core.MustFromContext(ctx)
|
||||||
|
v.RequireFeatures([]interface{}{outbound.ManagerType()}, func(fs []features.Feature) {
|
||||||
|
c.ohm = fs[0].(outbound.Manager)
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, rawConfig := range config.Service {
|
||||||
|
config, err := rawConfig.GetInstance()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rawService, err := common.CreateObject(ctx, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
service, ok := rawService.(Service)
|
||||||
|
if !ok {
|
||||||
|
return nil, newError("not a Service.")
|
||||||
|
}
|
||||||
|
c.services = append(c.services, service)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,19 +64,7 @@ func (c *Commander) Type() interface{} {
|
||||||
func (c *Commander) Start() error {
|
func (c *Commander) Start() error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
c.server = grpc.NewServer()
|
c.server = grpc.NewServer()
|
||||||
for _, rawConfig := range c.config.Service {
|
for _, service := range c.services {
|
||||||
config, err := rawConfig.GetInstance()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rawService, err := core.CreateObject(c.v, config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
service, ok := rawService.(Service)
|
|
||||||
if !ok {
|
|
||||||
return newError("not a Service.")
|
|
||||||
}
|
|
||||||
service.Register(c.server)
|
service.Register(c.server)
|
||||||
}
|
}
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
@ -75,12 +80,12 @@ func (c *Commander) Start() error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := c.ohm.RemoveHandler(context.Background(), c.config.Tag); err != nil {
|
if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil {
|
||||||
newError("failed to remove existing handler").WriteToLog()
|
newError("failed to remove existing handler").WriteToLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.ohm.AddHandler(context.Background(), &Outbound{
|
return c.ohm.AddHandler(context.Background(), &Outbound{
|
||||||
tag: c.config.Tag,
|
tag: c.tag,
|
||||||
listener: listener,
|
listener: listener,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
"v2ray.com/core/common/session"
|
"v2ray.com/core/common/session"
|
||||||
"v2ray.com/core/common/vio"
|
"v2ray.com/core/common/vio"
|
||||||
|
"v2ray.com/core/features"
|
||||||
"v2ray.com/core/features/outbound"
|
"v2ray.com/core/features/outbound"
|
||||||
"v2ray.com/core/features/policy"
|
"v2ray.com/core/features/policy"
|
||||||
"v2ray.com/core/features/routing"
|
"v2ray.com/core/features/routing"
|
||||||
|
@ -91,17 +92,22 @@ type DefaultDispatcher struct {
|
||||||
|
|
||||||
// NewDefaultDispatcher create a new DefaultDispatcher.
|
// NewDefaultDispatcher create a new DefaultDispatcher.
|
||||||
func NewDefaultDispatcher(ctx context.Context, config *Config) (*DefaultDispatcher, error) {
|
func NewDefaultDispatcher(ctx context.Context, config *Config) (*DefaultDispatcher, error) {
|
||||||
v := core.MustFromContext(ctx)
|
d := &DefaultDispatcher{}
|
||||||
d := &DefaultDispatcher{
|
|
||||||
ohm: v.OutboundHandlerManager(),
|
v := core.MustFromContext(ctx)
|
||||||
router: v.Router(),
|
v.RequireFeatures([]interface{}{outbound.ManagerType(), routing.RouterType(), policy.ManagerType()}, func(fs []features.Feature) {
|
||||||
policy: v.PolicyManager(),
|
d.ohm = fs[0].(outbound.Manager)
|
||||||
stats: v.Stats(),
|
d.router = fs[1].(routing.Router)
|
||||||
}
|
d.policy = fs[2].(policy.Manager)
|
||||||
|
})
|
||||||
|
v.RequireFeatures([]interface{}{core.ServerType()}, func([]features.Feature) {
|
||||||
|
f := v.GetFeature(stats.ManagerType())
|
||||||
|
if f == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.stats = f.(stats.Manager)
|
||||||
|
})
|
||||||
|
|
||||||
if err := v.RegisterFeature(d); err != nil {
|
|
||||||
return nil, newError("unable to register Dispatcher").Base(err)
|
|
||||||
}
|
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"v2ray.com/core/features/routing"
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
|
@ -42,9 +44,6 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||||
server.hosts = hosts
|
server.hosts = hosts
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
if err := v.RegisterFeature(server); err != nil {
|
|
||||||
return nil, newError("unable to register DNSClient.").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
addNameServer := func(endpoint *net.Endpoint) int {
|
addNameServer := func(endpoint *net.Endpoint) int {
|
||||||
address := endpoint.Address.AsAddress()
|
address := endpoint.Address.AsAddress()
|
||||||
|
@ -56,7 +55,12 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||||
dest.Network = net.Network_UDP
|
dest.Network = net.Network_UDP
|
||||||
}
|
}
|
||||||
if dest.Network == net.Network_UDP {
|
if dest.Network == net.Network_UDP {
|
||||||
server.servers = append(server.servers, NewClassicNameServer(dest, v.Dispatcher(), server.clientIP))
|
idx := len(server.servers)
|
||||||
|
server.servers = append(server.servers, nil)
|
||||||
|
v.RequireFeatures([]interface{}{routing.DispatcherType()}, func(fs []features.Feature) {
|
||||||
|
dispatcher := fs[0].(routing.Dispatcher)
|
||||||
|
server.servers[idx] = NewClassicNameServer(dest, dispatcher, server.clientIP)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len(server.servers) - 1
|
return len(server.servers) - 1
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
_ "v2ray.com/core/app/proxyman/outbound"
|
_ "v2ray.com/core/app/proxyman/outbound"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
|
feature_dns "v2ray.com/core/features/dns"
|
||||||
"v2ray.com/core/proxy/freedom"
|
"v2ray.com/core/proxy/freedom"
|
||||||
"v2ray.com/core/testing/servers/udp"
|
"v2ray.com/core/testing/servers/udp"
|
||||||
. "v2ray.com/ext/assert"
|
. "v2ray.com/ext/assert"
|
||||||
|
@ -85,7 +86,7 @@ func TestUDPServer(t *testing.T) {
|
||||||
v, err := core.New(config)
|
v, err := core.New(config)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
|
|
||||||
client := v.DNSClient()
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com")
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
|
@ -171,7 +172,7 @@ func TestPrioritizedDomain(t *testing.T) {
|
||||||
v, err := core.New(config)
|
v, err := core.New(config)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
|
|
||||||
client := v.DNSClient()
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com")
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core"
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
)
|
)
|
||||||
|
@ -28,11 +27,6 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
|
||||||
}
|
}
|
||||||
log.RegisterHandler(g)
|
log.RegisterHandler(g)
|
||||||
|
|
||||||
v := core.FromContext(ctx)
|
|
||||||
if v != nil {
|
|
||||||
common.Must(v.RegisterFeature(g))
|
|
||||||
}
|
|
||||||
|
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package policy
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"v2ray.com/core"
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/features/policy"
|
"v2ray.com/core/features/policy"
|
||||||
)
|
)
|
||||||
|
@ -28,13 +27,6 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.FromContext(ctx)
|
|
||||||
if v != nil {
|
|
||||||
if err := v.RegisterFeature(m); err != nil {
|
|
||||||
return nil, newError("unable to register PolicyManager in core").Base(err).AtError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
|
"v2ray.com/core/features"
|
||||||
"v2ray.com/core/features/inbound"
|
"v2ray.com/core/features/inbound"
|
||||||
"v2ray.com/core/features/outbound"
|
"v2ray.com/core/features/outbound"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
|
@ -136,11 +138,14 @@ type service struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Register(server *grpc.Server) {
|
func (s *service) Register(server *grpc.Server) {
|
||||||
RegisterHandlerServiceServer(server, &handlerServer{
|
hs := &handlerServer{
|
||||||
s: s.v,
|
s: s.v,
|
||||||
ihm: s.v.InboundHandlerManager(),
|
}
|
||||||
ohm: s.v.OutboundHandlerManager(),
|
s.v.RequireFeatures([]interface{}{inbound.ManagerType(), outbound.ManagerType()}, func(fs []features.Feature) {
|
||||||
|
hs.ihm = fs[0].(inbound.Manager)
|
||||||
|
hs.ohm = fs[1].(outbound.Manager)
|
||||||
})
|
})
|
||||||
|
RegisterHandlerServiceServer(server, hs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"v2ray.com/core/common/dice"
|
"v2ray.com/core/common/dice"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
|
"v2ray.com/core/features/policy"
|
||||||
"v2ray.com/core/features/stats"
|
"v2ray.com/core/features/stats"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
|
@ -19,9 +20,9 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
|
||||||
var uplinkCounter stats.Counter
|
var uplinkCounter stats.Counter
|
||||||
var downlinkCounter stats.Counter
|
var downlinkCounter stats.Counter
|
||||||
|
|
||||||
policy := v.PolicyManager()
|
policy := v.GetFeature(policy.ManagerType()).(policy.Manager)
|
||||||
statsManager := v.Stats()
|
|
||||||
if len(tag) > 0 && policy.ForSystem().Stats.InboundUplink {
|
if len(tag) > 0 && policy.ForSystem().Stats.InboundUplink {
|
||||||
|
statsManager := v.GetFeature(stats.ManagerType()).(stats.Manager)
|
||||||
name := "inbound>>>" + tag + ">>>traffic>>>uplink"
|
name := "inbound>>>" + tag + ">>>traffic>>>uplink"
|
||||||
c, _ := stats.GetOrRegisterCounter(statsManager, name)
|
c, _ := stats.GetOrRegisterCounter(statsManager, name)
|
||||||
if c != nil {
|
if c != nil {
|
||||||
|
@ -29,6 +30,7 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(tag) > 0 && policy.ForSystem().Stats.InboundDownlink {
|
if len(tag) > 0 && policy.ForSystem().Stats.InboundDownlink {
|
||||||
|
statsManager := v.GetFeature(stats.ManagerType()).(stats.Manager)
|
||||||
name := "inbound>>>" + tag + ">>>traffic>>>downlink"
|
name := "inbound>>>" + tag + ">>>traffic>>>downlink"
|
||||||
c, _ := stats.GetOrRegisterCounter(statsManager, name)
|
c, _ := stats.GetOrRegisterCounter(statsManager, name)
|
||||||
if c != nil {
|
if c != nil {
|
||||||
|
|
|
@ -27,10 +27,6 @@ func New(ctx context.Context, config *proxyman.InboundConfig) (*Manager, error)
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
taggedHandlers: make(map[string]inbound.Handler),
|
taggedHandlers: make(map[string]inbound.Handler),
|
||||||
}
|
}
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
if err := v.RegisterFeature(m); err != nil {
|
|
||||||
return nil, newError("unable to register InboundHandlerManager").Base(err)
|
|
||||||
}
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"v2ray.com/core/features"
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
|
@ -304,9 +306,11 @@ type Server struct {
|
||||||
|
|
||||||
// NewServer creates a new mux.Server.
|
// NewServer creates a new mux.Server.
|
||||||
func NewServer(ctx context.Context) *Server {
|
func NewServer(ctx context.Context) *Server {
|
||||||
s := &Server{
|
s := &Server{}
|
||||||
dispatcher: core.MustFromContext(ctx).Dispatcher(),
|
v := core.MustFromContext(ctx)
|
||||||
}
|
v.RequireFeatures([]interface{}{routing.DispatcherType()}, func(fs []features.Feature) {
|
||||||
|
s.dispatcher = fs[0].(routing.Dispatcher)
|
||||||
|
})
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
config: config,
|
config: config,
|
||||||
outboundManager: v.OutboundHandlerManager(),
|
outboundManager: v.GetFeature(outbound.ManagerType()).(outbound.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.SenderSettings != nil {
|
if config.SenderSettings != nil {
|
||||||
|
|
|
@ -26,10 +26,6 @@ func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager, error)
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
taggedHandler: make(map[string]outbound.Handler),
|
taggedHandler: make(map[string]outbound.Handler),
|
||||||
}
|
}
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
if err := v.RegisterFeature(m); err != nil {
|
|
||||||
return nil, newError("unable to register outbound.Manager").Base(err)
|
|
||||||
}
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/session"
|
"v2ray.com/core/common/session"
|
||||||
|
"v2ray.com/core/features"
|
||||||
"v2ray.com/core/features/dns"
|
"v2ray.com/core/features/dns"
|
||||||
"v2ray.com/core/features/routing"
|
"v2ray.com/core/features/routing"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
|
@ -23,11 +24,9 @@ type Router struct {
|
||||||
|
|
||||||
// NewRouter creates a new Router based on the given config.
|
// NewRouter creates a new Router based on the given config.
|
||||||
func NewRouter(ctx context.Context, config *Config) (*Router, error) {
|
func NewRouter(ctx context.Context, config *Config) (*Router, error) {
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
r := &Router{
|
r := &Router{
|
||||||
domainStrategy: config.DomainStrategy,
|
domainStrategy: config.DomainStrategy,
|
||||||
rules: make([]Rule, len(config.Rule)),
|
rules: make([]Rule, len(config.Rule)),
|
||||||
dns: v.DNSClient(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, rule := range config.Rule {
|
for idx, rule := range config.Rule {
|
||||||
|
@ -39,9 +38,10 @@ func NewRouter(ctx context.Context, config *Config) (*Router, error) {
|
||||||
r.rules[idx].Condition = cond
|
r.rules[idx].Condition = cond
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := v.RegisterFeature(r); err != nil {
|
v := core.MustFromContext(ctx)
|
||||||
return nil, newError("unable to register Router").Base(err)
|
v.RequireFeatures([]interface{}{dns.ClientType()}, func(fs []features.Feature) {
|
||||||
}
|
r.dns = fs[0].(dns.Client)
|
||||||
|
})
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
"v2ray.com/core/common/session"
|
"v2ray.com/core/common/session"
|
||||||
|
"v2ray.com/core/features/routing"
|
||||||
. "v2ray.com/ext/assert"
|
. "v2ray.com/ext/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ func TestSimpleRouter(t *testing.T) {
|
||||||
v, err := core.New(config)
|
v, err := core.New(config)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
r := v.Router()
|
r := v.GetFeature(routing.RouterType()).(routing.Router)
|
||||||
|
|
||||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
|
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
|
||||||
tag, err := r.PickRoute(ctx)
|
tag, err := r.PickRoute(ctx)
|
||||||
|
|
|
@ -79,7 +79,8 @@ type service struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Register(server *grpc.Server) {
|
func (s *service) Register(server *grpc.Server) {
|
||||||
RegisterStatsServiceServer(server, NewStatsServer(s.v.Stats()))
|
f := s.v.GetFeature(feature_stats.ManagerType())
|
||||||
|
RegisterStatsServiceServer(server, NewStatsServer(f.(feature_stats.Manager)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"v2ray.com/core"
|
|
||||||
"v2ray.com/core/features/stats"
|
"v2ray.com/core/features/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,13 +41,6 @@ func NewManager(ctx context.Context, config *Config) (*Manager, error) {
|
||||||
counters: make(map[string]*Counter),
|
counters: make(map[string]*Counter),
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.FromContext(ctx)
|
|
||||||
if v != nil {
|
|
||||||
if err := v.RegisterFeature(m); err != nil {
|
|
||||||
return nil, newError("failed to register StatManager").Base(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
59
dns.go
59
dns.go
|
@ -1,59 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/net"
|
|
||||||
"v2ray.com/core/features/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncDNSClient struct {
|
|
||||||
sync.RWMutex
|
|
||||||
dns.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDNSClient) Type() interface{} {
|
|
||||||
return dns.ClientType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDNSClient) LookupIP(host string) ([]net.IP, error) {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
if d.Client == nil {
|
|
||||||
return net.LookupIP(host)
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.Client.LookupIP(host)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDNSClient) Start() error {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
if d.Client == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.Client.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDNSClient) Close() error {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(d.Client)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDNSClient) Set(client dns.Client) {
|
|
||||||
if client == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d.Lock()
|
|
||||||
defer d.Unlock()
|
|
||||||
|
|
||||||
common.Close(d.Client) // nolint: errcheck
|
|
||||||
d.Client = client
|
|
||||||
}
|
|
|
@ -15,3 +15,16 @@ type Client interface {
|
||||||
func ClientType() interface{} {
|
func ClientType() interface{} {
|
||||||
return (*Client)(nil)
|
return (*Client)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LocalClient struct{}
|
||||||
|
|
||||||
|
func (LocalClient) Type() interface{} {
|
||||||
|
return ClientType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (LocalClient) Start() error { return nil }
|
||||||
|
func (LocalClient) Close() error { return nil }
|
||||||
|
|
||||||
|
func (LocalClient) LookupIP(host string) ([]net.IP, error) {
|
||||||
|
return net.LookupIP(host)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package policy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DefaultManager struct{}
|
||||||
|
|
||||||
|
func (DefaultManager) Type() interface{} {
|
||||||
|
return ManagerType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultManager) ForLevel(level uint32) Session {
|
||||||
|
p := SessionDefault()
|
||||||
|
if level == 1 {
|
||||||
|
p.Timeouts.ConnectionIdle = time.Second * 600
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultManager) ForSystem() System {
|
||||||
|
return System{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultManager) Start() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultManager) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package routing
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/features"
|
"v2ray.com/core/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,3 +19,21 @@ type Router interface {
|
||||||
func RouterType() interface{} {
|
func RouterType() interface{} {
|
||||||
return (*Router)(nil)
|
return (*Router)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DefaultRouter struct{}
|
||||||
|
|
||||||
|
func (DefaultRouter) Type() interface{} {
|
||||||
|
return RouterType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultRouter) PickRoute(ctx context.Context) (string, error) {
|
||||||
|
return "", common.ErrNoClue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultRouter) Start() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (DefaultRouter) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
|
"v2ray.com/core/features/routing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateObject creates a new object based on the given V2Ray instance and config. The V2Ray instance may be nil.
|
// CreateObject creates a new object based on the given V2Ray instance and config. The V2Ray instance may be nil.
|
||||||
|
@ -41,7 +42,11 @@ func StartInstance(configFormat string, configBytes []byte) (*Instance, error) {
|
||||||
// Since it is under a proxy context, the LocalAddr() and RemoteAddr() in returned net.Conn
|
// Since it is under a proxy context, the LocalAddr() and RemoteAddr() in returned net.Conn
|
||||||
// will not show real addresses being used for communication.
|
// will not show real addresses being used for communication.
|
||||||
func Dial(ctx context.Context, v *Instance, dest net.Destination) (net.Conn, error) {
|
func Dial(ctx context.Context, v *Instance, dest net.Destination) (net.Conn, error) {
|
||||||
r, err := v.Dispatcher().Dispatch(ctx, dest)
|
dispatcher := v.GetFeature(routing.DispatcherType())
|
||||||
|
if dispatcher == nil {
|
||||||
|
return nil, newError("routing.Dispatcher is not registered in V2Ray core")
|
||||||
|
}
|
||||||
|
r, err := dispatcher.(routing.Dispatcher).Dispatch(ctx, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
143
network.go
143
network.go
|
@ -1,143 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/features/inbound"
|
|
||||||
"v2ray.com/core/features/outbound"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncInboundHandlerManager struct {
|
|
||||||
sync.RWMutex
|
|
||||||
inbound.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncInboundHandlerManager) Type() interface{} {
|
|
||||||
return inbound.ManagerType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) GetHandler(ctx context.Context, tag string) (inbound.Handler, error) {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return nil, newError("inbound.Manager not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.GetHandler(ctx, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) AddHandler(ctx context.Context, handler inbound.Handler) error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return newError("inbound.Manager not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.AddHandler(ctx, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) Start() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return newError("inbound.Manager not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) Close() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(m.Manager)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncInboundHandlerManager) Set(manager inbound.Manager) {
|
|
||||||
if manager == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Lock()
|
|
||||||
defer m.Unlock()
|
|
||||||
|
|
||||||
common.Close(m.Manager) // nolint: errcheck
|
|
||||||
m.Manager = manager
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncOutboundHandlerManager struct {
|
|
||||||
sync.RWMutex
|
|
||||||
outbound.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncOutboundHandlerManager) Type() interface{} {
|
|
||||||
return outbound.ManagerType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) GetHandler(tag string) outbound.Handler {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.GetHandler(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) GetDefaultHandler() outbound.Handler {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.GetDefaultHandler()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) AddHandler(ctx context.Context, handler outbound.Handler) error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return newError("OutboundHandlerManager not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.AddHandler(ctx, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) Start() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return newError("OutboundHandlerManager not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) Close() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(m.Manager)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncOutboundHandlerManager) Set(manager outbound.Manager) {
|
|
||||||
if manager == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Lock()
|
|
||||||
defer m.Unlock()
|
|
||||||
|
|
||||||
common.Close(m.Manager) // nolint: errcheck
|
|
||||||
m.Manager = manager
|
|
||||||
}
|
|
74
policy.go
74
policy.go
|
@ -1,74 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/features/policy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncPolicyManager struct {
|
|
||||||
sync.RWMutex
|
|
||||||
policy.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncPolicyManager) Type() interface{} {
|
|
||||||
return policy.ManagerType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncPolicyManager) ForLevel(level uint32) policy.Session {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
p := policy.SessionDefault()
|
|
||||||
if level == 1 {
|
|
||||||
p.Timeouts.ConnectionIdle = time.Second * 600
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.ForLevel(level)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncPolicyManager) ForSystem() policy.System {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return policy.System{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.ForSystem()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncPolicyManager) Start() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
if m.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Manager.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncPolicyManager) Close() error {
|
|
||||||
m.RLock()
|
|
||||||
defer m.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(m.Manager)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *syncPolicyManager) Set(manager policy.Manager) {
|
|
||||||
if manager == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Lock()
|
|
||||||
defer m.Unlock()
|
|
||||||
|
|
||||||
common.Close(m.Manager) // nolint: errcheck
|
|
||||||
m.Manager = manager
|
|
||||||
}
|
|
|
@ -35,7 +35,7 @@ func New(ctx context.Context, config *Config) (*DokodemoDoor, error) {
|
||||||
config: config,
|
config: config,
|
||||||
address: config.GetPredefinedAddress(),
|
address: config.GetPredefinedAddress(),
|
||||||
port: net.Port(config.Port),
|
port: net.Port(config.Port),
|
||||||
policyManager: v.PolicyManager(),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
return d, nil
|
return d, nil
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"v2ray.com/core/features"
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
@ -31,13 +33,16 @@ type Handler struct {
|
||||||
|
|
||||||
// New creates a new Freedom handler.
|
// New creates a new Freedom handler.
|
||||||
func New(ctx context.Context, config *Config) (*Handler, error) {
|
func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
f := &Handler{
|
f := &Handler{
|
||||||
config: *config,
|
config: *config,
|
||||||
policyManager: v.PolicyManager(),
|
|
||||||
dns: v.DNSClient(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
|
v.RequireFeatures([]interface{}{policy.ManagerType(), dns.ClientType()}, func(fs []features.Feature) {
|
||||||
|
f.policyManager = fs[0].(policy.Manager)
|
||||||
|
f.dns = fs[1].(dns.Client)
|
||||||
|
})
|
||||||
|
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,15 +28,16 @@ import (
|
||||||
|
|
||||||
// Server is an HTTP proxy server.
|
// Server is an HTTP proxy server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
v *core.Instance
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new HTTP inbound handler.
|
// NewServer creates a new HTTP inbound handler.
|
||||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
s := &Server{
|
s := &Server{
|
||||||
config: config,
|
config: config,
|
||||||
v: core.MustFromContext(ctx),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
@ -44,7 +45,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
|
|
||||||
func (s *Server) policy() policy.Session {
|
func (s *Server) policy() policy.Session {
|
||||||
config := s.config
|
config := s.config
|
||||||
p := s.v.PolicyManager().ForLevel(config.UserLevel)
|
p := s.policyManager.ForLevel(config.UserLevel)
|
||||||
if config.Timeout > 0 && config.UserLevel == 0 {
|
if config.Timeout > 0 && config.UserLevel == 0 {
|
||||||
p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second
|
p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
return &Server{
|
return &Server{
|
||||||
user: user,
|
user: user,
|
||||||
account: account,
|
account: account,
|
||||||
policy: v.PolicyManager(),
|
policy: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,25 @@ package shadowsocks
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"v2ray.com/core/common/session"
|
|
||||||
"v2ray.com/core/common/task"
|
|
||||||
"v2ray.com/core/common/vio"
|
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
"v2ray.com/core/common/retry"
|
"v2ray.com/core/common/retry"
|
||||||
|
"v2ray.com/core/common/session"
|
||||||
"v2ray.com/core/common/signal"
|
"v2ray.com/core/common/signal"
|
||||||
|
"v2ray.com/core/common/task"
|
||||||
|
"v2ray.com/core/common/vio"
|
||||||
|
"v2ray.com/core/features/policy"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is a inbound handler for Shadowsocks protocol
|
// Client is a inbound handler for Shadowsocks protocol
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
v *core.Instance
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient create a new Shadowsocks client.
|
// NewClient create a new Shadowsocks client.
|
||||||
|
@ -37,9 +37,11 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
if serverList.Size() == 0 {
|
if serverList.Size() == 0 {
|
||||||
return nil, newError("0 server")
|
return nil, newError("0 server")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
client := &Client{
|
client := &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||||
v: core.MustFromContext(ctx),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
@ -97,7 +99,7 @@ func (c *Client) Process(ctx context.Context, link *vio.Link, dialer proxy.Diale
|
||||||
request.Option |= RequestOptionOneTimeAuth
|
request.Option |= RequestOptionOneTimeAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionPolicy := c.v.PolicyManager().ForLevel(user.Level)
|
sessionPolicy := c.policyManager.ForLevel(user.Level)
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config ServerConfig
|
config ServerConfig
|
||||||
user *protocol.MemoryUser
|
user *protocol.MemoryUser
|
||||||
v *core.Instance
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer create a new Shadowsocks server.
|
// NewServer create a new Shadowsocks server.
|
||||||
|
@ -37,10 +37,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
return nil, newError("failed to parse user account").Base(err)
|
return nil, newError("failed to parse user account").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
s := &Server{
|
s := &Server{
|
||||||
config: *config,
|
config: *config,
|
||||||
user: mUser,
|
user: mUser,
|
||||||
v: core.MustFromContext(ctx),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
@ -150,7 +151,7 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||||
sessionPolicy := s.v.PolicyManager().ForLevel(s.user.Level)
|
sessionPolicy := s.policyManager.ForLevel(s.user.Level)
|
||||||
conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake))
|
conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake))
|
||||||
|
|
||||||
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
|
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
return &Client{
|
return &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||||
policyManager: v.PolicyManager(),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
s := &Server{
|
s := &Server{
|
||||||
config: config,
|
config: config,
|
||||||
policyManager: v.PolicyManager(),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,8 +114,8 @@ type Handler struct {
|
||||||
func New(ctx context.Context, config *Config) (*Handler, error) {
|
func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
handler := &Handler{
|
handler := &Handler{
|
||||||
policyManager: v.PolicyManager(),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
inboundHandlerManager: v.InboundHandlerManager(),
|
inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
|
||||||
clients: vmess.NewTimedUserValidator(protocol.DefaultIDHash),
|
clients: vmess.NewTimedUserValidator(protocol.DefaultIDHash),
|
||||||
detours: config.Detour,
|
detours: config.Detour,
|
||||||
usersByEmail: newUserByEmail(config.GetDefaultValue()),
|
usersByEmail: newUserByEmail(config.GetDefaultValue()),
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"v2ray.com/core/common/signal"
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/common/task"
|
"v2ray.com/core/common/task"
|
||||||
"v2ray.com/core/common/vio"
|
"v2ray.com/core/common/vio"
|
||||||
|
"v2ray.com/core/features/policy"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/proxy/vmess"
|
"v2ray.com/core/proxy/vmess"
|
||||||
"v2ray.com/core/proxy/vmess/encoding"
|
"v2ray.com/core/proxy/vmess/encoding"
|
||||||
|
@ -25,9 +26,9 @@ import (
|
||||||
|
|
||||||
// Handler is an outbound connection handler for VMess protocol.
|
// Handler is an outbound connection handler for VMess protocol.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
serverList *protocol.ServerList
|
serverList *protocol.ServerList
|
||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
v *core.Instance
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new VMess outbound handler.
|
// New creates a new VMess outbound handler.
|
||||||
|
@ -40,10 +41,12 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
}
|
}
|
||||||
serverList.AddServer(s)
|
serverList.AddServer(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
handler := &Handler{
|
handler := &Handler{
|
||||||
serverList: serverList,
|
serverList: serverList,
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||||
v: core.MustFromContext(ctx),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
|
@ -109,7 +112,7 @@ func (v *Handler) Process(ctx context.Context, link *vio.Link, dialer proxy.Dial
|
||||||
output := link.Writer
|
output := link.Writer
|
||||||
|
|
||||||
session := encoding.NewClientSession(protocol.DefaultIDHash)
|
session := encoding.NewClientSession(protocol.DefaultIDHash)
|
||||||
sessionPolicy := v.v.PolicyManager().ForLevel(request.User.Level)
|
sessionPolicy := v.policyManager.ForLevel(request.User.Level)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
|
111
router.go
111
router.go
|
@ -1,111 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/net"
|
|
||||||
"v2ray.com/core/common/vio"
|
|
||||||
"v2ray.com/core/features/routing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncDispatcher struct {
|
|
||||||
sync.RWMutex
|
|
||||||
routing.Dispatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncDispatcher) Type() interface{} {
|
|
||||||
return routing.DispatcherType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDispatcher) Dispatch(ctx context.Context, dest net.Destination) (*vio.Link, error) {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
if d.Dispatcher == nil {
|
|
||||||
return nil, newError("Dispatcher not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.Dispatcher.Dispatch(ctx, dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDispatcher) Start() error {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
if d.Dispatcher == nil {
|
|
||||||
return newError("Dispatcher not set.").AtError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return d.Dispatcher.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDispatcher) Close() error {
|
|
||||||
d.RLock()
|
|
||||||
defer d.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(d.Dispatcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *syncDispatcher) Set(disp routing.Dispatcher) {
|
|
||||||
if disp == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d.Lock()
|
|
||||||
defer d.Unlock()
|
|
||||||
|
|
||||||
common.Close(d.Dispatcher) // nolint: errcheck
|
|
||||||
d.Dispatcher = disp
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncRouter struct {
|
|
||||||
sync.RWMutex
|
|
||||||
routing.Router
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncRouter) Type() interface{} {
|
|
||||||
return routing.RouterType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *syncRouter) PickRoute(ctx context.Context) (string, error) {
|
|
||||||
r.RLock()
|
|
||||||
defer r.RUnlock()
|
|
||||||
|
|
||||||
if r.Router == nil {
|
|
||||||
return "", common.ErrNoClue
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.Router.PickRoute(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *syncRouter) Start() error {
|
|
||||||
r.RLock()
|
|
||||||
defer r.RUnlock()
|
|
||||||
|
|
||||||
if r.Router == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.Router.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *syncRouter) Close() error {
|
|
||||||
r.RLock()
|
|
||||||
defer r.RUnlock()
|
|
||||||
|
|
||||||
return common.Close(r.Router)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *syncRouter) Set(router routing.Router) {
|
|
||||||
if router == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Lock()
|
|
||||||
defer r.Unlock()
|
|
||||||
|
|
||||||
common.Close(r.Router) // nolint: errcheck
|
|
||||||
r.Router = router
|
|
||||||
}
|
|
70
stats.go
70
stats.go
|
@ -1,70 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/features/stats"
|
|
||||||
)
|
|
||||||
|
|
||||||
type syncStatManager struct {
|
|
||||||
sync.RWMutex
|
|
||||||
stats.Manager
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*syncStatManager) Type() interface{} {
|
|
||||||
return stats.ManagerType()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncStatManager) Start() error {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if s.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Manager.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncStatManager) Close() error {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if s.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s.Manager.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncStatManager) RegisterCounter(name string) (stats.Counter, error) {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if s.Manager == nil {
|
|
||||||
return nil, newError("StatManager not set.")
|
|
||||||
}
|
|
||||||
return s.Manager.RegisterCounter(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncStatManager) GetCounter(name string) stats.Counter {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
if s.Manager == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s.Manager.GetCounter(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncStatManager) Set(m stats.Manager) {
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
if s.Manager != nil {
|
|
||||||
s.Manager.Close() // nolint: errcheck
|
|
||||||
}
|
|
||||||
s.Manager = m
|
|
||||||
}
|
|
296
v2ray.go
296
v2ray.go
|
@ -2,49 +2,71 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
fmt "fmt"
|
||||||
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
"v2ray.com/core/common/uuid"
|
|
||||||
"v2ray.com/core/features"
|
"v2ray.com/core/features"
|
||||||
"v2ray.com/core/features/dns"
|
"v2ray.com/core/features/dns"
|
||||||
"v2ray.com/core/features/inbound"
|
"v2ray.com/core/features/inbound"
|
||||||
"v2ray.com/core/features/outbound"
|
"v2ray.com/core/features/outbound"
|
||||||
"v2ray.com/core/features/policy"
|
"v2ray.com/core/features/policy"
|
||||||
"v2ray.com/core/features/routing"
|
"v2ray.com/core/features/routing"
|
||||||
"v2ray.com/core/features/stats"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
|
// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
|
||||||
// Deprecated. Use Instance directly.
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
common.Runnable
|
common.Runnable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerType returns the type of the server.
|
||||||
|
func ServerType() interface{} {
|
||||||
|
return (*Instance)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type resolution struct {
|
||||||
|
deps []interface{}
|
||||||
|
callback func([]features.Feature)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFeature(allFeatures []features.Feature, t interface{}) features.Feature {
|
||||||
|
for _, f := range allFeatures {
|
||||||
|
if f.Type() == t {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolution) resolve(allFeatures []features.Feature) bool {
|
||||||
|
var fs []features.Feature
|
||||||
|
for _, d := range r.deps {
|
||||||
|
f := getFeature(allFeatures, d)
|
||||||
|
if f == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fs = append(fs, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.callback(fs)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Instance combines all functionalities in V2Ray.
|
// Instance combines all functionalities in V2Ray.
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
dnsClient syncDNSClient
|
access sync.Mutex
|
||||||
policyManager syncPolicyManager
|
features []features.Feature
|
||||||
dispatcher syncDispatcher
|
featureResolutions []resolution
|
||||||
router syncRouter
|
running bool
|
||||||
ihm syncInboundHandlerManager
|
|
||||||
ohm syncOutboundHandlerManager
|
|
||||||
stats syncStatManager
|
|
||||||
|
|
||||||
access sync.Mutex
|
|
||||||
features []features.Feature
|
|
||||||
id uuid.UUID
|
|
||||||
running bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new V2Ray instance based on given configuration.
|
// New returns a new V2Ray instance based on given configuration.
|
||||||
// The instance is not started at this point.
|
// The instance is not started at this point.
|
||||||
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
|
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
|
||||||
func New(config *Config) (*Instance, error) {
|
func New(config *Config) (*Instance, error) {
|
||||||
var server = &Instance{
|
var server = &Instance{}
|
||||||
id: uuid.New(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Transport != nil {
|
if config.Transport != nil {
|
||||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||||
|
@ -58,45 +80,83 @@ func New(config *Config) (*Instance, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := CreateObject(server, settings); err != nil {
|
obj, err := CreateObject(server, settings)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, inboundConfig := range config.Inbound {
|
|
||||||
rawHandler, err := CreateObject(server, inboundConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
handler, ok := rawHandler.(inbound.Handler)
|
if feature, ok := obj.(features.Feature); ok {
|
||||||
if !ok {
|
server.AddFeature(feature)
|
||||||
return nil, newError("not an InboundHandler")
|
|
||||||
}
|
|
||||||
if err := server.InboundHandlerManager().AddHandler(context.Background(), handler); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, outboundConfig := range config.Outbound {
|
if server.GetFeature(dns.ClientType()) == nil {
|
||||||
rawHandler, err := CreateObject(server, outboundConfig)
|
server.AddFeature(dns.LocalClient{})
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
|
||||||
|
if server.GetFeature(policy.ManagerType()) == nil {
|
||||||
|
server.AddFeature(policy.DefaultManager{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if server.GetFeature(routing.RouterType()) == nil {
|
||||||
|
server.AddFeature(routing.DefaultRouter{})
|
||||||
|
}
|
||||||
|
|
||||||
|
server.AddFeature(&Instance{})
|
||||||
|
|
||||||
|
if server.featureResolutions != nil {
|
||||||
|
fmt.Println("registered")
|
||||||
|
for _, d := range server.features {
|
||||||
|
fmt.Println(reflect.TypeOf(d.Type()))
|
||||||
}
|
}
|
||||||
handler, ok := rawHandler.(outbound.Handler)
|
for idx, r := range server.featureResolutions {
|
||||||
if !ok {
|
fmt.Println(idx)
|
||||||
return nil, newError("not an OutboundHandler")
|
for _, d := range r.deps {
|
||||||
|
fmt.Println(reflect.TypeOf(d))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := server.OutboundHandlerManager().AddHandler(context.Background(), handler); err != nil {
|
return nil, newError("not all dependency are resolved.")
|
||||||
return nil, err
|
}
|
||||||
|
|
||||||
|
if len(config.Inbound) > 0 {
|
||||||
|
inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
|
||||||
|
for _, inboundConfig := range config.Inbound {
|
||||||
|
rawHandler, err := CreateObject(server, inboundConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
handler, ok := rawHandler.(inbound.Handler)
|
||||||
|
if !ok {
|
||||||
|
return nil, newError("not an InboundHandler")
|
||||||
|
}
|
||||||
|
if err := inboundManager.AddHandler(context.Background(), handler); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Outbound) > 0 {
|
||||||
|
outboundManager := server.GetFeature(outbound.ManagerType()).(outbound.Manager)
|
||||||
|
for _, outboundConfig := range config.Outbound {
|
||||||
|
rawHandler, err := CreateObject(server, outboundConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
handler, ok := rawHandler.(outbound.Handler)
|
||||||
|
if !ok {
|
||||||
|
return nil, newError("not an OutboundHandler")
|
||||||
|
}
|
||||||
|
if err := outboundManager.AddHandler(context.Background(), handler); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns a unique ID for this V2Ray instance.
|
// Type implements common.HasType.
|
||||||
func (s *Instance) ID() uuid.UUID {
|
func (s *Instance) Type() interface{} {
|
||||||
return s.id
|
return ServerType()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close shutdown the V2Ray instance.
|
// Close shutdown the V2Ray instance.
|
||||||
|
@ -107,7 +167,7 @@ func (s *Instance) Close() error {
|
||||||
s.running = false
|
s.running = false
|
||||||
|
|
||||||
var errors []interface{}
|
var errors []interface{}
|
||||||
for _, f := range s.allFeatures() {
|
for _, f := range s.features {
|
||||||
if err := f.Close(); err != nil {
|
if err := f.Close(); err != nil {
|
||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
|
@ -119,6 +179,51 @@ func (s *Instance) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequireFeatures registers a callback, which will be called when all dependent features are registered.
|
||||||
|
func (s *Instance) RequireFeatures(featureTypes []interface{}, callback func([]features.Feature)) {
|
||||||
|
r := resolution{
|
||||||
|
deps: featureTypes,
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
if r.resolve(s.features) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.featureResolutions = append(s.featureResolutions, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFeature registers a feature into current Instance.
|
||||||
|
func (s *Instance) AddFeature(feature features.Feature) {
|
||||||
|
s.features = append(s.features, feature)
|
||||||
|
|
||||||
|
if s.running {
|
||||||
|
if err := feature.Start(); err != nil {
|
||||||
|
newError("failed to start feature").Base(err).WriteToLog()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.featureResolutions == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var pendingResolutions []resolution
|
||||||
|
for _, r := range s.featureResolutions {
|
||||||
|
if !r.resolve(s.features) {
|
||||||
|
pendingResolutions = append(pendingResolutions, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(pendingResolutions) == 0 {
|
||||||
|
s.featureResolutions = nil
|
||||||
|
} else if len(pendingResolutions) < len(s.featureResolutions) {
|
||||||
|
s.featureResolutions = pendingResolutions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFeature returns a feature of the given type, or nil if such feature is not registered.
|
||||||
|
func (s *Instance) GetFeature(featureType interface{}) features.Feature {
|
||||||
|
return getFeature(s.features, featureType)
|
||||||
|
}
|
||||||
|
|
||||||
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
|
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
|
||||||
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
|
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
|
||||||
func (s *Instance) Start() error {
|
func (s *Instance) Start() error {
|
||||||
|
@ -126,7 +231,7 @@ func (s *Instance) Start() error {
|
||||||
defer s.access.Unlock()
|
defer s.access.Unlock()
|
||||||
|
|
||||||
s.running = true
|
s.running = true
|
||||||
for _, f := range s.allFeatures() {
|
for _, f := range s.features {
|
||||||
if err := f.Start(); err != nil {
|
if err := f.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -136,104 +241,3 @@ func (s *Instance) Start() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterFeature registers the given feature into V2Ray.
|
|
||||||
// If feature is one of the following types, the corresponding feature in this Instance
|
|
||||||
// will be replaced: DNSClient, PolicyManager, Router, Dispatcher, InboundHandlerManager, OutboundHandlerManager.
|
|
||||||
func (s *Instance) RegisterFeature(instance features.Feature) error {
|
|
||||||
running := false
|
|
||||||
|
|
||||||
switch instance.Type().(type) {
|
|
||||||
case dns.Client, *dns.Client:
|
|
||||||
s.dnsClient.Set(instance.(dns.Client))
|
|
||||||
case policy.Manager, *policy.Manager:
|
|
||||||
s.policyManager.Set(instance.(policy.Manager))
|
|
||||||
case routing.Router, *routing.Router:
|
|
||||||
s.router.Set(instance.(routing.Router))
|
|
||||||
case routing.Dispatcher, *routing.Dispatcher:
|
|
||||||
s.dispatcher.Set(instance.(routing.Dispatcher))
|
|
||||||
case inbound.Manager, *inbound.Manager:
|
|
||||||
s.ihm.Set(instance.(inbound.Manager))
|
|
||||||
case outbound.Manager, *outbound.Manager:
|
|
||||||
s.ohm.Set(instance.(outbound.Manager))
|
|
||||||
case stats.Manager, *stats.Manager:
|
|
||||||
s.stats.Set(instance.(stats.Manager))
|
|
||||||
default:
|
|
||||||
s.access.Lock()
|
|
||||||
s.features = append(s.features, instance)
|
|
||||||
running = s.running
|
|
||||||
s.access.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
if running {
|
|
||||||
return instance.Start()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Instance) allFeatures() []features.Feature {
|
|
||||||
return append([]features.Feature{s.DNSClient(), s.PolicyManager(), s.Dispatcher(), s.Router(), s.InboundHandlerManager(), s.OutboundHandlerManager(), s.Stats()}, s.features...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFeature returns a feature that was registered in this Instance. Nil if not found.
|
|
||||||
// The returned Feature must implement common.HasType and whose type equals to the given feature type.
|
|
||||||
func (s *Instance) GetFeature(featureType interface{}) features.Feature {
|
|
||||||
switch featureType.(type) {
|
|
||||||
case dns.Client, *dns.Client:
|
|
||||||
return s.DNSClient()
|
|
||||||
case policy.Manager, *policy.Manager:
|
|
||||||
return s.PolicyManager()
|
|
||||||
case routing.Router, *routing.Router:
|
|
||||||
return s.Router()
|
|
||||||
case routing.Dispatcher, *routing.Dispatcher:
|
|
||||||
return s.Dispatcher()
|
|
||||||
case inbound.Manager, *inbound.Manager:
|
|
||||||
return s.InboundHandlerManager()
|
|
||||||
case outbound.Manager, *outbound.Manager:
|
|
||||||
return s.OutboundHandlerManager()
|
|
||||||
case stats.Manager, *stats.Manager:
|
|
||||||
return s.Stats()
|
|
||||||
default:
|
|
||||||
for _, f := range s.features {
|
|
||||||
if f.Type() == featureType {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DNSClient returns the dns.Client used by this Instance. The returned dns.Client is always functional.
|
|
||||||
func (s *Instance) DNSClient() dns.Client {
|
|
||||||
return &(s.dnsClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PolicyManager returns the policy.Manager used by this Instance. The returned policy.Manager is always functional.
|
|
||||||
func (s *Instance) PolicyManager() policy.Manager {
|
|
||||||
return &(s.policyManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Router returns the Router used by this Instance. The returned Router is always functional.
|
|
||||||
func (s *Instance) Router() routing.Router {
|
|
||||||
return &(s.router)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatcher returns the Dispatcher used by this Instance. If Dispatcher was not registered before, the returned value doesn't work, although it is not nil.
|
|
||||||
func (s *Instance) Dispatcher() routing.Dispatcher {
|
|
||||||
return &(s.dispatcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InboundHandlerManager returns the InboundHandlerManager used by this Instance. If InboundHandlerManager was not registered before, the returned value doesn't work.
|
|
||||||
func (s *Instance) InboundHandlerManager() inbound.Manager {
|
|
||||||
return &(s.ihm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OutboundHandlerManager returns the OutboundHandlerManager used by this Instance. If OutboundHandlerManager was not registered before, the returned value doesn't work.
|
|
||||||
func (s *Instance) OutboundHandlerManager() outbound.Manager {
|
|
||||||
return &(s.ohm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stats returns the stats.Manager used by this Instance. If StatManager was not registered before, the returned value doesn't work.
|
|
||||||
func (s *Instance) Stats() stats.Manager {
|
|
||||||
return &(s.stats)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue