浏览代码

move policy and dnsClient

Darien Raymond 7 年之前
父节点
当前提交
b4821c5ed5

+ 2 - 1
app/dispatcher/default.go

@@ -18,6 +18,7 @@ import (
 	"v2ray.com/core/common/stats"
 	"v2ray.com/core/common/vio"
 	"v2ray.com/core/features/outbound"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	feature_stats "v2ray.com/core/features/stats"
 	"v2ray.com/core/transport/pipe"
@@ -85,7 +86,7 @@ func (r *cachedReader) CloseError() {
 type DefaultDispatcher struct {
 	ohm    outbound.HandlerManager
 	router routing.Router
-	policy core.PolicyManager
+	policy policy.Manager
 	stats  feature_stats.Manager
 }
 

+ 2 - 1
app/dns/server.go

@@ -7,6 +7,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/miekg/dns"
 	"v2ray.com/core"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
@@ -40,7 +41,7 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 	server.hosts = hosts
 
 	v := core.MustFromContext(ctx)
-	if err := v.RegisterFeature((*core.DNSClient)(nil), server); err != nil {
+	if err := v.RegisterFeature((*dns.Client)(nil), server); err != nil {
 		return nil, newError("unable to register DNSClient.").Base(err)
 	}
 

+ 9 - 9
app/policy/config.go

@@ -3,7 +3,7 @@ package policy
 import (
 	"time"
 
-	"v2ray.com/core"
+	"v2ray.com/core/features/policy"
 )
 
 // Duration converts Second to time.Duration.
@@ -15,7 +15,7 @@ func (s *Second) Duration() time.Duration {
 }
 
 func defaultPolicy() *Policy {
-	p := core.DefaultPolicy()
+	p := policy.SessionDefault()
 
 	return &Policy{
 		Timeout: &Policy_Timeout{
@@ -60,9 +60,9 @@ func (p *Policy) overrideWith(another *Policy) {
 	}
 }
 
-// ToCorePolicy converts this Policy to core.Policy.
-func (p *Policy) ToCorePolicy() core.Policy {
-	cp := core.DefaultPolicy()
+// ToCorePolicy converts this Policy to policy.Session.
+func (p *Policy) ToCorePolicy() policy.Session {
+	cp := policy.SessionDefault()
 
 	if p.Timeout != nil {
 		cp.Timeouts.ConnectionIdle = p.Timeout.ConnectionIdle.Duration()
@@ -80,10 +80,10 @@ func (p *Policy) ToCorePolicy() core.Policy {
 	return cp
 }
 
-// ToCorePolicy converts this SystemPolicy to core.SystemPolicy.
-func (p *SystemPolicy) ToCorePolicy() core.SystemPolicy {
-	return core.SystemPolicy{
-		Stats: core.SystemStatsPolicy{
+// ToCorePolicy converts this SystemPolicy to policy.System.
+func (p *SystemPolicy) ToCorePolicy() policy.System {
+	return policy.System{
+		Stats: policy.SystemStats{
 			InboundUplink:   p.Stats.InboundUplink,
 			InboundDownlink: p.Stats.InboundDownlink,
 		},

+ 8 - 7
app/policy/manager.go

@@ -5,6 +5,7 @@ import (
 
 	"v2ray.com/core"
 	"v2ray.com/core/common"
+	"v2ray.com/core/features/policy"
 )
 
 // Instance is an instance of Policy manager.
@@ -29,7 +30,7 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
 
 	v := core.FromContext(ctx)
 	if v != nil {
-		if err := v.RegisterFeature((*core.PolicyManager)(nil), m); err != nil {
+		if err := v.RegisterFeature((*policy.Manager)(nil), m); err != nil {
 			return nil, newError("unable to register PolicyManager in core").Base(err).AtError()
 		}
 	}
@@ -37,18 +38,18 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
 	return m, nil
 }
 
-// ForLevel implements core.PolicyManager.
-func (m *Instance) ForLevel(level uint32) core.Policy {
+// ForLevel implements policy.Manager.
+func (m *Instance) ForLevel(level uint32) policy.Session {
 	if p, ok := m.levels[level]; ok {
 		return p.ToCorePolicy()
 	}
-	return core.DefaultPolicy()
+	return policy.SessionDefault()
 }
 
-// ForSystem implements core.PolicyManager.
-func (m *Instance) ForSystem() core.SystemPolicy {
+// ForSystem implements policy.Manager.
+func (m *Instance) ForSystem() policy.System {
 	if m.system == nil {
-		return core.SystemPolicy{}
+		return policy.System{}
 	}
 	return m.system.ToCorePolicy()
 }

+ 2 - 2
app/policy/manager_test.go

@@ -5,8 +5,8 @@ import (
 	"testing"
 	"time"
 
-	"v2ray.com/core"
 	. "v2ray.com/core/app/policy"
+	"v2ray.com/core/features/policy"
 	. "v2ray.com/ext/assert"
 )
 
@@ -26,7 +26,7 @@ func TestPolicy(t *testing.T) {
 	})
 	assert(err, IsNil)
 
-	pDefault := core.DefaultPolicy()
+	pDefault := policy.SessionDefault()
 
 	p0 := manager.ForLevel(0)
 	assert(p0.Timeouts.Handshake, Equals, 2*time.Second)

+ 1 - 1
app/policy/policy.go

@@ -1,4 +1,4 @@
-// Package policy is an implementation of core.PolicyManager feature.
+// Package policy is an implementation of policy.Manager feature.
 package policy
 
 //go:generate errorgen

+ 5 - 5
app/router/router.go

@@ -5,12 +5,12 @@ package router
 import (
 	"context"
 
-	"v2ray.com/core/common/session"
-	"v2ray.com/core/features/routing"
-
 	"v2ray.com/core"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
+	"v2ray.com/core/common/session"
+	"v2ray.com/core/features/dns"
+	"v2ray.com/core/features/routing"
 	"v2ray.com/core/proxy"
 )
 
@@ -18,7 +18,7 @@ import (
 type Router struct {
 	domainStrategy Config_DomainStrategy
 	rules          []Rule
-	dns            core.DNSClient
+	dns            dns.Client
 }
 
 // NewRouter creates a new Router based on the given config.
@@ -46,7 +46,7 @@ func NewRouter(ctx context.Context, config *Config) (*Router, error) {
 }
 
 type ipResolver struct {
-	dns      core.DNSClient
+	dns      dns.Client
 	ip       []net.Address
 	domain   string
 	resolved bool

+ 10 - 15
dns.go

@@ -5,49 +5,44 @@ import (
 	"sync"
 
 	"v2ray.com/core/common"
+	"v2ray.com/core/features/dns"
 )
 
-// DNSClient is a V2Ray feature for querying DNS information.
-type DNSClient interface {
-	Feature
-	LookupIP(host string) ([]net.IP, error)
-}
-
 type syncDNSClient struct {
 	sync.RWMutex
-	DNSClient
+	dns.Client
 }
 
 func (d *syncDNSClient) LookupIP(host string) ([]net.IP, error) {
 	d.RLock()
 	defer d.RUnlock()
 
-	if d.DNSClient == nil {
+	if d.Client == nil {
 		return net.LookupIP(host)
 	}
 
-	return d.DNSClient.LookupIP(host)
+	return d.Client.LookupIP(host)
 }
 
 func (d *syncDNSClient) Start() error {
 	d.RLock()
 	defer d.RUnlock()
 
-	if d.DNSClient == nil {
+	if d.Client == nil {
 		return nil
 	}
 
-	return d.DNSClient.Start()
+	return d.Client.Start()
 }
 
 func (d *syncDNSClient) Close() error {
 	d.RLock()
 	defer d.RUnlock()
 
-	return common.Close(d.DNSClient)
+	return common.Close(d.Client)
 }
 
-func (d *syncDNSClient) Set(client DNSClient) {
+func (d *syncDNSClient) Set(client dns.Client) {
 	if client == nil {
 		return
 	}
@@ -55,6 +50,6 @@ func (d *syncDNSClient) Set(client DNSClient) {
 	d.Lock()
 	defer d.Unlock()
 
-	common.Close(d.DNSClient) // nolint: errcheck
-	d.DNSClient = client
+	common.Close(d.Client) // nolint: errcheck
+	d.Client = client
 }

+ 13 - 0
features/dns/client.go

@@ -0,0 +1,13 @@
+package dns
+
+import (
+	"net"
+
+	"v2ray.com/core/features"
+)
+
+// Client is a V2Ray feature for querying DNS information.
+type Client interface {
+	features.Feature
+	LookupIP(host string) ([]net.IP, error)
+}

+ 134 - 0
features/policy/policy.go

@@ -0,0 +1,134 @@
+package policy
+
+import (
+	"context"
+	"runtime"
+	"time"
+
+	"v2ray.com/core/common/platform"
+	"v2ray.com/core/features"
+)
+
+// Timeout contains limits for connection timeout.
+type Timeout struct {
+	// Timeout for handshake phase in a connection.
+	Handshake time.Duration
+	// Timeout for connection being idle, i.e., there is no egress or ingress traffic in this connection.
+	ConnectionIdle time.Duration
+	// Timeout for an uplink only connection, i.e., the downlink of the connection has been closed.
+	UplinkOnly time.Duration
+	// Timeout for an downlink only connection, i.e., the uplink of the connection has been closed.
+	DownlinkOnly time.Duration
+}
+
+// Stats contains settings for stats counters.
+type Stats struct {
+	// Whether or not to enable stat counter for user uplink traffic.
+	UserUplink bool
+	// Whether or not to enable stat counter for user downlink traffic.
+	UserDownlink bool
+}
+
+// Buffer contains settings for internal buffer.
+type Buffer struct {
+	// Size of buffer per connection, in bytes. -1 for unlimited buffer.
+	PerConnection int32
+}
+
+// SystemStats contains stat policy settings on system level.
+type SystemStats struct {
+	// Whether or not to enable stat counter for uplink traffic in inbound handlers.
+	InboundUplink bool
+	// Whether or not to enable stat counter for downlink traffic in inbound handlers.
+	InboundDownlink bool
+}
+
+// System contains policy settings at system level.
+type System struct {
+	Stats  SystemStats
+	Buffer Buffer
+}
+
+// Session is session based settings for controlling V2Ray requests. It contains various settings (or limits) that may differ for different users in the context.
+type Session struct {
+	Timeouts Timeout // Timeout settings
+	Stats    Stats
+	Buffer   Buffer
+}
+
+// Manager is a feature that provides Policy for the given user by its id or level.
+type Manager interface {
+	features.Feature
+
+	// ForLevel returns the Session policy for the given user level.
+	ForLevel(level uint32) Session
+
+	// ForSystem returns the System policy for V2Ray system.
+	ForSystem() System
+}
+
+var defaultBufferSize int32
+
+func init() {
+	const key = "v2ray.ray.buffer.size"
+	const defaultValue = -17
+	size := platform.EnvFlag{
+		Name:    key,
+		AltName: platform.NormalizeEnvName(key),
+	}.GetValueAsInt(defaultValue)
+
+	switch size {
+	case 0:
+		defaultBufferSize = -1 // For pipe to use unlimited size
+	case defaultValue: // Env flag not defined. Use default values per CPU-arch.
+		switch runtime.GOARCH {
+		case "arm", "arm64", "mips", "mipsle", "mips64", "mips64le":
+			defaultBufferSize = 16 * 1024 // 16k cache for low-end devices
+		default:
+			defaultBufferSize = 2 * 1024 * 1024
+		}
+	default:
+		defaultBufferSize = int32(size) * 1024 * 1024
+	}
+}
+
+func defaultBufferPolicy() Buffer {
+	return Buffer{
+		PerConnection: defaultBufferSize,
+	}
+}
+
+// SessionDefault returns the Policy when user is not specified.
+func SessionDefault() Session {
+	return Session{
+		Timeouts: Timeout{
+			Handshake:      time.Second * 4,
+			ConnectionIdle: time.Second * 300,
+			UplinkOnly:     time.Second * 2,
+			DownlinkOnly:   time.Second * 5,
+		},
+		Stats: Stats{
+			UserUplink:   false,
+			UserDownlink: false,
+		},
+		Buffer: defaultBufferPolicy(),
+	}
+}
+
+type policyKey int32
+
+const (
+	bufferPolicyKey policyKey = 0
+)
+
+func ContextWithBufferPolicy(ctx context.Context, p Buffer) context.Context {
+	return context.WithValue(ctx, bufferPolicyKey, p)
+}
+
+func BufferPolicyFromContext(ctx context.Context) Buffer {
+	pPolicy := ctx.Value(bufferPolicyKey)
+	if pPolicy == nil {
+		return defaultBufferPolicy()
+	}
+	return pPolicy.(Buffer)
+}

+ 16 - 142
policy.go

@@ -1,189 +1,63 @@
 package core
 
 import (
-	"context"
-	"runtime"
 	"sync"
 	"time"
 
 	"v2ray.com/core/common"
-	"v2ray.com/core/common/platform"
+	"v2ray.com/core/features/policy"
 )
 
-// TimeoutPolicy contains limits for connection timeout.
-type TimeoutPolicy struct {
-	// Timeout for handshake phase in a connection.
-	Handshake time.Duration
-	// Timeout for connection being idle, i.e., there is no egress or ingress traffic in this connection.
-	ConnectionIdle time.Duration
-	// Timeout for an uplink only connection, i.e., the downlink of the connection has been closed.
-	UplinkOnly time.Duration
-	// Timeout for an downlink only connection, i.e., the uplink of the connection has been closed.
-	DownlinkOnly time.Duration
-}
-
-// StatsPolicy contains settings for stats counters.
-type StatsPolicy struct {
-	// Whether or not to enable stat counter for user uplink traffic.
-	UserUplink bool
-	// Whether or not to enable stat counter for user downlink traffic.
-	UserDownlink bool
-}
-
-// BufferPolicy contains settings for internal buffer.
-type BufferPolicy struct {
-	// Size of buffer per connection, in bytes. -1 for unlimited buffer.
-	PerConnection int32
-}
-
-// SystemStatsPolicy contains stat policy settings on system level.
-type SystemStatsPolicy struct {
-	// Whether or not to enable stat counter for uplink traffic in inbound handlers.
-	InboundUplink bool
-	// Whether or not to enable stat counter for downlink traffic in inbound handlers.
-	InboundDownlink bool
-}
-
-// SystemPolicy contains policy settings at system level.
-type SystemPolicy struct {
-	Stats  SystemStatsPolicy
-	Buffer BufferPolicy
-}
-
-// Policy is session based settings for controlling V2Ray requests. It contains various settings (or limits) that may differ for different users in the context.
-type Policy struct {
-	Timeouts TimeoutPolicy // Timeout settings
-	Stats    StatsPolicy
-	Buffer   BufferPolicy
-}
-
-// PolicyManager is a feature that provides Policy for the given user by its id or level.
-type PolicyManager interface {
-	Feature
-
-	// ForLevel returns the Policy for the given user level.
-	ForLevel(level uint32) Policy
-
-	// ForSystem returns the Policy for V2Ray system.
-	ForSystem() SystemPolicy
-}
-
-var defaultBufferSize int32
-
-func init() {
-	const key = "v2ray.ray.buffer.size"
-	const defaultValue = -17
-	size := platform.EnvFlag{
-		Name:    key,
-		AltName: platform.NormalizeEnvName(key),
-	}.GetValueAsInt(defaultValue)
-
-	switch size {
-	case 0:
-		defaultBufferSize = -1 // For pipe to use unlimited size
-	case defaultValue: // Env flag not defined. Use default values per CPU-arch.
-		switch runtime.GOARCH {
-		case "arm", "arm64", "mips", "mipsle", "mips64", "mips64le":
-			defaultBufferSize = 16 * 1024 // 16k cache for low-end devices
-		default:
-			defaultBufferSize = 2 * 1024 * 1024
-		}
-	default:
-		defaultBufferSize = int32(size) * 1024 * 1024
-	}
-}
-
-func defaultBufferPolicy() BufferPolicy {
-	return BufferPolicy{
-		PerConnection: defaultBufferSize,
-	}
-}
-
-// DefaultPolicy returns the Policy when user is not specified.
-func DefaultPolicy() Policy {
-	return Policy{
-		Timeouts: TimeoutPolicy{
-			Handshake:      time.Second * 4,
-			ConnectionIdle: time.Second * 300,
-			UplinkOnly:     time.Second * 2,
-			DownlinkOnly:   time.Second * 5,
-		},
-		Stats: StatsPolicy{
-			UserUplink:   false,
-			UserDownlink: false,
-		},
-		Buffer: defaultBufferPolicy(),
-	}
-}
-
-type policyKey int
-
-const (
-	bufferPolicyKey policyKey = 0
-)
-
-func ContextWithBufferPolicy(ctx context.Context, p BufferPolicy) context.Context {
-	return context.WithValue(ctx, bufferPolicyKey, p)
-}
-
-func BufferPolicyFromContext(ctx context.Context) BufferPolicy {
-	pPolicy := ctx.Value(bufferPolicyKey)
-	if pPolicy == nil {
-		return defaultBufferPolicy()
-	}
-	return pPolicy.(BufferPolicy)
-}
-
 type syncPolicyManager struct {
 	sync.RWMutex
-	PolicyManager
+	policy.Manager
 }
 
-func (m *syncPolicyManager) ForLevel(level uint32) Policy {
+func (m *syncPolicyManager) ForLevel(level uint32) policy.Session {
 	m.RLock()
 	defer m.RUnlock()
 
-	if m.PolicyManager == nil {
-		p := DefaultPolicy()
+	if m.Manager == nil {
+		p := policy.SessionDefault()
 		if level == 1 {
 			p.Timeouts.ConnectionIdle = time.Second * 600
 		}
 		return p
 	}
 
-	return m.PolicyManager.ForLevel(level)
+	return m.Manager.ForLevel(level)
 }
 
-func (m *syncPolicyManager) ForSystem() SystemPolicy {
+func (m *syncPolicyManager) ForSystem() policy.System {
 	m.RLock()
 	defer m.RUnlock()
 
-	if m.PolicyManager == nil {
-		return SystemPolicy{}
+	if m.Manager == nil {
+		return policy.System{}
 	}
 
-	return m.PolicyManager.ForSystem()
+	return m.Manager.ForSystem()
 }
 
 func (m *syncPolicyManager) Start() error {
 	m.RLock()
 	defer m.RUnlock()
 
-	if m.PolicyManager == nil {
+	if m.Manager == nil {
 		return nil
 	}
 
-	return m.PolicyManager.Start()
+	return m.Manager.Start()
 }
 
 func (m *syncPolicyManager) Close() error {
 	m.RLock()
 	defer m.RUnlock()
 
-	return common.Close(m.PolicyManager)
+	return common.Close(m.Manager)
 }
 
-func (m *syncPolicyManager) Set(manager PolicyManager) {
+func (m *syncPolicyManager) Set(manager policy.Manager) {
 	if manager == nil {
 		return
 	}
@@ -191,6 +65,6 @@ func (m *syncPolicyManager) Set(manager PolicyManager) {
 	m.Lock()
 	defer m.Unlock()
 
-	common.Close(m.PolicyManager) // nolint: errcheck
-	m.PolicyManager = manager
+	common.Close(m.Manager) // nolint: errcheck
+	m.Manager = manager
 }

+ 4 - 3
proxy/dokodemo/dokodemo.go

@@ -13,13 +13,14 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/pipe"
 )
 
 type DokodemoDoor struct {
-	policyManager core.PolicyManager
+	policyManager policy.Manager
 	config        *Config
 	address       net.Address
 	port          net.Port
@@ -44,7 +45,7 @@ func (d *DokodemoDoor) Network() net.NetworkList {
 	return *(d.config.NetworkList)
 }
 
-func (d *DokodemoDoor) policy() core.Policy {
+func (d *DokodemoDoor) policy() policy.Session {
 	config := d.config
 	p := d.policyManager.ForLevel(config.UserLevel)
 	if config.Timeout > 0 && config.UserLevel == 0 {
@@ -82,7 +83,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
 	ctx, cancel := context.WithCancel(ctx)
 	timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)
 
-	ctx = core.ContextWithBufferPolicy(ctx, plcy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, plcy.Buffer)
 	link, err := dispatcher.Dispatch(ctx, dest)
 	if err != nil {
 		return newError("failed to dispatch request").Base(err)

+ 5 - 3
proxy/freedom/freedom.go

@@ -6,6 +6,7 @@ import (
 	"context"
 	"time"
 
+	"github.com/miekg/dns"
 	"v2ray.com/core"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
@@ -16,14 +17,15 @@ import (
 	"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/transport/internet"
 )
 
 // Handler handles Freedom connections.
 type Handler struct {
-	policyManager core.PolicyManager
-	dns           core.DNSClient
+	policyManager policy.Manager
+	dns           dns.Client
 	config        Config
 }
 
@@ -39,7 +41,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
 	return f, nil
 }
 
-func (h *Handler) policy() core.Policy {
+func (h *Handler) policy() policy.Session {
 	p := h.policyManager.ForLevel(h.config.UserLevel)
 	if h.config.Timeout > 0 && h.config.UserLevel == 0 {
 		p.Timeouts.ConnectionIdle = time.Duration(h.config.Timeout) * time.Second

+ 3 - 2
proxy/http/server.go

@@ -20,6 +20,7 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/pipe"
@@ -41,7 +42,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
 	return s, nil
 }
 
-func (s *Server) policy() core.Policy {
+func (s *Server) policy() policy.Session {
 	config := s.config
 	p := s.v.PolicyManager().ForLevel(config.UserLevel)
 	if config.Timeout > 0 && config.UserLevel == 0 {
@@ -176,7 +177,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade
 	ctx, cancel := context.WithCancel(ctx)
 	timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)
 
-	ctx = core.ContextWithBufferPolicy(ctx, plcy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, plcy.Buffer)
 	link, err := dispatcher.Dispatch(ctx, dest)
 	if err != nil {
 		return err

+ 3 - 2
proxy/mtproto/server.go

@@ -14,6 +14,7 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/pipe"
@@ -32,7 +33,7 @@ var (
 type Server struct {
 	user    *protocol.User
 	account *Account
-	policy  core.PolicyManager
+	policy  policy.Manager
 }
 
 func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
@@ -114,7 +115,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
 
 	ctx, cancel := context.WithCancel(ctx)
 	timer := signal.CancelAfterInactivity(ctx, cancel, sPolicy.Timeouts.ConnectionIdle)
-	ctx = core.ContextWithBufferPolicy(ctx, sPolicy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, sPolicy.Buffer)
 
 	sc := SessionContext{
 		ConnectionType: ct,

+ 2 - 1
proxy/shadowsocks/server.go

@@ -13,6 +13,7 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/internet/udp"
@@ -175,7 +176,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 	ctx, cancel := context.WithCancel(ctx)
 	timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
 
-	ctx = core.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
 	link, err := dispatcher.Dispatch(ctx, dest)
 	if err != nil {
 		return err

+ 2 - 1
proxy/socks/client.go

@@ -7,6 +7,7 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/task"
 	"v2ray.com/core/common/vio"
+	"v2ray.com/core/features/policy"
 
 	"v2ray.com/core"
 	"v2ray.com/core/common"
@@ -22,7 +23,7 @@ import (
 // Client is a Socks5 client.
 type Client struct {
 	serverPicker  protocol.ServerPicker
-	policyManager core.PolicyManager
+	policyManager policy.Manager
 }
 
 // NewClient create a new Socks5 client based on the given config.

+ 3 - 2
proxy/socks/server.go

@@ -14,6 +14,7 @@ import (
 	"v2ray.com/core/common/session"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/task"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/internet/udp"
@@ -35,7 +36,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
 	return s, nil
 }
 
-func (s *Server) policy() core.Policy {
+func (s *Server) policy() policy.Session {
 	config := s.config
 	p := s.v.PolicyManager().ForLevel(config.UserLevel)
 	if config.Timeout > 0 {
@@ -137,7 +138,7 @@ func (s *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
 	timer := signal.CancelAfterInactivity(ctx, cancel, s.policy().Timeouts.ConnectionIdle)
 
 	plcy := s.policy()
-	ctx = core.ContextWithBufferPolicy(ctx, plcy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, plcy.Buffer)
 	link, err := dispatcher.Dispatch(ctx, dest)
 	if err != nil {
 		return err

+ 3 - 2
proxy/vmess/inbound/inbound.go

@@ -21,6 +21,7 @@ import (
 	"v2ray.com/core/common/task"
 	"v2ray.com/core/common/uuid"
 	feature_inbound "v2ray.com/core/features/inbound"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/proxy/vmess"
 	"v2ray.com/core/proxy/vmess/encoding"
@@ -100,7 +101,7 @@ func (v *userByEmail) Remove(email string) bool {
 
 // Handler is an inbound connection handler that handles messages in VMess protocol.
 type Handler struct {
-	policyManager         core.PolicyManager
+	policyManager         policy.Manager
 	inboundHandlerManager feature_inbound.Manager
 	clients               *vmess.TimedUserValidator
 	usersByEmail          *userByEmail
@@ -269,7 +270,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
 	ctx, cancel := context.WithCancel(ctx)
 	timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
 
-	ctx = core.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
+	ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
 	link, err := dispatcher.Dispatch(ctx, request.Destination())
 	if err != nil {
 		return newError("failed to dispatch request to ", request.Destination()).Base(err)

+ 2 - 2
transport/pipe/pipe.go

@@ -3,9 +3,9 @@ package pipe
 import (
 	"context"
 
-	"v2ray.com/core"
 	"v2ray.com/core/common/signal"
 	"v2ray.com/core/common/signal/done"
+	"v2ray.com/core/features/policy"
 )
 
 // Option for creating new Pipes.
@@ -36,7 +36,7 @@ func DiscardOverflow() Option {
 func OptionsFromContext(ctx context.Context) []Option {
 	var opt []Option
 
-	bp := core.BufferPolicyFromContext(ctx)
+	bp := policy.BufferPolicyFromContext(ctx)
 	if bp.PerConnection >= 0 {
 		opt = append(opt, WithSizeLimit(bp.PerConnection))
 	} else {

+ 16 - 19
v2ray.go

@@ -7,8 +7,11 @@ import (
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/serial"
 	"v2ray.com/core/common/uuid"
+	"v2ray.com/core/features"
+	"v2ray.com/core/features/dns"
 	"v2ray.com/core/features/inbound"
 	"v2ray.com/core/features/outbound"
+	"v2ray.com/core/features/policy"
 	"v2ray.com/core/features/routing"
 	"v2ray.com/core/features/stats"
 )
@@ -19,12 +22,6 @@ type Server interface {
 	common.Runnable
 }
 
-// Feature is the interface for V2Ray features. All features must implement this interface.
-// All existing features have an implementation in app directory. These features can be replaced by third-party ones.
-type Feature interface {
-	common.Runnable
-}
-
 // Instance combines all functionalities in V2Ray.
 type Instance struct {
 	dnsClient     syncDNSClient
@@ -36,7 +33,7 @@ type Instance struct {
 	stats         syncStatManager
 
 	access   sync.Mutex
-	features []Feature
+	features []features.Feature
 	id       uuid.UUID
 	running  bool
 }
@@ -143,14 +140,14 @@ func (s *Instance) Start() error {
 // 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(feature interface{}, instance Feature) error {
+func (s *Instance) RegisterFeature(feature interface{}, instance features.Feature) error {
 	running := false
 
 	switch feature.(type) {
-	case DNSClient, *DNSClient:
-		s.dnsClient.Set(instance.(DNSClient))
-	case PolicyManager, *PolicyManager:
-		s.policyManager.Set(instance.(PolicyManager))
+	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:
@@ -174,13 +171,13 @@ func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error
 	return nil
 }
 
-func (s *Instance) allFeatures() []Feature {
-	return append([]Feature{s.DNSClient(), s.PolicyManager(), s.Dispatcher(), s.Router(), s.InboundHandlerManager(), s.OutboundHandlerManager(), s.Stats()}, s.features...)
+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{}) Feature {
+func (s *Instance) GetFeature(featureType interface{}) features.Feature {
 	for _, f := range s.features {
 		if hasType, ok := f.(common.HasType); ok {
 			if hasType.Type() == featureType {
@@ -191,13 +188,13 @@ func (s *Instance) GetFeature(featureType interface{}) Feature {
 	return nil
 }
 
-// DNSClient returns the DNSClient used by this Instance. The returned DNSClient is always functional.
-func (s *Instance) DNSClient() DNSClient {
+// 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 PolicyManager used by this Instance. The returned PolicyManager is always functional.
-func (s *Instance) PolicyManager() PolicyManager {
+// 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)
 }