diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 217b3a64b..845f74b5a 100644 --- a/app/dispatcher/default.go +++ b/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 } diff --git a/app/dns/server.go b/app/dns/server.go index 1a286619e..de831fe5e 100644 --- a/app/dns/server.go +++ b/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) } diff --git a/app/policy/config.go b/app/policy/config.go index ed4bca27d..ffe81138f 100644 --- a/app/policy/config.go +++ b/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, }, diff --git a/app/policy/manager.go b/app/policy/manager.go index fd04ada03..5da6ce28c 100644 --- a/app/policy/manager.go +++ b/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() } diff --git a/app/policy/manager_test.go b/app/policy/manager_test.go index dde4e2acc..f830aa813 100644 --- a/app/policy/manager_test.go +++ b/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) diff --git a/app/policy/policy.go b/app/policy/policy.go index c7a435245..bb3ac3b3b 100644 --- a/app/policy/policy.go +++ b/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 diff --git a/app/router/router.go b/app/router/router.go index 1be4778be..baec3a453 100644 --- a/app/router/router.go +++ b/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 diff --git a/dns.go b/dns.go index ed618ef7d..349e89077 100644 --- a/dns.go +++ b/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 } diff --git a/features/dns/client.go b/features/dns/client.go new file mode 100644 index 000000000..e1ab41347 --- /dev/null +++ b/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) +} diff --git a/features/policy/policy.go b/features/policy/policy.go new file mode 100644 index 000000000..650de93a0 --- /dev/null +++ b/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) +} diff --git a/policy.go b/policy.go index 513ba5416..24e4aaa77 100644 --- a/policy.go +++ b/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 } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 4b44285fd..144350c41 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/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) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index f7a1c3fd1..06c672ce8 100644 --- a/proxy/freedom/freedom.go +++ b/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 diff --git a/proxy/http/server.go b/proxy/http/server.go index e7499c39a..74ecd5efc 100755 --- a/proxy/http/server.go +++ b/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 diff --git a/proxy/mtproto/server.go b/proxy/mtproto/server.go index 880d4a78c..3c315427a 100644 --- a/proxy/mtproto/server.go +++ b/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, diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index 323bd0763..fefd4c814 100644 --- a/proxy/shadowsocks/server.go +++ b/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 diff --git a/proxy/socks/client.go b/proxy/socks/client.go index 1f3398af5..a17f9951c 100644 --- a/proxy/socks/client.go +++ b/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. diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 590ec1919..11c2338bc 100644 --- a/proxy/socks/server.go +++ b/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 diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index b9bda6134..8f6e9d815 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/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) diff --git a/transport/pipe/pipe.go b/transport/pipe/pipe.go index a09ce7ccb..4ad251cae 100644 --- a/transport/pipe/pipe.go +++ b/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 { diff --git a/v2ray.go b/v2ray.go index d25d14f72..289836ba0 100755 --- a/v2ray.go +++ b/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) }